diff options
Diffstat (limited to 'libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java')
| -rw-r--r-- | libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java | 102 |
1 files changed, 78 insertions, 24 deletions
diff --git a/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java b/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java index a4487d146e8..9870412f2da 100644 --- a/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java +++ b/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java @@ -1,5 +1,5 @@ /* ChunkedInputStream.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,28 +38,46 @@ exception statement from your version. */ package gnu.java.net.protocol.http; -import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ProtocolException; + +// +// Note that we rely on the implemtation of skip() in the super class +// (InputStream) calling our read methods to account for chunk headers +// while skipping. +// + + /** * Input stream wrapper for the "chunked" transfer-coding. * * @author Chris Burdess (dog@gnu.org) */ public class ChunkedInputStream - extends FilterInputStream + extends InputStream { private static final byte CR = 0x0d; private static final byte LF = 0x0a; + Headers headers; + + /** The underlying stream. */ + private InputStream in; + + /** Size of the chunk we're reading. */ int size; + /** Number of bytes we've read in this chunk. */ int count; + /** + * True when we should read meta-information, false when we should + * read data. + */ boolean meta; + /** True when we've hit EOF. */ boolean eof; - Headers headers; /** * Constructor. @@ -68,7 +86,7 @@ public class ChunkedInputStream */ public ChunkedInputStream(InputStream in, Headers headers) { - super(in); + this.in = in; this.headers = headers; size = -1; count = 0; @@ -84,21 +102,10 @@ public class ChunkedInputStream { return -1; } - int ret = (int) buf[0]; - if (ret < 0) - { - ret += 0x100; - } - return ret; - } - - public int read(byte[] buffer) - throws IOException - { - return read(buffer, 0, buffer.length); + return 0xff & buf[0]; } - public int read(byte[] buffer, int offset, int length) + public synchronized int read(byte[] buffer, int offset, int length) throws IOException { if (eof) @@ -120,7 +127,18 @@ public class ChunkedInputStream } else if (c == 0x0a && last == 0x0d) // CRLF { - size = Integer.parseInt(buf.toString(), 16); + try + { + size = Integer.parseInt(buf.toString(), 16); + } + catch (NumberFormatException nfe) + { + IOException ioe = new IOException("Bad chunk header"); + ioe.initCause(nfe); + // Unrecoverable. Don't try to read more. + in.close(); + throw ioe; + } break; } else if (!seenSemi && c >= 0x30) @@ -142,17 +160,22 @@ public class ChunkedInputStream } else { - int diff = length - offset; - int max = size - count; - max = (diff < max) ? diff : max; - int len = (max > 0) ? in.read(buffer, offset, max) : 0; + int canRead = Math.min(size - count, length); + int len = in.read(buffer, offset, canRead); + if (len == -1) + { + // This is an error condition but it isn't clear what we + // should do with it. + eof = true; + return -1; + } count += len; if (count == size) { // Read CRLF int c1 = in.read(); int c2 = in.read(); - if (c1 == -1 && c2 == -1) + if (c1 == -1 || c2 == -1) { // EOF before CRLF: bad, but ignore eof = true; @@ -167,6 +190,37 @@ public class ChunkedInputStream return len; } } + + /** + * This method returns the number of bytes that can be read from + * this stream before a read might block. Even if the underlying + * InputStream has data available past the end of the current chunk, + * we have no way of knowing how large the next chunk header will + * be. So we cannot report available data past the current chunk. + * + * @return The number of bytes that can be read before a read might + * block + * + * @exception IOException If an error occurs + */ + public int available() throws IOException + { + if (meta) + return 0; + + return Math.min(in.available(), size - count); + } + + /** + * This method closes the ChunkedInputStream by closing the underlying + * InputStream. + * + * @exception IOException If an error occurs + */ + public void close() throws IOException + { + in.close(); + } } |

