/***********************************************************************
*
* $CVSHeader$
*
* This file is part of WebScarab, an Open Web Application Security
* Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2004 Rogan Dawes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Getting Source
* ==============
*
* Source for this application is maintained at Sourceforge.net, a
* repository for free software projects.
*
* For details, please see http://www.sourceforge.net/projects/owasp
*
*/
/*
* ChunkedInputStream.java
*
* Created on May 25, 2003, 11:00 AM
*/
package org.owasp.webscarab.httpclient;
import java.util.ArrayList;
import java.util.logging.Logger;
import java.io.InputStream;
import java.io.FilterInputStream;
import java.io.IOException;
/**
*
* @author rdawes
*/
public class ChunkedInputStream extends FilterInputStream {
byte[] chunk = null;
int start = 0;
int size = 0;
String[][] _trailer = null;
private Logger _logger = Logger.getLogger(this.getClass().getName());
public ChunkedInputStream(InputStream in) throws IOException {
super(in);
readChunk();
}
public String[][] getTrailer() {
return _trailer;
}
private void readChunk() throws IOException {
String line = readLine().trim();
try {
size = Integer.parseInt(line.trim(),16);
_logger.finest("Expecting a chunk of " + size + " bytes");
chunk = new byte[size];
int read = 0;
while (read < size) {
int got = in.read(chunk,read, Math.min(1024,size-read));
_logger.finest("read " + got + " bytes");
if (got>0) {
read = read + got;
} else if (read == 0) {
_logger.info("read 0 bytes from the input stream! Huh!?");
} else {
_logger.info("No more bytes to read from the stream, read " + read + " of " + size);
continue;
}
}
_logger.finest("Got " + size + " bytes");
if (size == 0) { // read the trailer and the CRLF
readTrailer();
} else {
readLine(); // read the trailing line feed after the chunk body, but before the next chunk size
}
start = 0;
} catch (NumberFormatException nfe) {
_logger.severe("Error parsing chunk size from '" + line + "' : " + nfe);
}
}
public int read() throws IOException {
if (size == 0) {
return -1;
}
if (start == size) {
readChunk();
}
if (size == 0) {
return -1;
}
return chunk[start++];
}
public int read(byte[] b) throws IOException {
return read(b,0,b.length);
}
public int read(byte[] b, int off, int len) throws IOException {
if (size == 0) {
return -1;
}
if (start == size) {
readChunk();
}
if (size == 0) {
return -1;
}
if (len - off < available()) {
} else {
len = available();
}
System.arraycopy(chunk, start, b, off, len);
start += len;
return len;
}
public int available() throws IOException {
return size - start;
}
public boolean markSupported() {
return false;
}
private String readLine() throws IOException {
String line = new String();
int i;
byte[] b={(byte)0x00};
i = in.read();
while (i > -1 && i != 10 && i != 13) {
// Convert the int to a byte
// we use an array because we can't concat a single byte :-(
b[0] = (byte)(i & 0xFF);
String input = new String(b,0,1);
line = line.concat(input);
i = in.read();
}
if (i == 13) { // 10 is unix LF, but DOS does 13+10, so read the 10 if we got 13
i = in.read();
}
_logger.finest("Read '" + line + "'");
return line;
}
private void readTrailer() throws IOException {
String line = readLine();
ArrayList<String[]> trailer = new ArrayList<String[]>();
while (!line.equals("")) {
String[] pair = line.split(": *",2);
if (pair.length == 2) {
trailer.add(pair);
}
line = readLine();
}
if (trailer.size()>0) {
_trailer = new String[trailer.size()][2];
for (int i=0; i<trailer.size(); i++) {
String[] pair = (String[]) trailer.get(i);
_trailer[i][0] = pair[0];
_trailer[i][1] = pair[1];
}
}
}
}