View Javadoc
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.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.FilterInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStreamWriter;
25  import java.util.Iterator;
26  import java.util.List;
27  import javax.servlet.http.HttpServletRequest;
28  
29  import org.apache.commons.fileupload.FileUploadBase.IOFileUploadException;
30  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
31  import org.apache.commons.fileupload.servlet.ServletFileUpload;
32  import org.apache.commons.fileupload.servlet.ServletRequestContext;
33  
34  import junit.framework.TestCase;
35  
36  /**
37   * Unit test for items with varying sizes.
38   */
39  public class StreamingTest extends TestCase {
40  
41      /**
42       * Tests a file upload with varying file sizes.
43       */
44      public void testFileUpload()
45              throws IOException, FileUploadException {
46          byte[] request = newRequest();
47          List<FileItem> fileItems = parseUpload(request);
48          Iterator<FileItem> fileIter = fileItems.iterator();
49          int add = 16;
50          int num = 0;
51          for (int i = 0;  i < 16384;  i += add) {
52              if (++add == 32) {
53                  add = 16;
54              }
55              FileItem item = fileIter.next();
56              assertEquals("field" + (num++), item.getFieldName());
57              byte[] bytes = item.get();
58              assertEquals(i, bytes.length);
59              for (int j = 0;  j < i;  j++) {
60                  assertEquals((byte) j, bytes[j]);
61              }
62          }
63          assertTrue(!fileIter.hasNext());
64      }
65  
66      /**
67       * Tests, whether an invalid request throws a proper
68       * exception.
69       */
70      public void testFileUploadException()
71              throws IOException, FileUploadException {
72          byte[] request = newRequest();
73          byte[] invalidRequest = new byte[request.length-11];
74          System.arraycopy(request, 0, invalidRequest, 0, request.length-11);
75          try {
76              parseUpload(invalidRequest);
77              fail("Expected EndOfStreamException");
78          } catch (IOFileUploadException e) {
79              assertTrue(e.getCause() instanceof MultipartStream.MalformedStreamException);
80          }
81      }
82  
83      /**
84       * Tests, whether an IOException is properly delegated.
85       */
86      public void testIOException()
87              throws IOException {
88          byte[] request = newRequest();
89          InputStream stream = new FilterInputStream(new ByteArrayInputStream(request)){
90              private int num;
91              @Override
92              public int read() throws IOException {
93                  if (++num > 123) {
94                      throw new IOException("123");
95                  }
96                  return super.read();
97              }
98              @Override
99              public int read(byte[] pB, int pOff, int pLen)
100                     throws IOException {
101                 for (int i = 0;  i < pLen;  i++) {
102                     int res = read();
103                     if (res == -1) {
104                         return i == 0 ? -1 : i;
105                     }
106                     pB[pOff+i] = (byte) res;
107                 }
108                 return pLen;
109             }
110         };
111         try {
112             parseUpload(stream, request.length);
113             fail("Expected IOException");
114         } catch (FileUploadException e) {
115             assertTrue(e.getCause() instanceof IOException);
116             assertEquals("123", e.getCause().getMessage());
117         }
118     }
119 
120     /**
121      * Test for FILEUPLOAD-135
122      */
123     public void testFILEUPLOAD135()
124             throws IOException, FileUploadException {
125         byte[] request = newShortRequest();
126         final ByteArrayInputStream bais = new ByteArrayInputStream(request);
127         List<FileItem> fileItems = parseUpload(new InputStream() {
128             @Override
129             public int read()
130             throws IOException
131             {
132                 return bais.read();
133             }
134             @Override
135             public int read(byte b[], int off, int len) throws IOException
136             {
137                 return bais.read(b, off, Math.min(len, 3));
138             }
139 
140         }, request.length);
141         Iterator<FileItem> fileIter = fileItems.iterator();
142         assertTrue(fileIter.hasNext());
143         FileItem item = fileIter.next();
144         assertEquals("field", item.getFieldName());
145         byte[] bytes = item.get();
146         assertEquals(3, bytes.length);
147         assertEquals((byte)'1', bytes[0]);
148         assertEquals((byte)'2', bytes[1]);
149         assertEquals((byte)'3', bytes[2]);
150         assertTrue(!fileIter.hasNext());
151     }
152 
153     private List<FileItem> parseUpload(byte[] bytes) throws FileUploadException {
154         return parseUpload(new ByteArrayInputStream(bytes), bytes.length);
155     }
156 
157     private FileItemIterator parseUpload(int pLength, InputStream pStream)
158             throws FileUploadException, IOException {
159         String contentType = "multipart/form-data; boundary=---1234";
160 
161         FileUploadBase upload = new ServletFileUpload();
162         upload.setFileItemFactory(new DiskFileItemFactory());
163         HttpServletRequest request = new MockHttpServletRequest(pStream,
164                 pLength, contentType);
165 
166         return upload.getItemIterator(new ServletRequestContext(request));
167     }
168 
169     private List<FileItem> parseUpload(InputStream pStream, int pLength)
170             throws FileUploadException {
171         String contentType = "multipart/form-data; boundary=---1234";
172 
173         FileUploadBase upload = new ServletFileUpload();
174         upload.setFileItemFactory(new DiskFileItemFactory());
175         HttpServletRequest request = new MockHttpServletRequest(pStream,
176                 pLength, contentType);
177 
178         List<FileItem> fileItems = upload.parseRequest(new ServletRequestContext(request));
179         return fileItems;
180     }
181 
182     private String getHeader(String pField) {
183         return "-----1234\r\n"
184             + "Content-Disposition: form-data; name=\"" + pField + "\"\r\n"
185             + "\r\n";
186 
187     }
188 
189     private String getFooter() {
190         return "-----1234--\r\n";
191     }
192 
193     private byte[] newShortRequest() throws IOException {
194         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
195         final OutputStreamWriter osw = new OutputStreamWriter(baos, "US-ASCII");
196         osw.write(getHeader("field"));
197         osw.write("123");
198         osw.write("\r\n");
199         osw.write(getFooter());
200         osw.close();
201         return baos.toByteArray();
202     }
203 
204     private byte[] newRequest() throws IOException {
205         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
206         final OutputStreamWriter osw = new OutputStreamWriter(baos, "US-ASCII");
207         int add = 16;
208         int num = 0;
209         for (int i = 0;  i < 16384;  i += add) {
210             if (++add == 32) {
211                 add = 16;
212             }
213             osw.write(getHeader("field" + (num++)));
214             osw.flush();
215             for (int j = 0;  j < i;  j++) {
216                 baos.write((byte) j);
217             }
218             osw.write("\r\n");
219         }
220         osw.write(getFooter());
221         osw.close();
222         return baos.toByteArray();
223     }
224 
225     /**
226      * Tests, whether an {@link InvalidFileNameException} is thrown.
227      */
228     public void testInvalidFileNameException() throws Exception {
229         final String fileName = "foo.exe\u0000.png";
230         final String request =
231             "-----1234\r\n" +
232             "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n" +
233             "Content-Type: text/whatever\r\n" +
234             "\r\n" +
235             "This is the content of the file\n" +
236             "\r\n" +
237             "-----1234\r\n" +
238             "Content-Disposition: form-data; name=\"field\"\r\n" +
239             "\r\n" +
240             "fieldValue\r\n" +
241             "-----1234\r\n" +
242             "Content-Disposition: form-data; name=\"multi\"\r\n" +
243             "\r\n" +
244             "value1\r\n" +
245             "-----1234\r\n" +
246             "Content-Disposition: form-data; name=\"multi\"\r\n" +
247             "\r\n" +
248             "value2\r\n" +
249             "-----1234--\r\n";
250         final byte[] reqBytes = request.getBytes("US-ASCII");
251 
252         FileItemIterator fileItemIter = parseUpload(reqBytes.length, new ByteArrayInputStream(reqBytes));
253         final FileItemStream fileItemStream = fileItemIter.next();
254         try {
255             fileItemStream.getName();
256             fail("Expected exception");
257         } catch (InvalidFileNameException e) {
258             assertEquals(fileName, e.getName());
259             assertTrue(e.getMessage().indexOf(fileName) == -1);
260             assertTrue(e.getMessage().indexOf("foo.exe\\0.png") != -1);
261         }
262 
263         List<FileItem> fileItems = parseUpload(reqBytes);
264         final FileItem fileItem = fileItems.get(0);
265         try {
266             fileItem.getName();
267             fail("Expected exception");
268         } catch (InvalidFileNameException e) {
269             assertEquals(fileName, e.getName());
270             assertTrue(e.getMessage().indexOf(fileName) == -1);
271             assertTrue(e.getMessage().indexOf("foo.exe\\0.png") != -1);
272         }
273     }
274 
275 }