private void setFinalBuffer(ChannelBuffer buffer) throws ErrorDataDecoderException, IOException { currentAttribute.addContent(buffer, true); String value = decodeAttribute(currentAttribute.getChannelBuffer().toString(charset), charset); currentAttribute.setValue(value); addHttpData(currentAttribute); currentAttribute = null; }
/** * This method 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() throws ErrorDataDecoderException { int firstpos = undecodedChunk.readerIndex(); int currentpos = firstpos; int equalpos = firstpos; int ampersandpos = firstpos; if (currentStatus == MultiPartStatus.NOTSTARTED) { currentStatus = MultiPartStatus.DISPOSITION; } boolean contRead = true; try { while (undecodedChunk.readable() && contRead) { char read = (char) undecodedChunk.readUnsignedByte(); currentpos++; switch (currentStatus) { case DISPOSITION: // search '=' 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); currentAttribute.setValue(""); // empty addHttpData(currentAttribute); currentAttribute = null; firstpos = currentpos; contRead = true; } break; case FIELD: // search '&' or end of line if (read == '&') { currentStatus = MultiPartStatus.DISPOSITION; ampersandpos = currentpos - 1; setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos)); firstpos = currentpos; contRead = true; } else if (read == HttpCodecUtil.CR) { if (undecodedChunk.readable()) { read = (char) undecodedChunk.readUnsignedByte(); currentpos++; if (read == HttpCodecUtil.LF) { currentStatus = MultiPartStatus.PREEPILOGUE; ampersandpos = currentpos - 2; setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos)); firstpos = currentpos; contRead = false; } else { // Error contRead = false; throw new ErrorDataDecoderException("Bad end of line"); } } else { currentpos--; } } else if (read == HttpCodecUtil.LF) { currentStatus = MultiPartStatus.PREEPILOGUE; ampersandpos = currentpos - 1; setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos)); firstpos = currentpos; contRead = false; } break; default: // just stop contRead = false; } } if (isLastChunk && currentAttribute != null) { // special case ampersandpos = currentpos; if (ampersandpos > firstpos) { setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos)); } else if (!currentAttribute.isCompleted()) { setFinalBuffer(ChannelBuffers.EMPTY_BUFFER); } firstpos = currentpos; currentStatus = MultiPartStatus.EPILOGUE; return; } if (contRead && currentAttribute != null) { // reset index except if to continue in case of FIELD status if (currentStatus == MultiPartStatus.FIELD) { currentAttribute.addContent(undecodedChunk.slice(firstpos, currentpos - firstpos), false); firstpos = currentpos; } undecodedChunk.readerIndex(firstpos); } else { // end of line so keep index } } catch (ErrorDataDecoderException e) { // error while decoding undecodedChunk.readerIndex(firstpos); throw e; } catch (IOException e) { // error while decoding undecodedChunk.readerIndex(firstpos); throw new ErrorDataDecoderException(e); } }
/** * Load the field value from a Multipart request * * @throws NotEnoughDataDecoderException Need more chunks * @throws ErrorDataDecoderException */ private void loadFieldMultipart(String delimiter) throws NotEnoughDataDecoderException, ErrorDataDecoderException { int readerIndex = undecodedChunk.readerIndex(); try { // found the decoder limit boolean newLine = true; int index = 0; int lastPosition = undecodedChunk.readerIndex(); boolean found = false; while (undecodedChunk.readable()) { byte nextByte = undecodedChunk.readByte(); if (newLine) { // Check the delimiter if (nextByte == delimiter.codePointAt(index)) { index++; if (delimiter.length() == index) { found = true; break; } continue; } else { newLine = false; index = 0; // continue until end of line if (nextByte == HttpCodecUtil.CR) { if (undecodedChunk.readable()) { nextByte = undecodedChunk.readByte(); if (nextByte == HttpCodecUtil.LF) { newLine = true; index = 0; lastPosition = undecodedChunk.readerIndex() - 2; } } } else if (nextByte == HttpCodecUtil.LF) { newLine = true; index = 0; lastPosition = undecodedChunk.readerIndex() - 1; } else { lastPosition = undecodedChunk.readerIndex(); } } } else { // continue until end of line if (nextByte == HttpCodecUtil.CR) { if (undecodedChunk.readable()) { nextByte = undecodedChunk.readByte(); if (nextByte == HttpCodecUtil.LF) { newLine = true; index = 0; lastPosition = undecodedChunk.readerIndex() - 2; } } } else if (nextByte == HttpCodecUtil.LF) { newLine = true; index = 0; lastPosition = undecodedChunk.readerIndex() - 1; } else { lastPosition = undecodedChunk.readerIndex(); } } } if (found) { // found so lastPosition is correct // but position is just after the delimiter (either close delimiter or simple one) // so go back of delimiter size try { currentAttribute.addContent( undecodedChunk.slice(readerIndex, lastPosition - readerIndex), true); } catch (IOException e) { throw new ErrorDataDecoderException(e); } undecodedChunk.readerIndex(lastPosition); } else { try { currentAttribute.addContent( undecodedChunk.slice(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); } }