use of io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException in project netty by netty.
the class HttpPostMultipartRequestDecoder method findMultipartDisposition.
/**
* Find the next Disposition
*
* @return the next InterfaceHttpData if any
* @throws ErrorDataDecoderException
*/
private InterfaceHttpData findMultipartDisposition() {
int readerIndex = undecodedChunk.readerIndex();
if (currentStatus == MultiPartStatus.DISPOSITION) {
currentFieldAttributes = new TreeMap<CharSequence, Attribute>(CaseIgnoringComparator.INSTANCE);
}
// read many lines until empty line with newline found! Store all data
while (!skipOneLine()) {
String newline;
try {
skipControlCharacters();
newline = readLine();
} catch (NotEnoughDataDecoderException ignored) {
undecodedChunk.readerIndex(readerIndex);
return null;
}
String[] contents = splitMultipartHeader(newline);
if (HttpHeaderNames.CONTENT_DISPOSITION.contentEqualsIgnoreCase(contents[0])) {
boolean checkSecondArg;
if (currentStatus == MultiPartStatus.DISPOSITION) {
checkSecondArg = HttpHeaderValues.FORM_DATA.contentEqualsIgnoreCase(contents[1]);
} else {
checkSecondArg = HttpHeaderValues.ATTACHMENT.contentEqualsIgnoreCase(contents[1]) || HttpHeaderValues.FILE.contentEqualsIgnoreCase(contents[1]);
}
if (checkSecondArg) {
// read next values and store them in the map as Attribute
for (int i = 2; i < contents.length; i++) {
String[] values = contents[i].split("=", 2);
Attribute attribute;
try {
String name = cleanString(values[0]);
String value = values[1];
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
if (HttpHeaderValues.FILENAME.contentEquals(name)) {
// filename value is quoted string so strip them
value = value.substring(1, value.length() - 1);
} else {
// otherwise we need to clean the value
value = cleanString(value);
}
attribute = factory.createAttribute(request, name, value);
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(attribute.getName(), attribute);
}
}
} else if (HttpHeaderNames.CONTENT_TRANSFER_ENCODING.contentEqualsIgnoreCase(contents[0])) {
Attribute attribute;
try {
attribute = factory.createAttribute(request, HttpHeaderNames.CONTENT_TRANSFER_ENCODING.toString(), cleanString(contents[1]));
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(HttpHeaderNames.CONTENT_TRANSFER_ENCODING, attribute);
} else if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(contents[0])) {
Attribute attribute;
try {
attribute = factory.createAttribute(request, HttpHeaderNames.CONTENT_LENGTH.toString(), cleanString(contents[1]));
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(HttpHeaderNames.CONTENT_LENGTH, attribute);
} else if (HttpHeaderNames.CONTENT_TYPE.contentEqualsIgnoreCase(contents[0])) {
// Take care of possible "multipart/mixed"
if (HttpHeaderValues.MULTIPART_MIXED.contentEqualsIgnoreCase(contents[1])) {
if (currentStatus == MultiPartStatus.DISPOSITION) {
String values = StringUtil.substringAfter(contents[2], '=');
multipartMixedBoundary = "--" + values;
currentStatus = MultiPartStatus.MIXEDDELIMITER;
return decodeMultipart(MultiPartStatus.MIXEDDELIMITER);
} else {
throw new ErrorDataDecoderException("Mixed Multipart found in a previous Mixed Multipart");
}
} else {
for (int i = 1; i < contents.length; i++) {
if (contents[i].toLowerCase().startsWith(HttpHeaderValues.CHARSET.toString())) {
String values = StringUtil.substringAfter(contents[i], '=');
Attribute attribute;
try {
attribute = factory.createAttribute(request, HttpHeaderValues.CHARSET.toString(), cleanString(values));
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(HttpHeaderValues.CHARSET, attribute);
} else {
Attribute attribute;
try {
attribute = factory.createAttribute(request, cleanString(contents[0]), contents[i]);
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(attribute.getName(), attribute);
}
}
}
} else {
throw new ErrorDataDecoderException("Unknown Params: " + newline);
}
}
// Is it a FileUpload
Attribute filenameAttribute = currentFieldAttributes.get(HttpHeaderValues.FILENAME);
if (currentStatus == MultiPartStatus.DISPOSITION) {
if (filenameAttribute != null) {
// FileUpload
currentStatus = MultiPartStatus.FILEUPLOAD;
// do not change the buffer position
return decodeMultipart(MultiPartStatus.FILEUPLOAD);
} else {
// Field
currentStatus = MultiPartStatus.FIELD;
// do not change the buffer position
return decodeMultipart(MultiPartStatus.FIELD);
}
} else {
if (filenameAttribute != null) {
// FileUpload
currentStatus = MultiPartStatus.MIXEDFILEUPLOAD;
// do not change the buffer position
return decodeMultipart(MultiPartStatus.MIXEDFILEUPLOAD);
} else {
// Field is not supported in MIXED mode
throw new ErrorDataDecoderException("Filename not found");
}
}
}
use of io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException in project netty by netty.
the class HttpPostMultipartRequestDecoder method getFileUpload.
/**
* Get the FileUpload (new one or current one)
*
* @param delimiter
* the delimiter to use
* @return the InterfaceHttpData if any
* @throws ErrorDataDecoderException
*/
protected InterfaceHttpData getFileUpload(String delimiter) {
// eventually restart from existing FileUpload
// Now get value according to Content-Type and Charset
Attribute encoding = currentFieldAttributes.get(HttpHeaderNames.CONTENT_TRANSFER_ENCODING);
Charset localCharset = charset;
// Default
TransferEncodingMechanism mechanism = TransferEncodingMechanism.BIT7;
if (encoding != null) {
String code;
try {
code = encoding.getValue().toLowerCase();
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
}
if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT7.value())) {
localCharset = CharsetUtil.US_ASCII;
} else if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT8.value())) {
localCharset = CharsetUtil.ISO_8859_1;
mechanism = TransferEncodingMechanism.BIT8;
} else if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value())) {
// no real charset, so let the default
mechanism = TransferEncodingMechanism.BINARY;
} else {
throw new ErrorDataDecoderException("TransferEncoding Unknown: " + code);
}
}
Attribute charsetAttribute = currentFieldAttributes.get(HttpHeaderValues.CHARSET);
if (charsetAttribute != null) {
try {
localCharset = Charset.forName(charsetAttribute.getValue());
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
} catch (UnsupportedCharsetException e) {
throw new ErrorDataDecoderException(e);
}
}
if (currentFileUpload == null) {
Attribute filenameAttribute = currentFieldAttributes.get(HttpHeaderValues.FILENAME);
Attribute nameAttribute = currentFieldAttributes.get(HttpHeaderValues.NAME);
Attribute contentTypeAttribute = currentFieldAttributes.get(HttpHeaderNames.CONTENT_TYPE);
Attribute lengthAttribute = currentFieldAttributes.get(HttpHeaderNames.CONTENT_LENGTH);
long size;
try {
size = lengthAttribute != null ? Long.parseLong(lengthAttribute.getValue()) : 0L;
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
} catch (NumberFormatException ignored) {
size = 0;
}
try {
String contentType;
if (contentTypeAttribute != null) {
contentType = contentTypeAttribute.getValue();
} else {
contentType = HttpPostBodyUtil.DEFAULT_BINARY_CONTENT_TYPE;
}
currentFileUpload = factory.createFileUpload(request, cleanString(nameAttribute.getValue()), cleanString(filenameAttribute.getValue()), contentType, mechanism.value(), localCharset, size);
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
}
}
// load data as much as possible
try {
readFileUploadByteMultipart(delimiter);
} catch (NotEnoughDataDecoderException e) {
// So do not change the currentStatus
return null;
}
if (currentFileUpload.isCompleted()) {
// ready to load the next one
if (currentStatus == MultiPartStatus.FILEUPLOAD) {
currentStatus = MultiPartStatus.HEADERDELIMITER;
currentFieldAttributes = null;
} else {
currentStatus = MultiPartStatus.MIXEDDELIMITER;
cleanMixedAttributes();
}
FileUpload fileUpload = currentFileUpload;
currentFileUpload = null;
return fileUpload;
}
// So do not change the currentStatus
return null;
}
use of io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException 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);
}
}
use of io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException in project netty by netty.
the class HttpPostMultipartRequestDecoder method readFileUploadByteMultipartStandard.
/**
* 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 readFileUploadByteMultipartStandard(String delimiter) {
int readerIndex = undecodedChunk.readerIndex();
// found the decoder limit
boolean newLine = true;
int index = 0;
int lastPosition = undecodedChunk.readerIndex();
boolean found = false;
while (undecodedChunk.isReadable()) {
byte nextByte = undecodedChunk.readByte();
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 (undecodedChunk.isReadable()) {
nextByte = undecodedChunk.readByte();
if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 2;
} else {
// save last valid position
lastPosition = undecodedChunk.readerIndex() - 1;
// Unread next byte.
undecodedChunk.readerIndex(lastPosition);
}
}
} else if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 1;
} else {
// save last valid position
lastPosition = undecodedChunk.readerIndex();
}
}
} else {
// continue until end of line
if (nextByte == HttpConstants.CR) {
if (undecodedChunk.isReadable()) {
nextByte = undecodedChunk.readByte();
if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 2;
} else {
// save last valid position
lastPosition = undecodedChunk.readerIndex() - 1;
// Unread next byte.
undecodedChunk.readerIndex(lastPosition);
}
}
} else if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 1;
} else {
// save last valid position
lastPosition = undecodedChunk.readerIndex();
}
}
}
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);
}
}
}
use of io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException in project netty by netty.
the class HttpPostMultipartRequestDecoder method loadFieldMultipartStandard.
/**
* Load the field value from a Multipart request
*
* @throws NotEnoughDataDecoderException
* Need more chunks
* @throws ErrorDataDecoderException
*/
private void loadFieldMultipartStandard(String delimiter) {
int readerIndex = undecodedChunk.readerIndex();
try {
// found the decoder limit
boolean newLine = true;
int index = 0;
int lastPosition = undecodedChunk.readerIndex();
boolean found = false;
while (undecodedChunk.isReadable()) {
byte nextByte = undecodedChunk.readByte();
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 (undecodedChunk.isReadable()) {
nextByte = undecodedChunk.readByte();
if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 2;
} else {
// Unread second nextByte
lastPosition = undecodedChunk.readerIndex() - 1;
undecodedChunk.readerIndex(lastPosition);
}
} else {
lastPosition = undecodedChunk.readerIndex() - 1;
}
} else if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 1;
} else {
lastPosition = undecodedChunk.readerIndex();
}
}
} else {
// continue until end of line
if (nextByte == HttpConstants.CR) {
if (undecodedChunk.isReadable()) {
nextByte = undecodedChunk.readByte();
if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 2;
} else {
// Unread second nextByte
lastPosition = undecodedChunk.readerIndex() - 1;
undecodedChunk.readerIndex(lastPosition);
}
} else {
lastPosition = undecodedChunk.readerIndex() - 1;
}
} else if (nextByte == HttpConstants.LF) {
newLine = true;
index = 0;
lastPosition = undecodedChunk.readerIndex() - 1;
} else {
lastPosition = undecodedChunk.readerIndex();
}
}
}
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);
}
}
Aggregations