Add support for 'charset' property for multipart boundaries

- Fixes #2004
This commit is contained in:
Frederic Bregier 2013-12-07 12:18:56 +01:00 committed by Trustin Lee
parent b17a765615
commit 9bd44a1d7c
2 changed files with 55 additions and 19 deletions

View File

@ -59,7 +59,7 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
/** /**
* Default charset to use * Default charset to use
*/ */
private final Charset charset; private Charset charset;
/** /**
* Does the last chunk already received * Does the last chunk already received
@ -193,10 +193,18 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
} }
/** /**
* Set from the request ContentType the multipartDataBoundary. * Set from the request ContentType the multipartDataBoundary and the possible charset.
*/ */
private void setMultipart(String contentType) { private void setMultipart(String contentType) {
multipartDataBoundary = HttpPostRequestDecoder.getMultipartDataBoundary(contentType); String[] dataBoundary = HttpPostRequestDecoder.getMultipartDataBoundary(contentType);
if (dataBoundary != null) {
multipartDataBoundary = dataBoundary[0];
if (dataBoundary.length > 1 && dataBoundary[1] != null) {
charset = Charset.forName(dataBoundary[1]);
}
} else {
multipartDataBoundary = null;
}
currentStatus = MultiPartStatus.HEADERDELIMITER; currentStatus = MultiPartStatus.HEADERDELIMITER;
} }

View File

@ -148,23 +148,40 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder {
/** /**
* Check from the request ContentType if this request is a Multipart request. * Check from the request ContentType if this request is a Multipart request.
* @return the multipartDataBoundary if it exists, else null * @return an array of String if multipartDataBoundary exists with the multipartDataBoundary
* as first element, charset if any as second (missing if not set), else null
*/ */
protected static String getMultipartDataBoundary(String contentType) { protected static String[] getMultipartDataBoundary(String contentType) {
// Check if Post using "multipart/form-data; boundary=--89421926422648" // Check if Post using "multipart/form-data; boundary=--89421926422648 [; charset=xxx]"
String[] headerContentType = splitHeaderContentType(contentType); String[] headerContentType = splitHeaderContentType(contentType);
if (headerContentType[0].toLowerCase().startsWith( if (headerContentType[0].toLowerCase().startsWith(
HttpHeaders.Values.MULTIPART_FORM_DATA) && HttpHeaders.Values.MULTIPART_FORM_DATA)) {
headerContentType[1].toLowerCase().startsWith( int mrank = 1, crank = 2;
HttpHeaders.Values.BOUNDARY)) { if (headerContentType[1].toLowerCase().startsWith(
String[] boundary = StringUtil.split(headerContentType[1], '='); HttpHeaders.Values.BOUNDARY)) {
mrank = 1;
crank = 2;
} else if (headerContentType[2].toLowerCase().startsWith(
HttpHeaders.Values.BOUNDARY)) {
mrank = 2;
crank = 1;
} else {
return null;
}
String[] boundary = StringUtil.split(headerContentType[mrank], '=');
if (boundary.length != 2) { if (boundary.length != 2) {
throw new ErrorDataDecoderException("Needs a boundary value"); throw new ErrorDataDecoderException("Needs a boundary value");
} }
return "--" + boundary[1]; if (headerContentType[crank].toLowerCase().startsWith(
} else { HttpHeaders.Values.CHARSET)) {
return null; String[] charset = StringUtil.split(headerContentType[crank], '=');
if (charset.length > 1) {
return new String[] {"--" + boundary[1], charset[1]};
}
}
return new String[] {"--" + boundary[1]};
} }
return null;
} }
@Override @Override
@ -228,26 +245,37 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder {
} }
/** /**
* Split the very first line (Content-Type value) in 2 Strings * Split the very first line (Content-Type value) in 3 Strings
* *
* @return the array of 2 Strings * @return the array of 3 Strings
*/ */
private static String[] splitHeaderContentType(String sb) { private static String[] splitHeaderContentType(String sb) {
int aStart; int aStart;
int aEnd; int aEnd;
int bStart; int bStart;
int bEnd; int bEnd;
int cStart;
int cEnd;
aStart = HttpPostBodyUtil.findNonWhitespace(sb, 0); aStart = HttpPostBodyUtil.findNonWhitespace(sb, 0);
aEnd = sb.indexOf(';'); aEnd = sb.indexOf(';');
if (aEnd == -1) { if (aEnd == -1) {
return new String[] { sb, "" }; return new String[] { sb, "", "" };
} }
bStart = HttpPostBodyUtil.findNonWhitespace(sb, aEnd + 1);
if (sb.charAt(aEnd - 1) == ' ') { if (sb.charAt(aEnd - 1) == ' ') {
aEnd--; aEnd--;
} }
bStart = HttpPostBodyUtil.findNonWhitespace(sb, aEnd + 1); bEnd = sb.indexOf(';', bStart);
bEnd = HttpPostBodyUtil.findEndOfString(sb); if (bEnd == -1) {
return new String[] { sb.substring(aStart, aEnd), sb.substring(bStart, bEnd) }; bEnd = HttpPostBodyUtil.findEndOfString(sb);
return new String[] { sb.substring(aStart, aEnd), sb.substring(bStart, bEnd), "" };
}
cStart = HttpPostBodyUtil.findNonWhitespace(sb, bEnd + 1);
if (sb.charAt(bEnd - 1) == ' ') {
bEnd--;
}
cEnd = HttpPostBodyUtil.findEndOfString(sb);
return new String[] { sb.substring(aStart, aEnd), sb.substring(bStart, bEnd), sb.substring(cStart, cEnd) };
} }
/** /**