1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.entity.mime;
29
30 import java.io.ByteArrayOutputStream;
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileWriter;
34 import java.io.Writer;
35 import java.nio.charset.Charset;
36 import java.util.Arrays;
37
38 import org.apache.http.Consts;
39 import org.apache.http.entity.ContentType;
40 import org.apache.http.entity.mime.content.FileBody;
41 import org.apache.http.entity.mime.content.InputStreamBody;
42 import org.apache.http.entity.mime.content.StringBody;
43 import org.junit.After;
44 import org.junit.Assert;
45 import org.junit.Test;
46
47 public class TestMultipartForm {
48
49 private File tmpfile;
50
51 @After
52 public void cleanup() {
53 if (tmpfile != null) {
54 tmpfile.delete();
55 }
56 }
57
58 @Test
59 public void testMultipartFormStringParts() throws Exception {
60 final FormBodyPart p1 = FormBodyPartBuilder.create(
61 "field1",
62 new StringBody("this stuff", ContentType.DEFAULT_TEXT)).build();
63 final FormBodyPart p2 = FormBodyPartBuilder.create(
64 "field2",
65 new StringBody("that stuff", ContentType.create(
66 ContentType.TEXT_PLAIN.getMimeType(), Consts.UTF_8))).build();
67 final FormBodyPart p3 = FormBodyPartBuilder.create(
68 "field3",
69 new StringBody("all kind of stuff", ContentType.DEFAULT_TEXT)).build();
70 final HttpStrictMultipart multipart = new HttpStrictMultipart(null, "foo",
71 Arrays.asList(p1, p2, p3));
72
73 final ByteArrayOutputStream out = new ByteArrayOutputStream();
74 multipart.writeTo(out);
75 out.close();
76
77 final String expected =
78 "--foo\r\n" +
79 "Content-Disposition: form-data; name=\"field1\"\r\n" +
80 "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
81 "Content-Transfer-Encoding: 8bit\r\n" +
82 "\r\n" +
83 "this stuff\r\n" +
84 "--foo\r\n" +
85 "Content-Disposition: form-data; name=\"field2\"\r\n" +
86 "Content-Type: text/plain; charset=UTF-8\r\n" +
87 "Content-Transfer-Encoding: 8bit\r\n" +
88 "\r\n" +
89 "that stuff\r\n" +
90 "--foo\r\n" +
91 "Content-Disposition: form-data; name=\"field3\"\r\n" +
92 "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
93 "Content-Transfer-Encoding: 8bit\r\n" +
94 "\r\n" +
95 "all kind of stuff\r\n" +
96 "--foo--\r\n";
97 final String s = out.toString("US-ASCII");
98 Assert.assertEquals(expected, s);
99 Assert.assertEquals(s.length(), multipart.getTotalLength());
100 }
101
102 @Test
103 public void testMultipartFormCustomContentType() throws Exception {
104 final FormBodyPart p1 = FormBodyPartBuilder.create(
105 "field1",
106 new StringBody("this stuff", ContentType.DEFAULT_TEXT)).build();
107 final FormBodyPart p2 = FormBodyPartBuilder.create(
108 "field2",
109 new StringBody("that stuff", ContentType.parse("stuff/plain; param=value"))).build();
110 final HttpStrictMultipart multipart = new HttpStrictMultipart(null, "foo",
111 Arrays.asList(p1, p2));
112
113 final ByteArrayOutputStream out = new ByteArrayOutputStream();
114 multipart.writeTo(out);
115 out.close();
116
117 final String expected =
118 "--foo\r\n" +
119 "Content-Disposition: form-data; name=\"field1\"\r\n" +
120 "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
121 "Content-Transfer-Encoding: 8bit\r\n" +
122 "\r\n" +
123 "this stuff\r\n" +
124 "--foo\r\n" +
125 "Content-Disposition: form-data; name=\"field2\"\r\n" +
126 "Content-Type: stuff/plain; param=value\r\n" +
127 "Content-Transfer-Encoding: 8bit\r\n" +
128 "\r\n" +
129 "that stuff\r\n" +
130 "--foo--\r\n";
131 final String s = out.toString("US-ASCII");
132 Assert.assertEquals(expected, s);
133 Assert.assertEquals(s.length(), multipart.getTotalLength());
134 }
135
136 @Test
137 public void testMultipartFormBinaryParts() throws Exception {
138 tmpfile = File.createTempFile("tmp", ".bin");
139 final Writer writer = new FileWriter(tmpfile);
140 try {
141 writer.append("some random whatever");
142 } finally {
143 writer.close();
144 }
145
146 final FormBodyPart p1 = FormBodyPartBuilder.create(
147 "field1",
148 new FileBody(tmpfile)).build();
149 @SuppressWarnings("resource")
150 final FormBodyPart p2 = FormBodyPartBuilder.create(
151 "field2",
152 new InputStreamBody(new FileInputStream(tmpfile), "file.tmp")).build();
153 final HttpStrictMultipart multipart = new HttpStrictMultipart(null, "foo",
154 Arrays.asList(p1, p2));
155
156 final ByteArrayOutputStream out = new ByteArrayOutputStream();
157 multipart.writeTo(out);
158 out.close();
159
160 final String expected =
161 "--foo\r\n" +
162 "Content-Disposition: form-data; name=\"field1\"; " +
163 "filename=\"" + tmpfile.getName() + "\"\r\n" +
164 "Content-Type: application/octet-stream\r\n" +
165 "Content-Transfer-Encoding: binary\r\n" +
166 "\r\n" +
167 "some random whatever\r\n" +
168 "--foo\r\n" +
169 "Content-Disposition: form-data; name=\"field2\"; " +
170 "filename=\"file.tmp\"\r\n" +
171 "Content-Type: application/octet-stream\r\n" +
172 "Content-Transfer-Encoding: binary\r\n" +
173 "\r\n" +
174 "some random whatever\r\n" +
175 "--foo--\r\n";
176 final String s = out.toString("US-ASCII");
177 Assert.assertEquals(expected, s);
178 Assert.assertEquals(-1, multipart.getTotalLength());
179 }
180
181 @Test
182 public void testMultipartFormStrict() throws Exception {
183 tmpfile = File.createTempFile("tmp", ".bin");
184 final Writer writer = new FileWriter(tmpfile);
185 try {
186 writer.append("some random whatever");
187 } finally {
188 writer.close();
189 }
190
191 final FormBodyPart p1 = FormBodyPartBuilder.create(
192 "field1",
193 new FileBody(tmpfile)).build();
194 final FormBodyPart p2 = FormBodyPartBuilder.create(
195 "field2",
196 new FileBody(tmpfile, ContentType.create("text/plain", "ANSI_X3.4-1968"), "test-file")).build();
197 @SuppressWarnings("resource")
198 final FormBodyPart p3 = FormBodyPartBuilder.create(
199 "field3",
200 new InputStreamBody(new FileInputStream(tmpfile), "file.tmp")).build();
201 final HttpStrictMultipart multipart = new HttpStrictMultipart(null, "foo",
202 Arrays.asList(p1, p2, p3));
203
204 final ByteArrayOutputStream out = new ByteArrayOutputStream();
205 multipart.writeTo(out);
206 out.close();
207
208 final String expected =
209 "--foo\r\n" +
210 "Content-Disposition: form-data; name=\"field1\"; " +
211 "filename=\"" + tmpfile.getName() + "\"\r\n" +
212 "Content-Type: application/octet-stream\r\n" +
213 "Content-Transfer-Encoding: binary\r\n" +
214 "\r\n" +
215 "some random whatever\r\n" +
216 "--foo\r\n" +
217 "Content-Disposition: form-data; name=\"field2\"; " +
218 "filename=\"test-file\"\r\n" +
219 "Content-Type: text/plain; charset=US-ASCII\r\n" +
220 "Content-Transfer-Encoding: binary\r\n" +
221 "\r\n" +
222 "some random whatever\r\n" +
223 "--foo\r\n" +
224 "Content-Disposition: form-data; name=\"field3\"; " +
225 "filename=\"file.tmp\"\r\n" +
226 "Content-Type: application/octet-stream\r\n" +
227 "Content-Transfer-Encoding: binary\r\n" +
228 "\r\n" +
229 "some random whatever\r\n" +
230 "--foo--\r\n";
231 final String s = out.toString("US-ASCII");
232 Assert.assertEquals(expected, s);
233 Assert.assertEquals(-1, multipart.getTotalLength());
234 }
235
236 @Test
237 public void testMultipartFormRFC6532() throws Exception {
238 tmpfile = File.createTempFile("tmp", ".bin");
239 final Writer writer = new FileWriter(tmpfile);
240 try {
241 writer.append("some random whatever");
242 } finally {
243 writer.close();
244 }
245
246 final FormBodyPart p1 = FormBodyPartBuilder.create(
247 "field1\u0414",
248 new FileBody(tmpfile)).build();
249 final FormBodyPart p2 = FormBodyPartBuilder.create(
250 "field2",
251 new FileBody(tmpfile, ContentType.create("text/plain", "ANSI_X3.4-1968"), "test-file")).build();
252 @SuppressWarnings("resource")
253 final FormBodyPart p3 = FormBodyPartBuilder.create(
254 "field3",
255 new InputStreamBody(new FileInputStream(tmpfile), "file.tmp")).build();
256 final HttpRFC6532Multipart multipart = new HttpRFC6532Multipart(null, "foo",
257 Arrays.asList(p1, p2, p3));
258
259 final ByteArrayOutputStream out = new ByteArrayOutputStream();
260 multipart.writeTo(out);
261 out.close();
262
263 final String expected =
264 "--foo\r\n" +
265 "Content-Disposition: form-data; name=\"field1\u0414\"; " +
266 "filename=\"" + tmpfile.getName() + "\"\r\n" +
267 "Content-Type: application/octet-stream\r\n" +
268 "Content-Transfer-Encoding: binary\r\n" +
269 "\r\n" +
270 "some random whatever\r\n" +
271 "--foo\r\n" +
272 "Content-Disposition: form-data; name=\"field2\"; " +
273 "filename=\"test-file\"\r\n" +
274 "Content-Type: text/plain; charset=US-ASCII\r\n" +
275 "Content-Transfer-Encoding: binary\r\n" +
276 "\r\n" +
277 "some random whatever\r\n" +
278 "--foo\r\n" +
279 "Content-Disposition: form-data; name=\"field3\"; " +
280 "filename=\"file.tmp\"\r\n" +
281 "Content-Type: application/octet-stream\r\n" +
282 "Content-Transfer-Encoding: binary\r\n" +
283 "\r\n" +
284 "some random whatever\r\n" +
285 "--foo--\r\n";
286 final String s = out.toString("UTF-8");
287 Assert.assertEquals(expected, s);
288 Assert.assertEquals(-1, multipart.getTotalLength());
289 }
290
291 private static final int SWISS_GERMAN_HELLO [] = {
292 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
293 };
294
295 private static final int RUSSIAN_HELLO [] = {
296 0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
297 0x432, 0x435, 0x442
298 };
299
300 private static String constructString(final int [] unicodeChars) {
301 final StringBuilder buffer = new StringBuilder();
302 if (unicodeChars != null) {
303 for (final int unicodeChar : unicodeChars) {
304 buffer.append((char)unicodeChar);
305 }
306 }
307 return buffer.toString();
308 }
309
310 @Test
311 public void testMultipartFormBrowserCompatibleNonASCIIHeaders() throws Exception {
312 final String s1 = constructString(SWISS_GERMAN_HELLO);
313 final String s2 = constructString(RUSSIAN_HELLO);
314
315 tmpfile = File.createTempFile("tmp", ".bin");
316 final Writer writer = new FileWriter(tmpfile);
317 try {
318 writer.append("some random whatever");
319 } finally {
320 writer.close();
321 }
322
323 @SuppressWarnings("resource")
324 final FormBodyPart p1 = FormBodyPartBuilder.create(
325 "field1",
326 new InputStreamBody(new FileInputStream(tmpfile), s1 + ".tmp")).build();
327 @SuppressWarnings("resource")
328 final FormBodyPart p2 = FormBodyPartBuilder.create(
329 "field2",
330 new InputStreamBody(new FileInputStream(tmpfile), s2 + ".tmp")).build();
331 final HttpBrowserCompatibleMultipart multipart = new HttpBrowserCompatibleMultipart(
332 Consts.UTF_8, "foo",
333 Arrays.asList(p1, p2));
334
335 final ByteArrayOutputStream out = new ByteArrayOutputStream();
336 multipart.writeTo(out);
337 out.close();
338
339 final String expected =
340 "--foo\r\n" +
341 "Content-Disposition: form-data; name=\"field1\"; " +
342 "filename=\"" + s1 + ".tmp\"\r\n" +
343 "Content-Type: application/octet-stream\r\n" +
344 "\r\n" +
345 "some random whatever\r\n" +
346 "--foo\r\n" +
347 "Content-Disposition: form-data; name=\"field2\"; " +
348 "filename=\"" + s2 + ".tmp\"\r\n" +
349 "Content-Type: application/octet-stream\r\n" +
350 "\r\n" +
351 "some random whatever\r\n" +
352 "--foo--\r\n";
353 final String s = out.toString("UTF-8");
354 Assert.assertEquals(expected, s);
355 Assert.assertEquals(-1, multipart.getTotalLength());
356 }
357
358 @Test
359 public void testMultipartFormStringPartsMultiCharsets() throws Exception {
360 final String s1 = constructString(SWISS_GERMAN_HELLO);
361 final String s2 = constructString(RUSSIAN_HELLO);
362
363 final FormBodyPart p1 = FormBodyPartBuilder.create(
364 "field1",
365 new StringBody(s1, ContentType.create("text/plain", Charset.forName("ISO-8859-1")))).build();
366 final FormBodyPart p2 = FormBodyPartBuilder.create(
367 "field2",
368 new StringBody(s2, ContentType.create("text/plain", Charset.forName("KOI8-R")))).build();
369 final HttpStrictMultipart multipart = new HttpStrictMultipart(null, "foo",
370 Arrays.asList(p1, p2));
371
372 final ByteArrayOutputStream out1 = new ByteArrayOutputStream();
373 multipart.writeTo(out1);
374 out1.close();
375
376 final ByteArrayOutputStream out2 = new ByteArrayOutputStream();
377
378 out2.write((
379 "--foo\r\n" +
380 "Content-Disposition: form-data; name=\"field1\"\r\n" +
381 "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
382 "Content-Transfer-Encoding: 8bit\r\n" +
383 "\r\n").getBytes(Consts.ASCII));
384 out2.write(s1.getBytes(Consts.ISO_8859_1));
385 out2.write(("\r\n" +
386 "--foo\r\n" +
387 "Content-Disposition: form-data; name=\"field2\"\r\n" +
388 "Content-Type: text/plain; charset=KOI8-R\r\n" +
389 "Content-Transfer-Encoding: 8bit\r\n" +
390 "\r\n").getBytes(Consts.ASCII));
391 out2.write(s2.getBytes(Charset.forName("KOI8-R")));
392 out2.write(("\r\n" +
393 "--foo--\r\n").getBytes(Consts.ASCII));
394 out2.close();
395
396 final byte[] actual = out1.toByteArray();
397 final byte[] expected = out2.toByteArray();
398
399 Assert.assertEquals(expected.length, actual.length);
400 for (int i = 0; i < actual.length; i++) {
401 Assert.assertEquals(expected[i], actual[i]);
402 }
403 Assert.assertEquals(expected.length, multipart.getTotalLength());
404 }
405
406 }