Search in sources :

Example 1 with SeekAheadOptimize

use of io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize in project netty by netty.

the class HttpPostMultipartRequestDecoder method loadFieldMultipart.

/**
     * Load the field value from a Multipart request
     *
     * @throws NotEnoughDataDecoderException
     *             Need more chunks
     * @throws ErrorDataDecoderException
     */
private void loadFieldMultipart(String delimiter) {
    SeekAheadOptimize sao;
    try {
        sao = new SeekAheadOptimize(undecodedChunk);
    } catch (SeekAheadNoBackArrayException ignored) {
        loadFieldMultipartStandard(delimiter);
        return;
    }
    int readerIndex = undecodedChunk.readerIndex();
    try {
        // found the decoder limit
        boolean newLine = true;
        int index = 0;
        int lastPosition;
        int lastrealpos = sao.pos;
        boolean found = false;
        while (sao.pos < sao.limit) {
            byte nextByte = sao.bytes[sao.pos++];
            if (newLine) {
                // Check the delimiter
                if (nextByte == delimiter.codePointAt(index)) {
                    index++;
                    if (delimiter.length() == index) {
                        found = true;
                        break;
                    }
                } else {
                    newLine = false;
                    index = 0;
                    // continue until end of line
                    if (nextByte == HttpConstants.CR) {
                        if (sao.pos < sao.limit) {
                            nextByte = sao.bytes[sao.pos++];
                            if (nextByte == HttpConstants.LF) {
                                newLine = true;
                                index = 0;
                                lastrealpos = sao.pos - 2;
                            } else {
                                // Unread last nextByte
                                sao.pos--;
                                lastrealpos = sao.pos;
                            }
                        }
                    } else if (nextByte == HttpConstants.LF) {
                        newLine = true;
                        index = 0;
                        lastrealpos = sao.pos - 1;
                    } else {
                        lastrealpos = sao.pos;
                    }
                }
            } else {
                // continue until end of line
                if (nextByte == HttpConstants.CR) {
                    if (sao.pos < sao.limit) {
                        nextByte = sao.bytes[sao.pos++];
                        if (nextByte == HttpConstants.LF) {
                            newLine = true;
                            index = 0;
                            lastrealpos = sao.pos - 2;
                        } else {
                            // Unread last nextByte
                            sao.pos--;
                            lastrealpos = sao.pos;
                        }
                    }
                } else if (nextByte == HttpConstants.LF) {
                    newLine = true;
                    index = 0;
                    lastrealpos = sao.pos - 1;
                } else {
                    lastrealpos = sao.pos;
                }
            }
        }
        lastPosition = sao.getReadPosition(lastrealpos);
        if (found) {
            // so go back of delimiter size
            try {
                currentAttribute.addContent(undecodedChunk.copy(readerIndex, lastPosition - readerIndex), true);
            } catch (IOException e) {
                throw new ErrorDataDecoderException(e);
            }
            undecodedChunk.readerIndex(lastPosition);
        } else {
            try {
                currentAttribute.addContent(undecodedChunk.copy(readerIndex, lastPosition - readerIndex), false);
            } catch (IOException e) {
                throw new ErrorDataDecoderException(e);
            }
            undecodedChunk.readerIndex(lastPosition);
            throw new NotEnoughDataDecoderException();
        }
    } catch (IndexOutOfBoundsException e) {
        undecodedChunk.readerIndex(readerIndex);
        throw new NotEnoughDataDecoderException(e);
    }
}
Also used : SeekAheadOptimize(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize) SeekAheadNoBackArrayException(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException) NotEnoughDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException) IOException(java.io.IOException) ErrorDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException)

Example 2 with SeekAheadOptimize

use of io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize in project netty by netty.

the class HttpPostMultipartRequestDecoder method readLine.

/**
     * Read one line up to the CRLF or LF
     *
     * @return the String from one line
     * @throws NotEnoughDataDecoderException
     *             Need more chunks and reset the readerInder to the previous
     *             value
     */
