[#1358] Fix Encoding of multipart attribute names and filenames for non ASCII chars

This commit is contained in:
Norman Maurer 2013-05-14 15:24:01 +02:00
parent dbad71366d
commit a331c87a7a
2 changed files with 38 additions and 30 deletions

View File

@ -471,14 +471,14 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput<HttpContent>
*/ */
if (data instanceof Attribute) { if (data instanceof Attribute) {
if (duringMixedMode) { if (duringMixedMode) {
InternalAttribute internal = new InternalAttribute(); InternalAttribute internal = new InternalAttribute(charset);
internal.addValue("\r\n--" + multipartMixedBoundary + "--"); internal.addValue("\r\n--" + multipartMixedBoundary + "--");
multipartHttpDatas.add(internal); multipartHttpDatas.add(internal);
multipartMixedBoundary = null; multipartMixedBoundary = null;
currentFileUpload = null; currentFileUpload = null;
duringMixedMode = false; duringMixedMode = false;
} }
InternalAttribute internal = new InternalAttribute(); InternalAttribute internal = new InternalAttribute(charset);
if (!multipartHttpDatas.isEmpty()) { if (!multipartHttpDatas.isEmpty()) {
// previously a data field so CRLF // previously a data field so CRLF
internal.addValue("\r\n"); internal.addValue("\r\n");
@ -503,7 +503,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput<HttpContent>
globalBodySize += attribute.length() + internal.size(); globalBodySize += attribute.length() + internal.size();
} else if (data instanceof FileUpload) { } else if (data instanceof FileUpload) {
FileUpload fileUpload = (FileUpload) data; FileUpload fileUpload = (FileUpload) data;
InternalAttribute internal = new InternalAttribute(); InternalAttribute internal = new InternalAttribute(charset);
if (!multipartHttpDatas.isEmpty()) { if (!multipartHttpDatas.isEmpty()) {
// previously a data field so CRLF // previously a data field so CRLF
internal.addValue("\r\n"); internal.addValue("\r\n");
@ -525,7 +525,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput<HttpContent>
multipartMixedBoundary = null; multipartMixedBoundary = null;
// start a new one (could be replaced if mixed start again // start a new one (could be replaced if mixed start again
// from here // from here
internal = new InternalAttribute(); internal = new InternalAttribute(charset);
internal.addValue("\r\n"); internal.addValue("\r\n");
localMixed = false; localMixed = false;
// new currentFileUpload and no more in Mixed mode // new currentFileUpload and no more in Mixed mode
@ -640,7 +640,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput<HttpContent>
// Finalize the multipartHttpDatas // Finalize the multipartHttpDatas
if (!headerFinalized) { if (!headerFinalized) {
if (isMultipart) { if (isMultipart) {
InternalAttribute internal = new InternalAttribute(); InternalAttribute internal = new InternalAttribute(charset);
if (duringMixedMode) { if (duringMixedMode) {
internal.addValue("\r\n--" + multipartMixedBoundary + "--"); internal.addValue("\r\n--" + multipartMixedBoundary + "--");
} }
@ -799,14 +799,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput<HttpContent>
} }
ByteBuf buffer; ByteBuf buffer;
if (currentData instanceof InternalAttribute) { if (currentData instanceof InternalAttribute) {
String internal = currentData.toString(); buffer = ((InternalAttribute) currentData).toByteBuf();
byte[] bytes;
try {
bytes = internal.getBytes("ASCII");
} catch (UnsupportedEncodingException e) {
throw new ErrorDataEncoderException(e);
}
buffer = wrappedBuffer(bytes);
currentData = null; currentData = null;
} else { } else {
if (currentData instanceof Attribute) { if (currentData instanceof Attribute) {

View File

@ -15,6 +15,10 @@
*/ */
package io.netty.handler.codec.http.multipart; package io.netty.handler.codec.http.multipart;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,36 +27,46 @@ import java.util.List;
* (like Multipart Mixed mode) * (like Multipart Mixed mode)
*/ */
final class InternalAttribute implements InterfaceHttpData { final class InternalAttribute implements InterfaceHttpData {
private final List<String> value = new ArrayList<String>(); private final List<ByteBuf> value = new ArrayList<ByteBuf>();
private final Charset charset;
private int size;
public InternalAttribute(Charset charset) {
this.charset = charset;
}
@Override @Override
public HttpDataType getHttpDataType() { public HttpDataType getHttpDataType() {
return HttpDataType.InternalAttribute; return HttpDataType.InternalAttribute;
} }
public List<String> getValue() {
return value;
}
public void addValue(String value) { public void addValue(String value) {
if (value == null) { if (value == null) {
throw new NullPointerException("value"); throw new NullPointerException("value");
} }
this.value.add(value); ByteBuf buf = Unpooled.copiedBuffer(value, charset);
this.value.add(buf);
size += buf.readableBytes();
} }
public void addValue(String value, int rank) { public void addValue(String value, int rank) {
if (value == null) { if (value == null) {
throw new NullPointerException("value"); throw new NullPointerException("value");
} }
this.value.add(rank, value); ByteBuf buf = Unpooled.copiedBuffer(value, charset);
this.value.add(rank, buf);
size += buf.readableBytes();
} }
public void setValue(String value, int rank) { public void setValue(String value, int rank) {
if (value == null) { if (value == null) {
throw new NullPointerException("value"); throw new NullPointerException("value");
} }
this.value.set(rank, value); ByteBuf buf = Unpooled.copiedBuffer(value, charset);
ByteBuf old = this.value.set(rank, buf);
if (old != null) {
size -= old.readableBytes();
}
size += buf.readableBytes();
} }
@Override @Override
@ -82,22 +96,23 @@ final class InternalAttribute implements InterfaceHttpData {
return getName().compareToIgnoreCase(o.getName()); return getName().compareToIgnoreCase(o.getName());
} }
public int size() {
int size = 0;
for (String elt : value) {
size += elt.length();
}
return size;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for (String elt : value) { for (ByteBuf elt : value) {
result.append(elt); result.append(elt.toString(charset));
} }
return result.toString(); return result.toString();
} }
public int size() {
return size;
}
public ByteBuf toByteBuf() {
return Unpooled.compositeBuffer().addComponents(value).writerIndex(size()).readerIndex(0);
}
@Override @Override
public String getName() { public String getName() {
return "InternalAttribute"; return "InternalAttribute";