Frames | No Frames |
1: /* 2: * ChunkedInputStream.java 3: * Copyright (C) 2004 The Free Software Foundation 4: * 5: * This file is part of GNU inetlib, a library. 6: * 7: * GNU inetlib is free software; you can redistribute it and/or modify 8: * it under the terms of the GNU General Public License as published by 9: * the Free Software Foundation; either version 2 of the License, or 10: * (at your option) any later version. 11: * 12: * GNU inetlib is distributed in the hope that it will be useful, 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15: * GNU General Public License for more details. 16: * 17: * You should have received a copy of the GNU General Public License 18: * along with this library; if not, write to the Free Software 19: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20: * 21: * Linking this library statically or dynamically with other modules is 22: * making a combined work based on this library. Thus, the terms and 23: * conditions of the GNU General Public License cover the whole 24: * combination. 25: * 26: * As a special exception, the copyright holders of this library give you 27: * permission to link this library with independent modules to produce an 28: * executable, regardless of the license terms of these independent 29: * modules, and to copy and distribute the resulting executable under 30: * terms of your choice, provided that you also meet, for each linked 31: * independent module, the terms and conditions of the license of that 32: * module. An independent module is a module which is not derived from 33: * or based on this library. If you modify this library, you may extend 34: * this exception to your version of the library, but you are not 35: * obliged to do so. If you do not wish to do so, delete this 36: * exception statement from your version. 37: */ 38: 39: package gnu.inet.http; 40: 41: import java.io.FilterInputStream; 42: import java.io.InputStream; 43: import java.io.IOException; 44: import java.net.ProtocolException; 45: 46: /** 47: * Input stream wrapper for the "chunked" transfer-coding. 48: * 49: * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> 50: */ 51: public class ChunkedInputStream 52: extends FilterInputStream 53: { 54: 55: private static final byte CR = 0x0d; 56: private static final byte LF = 0x0a; 57: 58: int size; 59: int count; 60: boolean meta; 61: boolean eof; 62: Headers headers; 63: 64: /** 65: * Constructor. 66: * @param in the response socket input stream 67: * @param headers the headers to receive additional header lines 68: */ 69: public ChunkedInputStream(InputStream in, Headers headers) 70: { 71: super(in); 72: this.headers = headers; 73: size = -1; 74: count = 0; 75: meta = true; 76: } 77: 78: public int read() 79: throws IOException 80: { 81: byte[] buf = new byte[1]; 82: int len = read(buf, 0, 1); 83: if (len == -1) 84: { 85: return -1; 86: } 87: int ret = (int) buf[0]; 88: if (ret < 0) 89: { 90: ret += 0x100; 91: } 92: return ret; 93: } 94: 95: public int read(byte[] buffer) 96: throws IOException 97: { 98: return read(buffer, 0, buffer.length); 99: } 100: 101: public int read(byte[] buffer, int offset, int length) 102: throws IOException 103: { 104: if (eof) 105: { 106: return -1; 107: } 108: if (meta) 109: { 110: // Read chunk header 111: int c, last = 0; 112: boolean seenSemi = false; 113: StringBuffer buf = new StringBuffer(); 114: do 115: { 116: c = in.read(); 117: if (c == 0x3b) // ; 118: { 119: seenSemi = true; 120: } 121: else if (c == 0x0a && last == 0x0d) // CRLF 122: { 123: size = Integer.parseInt(buf.toString(), 16); 124: break; 125: } 126: else if (!seenSemi && c >= 0x30) 127: { 128: buf.append ((char) c); 129: } 130: last = c; 131: } 132: while(c != -1); 133: count = 0; 134: meta = false; 135: } 136: if (size == 0) 137: { 138: // Read trailer 139: headers.parse(in); 140: eof = true; 141: return -1; 142: } 143: else 144: { 145: int diff = length - offset; 146: int max = size - count; 147: max = (diff < max) ? diff : max; 148: int len = (max > 0) ? in.read(buffer, offset, max) : 0; 149: count += len; 150: if (count == size) 151: { 152: // Read CRLF 153: int c1 = in.read(); 154: int c2 = in.read(); 155: if (c1 == -1 && c2 == -1) 156: { 157: // EOF before CRLF: bad, but ignore 158: eof = true; 159: return -1; 160: } 161: if (c1 != 0x0d || c2 != 0x0a) 162: { 163: throw new ProtocolException("expecting CRLF: " + c1 + "," + c2); 164: } 165: meta = true; 166: } 167: return len; 168: } 169: } 170: 171: }