diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/mime/FormBodyPartBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/mime/FormBodyPartBuilder.java index 25bf4f2..5195cc6 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/mime/FormBodyPartBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/mime/FormBodyPartBuilder.java @@ -101,11 +101,11 @@ public FormBodyPart build() { if (headerCopy.getField(MIME.CONTENT_DISPOSITION) == null) { final StringBuilder buffer = new StringBuilder(); buffer.append("form-data; name=\""); - buffer.append(this.name); + buffer.append(encodeForHeader(this.name)); buffer.append("\""); if (this.body.getFilename() != null) { buffer.append("; filename=\""); - buffer.append(this.body.getFilename()); + buffer.append(encodeForHeader(this.body.getFilename())); buffer.append("\""); } headerCopy.addField(new MinimalField(MIME.CONTENT_DISPOSITION, buffer.toString())); @@ -136,4 +136,19 @@ public FormBodyPart build() { return new FormBodyPart(this.name, this.body, headerCopy); } + private static String encodeForHeader(final String headerName) { + if (headerName == null) { + return null; + } + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < headerName.length(); i++) { + final char x = headerName.charAt(i); + if (x == '"' || x == '\\' || x == '\r') { + sb.append("\\"); + } + sb.append(x); + } + return sb.toString(); + } + } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/mime/TestFormBodyPartBuilder.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/mime/TestFormBodyPartBuilder.java index e333b5f..741865f 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/mime/TestFormBodyPartBuilder.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/mime/TestFormBodyPartBuilder.java @@ -28,6 +28,7 @@ package org.apache.hc.client5.http.entity.mime; import java.io.File; +import java.io.ByteArrayInputStream; import java.util.Arrays; import java.util.List; @@ -57,6 +58,27 @@ public void testBuildBodyPartBasics() throws Exception { } @Test + public void testCharacterStuffing() throws Exception { + final FormBodyPartBuilder builder = FormBodyPartBuilder.create(); + final InputStreamBody fileBody = new InputStreamBody(new ByteArrayInputStream("hello world".getBytes("UTF-8")), "stuff_with \"quotes\" and \\slashes\\.bin"); + final FormBodyPart bodyPart2 = builder + .setName("yada_with \"quotes\" and \\slashes\\") + .setBody(fileBody) + .build(); + + Assert.assertNotNull(bodyPart2); + Assert.assertEquals("yada_with \"quotes\" and \\slashes\\", bodyPart2.getName()); + Assert.assertEquals(fileBody, bodyPart2.getBody()); + final Header header2 = bodyPart2.getHeader(); + Assert.assertNotNull(header2); + assertFields(Arrays.asList( + new MinimalField("Content-Disposition", "form-data; name=\"yada_with \\\"quotes\\\" and \\\\slashes\\\\\"; filename=\"stuff_with \\\"quotes\\\" and \\\\slashes\\\\.bin\""), + new MinimalField("Content-Type", "application/octet-stream"), + new MinimalField("Content-Transfer-Encoding", "binary")), + header2.getFields()); + } + + @Test public void testBuildBodyPartMultipleBuilds() throws Exception { final StringBody stringBody = new StringBody("stuff", ContentType.TEXT_PLAIN); final FormBodyPartBuilder builder = FormBodyPartBuilder.create();