From a331c87a7ae6ef3fdefe0d22a3c8a8a03c57148d Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Tue, 14 May 2013 15:24:01 +0200 Subject: [PATCH] [#1358] Fix Encoding of multipart attribute names and filenames for non ASCII chars --- .../multipart/HttpPostRequestEncoder.java | 19 +++---- .../http/multipart/InternalAttribute.java | 49 ++++++++++++------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java index 7a1ae253a9..41ede3403e 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java @@ -471,14 +471,14 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput */ if (data instanceof Attribute) { if (duringMixedMode) { - InternalAttribute internal = new InternalAttribute(); + InternalAttribute internal = new InternalAttribute(charset); internal.addValue("\r\n--" + multipartMixedBoundary + "--"); multipartHttpDatas.add(internal); multipartMixedBoundary = null; currentFileUpload = null; duringMixedMode = false; } - InternalAttribute internal = new InternalAttribute(); + InternalAttribute internal = new InternalAttribute(charset); if (!multipartHttpDatas.isEmpty()) { // previously a data field so CRLF internal.addValue("\r\n"); @@ -503,7 +503,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput globalBodySize += attribute.length() + internal.size(); } else if (data instanceof FileUpload) { FileUpload fileUpload = (FileUpload) data; - InternalAttribute internal = new InternalAttribute(); + InternalAttribute internal = new InternalAttribute(charset); if (!multipartHttpDatas.isEmpty()) { // previously a data field so CRLF internal.addValue("\r\n"); @@ -525,7 +525,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput multipartMixedBoundary = null; // start a new one (could be replaced if mixed start again // from here - internal = new InternalAttribute(); + internal = new InternalAttribute(charset); internal.addValue("\r\n"); localMixed = false; // new currentFileUpload and no more in Mixed mode @@ -640,7 +640,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput // Finalize the multipartHttpDatas if (!headerFinalized) { if (isMultipart) { - InternalAttribute internal = new InternalAttribute(); + InternalAttribute internal = new InternalAttribute(charset); if (duringMixedMode) { internal.addValue("\r\n--" + multipartMixedBoundary + "--"); } @@ -799,14 +799,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput } ByteBuf buffer; if (currentData instanceof InternalAttribute) { - String internal = currentData.toString(); - byte[] bytes; - try { - bytes = internal.getBytes("ASCII"); - } catch (UnsupportedEncodingException e) { - throw new ErrorDataEncoderException(e); - } - buffer = wrappedBuffer(bytes); + buffer = ((InternalAttribute) currentData).toByteBuf(); currentData = null; } else { if (currentData instanceof Attribute) { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/InternalAttribute.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/InternalAttribute.java index e929fb7c4b..2a83f1985f 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/InternalAttribute.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/InternalAttribute.java @@ -15,6 +15,10 @@ */ 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.List; @@ -23,36 +27,46 @@ import java.util.List; * (like Multipart Mixed mode) */ final class InternalAttribute implements InterfaceHttpData { - private final List value = new ArrayList(); + private final List value = new ArrayList(); + private final Charset charset; + private int size; + public InternalAttribute(Charset charset) { + this.charset = charset; + } @Override public HttpDataType getHttpDataType() { return HttpDataType.InternalAttribute; } - public List getValue() { - return value; - } - public void addValue(String value) { if (value == null) { 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) { if (value == null) { 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) { if (value == null) { 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 @@ -82,22 +96,23 @@ final class InternalAttribute implements InterfaceHttpData { return getName().compareToIgnoreCase(o.getName()); } - public int size() { - int size = 0; - for (String elt : value) { - size += elt.length(); - } - return size; - } @Override public String toString() { StringBuilder result = new StringBuilder(); - for (String elt : value) { - result.append(elt); + for (ByteBuf elt : value) { + result.append(elt.toString(charset)); } return result.toString(); } + public int size() { + return size; + } + + public ByteBuf toByteBuf() { + return Unpooled.compositeBuffer().addComponents(value).writerIndex(size()).readerIndex(0); + } + @Override public String getName() { return "InternalAttribute";