1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.fileupload;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.OutputStream;
22  import java.util.Arrays;
23  
24  import junit.framework.TestCase;
25  import org.apache.commons.fileupload.DefaultFileItem;
26  import org.apache.commons.fileupload.DefaultFileItemFactory;
27  
28  
29  /**
30   * Unit tests for {@link org.apache.commons.fileupload.DefaultFileItem}.
31   *
32   * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
33   */
34  public class DefaultFileItemTest extends TestCase
35   {
36  
37      /**
38       * Content type for regular form items.
39       */
40      private static final String textContentType = "text/plain";
41  
42      /**
43       * Content type for file uploads.
44       */
45      private static final String fileContentType = "application/octet-stream";
46  
47      /**
48       * Very low threshold for testing memory versus disk options.
49       */
50      private static final int threshold = 16;
51  
52      /**
53       * Standard JUnit test case constructor.
54       *
55       * @param name The name of the test case.
56       */
57      public DefaultFileItemTest(String name)
58      {
59          super(name);
60      }
61  
62      /**
63       * Test construction of a regular text field.
64       */
65      public void testTextFieldConstruction()
66      {
67          FileItemFactory factory = createFactory(null);
68          String textFieldName = "textField";
69  
70          FileItem item = factory.createItem(
71                  textFieldName,
72                  textContentType,
73                  true,
74                  null
75          );
76          assertNotNull(item);
77          assertEquals(item.getFieldName(), textFieldName);
78          assertEquals(item.getContentType(), textContentType);
79          assertTrue(item.isFormField());
80          assertNull(item.getName());
81      }
82  
83      /**
84       * Test construction of a file field.
85       */
86      public void testFileFieldConstruction()
87      {
88          FileItemFactory factory = createFactory(null);
89          String fileFieldName = "fileField";
90          String fileName = "originalFileName";
91  
92          FileItem item = factory.createItem(
93                  fileFieldName,
94                  fileContentType,
95                  false,
96                  fileName
97          );
98          assertNotNull(item);
99          assertEquals(item.getFieldName(), fileFieldName);
100         assertEquals(item.getContentType(), fileContentType);
101         assertFalse(item.isFormField());
102         assertEquals(item.getName(), fileName);
103     }
104 
105     /**
106      * Test creation of a field for which the amount of data falls below the
107      * configured threshold.
108      */
109     public void testBelowThreshold()
110     {
111         FileItemFactory factory = createFactory(null);
112         String textFieldName = "textField";
113         String textFieldValue = "0123456789";
114         byte[] testFieldValueBytes = textFieldValue.getBytes();
115 
116         FileItem item = factory.createItem(
117                 textFieldName,
118                 textContentType,
119                 true,
120                 null
121         );
122         assertNotNull(item);
123 
124         try
125         {
126             OutputStream os = item.getOutputStream();
127             os.write(testFieldValueBytes);
128             os.close();
129         }
130         catch(IOException e)
131         {
132             fail("Unexpected IOException");
133         }
134         assertTrue(item.isInMemory());
135         assertEquals(item.getSize(), testFieldValueBytes.length);
136         assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
137         assertEquals(item.getString(), textFieldValue);
138     }
139 
140     /**
141      * Test creation of a field for which the amount of data falls above the
142      * configured threshold, where no specific repository is configured.
143      */
144     public void testAboveThresholdDefaultRepository()
145     {
146         doTestAboveThreshold(null);
147     }
148 
149     /**
150      * Test creation of a field for which the amount of data falls above the
151      * configured threshold, where a specific repository is configured.
152      */
153     public void testAboveThresholdSpecifiedRepository()
154     {
155         String tempPath = System.getProperty("java.io.tmpdir");
156         String tempDirName = "testAboveThresholdSpecifiedRepository";
157         File tempDir = new File(tempPath, tempDirName);
158         tempDir.mkdir();
159         doTestAboveThreshold(tempDir);
160         assertTrue(tempDir.delete());
161     }
162 
163     /**
164      * Common code for cases where the amount of data is above the configured
165      * threshold, but the ultimate destination of the data has not yet been
166      * determined.
167      *
168      * @param repository The directory within which temporary files will be
169      *                   created.
170      */
171     public void doTestAboveThreshold(File repository)
172     {
173         FileItemFactory factory = createFactory(repository);
174         String textFieldName = "textField";
175         String textFieldValue = "01234567890123456789";
176         byte[] testFieldValueBytes = textFieldValue.getBytes();
177 
178         FileItem item = factory.createItem(
179                 textFieldName,
180                 textContentType,
181                 true,
182                 null
183         );
184         assertNotNull(item);
185 
186         try
187         {
188             OutputStream os = item.getOutputStream();
189             os.write(testFieldValueBytes);
190             os.close();
191         }
192         catch(IOException e)
193         {
194             fail("Unexpected IOException");
195         }
196         assertFalse(item.isInMemory());
197         assertEquals(item.getSize(), testFieldValueBytes.length);
198         assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
199         assertEquals(item.getString(), textFieldValue);
200 
201         assertTrue(item instanceof DefaultFileItem);
202         DefaultFileItem dfi = (DefaultFileItem) item;
203         File storeLocation = dfi.getStoreLocation();
204         assertNotNull(storeLocation);
205         assertTrue(storeLocation.exists());
206         assertEquals(storeLocation.length(), testFieldValueBytes.length);
207 
208         if (repository != null)
209         {
210             assertEquals(storeLocation.getParentFile(), repository);
211         }
212 
213         item.delete();
214     }
215 
216 
217     /**
218      * Creates a new <code>FileItemFactory</code> and returns it, obscuring
219      * from the caller the underlying implementation of this interface.
220      *
221      * @param repository The directory within which temporary files will be
222      *                   created.
223      * @return the new <code>FileItemFactory</code> instance.
224      */
225     protected FileItemFactory createFactory(File repository)
226     {
227         return new DefaultFileItemFactory(threshold, repository);
228     }
229 
230 
231     static final String CHARSET_ISO88591 = "ISO-8859-1";
232     static final String CHARSET_ASCII = "US-ASCII";
233     static final String CHARSET_UTF8 = "UTF-8";
234     static final String CHARSET_KOI8_R = "KOI8_R";
235     static final String CHARSET_WIN1251 = "Cp1251";
236 
237     static final int SWISS_GERMAN_STUFF_UNICODE [] = 
238     {
239         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
240     };
241     
242     static final int SWISS_GERMAN_STUFF_ISO8859_1 [] = 
243     {
244         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
245     };
246     
247     static final int SWISS_GERMAN_STUFF_UTF8 [] = 
248     {
249         0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4,
250         0x6D, 0xC3, 0xA4
251     };
252 
253     static final int RUSSIAN_STUFF_UNICODE [] = 
254     {
255         0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438, 
256         0x432, 0x435, 0x442 
257     }; 
258 
259     static final int RUSSIAN_STUFF_UTF8 [] = 
260     {
261         0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F, 
262         0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 
263         0xB5, 0xD1, 0x82
264     };
265 
266     static final int RUSSIAN_STUFF_KOI8R [] = 
267     {
268         0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7, 
269         0xC5, 0xD4
270     };
271 
272     static final int RUSSIAN_STUFF_WIN1251 [] = 
273     {
274         0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2, 
275         0xE5, 0xF2
276     };
277 
278 
279     private static String constructString(int[] unicodeChars)
280     {
281         StringBuffer buffer = new StringBuffer();
282         if (unicodeChars != null)
283         {
284             for (int i = 0; i < unicodeChars.length; i++)
285             {
286                 buffer.append((char) unicodeChars[i]);
287             }
288         }
289         return buffer.toString();
290     }
291 
292     /**
293      * Test construction of content charset.
294      */
295     public void testContentCharSet() throws Exception
296     {
297         FileItemFactory factory = createFactory(null);
298 
299         String teststr = constructString(SWISS_GERMAN_STUFF_UNICODE);
300 
301         FileItem item =
302             factory.createItem(
303                 "doesnotmatter",
304                 "text/plain; charset=" + CHARSET_ISO88591,
305                 true,
306                 null);
307         OutputStream outstream = item.getOutputStream();
308         for (int i = 0; i < SWISS_GERMAN_STUFF_ISO8859_1.length; i++)
309         {
310             outstream.write(SWISS_GERMAN_STUFF_ISO8859_1[i]);
311         }
312         outstream.close();
313         assertEquals(teststr, teststr, item.getString());
314 
315         item =
316             factory.createItem(
317                 "doesnotmatter",
318                 "text/plain; charset=" + CHARSET_UTF8,
319                 true,
320                 null);
321         outstream = item.getOutputStream();
322         for (int i = 0; i < SWISS_GERMAN_STUFF_UTF8.length; i++)
323         {
324             outstream.write(SWISS_GERMAN_STUFF_UTF8[i]);
325         }
326         outstream.close();
327         assertEquals(teststr, teststr, item.getString());
328 
329         teststr = constructString(RUSSIAN_STUFF_UNICODE);
330 
331         item =
332             factory.createItem(
333                 "doesnotmatter",
334                 "text/plain; charset=" + CHARSET_KOI8_R,
335                 true,
336                 null);
337         outstream = item.getOutputStream();
338         for (int i = 0; i < RUSSIAN_STUFF_KOI8R.length; i++)
339         {
340             outstream.write(RUSSIAN_STUFF_KOI8R[i]);
341         }
342         outstream.close();
343         assertEquals(teststr, teststr, item.getString());
344 
345         item =
346             factory.createItem(
347                 "doesnotmatter",
348                 "text/plain; charset=" + CHARSET_WIN1251,
349                 true,
350                 null);
351         outstream = item.getOutputStream();
352         for (int i = 0; i < RUSSIAN_STUFF_WIN1251.length; i++)
353         {
354             outstream.write(RUSSIAN_STUFF_WIN1251[i]);
355         }
356         outstream.close();
357         assertEquals(teststr, teststr, item.getString());
358 
359         item =
360             factory.createItem(
361                 "doesnotmatter",
362                 "text/plain; charset=" + CHARSET_UTF8,
363                 true,
364                 null);
365         outstream = item.getOutputStream();
366         for (int i = 0; i < RUSSIAN_STUFF_UTF8.length; i++)
367         {
368             outstream.write(RUSSIAN_STUFF_UTF8[i]);
369         }
370         outstream.close();
371         assertEquals(teststr, teststr, item.getString());
372     }
373 }