FileDocCategorySizeDatePackage
ChunkedInputFilter.javaAPI DocApache Tomcat 6.0.148698Fri Jul 20 04:20:30 BST 2007org.apache.coyote.http11.filters

ChunkedInputFilter

public class ChunkedInputFilter extends Object implements org.apache.coyote.http11.InputFilter
Chunked input filter. Parses chunked data according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
author
Remy Maucherat
author
Filip Hanik

Fields Summary
protected static final String
ENCODING_NAME
protected static final org.apache.tomcat.util.buf.ByteChunk
ENCODING
protected org.apache.coyote.InputBuffer
buffer
Next buffer in the pipeline.
protected int
remaining
Number of bytes remaining in the current chunk.
protected int
pos
Position in the buffer.
protected int
lastValid
Last valid byte in the buffer.
protected byte[]
buf
Read bytes buffer.
protected org.apache.tomcat.util.buf.ByteChunk
readChunk
Byte chunk used to read bytes.
protected boolean
endChunk
Flag set to true when the end chunk has been read.
protected boolean
needCRLFParse
Flag set to true if the next call to doRead() must parse a CRLF pair before doing anything else.
Constructors Summary
Methods Summary
public intavailable()
Amount of bytes still available in a buffer.

        return (lastValid - pos);
    
public intdoRead(org.apache.tomcat.util.buf.ByteChunk chunk, org.apache.coyote.Request req)
Read bytes.

return
If the filter does request length control, this value is significant; it should be the number of bytes consumed from the buffer, up until the end of the current request body, or the buffer length, whichever is greater. If the filter does not do request body length control, the returned value should be -1.


    // ------------------------------------------------------------- Properties


    // ---------------------------------------------------- InputBuffer Methods


                                                                    
         
          

        if (endChunk)
            return -1;

        if(needCRLFParse) {
            needCRLFParse = false;
            parseCRLF();
        }

        if (remaining <= 0) {
            if (!parseChunkHeader()) {
                throw new IOException("Invalid chunk header");
            }
            if (endChunk) {
                parseEndChunk();
                return -1;
            }
        }

        int result = 0;

        if (pos >= lastValid) {
            readBytes();
        }

        if (remaining > (lastValid - pos)) {
            result = lastValid - pos;
            remaining = remaining - result;
            chunk.setBytes(buf, pos, result);
            pos = lastValid;
        } else {
            result = remaining;
            chunk.setBytes(buf, pos, remaining);
            pos = pos + remaining;
            remaining = 0;
            needCRLFParse = true;
        }

        return result;

    
public longend()
End the current request.


        // Consume extra bytes : parse the stream until the end chunk is found
        while (doRead(readChunk, null) >= 0) {
        }

        // Return the number of extra bytes which were consumed
        return (lastValid - pos);

    
public org.apache.tomcat.util.buf.ByteChunkgetEncodingName()
Return the name of the associated encoding; Here, the value is "identity".

        return ENCODING;
    
protected booleanparseCRLF()
Parse CRLF at end of chunk.


        boolean eol = false;

        while (!eol) {

            if (pos >= lastValid) {
                if (readBytes() <= 0)
                    throw new IOException("Invalid CRLF");
            }

            if (buf[pos] == Constants.CR) {
            } else if (buf[pos] == Constants.LF) {
                eol = true;
            } else {
                throw new IOException("Invalid CRLF");
            }

            pos++;

        }

        return true;

    
protected booleanparseChunkHeader()
Parse the header of a chunk. A chunk header can look like A10CRLF F23;chunk-extension to be ignoredCRLF The letters before CRLF but after the trailer mark, must be valid hex digits, we should not parse F23IAMGONNAMESSTHISUP34CRLF as a valid header according to spec


        int result = 0;
        boolean eol = false;
        boolean readDigit = false;
        boolean trailer = false;

        while (!eol) {

            if (pos >= lastValid) {
                if (readBytes() <= 0)
                    return false;
            }

            if (buf[pos] == Constants.CR) {
            } else if (buf[pos] == Constants.LF) {
                eol = true;
            } else if (buf[pos] == Constants.SEMI_COLON) {
                trailer = true;
            } else if (!trailer) { 
                //don't read data after the trailer
                if (HexUtils.DEC[buf[pos]] != -1) {
                    readDigit = true;
                    result *= 16;
                    result += HexUtils.DEC[buf[pos]];
                } else {
                    //we shouldn't allow invalid, non hex characters
                    //in the chunked header
                    return false;
                }
            }

            pos++;

        }

        if (!readDigit)
            return false;

        if (result == 0)
            endChunk = true;

        remaining = result;
        if (remaining < 0)
            return false;

        return true;

    
protected booleanparseEndChunk()
Parse end chunk data. FIXME: Handle trailers


        return parseCRLF(); // FIXME

    
protected intreadBytes()
Read bytes from the previous buffer.


        int nRead = buffer.doRead(readChunk, null);
        pos = readChunk.getStart();
        lastValid = pos + nRead;
        buf = readChunk.getBytes();

        return nRead;

    
public voidrecycle()
Make the filter ready to process the next request.

        remaining = 0;
        pos = 0;
        lastValid = 0;
        endChunk = false;
    
public voidsetBuffer(org.apache.coyote.InputBuffer buffer)
Set the next buffer in the filter pipeline.

        this.buffer = buffer;
    
public voidsetRequest(org.apache.coyote.Request request)
Read the content length from the request.