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 }