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 static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertTrue;
22  import static org.junit.Assert.fail;
23  
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  import javax.servlet.http.HttpServletRequest;
31  
32  import org.apache.commons.fileupload.FileUploadBase.FileUploadIOException;
33  import org.apache.commons.fileupload.FileUploadBase.SizeException;
34  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
35  import org.apache.commons.fileupload.servlet.ServletFileUpload;
36  import org.apache.commons.fileupload.util.Streams;
37  import org.junit.Test;
38  
39  /**
40   * Unit test for items with varying sizes.
41   */
42  public class SizesTest {
43  
44      /**
45       * Runs a test with varying file sizes.
46       */
47      @Test
48      public void testFileUpload()
49              throws IOException, FileUploadException {
50          ByteArrayOutputStream baos = new ByteArrayOutputStream();
51          int add = 16;
52          int num = 0;
53          for (int i = 0;  i < 16384;  i += add) {
54              if (++add == 32) {
55                  add = 16;
56              }
57              String header = "-----1234\r\n"
58                  + "Content-Disposition: form-data; name=\"field" + (num++) + "\"\r\n"
59                  + "\r\n";
60              baos.write(header.getBytes("US-ASCII"));
61              for (int j = 0;  j < i;  j++) {
62                  baos.write((byte) j);
63              }
64              baos.write("\r\n".getBytes("US-ASCII"));
65          }
66          baos.write("-----1234--\r\n".getBytes("US-ASCII"));
67  
68          List<FileItem> fileItems =
69                  Util.parseUpload(new ServletFileUpload(new DiskFileItemFactory()), baos.toByteArray());
70          Iterator<FileItem> fileIter = fileItems.iterator();
71          add = 16;
72          num = 0;
73          for (int i = 0;  i < 16384;  i += add) {
74              if (++add == 32) {
75                  add = 16;
76              }
77              FileItem item = fileIter.next();
78              assertEquals("field" + (num++), item.getFieldName());
79              byte[] bytes = item.get();
80              assertEquals(i, bytes.length);
81              for (int j = 0;  j < i;  j++) {
82                  assertEquals((byte) j, bytes[j]);
83              }
84          }
85          assertTrue(!fileIter.hasNext());
86      }
87  
88      /** Checks, whether limiting the file size works.
89       */
90      @Test
91      public void testFileSizeLimit()
92              throws IOException, FileUploadException {
93          final String request =
94              "-----1234\r\n" +
95              "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
96              "Content-Type: text/whatever\r\n" +
97              "\r\n" +
98              "This is the content of the file\n" +
99              "\r\n" +
100             "-----1234--\r\n";
101 
102         ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
103         upload.setFileSizeMax(-1);
104         HttpServletRequest req = new MockHttpServletRequest(
105                 request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
106         List<FileItem> fileItems = upload.parseRequest(req);
107         assertEquals(1, fileItems.size());
108         FileItem item = fileItems.get(0);
109         assertEquals("This is the content of the file\n", new String(item.get()));
110 
111         upload = new ServletFileUpload(new DiskFileItemFactory());
112         upload.setFileSizeMax(40);
113         req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
114         fileItems = upload.parseRequest(req);
115         assertEquals(1, fileItems.size());
116         item = fileItems.get(0);
117         assertEquals("This is the content of the file\n", new String(item.get()));
118 
119         upload = new ServletFileUpload(new DiskFileItemFactory());
120         upload.setFileSizeMax(30);
121         req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
122         try {
123             upload.parseRequest(req);
124             fail("Expected exception.");
125         } catch (FileUploadBase.FileSizeLimitExceededException e) {
126             assertEquals(30, e.getPermittedSize());
127         }
128     }
129 
130     /** Checks, whether a faked Content-Length header is detected.
131      */
132     @Test
133     public void testFileSizeLimitWithFakedContentLength()
134             throws IOException, FileUploadException {
135         final String request =
136             "-----1234\r\n" +
137             "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
138             "Content-Type: text/whatever\r\n" +
139             "Content-Length: 10\r\n" +
140             "\r\n" +
141             "This is the content of the file\n" +
142             "\r\n" +
143             "-----1234--\r\n";
144 
145         ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
146         upload.setFileSizeMax(-1);
147         HttpServletRequest req = new MockHttpServletRequest(
148                 request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
149         List<FileItem> fileItems = upload.parseRequest(req);
150         assertEquals(1, fileItems.size());
151         FileItem item = fileItems.get(0);
152         assertEquals("This is the content of the file\n", new String(item.get()));
153 
154         upload = new ServletFileUpload(new DiskFileItemFactory());
155         upload.setFileSizeMax(40);
156         req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
157         fileItems = upload.parseRequest(req);
158         assertEquals(1, fileItems.size());
159         item = fileItems.get(0);
160         assertEquals("This is the content of the file\n", new String(item.get()));
161 
162         // provided Content-Length is larger than the FileSizeMax -> handled by ctor
163         upload = new ServletFileUpload(new DiskFileItemFactory());
164         upload.setFileSizeMax(5);
165         req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
166         try {
167             upload.parseRequest(req);
168             fail("Expected exception.");
169         } catch (FileUploadBase.FileSizeLimitExceededException e) {
170             assertEquals(5, e.getPermittedSize());
171         }
172 
173         // provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
174         upload = new ServletFileUpload(new DiskFileItemFactory());
175         upload.setFileSizeMax(15);
176         req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
177         try {
178             upload.parseRequest(req);
179             fail("Expected exception.");
180         } catch (FileUploadBase.FileSizeLimitExceededException e) {
181             assertEquals(15, e.getPermittedSize());
182         }
183     }
184 
185     /** Checks, whether the maxSize works.
186      */
187     @Test
188     public void testMaxSizeLimit()
189             throws IOException, FileUploadException {
190         final String request =
191             "-----1234\r\n" +
192             "Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
193             "Content-Type: text/whatever\r\n" +
194             "Content-Length: 10\r\n" +
195             "\r\n" +
196             "This is the content of the file\n" +
197             "\r\n" +
198             "-----1234\r\n" +
199             "Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
200             "Content-Type: text/whatever\r\n" +
201             "\r\n" +
202             "This is the content of the file\n" +
203             "\r\n" +
204             "-----1234--\r\n";
205 
206         ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
207         upload.setFileSizeMax(-1);
208         upload.setSizeMax(200);
209 
210         MockHttpServletRequest req = new MockHttpServletRequest(
211                 request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
212         try {
213             upload.parseRequest(req);
214             fail("Expected exception.");
215         } catch (FileUploadBase.SizeLimitExceededException e) {
216             assertEquals(200, e.getPermittedSize());
217         }
218     }
219 
220     @Test
221     public void testMaxSizeLimitUnknownContentLength()
222             throws IOException, FileUploadException {
223         final String request =
224             "-----1234\r\n" +
225             "Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
226             "Content-Type: text/whatever\r\n" +
227             "Content-Length: 10\r\n" +
228             "\r\n" +
229             "This is the content of the file\n" +
230             "\r\n" +
231             "-----1234\r\n" +
232             "Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\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 
239         ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
240         upload.setFileSizeMax(-1);
241         upload.setSizeMax(300);
242 
243         // the first item should be within the max size limit
244         // set the read limit to 10 to simulate a "real" stream
245         // otherwise the buffer would be immediately filled
246 
247         MockHttpServletRequest req = new MockHttpServletRequest(
248                 request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
249         req.setContentLength(-1);
250         req.setReadLimit(10);
251 
252         FileItemIterator it = upload.getItemIterator(req);
253         assertTrue(it.hasNext());
254 
255         FileItemStream item = it.next();
256         assertFalse(item.isFormField());
257         assertEquals("file1", item.getFieldName());
258         assertEquals("foo1.tab", item.getName());
259 
260         {
261             InputStream stream = item.openStream();
262             ByteArrayOutputStream baos = new ByteArrayOutputStream();
263             Streams.copy(stream, baos, true);
264         }
265 
266         // the second item is over the size max, thus we expect an error
267         try {
268             // the header is still within size max -> this shall still succeed
269             assertTrue(it.hasNext());
270         } catch (SizeException e) {
271             fail();
272         }
273 
274         item = it.next();
275 
276         try {
277             InputStream stream = item.openStream();
278             ByteArrayOutputStream baos = new ByteArrayOutputStream();
279             Streams.copy(stream, baos, true);
280             fail();
281         } catch (FileUploadIOException e) {
282             // expected
283         }
284     }
285 
286 }