741 |
10 Oct 06 |
olle |
1 |
/* |
1652 |
22 May 07 |
gregory |
$Id$ |
741 |
10 Oct 06 |
olle |
3 |
|
1916 |
31 Aug 07 |
jari |
Copyright (C) 2006 Olle Mansson |
1916 |
31 Aug 07 |
jari |
Copyright (C) 2007 Gregory Vincic |
741 |
10 Oct 06 |
olle |
6 |
|
1652 |
22 May 07 |
gregory |
This file is part of Proteios. |
1652 |
22 May 07 |
gregory |
Available at http://www.proteios.org/ |
741 |
10 Oct 06 |
olle |
9 |
|
1652 |
22 May 07 |
gregory |
Proteios is free software; you can redistribute it and/or modify it |
1652 |
22 May 07 |
gregory |
under the terms of the GNU General Public License as published by |
1652 |
22 May 07 |
gregory |
the Free Software Foundation; either version 2 of the License, or |
1652 |
22 May 07 |
gregory |
(at your option) any later version. |
741 |
10 Oct 06 |
olle |
14 |
|
1652 |
22 May 07 |
gregory |
Proteios is distributed in the hope that it will be useful, but |
1652 |
22 May 07 |
gregory |
WITHOUT ANY WARRANTY; without even the implied warranty of |
1652 |
22 May 07 |
gregory |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1652 |
22 May 07 |
gregory |
General Public License for more details. |
741 |
10 Oct 06 |
olle |
19 |
|
1652 |
22 May 07 |
gregory |
You should have received a copy of the GNU General Public License |
1652 |
22 May 07 |
gregory |
along with this program; if not, write to the Free Software |
1652 |
22 May 07 |
gregory |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
1652 |
22 May 07 |
gregory |
02111-1307, USA. |
1652 |
22 May 07 |
gregory |
24 |
*/ |
741 |
10 Oct 06 |
olle |
// Xerver Free Web Server |
741 |
10 Oct 06 |
olle |
// Copyright (C) 2002-2005 Omid Rouhani |
741 |
10 Oct 06 |
olle |
27 |
// |
741 |
10 Oct 06 |
olle |
28 |
// |
741 |
10 Oct 06 |
olle |
// This program is free software; you can redistribute it and/or |
741 |
10 Oct 06 |
olle |
// modify it under the terms of the GNU General Public License |
741 |
10 Oct 06 |
olle |
// as published by the Free Software Foundation; either version 2 |
741 |
10 Oct 06 |
olle |
// of the License, or (at your option) any later version. |
741 |
10 Oct 06 |
olle |
33 |
// |
741 |
10 Oct 06 |
olle |
// This program is distributed in the hope that it will be useful, |
741 |
10 Oct 06 |
olle |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
741 |
10 Oct 06 |
olle |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
741 |
10 Oct 06 |
olle |
// GNU General Public License for more details. |
741 |
10 Oct 06 |
olle |
38 |
// |
741 |
10 Oct 06 |
olle |
// You should have received a copy of the GNU General Public License |
741 |
10 Oct 06 |
olle |
// along with this program; if not, write to the Free Software |
741 |
10 Oct 06 |
olle |
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
741 |
10 Oct 06 |
olle |
42 |
// |
741 |
10 Oct 06 |
olle |
43 |
// |
741 |
10 Oct 06 |
olle |
44 |
// ############################################################# |
741 |
10 Oct 06 |
olle |
// ## YOU CAN CONTACT THE AUTHOR (OMID ROUHANI) AT: ## |
741 |
10 Oct 06 |
olle |
// ## HTTP://WWW.JAVASCRIPT.NU/XERVER/ ## |
741 |
10 Oct 06 |
olle |
47 |
// ## ## |
741 |
10 Oct 06 |
olle |
// ## IF YOUR SOFTWARE IS NOT RELEASED UNDER THE ## |
741 |
10 Oct 06 |
olle |
// ## GNU GENERAL PUBLIC LICENSE (GPL), ## |
741 |
10 Oct 06 |
olle |
// ## PLEASE DO NOT COPY ANYTHING FROM THIS SOURCE CODE!!! ## |
741 |
10 Oct 06 |
olle |
51 |
// ## ## |
741 |
10 Oct 06 |
olle |
// ## FOR FULL LICENSE, PLEASE READ "XERVER LICENSE". ## |
741 |
10 Oct 06 |
olle |
53 |
// ############################################################# |
1652 |
22 May 07 |
gregory |
54 |
package se.lu.thep.coreftpd.common; |
741 |
10 Oct 06 |
olle |
55 |
|
741 |
10 Oct 06 |
olle |
56 |
import java.io.DataInputStream; |
741 |
10 Oct 06 |
olle |
57 |
import java.io.InputStream; |
741 |
10 Oct 06 |
olle |
58 |
|
741 |
10 Oct 06 |
olle |
59 |
/** |
1652 |
22 May 07 |
gregory |
* <B>About this class:</B> <BR> |
1652 |
22 May 07 |
gregory |
* The difference between <CODE>DataInputStreamWithReadLine</CODE> and <CODE>DataInputStream</CODE> |
1652 |
22 May 07 |
gregory |
* is that <CODE>DataInputStreamWithReadLine</CODE> has a method called "<CODE>String |
1652 |
22 May 07 |
gregory |
* myReadLine(int maxLineSize)</CODE>". |
1652 |
22 May 07 |
gregory |
64 |
* |
741 |
10 Oct 06 |
olle |
* @author <a href="http://www.JavaScript.nu/xerver/" TARGET="_top">Omid Rouhani</a> |
741 |
10 Oct 06 |
olle |
* @version 1.0 |
741 |
10 Oct 06 |
olle |
67 |
*/ |
2418 |
22 Nov 07 |
gregory |
68 |
final public class DataInputStreamWithReadLine |
2418 |
22 Nov 07 |
gregory |
69 |
extends DataInputStream |
2418 |
22 Nov 07 |
gregory |
70 |
{ |
1652 |
22 May 07 |
gregory |
71 |
private final int i_bufferLength = 128; // Note: as myReadLine is recrusive, |
2418 |
22 Nov 07 |
gregory |
// you can make this value as |
2418 |
22 Nov 07 |
gregory |
// big/small as you want |
2418 |
22 Nov 07 |
gregory |
// (performance might however be |
2418 |
22 Nov 07 |
gregory |
// better/worse with other values). |
2418 |
22 Nov 07 |
gregory |
// The value of this DOES NOT set |
2418 |
22 Nov 07 |
gregory |
// the maximum length of the line |
2418 |
22 Nov 07 |
gregory |
// read!!! Arbitrary long lines can |
2418 |
22 Nov 07 |
gregory |
// be read anyway! |
1652 |
22 May 07 |
gregory |
80 |
private char c_lastLineBreakRead = ' '; // Enter anything but '\r' and '\n' |
1652 |
22 May 07 |
gregory |
81 |
|
2418 |
22 Nov 07 |
gregory |
82 |
|
2418 |
22 Nov 07 |
gregory |
// here and it will work fine!! |
1652 |
22 May 07 |
gregory |
84 |
public DataInputStreamWithReadLine(InputStream in) // now we can Extend |
2418 |
22 Nov 07 |
gregory |
// ReadInputStreamSTDIN |
2418 |
22 Nov 07 |
gregory |
// without problem |
741 |
10 Oct 06 |
olle |
87 |
{ |
741 |
10 Oct 06 |
olle |
88 |
super(in); |
741 |
10 Oct 06 |
olle |
89 |
} |
741 |
10 Oct 06 |
olle |
90 |
|
2418 |
22 Nov 07 |
gregory |
91 |
|
1652 |
22 May 07 |
gregory |
92 |
/** |
1652 |
22 May 07 |
gregory |
* Reads a line of bytes from the stream. <BR> |
1652 |
22 May 07 |
gregory |
* The String returned does not contain \r or \n. <BR> |
1652 |
22 May 07 |
gregory |
* If a \r or \n is found as the very first byte in the stream it will be |
1652 |
22 May 07 |
gregory |
* removed from the stream. If there are additional \r or \n in the stream |
1652 |
22 May 07 |
gregory |
* these might, or might not, be removed!! <BR> |
1652 |
22 May 07 |
gregory |
* However, this method does guaranty that when you call it for the first |
1652 |
22 May 07 |
gregory |
* time, it will ignore the 3 first \r and \n in the very beginning of the |
1652 |
22 May 07 |
gregory |
* stream (if there are 3 (or less) \r or \n, that is) and then read one |
1652 |
22 May 07 |
gregory |
* line and then return it. For each and every time you call this method |
1652 |
22 May 07 |
gregory |
* later (without reading from the stream with another method) it will |
1652 |
22 May 07 |
gregory |
* successfully read one line and return it. <BR> |
1652 |
22 May 07 |
gregory |
* You have to guaranty that the lines are using one of these formats |
1652 |
22 May 07 |
gregory |
* (example with 6 lines, including one empty line): <BR> |
1652 |
22 May 07 |
gregory |
* "line1\nline2\nline3\n\nline5\nline6" <BR> |
1652 |
22 May 07 |
gregory |
* "line1\rline2\rline3\r\rline5\rline6" <BR> |
1652 |
22 May 07 |
gregory |
* "line1\r\nline2\r\nline3\r\n\r\nline5\r\nline6" |
1652 |
22 May 07 |
gregory |
* <P> |
1652 |
22 May 07 |
gregory |
* Other formats might, or might not, work with this method. <BR> |
1652 |
22 May 07 |
gregory |
* <BR> |
1652 |
22 May 07 |
gregory |
* This method does not use the reset() or mark() methods. |
1652 |
22 May 07 |
gregory |
113 |
* |
2418 |
22 Nov 07 |
gregory |
* @param i_maxSizeToRead the maximum length of a line. If there is no \n or |
2418 |
22 Nov 07 |
gregory |
* \r within the first i_maxSizeToRead bytes, the bytes read are |
2418 |
22 Nov 07 |
gregory |
* converted into a String which is returned (with length |
2418 |
22 Nov 07 |
gregory |
* i_maxSizeToRead) |
1652 |
22 May 07 |
gregory |
118 |
*/ |
1652 |
22 May 07 |
gregory |
// i_maxSizeToRead = the maximum length of a line. If there is no \n or \r |
1652 |
22 May 07 |
gregory |
// within the first i_maxSizeToRead bytes, the bytes read are converted into |
1652 |
22 May 07 |
gregory |
// a String which is returned (with length i_maxSizeToRead) |
1652 |
22 May 07 |
gregory |
122 |
public String myReadLine(int i_maxSizeToRead) // IMPORTANT: as the line is |
2418 |
22 Nov 07 |
gregory |
// buffered before it is |
2418 |
22 Nov 07 |
gregory |
// returned i_maxSizeToRead |
2418 |
22 Nov 07 |
gregory |
// is used so no one shall |
2418 |
22 Nov 07 |
gregory |
// be able to send a very |
2418 |
22 Nov 07 |
gregory |
// long line without any \r |
2418 |
22 Nov 07 |
gregory |
// or \n to eat all memory. |
2418 |
22 Nov 07 |
gregory |
// THIS IS A IMPORTANT |
2418 |
22 Nov 07 |
gregory |
// SECURITY ISSUE!!! |
741 |
10 Oct 06 |
olle |
131 |
{ |
741 |
10 Oct 06 |
olle |
132 |
return myReadLineWithInitialNewLineCharacters(i_maxSizeToRead, true); |
741 |
10 Oct 06 |
olle |
133 |
} |
741 |
10 Oct 06 |
olle |
134 |
|
2418 |
22 Nov 07 |
gregory |
135 |
|
741 |
10 Oct 06 |
olle |
136 |
/** |
1652 |
22 May 07 |
gregory |
* <CODE>String myReadLine(int i_maxSizeToRead)</CODE> actually calls this |
1652 |
22 May 07 |
gregory |
* method with <CODE>myReadLineWithInitialNewLineCharacters(i_maxSizeToRead, |
2418 |
22 Nov 07 |
gregory |
* true)</CODE>. <BR> |
1652 |
22 May 07 |
gregory |
* <BR> |
1652 |
22 May 07 |
gregory |
* This method does not use the reset() or mark() methods. |
1652 |
22 May 07 |
gregory |
142 |
* |
2418 |
22 Nov 07 |
gregory |
* @param i_maxSizeToRead the maximum length of a line. If there is no \n or |
2418 |
22 Nov 07 |
gregory |
* \r within the first i_maxSizeToRead bytes, the bytes read are |
2418 |
22 Nov 07 |
gregory |
* converted into a String which is returned (with length |
2418 |
22 Nov 07 |
gregory |
* i_maxSizeToRead) |
2418 |
22 Nov 07 |
gregory |
* @param b_ignoreInitialNewLineCharacters If this is true then we will |
2418 |
22 Nov 07 |
gregory |
* ignore the initial new line characters ("\n" and "\r") |
1652 |
22 May 07 |
gregory |
149 |
*/ |
1652 |
22 May 07 |
gregory |
150 |
private String myReadLineWithInitialNewLineCharacters(int i_maxSizeToRead, |
1652 |
22 May 07 |
gregory |
151 |
boolean b_ignoreInitialNewLineCharacters) // IMPORTANT: as the |
2418 |
22 Nov 07 |
gregory |
// line is buffered |
2418 |
22 Nov 07 |
gregory |
// before it is returned |
2418 |
22 Nov 07 |
gregory |
// i_maxSizeToRead is |
2418 |
22 Nov 07 |
gregory |
// used so no one shall |
2418 |
22 Nov 07 |
gregory |
// be able to send a |
2418 |
22 Nov 07 |
gregory |
// very long line |
2418 |
22 Nov 07 |
gregory |
// without any \r or \n |
2418 |
22 Nov 07 |
gregory |
// to eat all memory. |
2418 |
22 Nov 07 |
gregory |
// THIS IS A IMPORTANT |
2418 |
22 Nov 07 |
gregory |
// SECURITY ISSUE!!! |
741 |
10 Oct 06 |
olle |
162 |
{ |
1652 |
22 May 07 |
gregory |
163 |
byte[] buffer = new byte[i_bufferLength]; |
741 |
10 Oct 06 |
olle |
164 |
byte b; |
741 |
10 Oct 06 |
olle |
165 |
char c; |
1652 |
22 May 07 |
gregory |
166 |
int i = 0; |
1652 |
22 May 07 |
gregory |
167 |
int n = 0; // Number of buffered bytes |
2418 |
22 Nov 07 |
gregory |
168 |
try |
2418 |
22 Nov 07 |
gregory |
169 |
{ |
1652 |
22 May 07 |
gregory |
170 |
int i_numberOfLineBreakRead = 0; |
1652 |
22 May 07 |
gregory |
171 |
boolean b_isFirstLoop = true; |
2418 |
22 Nov 07 |
gregory |
172 |
for (; i < i_bufferLength && i_maxSizeToRead > 0; i++) |
2418 |
22 Nov 07 |
gregory |
173 |
{ |
1652 |
22 May 07 |
gregory |
174 |
b = readByte(); |
1652 |
22 May 07 |
gregory |
175 |
c = (char) b; |
2418 |
22 Nov 07 |
gregory |
176 |
if (c == '\n' || c == '\r') |
2418 |
22 Nov 07 |
gregory |
177 |
{ |
1652 |
22 May 07 |
gregory |
// If [we are not ignoring the first \r or \n] and [we are |
1652 |
22 May 07 |
gregory |
// at the first character of the stream]... |
2418 |
22 Nov 07 |
gregory |
180 |
if (!b_ignoreInitialNewLineCharacters && b_isFirstLoop) |
2418 |
22 Nov 07 |
gregory |
181 |
{ |
1652 |
22 May 07 |
gregory |
// Then break here and return "". |
1652 |
22 May 07 |
gregory |
// This is necessary for this reason: if we have a |
1652 |
22 May 07 |
gregory |
// buffer length of 3 and a stream such as "abc\ndef" |
1652 |
22 May 07 |
gregory |
// then we don't want the readLine to return the string |
1652 |
22 May 07 |
gregory |
// "abcdef", but only "abc". To avoid this bug we have |
1652 |
22 May 07 |
gregory |
// this check. |
1652 |
22 May 07 |
gregory |
188 |
return ""; |
1652 |
22 May 07 |
gregory |
189 |
} |
1652 |
22 May 07 |
gregory |
190 |
i_numberOfLineBreakRead++; |
1652 |
22 May 07 |
gregory |
// IF [this is NOT the very first line read (reason: DO NOT |
1652 |
22 May 07 |
gregory |
// return "" BEFORE line2: |
1652 |
22 May 07 |
gregory |
// "line1\r\nline2\r\n\r\nline3\r\n")] |
1652 |
22 May 07 |
gregory |
// OR [we have read 3 line breaks (in normal case: this will |
1652 |
22 May 07 |
gregory |
// be "\n\r\n") (reason: return "" after line2: |
1652 |
22 May 07 |
gregory |
// "line1\r\nline2\r\n\r\nline3\r\n")] |
1652 |
22 May 07 |
gregory |
// OR [the first charcter we find now is the same as the |
1652 |
22 May 07 |
gregory |
// last line break character read last time this method was |
1652 |
22 May 07 |
gregory |
// called (reason: return "" after line2: |
1652 |
22 May 07 |
gregory |
// "line1\nline2\n\nline3\n")] |
2418 |
22 Nov 07 |
gregory |
201 |
if (!b_isFirstLoop || i_numberOfLineBreakRead == 3 || (c_lastLineBreakRead == c && i_numberOfLineBreakRead == 1)) // If |
2418 |
22 Nov 07 |
gregory |
// [the |
2418 |
22 Nov 07 |
gregory |
// first |
2418 |
22 Nov 07 |
gregory |
// byte |
2418 |
22 Nov 07 |
gregory |
// was |
2418 |
22 Nov 07 |
gregory |
// a \r |
2418 |
22 Nov 07 |
gregory |
// or |
2418 |
22 Nov 07 |
gregory |
// \n] |
2418 |
22 Nov 07 |
gregory |
// OR |
2418 |
22 Nov 07 |
gregory |
// [we |
2418 |
22 Nov 07 |
gregory |
// have |
2418 |
22 Nov 07 |
gregory |
// read |
2418 |
22 Nov 07 |
gregory |
// the |
2418 |
22 Nov 07 |
gregory |
// \r |
2418 |
22 Nov 07 |
gregory |
// or |
2418 |
22 Nov 07 |
gregory |
// \n |
2418 |
22 Nov 07 |
gregory |
// after |
2418 |
22 Nov 07 |
gregory |
// our |
2418 |
22 Nov 07 |
gregory |
// line |
2418 |
22 Nov 07 |
gregory |
// (or, |
2418 |
22 Nov 07 |
gregory |
// it's |
2418 |
22 Nov 07 |
gregory |
// a |
2418 |
22 Nov 07 |
gregory |
// real |
2418 |
22 Nov 07 |
gregory |
// empty |
2418 |
22 Nov 07 |
gregory |
// line, |
2418 |
22 Nov 07 |
gregory |
// such |
2418 |
22 Nov 07 |
gregory |
// as |
2418 |
22 Nov 07 |
gregory |
// "\n\n" |
2418 |
22 Nov 07 |
gregory |
// in |
2418 |
22 Nov 07 |
gregory |
// this |
2418 |
22 Nov 07 |
gregory |
// example: |
2418 |
22 Nov 07 |
gregory |
// "line1\nline2\n\nline3\nline4\n". |
2418 |
22 Nov 07 |
gregory |
// Note |
2418 |
22 Nov 07 |
gregory |
// that |
2418 |
22 Nov 07 |
gregory |
// the |
2418 |
22 Nov 07 |
gregory |
// example |
2418 |
22 Nov 07 |
gregory |
// line |
2418 |
22 Nov 07 |
gregory |
// given, |
2418 |
22 Nov 07 |
gregory |
// or |
2418 |
22 Nov 07 |
gregory |
// the |
2418 |
22 Nov 07 |
gregory |
// one |
2418 |
22 Nov 07 |
gregory |
// below, |
2418 |
22 Nov 07 |
gregory |
// both |
2418 |
22 Nov 07 |
gregory |
// will |
2418 |
22 Nov 07 |
gregory |
// work |
2418 |
22 Nov 07 |
gregory |
// well |
2418 |
22 Nov 07 |
gregory |
// with |
2418 |
22 Nov 07 |
gregory |
// this |
2418 |
22 Nov 07 |
gregory |
// "read-line-algorithm": |
2418 |
22 Nov 07 |
gregory |
// "line1\r\nline2\r\nline3\r\n\r\nline4\r\nLine5")] |
1652 |
22 May 07 |
gregory |
251 |
{ |
1652 |
22 May 07 |
gregory |
252 |
c_lastLineBreakRead = c; |
1652 |
22 May 07 |
gregory |
253 |
if (n > 0) |
1652 |
22 May 07 |
gregory |
254 |
return new String(buffer, 0, n); |
2418 |
22 Nov 07 |
gregory |
255 |
return ""; |
1652 |
22 May 07 |
gregory |
256 |
} |
2418 |
22 Nov 07 |
gregory |
257 |
} |
2418 |
22 Nov 07 |
gregory |
258 |
else |
2418 |
22 Nov 07 |
gregory |
259 |
{ |
1652 |
22 May 07 |
gregory |
260 |
i_maxSizeToRead--; |
1652 |
22 May 07 |
gregory |
261 |
buffer[n++] = b; |
1652 |
22 May 07 |
gregory |
262 |
b_isFirstLoop = false; |
741 |
10 Oct 06 |
olle |
263 |
} |
741 |
10 Oct 06 |
olle |
264 |
} |
741 |
10 Oct 06 |
olle |
265 |
} |
2418 |
22 Nov 07 |
gregory |
266 |
catch (Exception e) |
2418 |
22 Nov 07 |
gregory |
267 |
{} |
1652 |
22 May 07 |
gregory |
268 |
c_lastLineBreakRead = ' '; // We have gone out of the loop the "normal |
2418 |
22 Nov 07 |
gregory |
// way" (we did not run "return xxx" in the |
2418 |
22 Nov 07 |
gregory |
// loop.) |
1652 |
22 May 07 |
gregory |
// IMPORTANT: If we get an Exception above, it's possible to come here |
1652 |
22 May 07 |
gregory |
// with the values n=0 and i_maxSizeToRead="the value given as the |
1652 |
22 May 07 |
gregory |
// argument". If we then recursively call this function again with the |
1652 |
22 May 07 |
gregory |
// same value to i_maxSizeToRead and the error is a kind of error that |
1652 |
22 May 07 |
gregory |
// does always come (for me it was EOFException) we will loop |
1652 |
22 May 07 |
gregory |
// recursively forever without changing the value of n and |
1652 |
22 May 07 |
gregory |
// i_maxSizeToRead!!! AVOID THIS! We avoid this by returing "" if n=0 |
1652 |
22 May 07 |
gregory |
// (which will make this function to work good and as Expected). |
1652 |
22 May 07 |
gregory |
279 |
if (n == 0) |
741 |
10 Oct 06 |
olle |
280 |
return ""; |
1652 |
22 May 07 |
gregory |
281 |
else if (i == i_bufferLength) // If [\r or \n has not been found |
2418 |
22 Nov 07 |
gregory |
// within the first "i_bufferLength" |
2418 |
22 Nov 07 |
gregory |
// bytes]... |
2418 |
22 Nov 07 |
gregory |
284 |
return new String(buffer, 0, n) + myReadLineWithInitialNewLineCharacters( |
2418 |
22 Nov 07 |
gregory |
285 |
i_maxSizeToRead, false); // We have false so that we shall |
2418 |
22 Nov 07 |
gregory |
// not ignore |
2418 |
22 Nov 07 |
gregory |
// the initial \r or \n in the remaining of |
2418 |
22 Nov 07 |
gregory |
// the input stream. (if our for example is |
2418 |
22 Nov 07 |
gregory |
// 3 characters long and the stream contains |
2418 |
22 Nov 07 |
gregory |
// "abc\ndef", then this prevents the \n to |
2418 |
22 Nov 07 |
gregory |
// be ignored (and hence the entire string |
2418 |
22 Nov 07 |
gregory |
// abcdef is read as one single line)) |
741 |
10 Oct 06 |
olle |
293 |
else |
1652 |
22 May 07 |
gregory |
294 |
return new String(buffer, 0, n); |
741 |
10 Oct 06 |
olle |
295 |
} |
741 |
10 Oct 06 |
olle |
296 |
} |