private String readLine() {
    SeekAheadOptimize sao;
    try {
        sao = new SeekAheadOptimize(undecodedChunk);
    } catch (SeekAheadNoBackArrayException ignored) {
        return readLineStandard();
    }
    int readerIndex = undecodedChunk.readerIndex();
    try {
        ByteBuf line = buffer(64);
        while (sao.pos < sao.limit) {
            byte nextByte = sao.bytes[sao.pos++];
            if (nextByte == HttpConstants.CR) {
                if (sao.pos < sao.limit) {
                    nextByte = sao.bytes[sao.pos++];
                    if (nextByte == HttpConstants.LF) {
                        sao.setReadPosition(0);
                        return line.toString(charset);
                    } else {
                        // Write CR (not followed by LF)
                        sao.pos--;
                        line.writeByte(HttpConstants.CR);
                    }
                } else {
                    line.writeByte(nextByte);
                }
            } else if (nextByte == HttpConstants.LF) {
                sao.setReadPosition(0);
                return line.toString(charset);
            } else {
                line.writeByte(nextByte);
            }
        }
    } catch (IndexOutOfBoundsException e) {
        undecodedChunk.readerIndex(readerIndex);
        throw new NotEnoughDataDecoderException(e);
    }
    undecodedChunk.readerIndex(readerIndex);
    throw new NotEnoughDataDecoderException();
}
Also used : SeekAheadOptimize(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize) SeekAheadNoBackArrayException(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException) NotEnoughDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException) ByteBuf(io.netty.buffer.ByteBuf)

Example 3 with SeekAheadOptimize

use of io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize in project netty by netty.

the class HttpPostMultipartRequestDecoder method readDelimiter.

/**
     * Read one line up to --delimiter or --delimiter-- and if existing the CRLF
     * or LF. Note that CRLF or LF are mandatory for opening delimiter
     * (--delimiter) but not for closing delimiter (--delimiter--) since some
     * clients does not include CRLF in this case.
     *
     * @param delimiter
     *            of the form --string, such that '--' is already included
     * @return the String from one line as the delimiter searched (opening or
     *         closing)
     * @throws NotEnoughDataDecoderException
     *             Need more chunks and reset the readerInder to the previous
     *             value
     */
