View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
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  
37  import org.apache.http.entity.mime.FormBodyPart;
38  import org.apache.http.entity.mime.HttpMultipart;
39  import org.apache.http.entity.mime.HttpMultipartMode;
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.Assert;
44  import org.junit.Test;
45  
46  public class TestMultipartForm {
47  
48      @Test
49      public void testMultipartFormStringParts() throws Exception {
50          HttpMultipart multipart = new HttpMultipart("form-data", "foo");
51          FormBodyPart p1 = new FormBodyPart(
52                  "field1",
53                  new StringBody("this stuff"));
54          FormBodyPart p2 = new FormBodyPart(
55                  "field2",
56                  new StringBody("that stuff", Charset.forName("UTF-8")));
57          FormBodyPart p3 = new FormBodyPart(
58                  "field3",
59                  new StringBody("all kind of stuff"));
60  
61          multipart.addBodyPart(p1);
62          multipart.addBodyPart(p2);
63          multipart.addBodyPart(p3);
64  
65          ByteArrayOutputStream out = new ByteArrayOutputStream();
66          multipart.writeTo(out);
67          out.close();
68  
69          String expected =
70              "--foo\r\n" +
71              "Content-Disposition: form-data; name=\"field1\"\r\n" +
72              "Content-Type: text/plain; charset=US-ASCII\r\n" +
73              "Content-Transfer-Encoding: 8bit\r\n" +
74              "\r\n" +
75              "this stuff\r\n" +
76              "--foo\r\n" +
77              "Content-Disposition: form-data; name=\"field2\"\r\n" +
78              "Content-Type: text/plain; charset=UTF-8\r\n" +
79              "Content-Transfer-Encoding: 8bit\r\n" +
80              "\r\n" +
81              "that stuff\r\n" +
82              "--foo\r\n" +
83              "Content-Disposition: form-data; name=\"field3\"\r\n" +
84              "Content-Type: text/plain; charset=US-ASCII\r\n" +
85              "Content-Transfer-Encoding: 8bit\r\n" +
86              "\r\n" +
87              "all kind of stuff\r\n" +
88              "--foo--\r\n";
89          String s = out.toString("US-ASCII");
90          Assert.assertEquals(expected, s);
91          Assert.assertEquals(s.length(), multipart.getTotalLength());
92      }
93  
94      @Test
95      public void testMultipartFormBinaryParts() throws Exception {
96          File tmpfile = File.createTempFile("tmp", ".bin");
97          tmpfile.deleteOnExit();
98          Writer writer = new FileWriter(tmpfile);
99          try {
100             writer.append("some random whatever");
101         } finally {
102             writer.close();
103         }
104 
105         HttpMultipart multipart = new HttpMultipart("form-data", "foo");
106         FormBodyPart p1 = new FormBodyPart(
107                 "field1",
108                 new FileBody(tmpfile));
109         FormBodyPart p2 = new FormBodyPart(
110                 "field2",
111                 new InputStreamBody(new FileInputStream(tmpfile), "file.tmp"));
112 
113         multipart.addBodyPart(p1);
114         multipart.addBodyPart(p2);
115 
116         ByteArrayOutputStream out = new ByteArrayOutputStream();
117         multipart.writeTo(out);
118         out.close();
119 
120         String expected =
121             "--foo\r\n" +
122             "Content-Disposition: form-data; name=\"field1\"; " +
123                 "filename=\"" + tmpfile.getName() + "\"\r\n" +
124             "Content-Type: application/octet-stream\r\n" +
125             "Content-Transfer-Encoding: binary\r\n" +
126             "\r\n" +
127             "some random whatever\r\n" +
128             "--foo\r\n" +
129             "Content-Disposition: form-data; name=\"field2\"; " +
130                 "filename=\"file.tmp\"\r\n" +
131             "Content-Type: application/octet-stream\r\n" +
132             "Content-Transfer-Encoding: binary\r\n" +
133             "\r\n" +
134             "some random whatever\r\n" +
135             "--foo--\r\n";
136         String s = out.toString("US-ASCII");
137         Assert.assertEquals(expected, s);
138         Assert.assertEquals(-1, multipart.getTotalLength());
139 
140         tmpfile.delete();
141     }
142 
143     @Test
144     public void testMultipartFormBrowserCompatible() throws Exception {
145         File tmpfile = File.createTempFile("tmp", ".bin");
146         tmpfile.deleteOnExit();
147         Writer writer = new FileWriter(tmpfile);
148         try {
149             writer.append("some random whatever");
150         } finally {
151             writer.close();
152         }
153 
154         HttpMultipart multipart = new HttpMultipart("form-data", null, "foo", HttpMultipartMode.STRICT);
155         FormBodyPart p1 = new FormBodyPart(
156                 "field1",
157                 new FileBody(tmpfile));
158         FormBodyPart p2 = new FormBodyPart(
159                 "field2",
160                 new FileBody(tmpfile, "test-file", "text/plain", "ANSI_X3.4-1968"));
161         FormBodyPart p3 = new FormBodyPart(
162                 "field3",
163                 new InputStreamBody(new FileInputStream(tmpfile), "file.tmp"));
164 
165         multipart.addBodyPart(p1);
166         multipart.addBodyPart(p2);
167         multipart.addBodyPart(p3);
168 
169         ByteArrayOutputStream out = new ByteArrayOutputStream();
170         multipart.writeTo(out);
171         out.close();
172 
173         String expected =
174             "--foo\r\n" +
175             "Content-Disposition: form-data; name=\"field1\"; " +
176                 "filename=\"" + tmpfile.getName() + "\"\r\n" +
177             "Content-Type: application/octet-stream\r\n" +
178             "Content-Transfer-Encoding: binary\r\n" +
179             "\r\n" +
180             "some random whatever\r\n" +
181             "--foo\r\n" +
182             "Content-Disposition: form-data; name=\"field2\"; " +
183                 "filename=\"test-file\"\r\n" +
184             "Content-Type: text/plain; charset=ANSI_X3.4-1968\r\n" +
185             "Content-Transfer-Encoding: binary\r\n" +
186             "\r\n" +
187             "some random whatever\r\n" +
188             "--foo\r\n" +
189             "Content-Disposition: form-data; name=\"field3\"; " +
190                 "filename=\"file.tmp\"\r\n" +
191             "Content-Type: application/octet-stream\r\n" +
192             "Content-Transfer-Encoding: binary\r\n" +
193             "\r\n" +
194             "some random whatever\r\n" +
195             "--foo--\r\n";
196         String s = out.toString("US-ASCII");
197         Assert.assertEquals(expected, s);
198         Assert.assertEquals(-1, multipart.getTotalLength());
199 
200         tmpfile.delete();
201     }
202 
203     private static final int SWISS_GERMAN_HELLO [] = {
204         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
205     };
206 
207     private static final int RUSSIAN_HELLO [] = {
208         0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
209         0x432, 0x435, 0x442
210     };
211 
212     private static String constructString(int [] unicodeChars) {
213         StringBuilder buffer = new StringBuilder();
214         if (unicodeChars != null) {
215             for (int i = 0; i < unicodeChars.length; i++) {
216                 buffer.append((char)unicodeChars[i]);
217             }
218         }
219         return buffer.toString();
220     }
221 
222     @Test
223     public void testMultipartFormBrowserCompatibleNonASCIIHeaders() throws Exception {
224         String s1 = constructString(SWISS_GERMAN_HELLO);
225         String s2 = constructString(RUSSIAN_HELLO);
226 
227         File tmpfile = File.createTempFile("tmp", ".bin");
228         tmpfile.deleteOnExit();
229         Writer writer = new FileWriter(tmpfile);
230         try {
231             writer.append("some random whatever");
232         } finally {
233             writer.close();
234         }
235 
236         HttpMultipart multipart = new HttpMultipart("form-data", Charset.forName("UTF-8"), "foo", HttpMultipartMode.BROWSER_COMPATIBLE);
237         FormBodyPart p1 = new FormBodyPart(
238                 "field1",
239                 new InputStreamBody(new FileInputStream(tmpfile), s1 + ".tmp"));
240         FormBodyPart p2 = new FormBodyPart(
241                 "field2",
242                 new InputStreamBody(new FileInputStream(tmpfile), s2 + ".tmp"));
243 
244         multipart.addBodyPart(p1);
245         multipart.addBodyPart(p2);
246 
247         ByteArrayOutputStream out = new ByteArrayOutputStream();
248         multipart.writeTo(out);
249         out.close();
250 
251         String expected =
252             "--foo\r\n" +
253             "Content-Disposition: form-data; name=\"field1\"; " +
254                 "filename=\"" + s1 + ".tmp\"\r\n" +
255             "Content-Type: application/octet-stream\r\n" +
256             "\r\n" +
257             "some random whatever\r\n" +
258             "--foo\r\n" +
259             "Content-Disposition: form-data; name=\"field2\"; " +
260                 "filename=\"" + s2 + ".tmp\"\r\n" +
261             "Content-Type: application/octet-stream\r\n" +
262             "\r\n" +
263             "some random whatever\r\n" +
264             "--foo--\r\n";
265         String s = out.toString("UTF-8");
266         Assert.assertEquals(expected, s);
267         Assert.assertEquals(-1, multipart.getTotalLength());
268 
269         tmpfile.delete();
270     }
271 
272     @Test
273     public void testMultipartFormStringPartsMultiCharsets() throws Exception {
274         String s1 = constructString(SWISS_GERMAN_HELLO);
275         String s2 = constructString(RUSSIAN_HELLO);
276 
277         HttpMultipart multipart = new HttpMultipart("form-data", "foo");
278         FormBodyPart p1 = new FormBodyPart(
279                 "field1",
280                 new StringBody(s1, Charset.forName("ISO-8859-1")));
281         FormBodyPart p2 = new FormBodyPart(
282                 "field2",
283                 new StringBody(s2, Charset.forName("KOI8-R")));
284 
285         multipart.addBodyPart(p1);
286         multipart.addBodyPart(p2);
287 
288         ByteArrayOutputStream out1 = new ByteArrayOutputStream();
289         multipart.writeTo(out1);
290         out1.close();
291 
292         ByteArrayOutputStream out2 = new ByteArrayOutputStream();
293 
294         out2.write((
295             "--foo\r\n" +
296             "Content-Disposition: form-data; name=\"field1\"\r\n" +
297             "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
298             "Content-Transfer-Encoding: 8bit\r\n" +
299             "\r\n").getBytes("US-ASCII"));
300         out2.write(s1.getBytes("ISO-8859-1"));
301         out2.write(("\r\n" +
302             "--foo\r\n" +
303             "Content-Disposition: form-data; name=\"field2\"\r\n" +
304             "Content-Type: text/plain; charset=KOI8-R\r\n" +
305             "Content-Transfer-Encoding: 8bit\r\n" +
306             "\r\n").getBytes("US-ASCII"));
307         out2.write(s2.getBytes("KOI8-R"));
308         out2.write(("\r\n" +
309             "--foo--\r\n").getBytes("US-ASCII"));
310         out2.close();
311 
312         byte[] actual = out1.toByteArray();
313         byte[] expected = out2.toByteArray();
314 
315         Assert.assertEquals(expected.length, actual.length);
316         for (int i = 0; i < actual.length; i++) {
317             Assert.assertEquals(expected[i], actual[i]);
318         }
319         Assert.assertEquals(expected.length, multipart.getTotalLength());
320     }
321 
322 }