private String readDelimiter(String delimiter) {
    SeekAheadOptimize sao;
    try {
        sao = new SeekAheadOptimize(undecodedChunk);
    } catch (SeekAheadNoBackArrayException ignored) {
        return readDelimiterStandard(delimiter);
    }
    int readerIndex = undecodedChunk.readerIndex();
    int delimiterPos = 0;
    int len = delimiter.length();
    try {
        StringBuilder sb = new StringBuilder(64);
        // check conformity with delimiter
        while (sao.pos < sao.limit && delimiterPos < len) {
            byte nextByte = sao.bytes[sao.pos++];
            if (nextByte == delimiter.charAt(delimiterPos)) {
                delimiterPos++;
                sb.append((char) nextByte);
            } else {
                // delimiter not found so break here !
                undecodedChunk.readerIndex(readerIndex);
                throw new NotEnoughDataDecoderException();
            }
        }
        // Now check if either opening delimiter or closing delimiter
        if (sao.pos < sao.limit) {
            byte nextByte = sao.bytes[sao.pos++];
            if (nextByte == HttpConstants.CR) {
                // first check for opening delimiter
                if (sao.pos < sao.limit) {
                    nextByte = sao.bytes[sao.pos++];
                    if (nextByte == HttpConstants.LF) {
                        sao.setReadPosition(0);
                        return sb.toString();
                    } else {
                        // error CR without LF
                        // delimiter not found so break here !
                        undecodedChunk.readerIndex(readerIndex);
                        throw new NotEnoughDataDecoderException();
                    }
                } else {
                    // error since CR must be followed by LF
                    // delimiter not found so break here !
                    undecodedChunk.readerIndex(readerIndex);
                    throw new NotEnoughDataDecoderException();
                }
            } else if (nextByte == HttpConstants.LF) {
                // same first check for opening delimiter where LF used with
                // no CR
                sao.setReadPosition(0);
                return sb.toString();
            } else if (nextByte == '-') {
                sb.append('-');
                // second check for closing delimiter
                if (sao.pos < sao.limit) {
                    nextByte = sao.bytes[sao.pos++];
                    if (nextByte == '-') {
                        sb.append('-');
                        // now try to find if CRLF or LF there
                        if (sao.pos < sao.limit) {
                            nextByte = sao.bytes[sao.pos++];
                            if (nextByte == HttpConstants.CR) {
                                if (sao.pos < sao.limit) {
                                    nextByte = sao.bytes[sao.pos++];
                                    if (nextByte == HttpConstants.LF) {
                                        sao.setReadPosition(0);
                                        return sb.toString();
                                    } else {
                                        // error CR without LF
                                        // delimiter not found so break here !
                                        undecodedChunk.readerIndex(readerIndex);
                                        throw new NotEnoughDataDecoderException();
                                    }
                                } else {
                                    // error CR without LF
                                    // delimiter not found so break here !
                                    undecodedChunk.readerIndex(readerIndex);
                                    throw new NotEnoughDataDecoderException();
                                }
                            } else if (nextByte == HttpConstants.LF) {
                                sao.setReadPosition(0);
                                return sb.toString();
                            } else {
                                // No CRLF but ok however (Adobe Flash
                                // uploader)
                                // minus 1 since we read one char ahead but
                                // should not
                                sao.setReadPosition(1);
                                return sb.toString();
                            }
                        }
                        // FIXME what do we do here?
                        // either considering it is fine, either waiting for
                        // more data to come?
                        // lets try considering it is fine...
                        sao.setReadPosition(0);
                        return sb.toString();
                    }
                // whatever now => error since incomplete
                // only one '-' => not enough or whatever not enough
                // element
                }
            }
        }
    } catch (IndexOutOfBoundsException e) {
        undecodedChunk.readerIndex(readerIndex);
        throw new NotEnoughDataDecoderException(e);
    }
    undecodedChunk.readerIndex(readerIndex);
    throw new NotEnoughDataDecoderException();
}
Also used : SeekAheadOptimize(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize) SeekAheadNoBackArrayException(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException) NotEnoughDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException)

Example 4 with SeekAheadOptimize

use of io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize in project netty by netty.

the class HttpPostStandardRequestDecoder method parseBodyAttributes.

/**
     * This getMethod fill the map and list with as much Attribute as possible from
     * Body in not Multipart mode.
     *
     * @throws ErrorDataDecoderException
     *             if there is a problem with the charset decoding or other
     *             errors
     */
private void parseBodyAttributes() {
    SeekAheadOptimize sao;
    try {
        sao = new SeekAheadOptimize(undecodedChunk);
    } catch (SeekAheadNoBackArrayException ignored) {
        parseBodyAttributesStandard();
        return;
    }
    int firstpos = undecodedChunk.readerIndex();
    int currentpos = firstpos;
    int equalpos;
    int ampersandpos;
    if (currentStatus == MultiPartStatus.NOTSTARTED) {
        currentStatus = MultiPartStatus.DISPOSITION;
    }
    boolean contRead = true;
    try {
        loop: while (sao.pos < sao.limit) {
            char read = (char) (sao.bytes[sao.pos++] & 0xFF);
            currentpos++;
            switch(currentStatus) {
                case // search '='
                DISPOSITION:
                    if (read == '=') {
                        currentStatus = MultiPartStatus.FIELD;
                        equalpos = currentpos - 1;
                        String key = decodeAttribute(undecodedChunk.toString(firstpos, equalpos - firstpos, charset), charset);
                        currentAttribute = factory.createAttribute(request, key);
                        firstpos = currentpos;
                    } else if (read == '&') {
                        // special empty FIELD
                        currentStatus = MultiPartStatus.DISPOSITION;
                        ampersandpos = currentpos - 1;
                        String key = decodeAttribute(undecodedChunk.toString(firstpos, ampersandpos - firstpos, charset), charset);
                        currentAttribute = factory.createAttribute(request, key);
                        // empty
                        currentAttribute.setValue("");
                        addHttpData(currentAttribute);
                        currentAttribute = null;
                        firstpos = currentpos;
                        contRead = true;
                    }
                    break;
                case // search '&' or end of line
                FIELD:
                    if (read == '&') {
                        currentStatus = MultiPartStatus.DISPOSITION;
                        ampersandpos = currentpos - 1;
                        setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos));
                        firstpos = currentpos;
                        contRead = true;
                    } else if (read == HttpConstants.CR) {
                        if (sao.pos < sao.limit) {
                            read = (char) (sao.bytes[sao.pos++] & 0xFF);
                            currentpos++;
                            if (read == HttpConstants.LF) {
                                currentStatus = MultiPartStatus.PREEPILOGUE;
                                ampersandpos = currentpos - 2;
                                sao.setReadPosition(0);
                                setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos));
                                firstpos = currentpos;
                                contRead = false;
                                break loop;
                            } else {
                                // Error
                                sao.setReadPosition(0);
                                throw new ErrorDataDecoderException("Bad end of line");
                            }
                        } else {
                            if (sao.limit > 0) {
                                currentpos--;
                            }
                        }
                    } else if (read == HttpConstants.LF) {
                        currentStatus = MultiPartStatus.PREEPILOGUE;
                        ampersandpos = currentpos - 1;
                        sao.setReadPosition(0);
                        setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos));
                        firstpos = currentpos;
                        contRead = false;
                        break loop;
                    }
                    break;
                default:
                    // just stop
                    sao.setReadPosition(0);
                    contRead = false;
                    break loop;
            }
        }
        if (isLastChunk && currentAttribute != null) {
            // special case
            ampersandpos = currentpos;
            if (ampersandpos > firstpos) {
                setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos));
            } else if (!currentAttribute.isCompleted()) {
                setFinalBuffer(EMPTY_BUFFER);
            }
            firstpos = currentpos;
            currentStatus = MultiPartStatus.EPILOGUE;
            undecodedChunk.readerIndex(firstpos);
            return;
        }
        if (contRead && currentAttribute != null) {
            // reset index except if to continue in case of FIELD getStatus
            if (currentStatus == MultiPartStatus.FIELD) {
                currentAttribute.addContent(undecodedChunk.copy(firstpos, currentpos - firstpos), false);
                firstpos = currentpos;
            }
            undecodedChunk.readerIndex(firstpos);
        } else {
            // end of line or end of block so keep index to last valid position
            undecodedChunk.readerIndex(firstpos);
        }
    } catch (ErrorDataDecoderException e) {
        // error while decoding
        undecodedChunk.readerIndex(firstpos);
        throw e;
    } catch (IOException e) {
        // error while decoding
        undecodedChunk.readerIndex(firstpos);
        throw new ErrorDataDecoderException(e);
    } catch (IllegalArgumentException e) {
        // error while decoding
        undecodedChunk.readerIndex(firstpos);
        throw new ErrorDataDecoderException(e);
    }
}
Also used : SeekAheadOptimize(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize) SeekAheadNoBackArrayException(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException) IOException(java.io.IOException) ErrorDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException)

Example 5 with SeekAheadOptimize

use of io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize in project netty by netty.

the class HttpPostMultipartRequestDecoder method readFileUploadByteMultipart.

/**
     * Read a FileUpload data as Byte (Binary) and add the bytes directly to the
     * FileUpload. If the delimiter is found, the FileUpload is completed.
     *
     * @throws NotEnoughDataDecoderException
     *             Need more chunks but do not reset the readerInder since some
     *             values will be already added to the FileOutput
     * @throws ErrorDataDecoderException
     *             write IO error occurs with the FileUpload
     */
private void readFileUploadByteMultipart(String delimiter) {
    SeekAheadOptimize sao;
    try {
        sao = new SeekAheadOptimize(undecodedChunk);
    } catch (SeekAheadNoBackArrayException ignored) {
        readFileUploadByteMultipartStandard(delimiter);
        return;
    }
    int readerIndex = undecodedChunk.readerIndex();
    // found the decoder limit
    boolean newLine = true;
    int index = 0;
    int lastrealpos = sao.pos;
    int lastPosition;
    boolean found = false;
    while (sao.pos < sao.limit) {
        byte nextByte = sao.bytes[sao.pos++];
        if (newLine) {
            // Check the delimiter
            if (nextByte == delimiter.codePointAt(index)) {
                index++;
                if (delimiter.length() == index) {
                    found = true;
                    break;
                }
            } else {
                newLine = false;
                index = 0;
                // continue until end of line
                if (nextByte == HttpConstants.CR) {
                    if (sao.pos < sao.limit) {
                        nextByte = sao.bytes[sao.pos++];
                        if (nextByte == HttpConstants.LF) {
                            newLine = true;
                            index = 0;
                            lastrealpos = sao.pos - 2;
                        } else {
                            // unread next byte
                            sao.pos--;
                            // save last valid position
                            lastrealpos = sao.pos;
                        }
                    }
                } else if (nextByte == HttpConstants.LF) {
                    newLine = true;
                    index = 0;
                    lastrealpos = sao.pos - 1;
                } else {
                    // save last valid position
                    lastrealpos = sao.pos;
                }
            }
        } else {
            // continue until end of line
            if (nextByte == HttpConstants.CR) {
                if (sao.pos < sao.limit) {
                    nextByte = sao.bytes[sao.pos++];
                    if (nextByte == HttpConstants.LF) {
                        newLine = true;
                        index = 0;
                        lastrealpos = sao.pos - 2;
                    } else {
                        // unread next byte
                        sao.pos--;
                        // save last valid position
                        lastrealpos = sao.pos;
                    }
                }
            } else if (nextByte == HttpConstants.LF) {
                newLine = true;
                index = 0;
                lastrealpos = sao.pos - 1;
            } else {
                // save last valid position
                lastrealpos = sao.pos;
            }
        }
    }
    lastPosition = sao.getReadPosition(lastrealpos);
    ByteBuf buffer = undecodedChunk.copy(readerIndex, lastPosition - readerIndex);
    if (found) {
        // found so lastPosition is correct and final
        try {
            currentFileUpload.addContent(buffer, true);
            // just before the CRLF and delimiter
            undecodedChunk.readerIndex(lastPosition);
        } catch (IOException e) {
            throw new ErrorDataDecoderException(e);
        }
    } else {
        // position is OK
        try {
            currentFileUpload.addContent(buffer, false);
            // last valid char (not CR, not LF, not beginning of delimiter)
            undecodedChunk.readerIndex(lastPosition);
            throw new NotEnoughDataDecoderException();
        } catch (IOException e) {
            throw new ErrorDataDecoderException(e);
        }
    }
}
Also used : SeekAheadOptimize(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize) SeekAheadNoBackArrayException(io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException) NotEnoughDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException) IOException(java.io.IOException) ByteBuf(io.netty.buffer.ByteBuf) ErrorDataDecoderException(io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException)

Aggregations

SeekAheadNoBackArrayException (io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException)5 SeekAheadOptimize (io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize)5 NotEnoughDataDecoderException (io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException)4 ErrorDataDecoderException (io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException)3 IOException (java.io.IOException)3 ByteBuf (io.netty.buffer.ByteBuf)2