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.fileupload2.core;
    18
    19  import static org.junit.jupiter.api.Assertions.assertEquals;
    20  import static org.junit.jupiter.api.Assertions.assertFalse;
    21  import static org.junit.jupiter.api.Assertions.assertThrows;
    22  import static org.junit.jupiter.api.Assertions.assertTrue;
    23  import static org.junit.jupiter.api.Assertions.fail;
    24
    25  import java.io.ByteArrayOutputStream;
    26  import java.io.IOException;
    27
    28  import org.apache.commons.io.IOUtils;
    29  import org.junit.jupiter.api.Test;
    30
    31  /**
    32   * Unit test for items with varying sizes.
    33   *
    34   * @param <AFU> The FileUpload type.
    35   * @param <R>   The FileUpload request type.
    36   * @param <I>   The FileItem type.
    37   * @param <F>   The FileItemFactory type.
    38   */
    39  public abstract class AbstractSizesTest<AFU extends AbstractFileUpload<R, I, F>, R, I extends FileItem<I>, F extends FileItemFactory<I>>
    40          extends AbstractTest<AFU, R, I, F> {
    41
    42      /**
    43       * Checks, whether limiting the file size works.
    44       *
    45       * @throws IOException Test failure.
    46       */
    47      @Test
    48      public void testFileSizeLimit() throws IOException {
    49          final var content = "This is the content of the file\n";
    50          final var contentSize = content.getBytes().length;
    51
    52          // @formatter:off
    53          final var request =
    54              "-----1234\r\n" +
    55              "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
    56              "Content-Type: text/whatever\r\n" +
    57              "\r\n" +
    58              content +
    59              "\r\n" +
    60              "-----1234--\r\n";
    61          // @formatter:on
    62
    63          var upload = newFileUpload();
    64          upload.setFileSizeMax(-1);
    65          var req = newMockHttpServletRequest(request, null, null);
    66          var fileItems = upload.parseRequest(req);
    67          assertEquals(1, fileItems.size());
    68          var item = fileItems.get(0);
    69          assertEquals(content, new String(item.get()));
    70
    71          upload = newFileUpload();
    72          upload.setFileSizeMax(40);
    73          req = newMockHttpServletRequest(request, null, null);
    74          fileItems = upload.parseRequest(req);
    75          assertEquals(1, fileItems.size());
    76          item = fileItems.get(0);
    77          assertEquals(content, new String(item.get()));
    78
    79          upload = newFileUpload();
    80          upload.setFileSizeMax(contentSize);
    81          req = newMockHttpServletRequest(request, null, null);
    82          fileItems = upload.parseRequest(req);
    83          assertEquals(1, fileItems.size());
    84          item = fileItems.get(0);
    85          assertEquals(content, new String(item.get()));
    86
    87          upload = newFileUpload();
    88          upload.setFileSizeMax(contentSize - 1);
    89          req = newMockHttpServletRequest(request, null, null);
    90          try {
    91              upload.parseRequest(req);
    92              fail("Expected exception.");
    93          } catch (final FileUploadByteCountLimitException e) {
    94              assertEquals(contentSize - 1, e.getPermitted());
    95          }
    96
    97          upload = newFileUpload();
    98          upload.setFileSizeMax(30);
    99          req = newMockHttpServletRequest(request, null, null);
    100         try {
    101             upload.parseRequest(req);
    102             fail("Expected exception.");
    103         } catch (final FileUploadByteCountLimitException e) {
    104             assertEquals(30, e.getPermitted());
    105         }
    106     }
    107
    108     /**
    109      * Checks, whether a faked Content-Length header is detected.
    110      *
    111      * @throws IOException Test failure.
    112      */
    113     @Test
    114     public void testFileSizeLimitWithFakedContentLength() throws IOException {
    115         // @formatter:off
    116         final var request =
    117             "-----1234\r\n" +
    118             "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
    119             "Content-Type: text/whatever\r\n" +
    120             "Content-Length: 10\r\n" +
    121             "\r\n" +
    122             "This is the content of the file\n" +
    123             "\r\n" +
    124             "-----1234--\r\n";
    125         // @formatter:on
    126
    127         var upload = newFileUpload();
    128         upload.setFileSizeMax(-1);
    129         var req = newMockHttpServletRequest(request, null, null);
    130         var fileItems = upload.parseRequest(req);
    131         assertEquals(1, fileItems.size());
    132         var item = fileItems.get(0);
    133         assertEquals("This is the content of the file\n", new String(item.get()));
    134
    135         upload = newFileUpload();
    136         upload.setFileSizeMax(40);
    137         req = newMockHttpServletRequest(request, null, null);
    138         fileItems = upload.parseRequest(req);
    139         assertEquals(1, fileItems.size());
    140         item = fileItems.get(0);
    141         assertEquals("This is the content of the file\n", new String(item.get()));
    142
    143         // provided Content-Length is larger than the FileSizeMax -> handled by ctor
    144         upload = newFileUpload();
    145         upload.setFileSizeMax(5);
    146         req = newMockHttpServletRequest(request, null, null);
    147         try {
    148             upload.parseRequest(req);
    149             fail("Expected exception.");
    150         } catch (final FileUploadByteCountLimitException e) {
    151             assertEquals(5, e.getPermitted());
    152         }
    153
    154         // provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
    155         upload = newFileUpload();
    156         upload.setFileSizeMax(15);
    157         req = newMockHttpServletRequest(request, null, null);
    158         try {
    159             upload.parseRequest(req);
    160             fail("Expected exception.");
    161         } catch (final FileUploadByteCountLimitException e) {
    162             assertEquals(15, e.getPermitted());
    163         }
    164     }
    165
    166     /**
    167      * Checks whether maxSize works.
    168      *
    169      * @throws IOException Test failure.
    170      */
    171     @Test
    172     public void testMaxSizeLimit() throws IOException {
    173         // @formatter:off
    174         final var request =
    175             "-----1234\r\n" +
    176             "Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
    177             "Content-Type: text/whatever\r\n" +
    178             "Content-Length: 10\r\n" +
    179             "\r\n" +
    180             "This is the content of the file\n" +
    181             "\r\n" +
    182             "-----1234\r\n" +
    183             "Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
    184             "Content-Type: text/whatever\r\n" +
    185             "\r\n" +
    186             "This is the content of the file\n" +
    187             "\r\n" +
    188             "-----1234--\r\n";
    189         // @formatter:on
    190
    191         final var upload = newFileUpload();
    192         upload.setFileSizeMax(-1);
    193         upload.setSizeMax(200);
    194
    195         final var req = newMockHttpServletRequest(request, null, null);
    196         try {
    197             upload.parseRequest(req);
    198             fail("Expected exception.");
    199         } catch (final FileUploadSizeException e) {
    200             assertEquals(200, e.getPermitted());
    201         }
    202     }
    203
    204     @Test
    205     public void testMaxSizeLimitUnknownContentLength() throws IOException {
    206         // @formatter:off
    207         final var request =
    208             "-----1234\r\n" +
    209             "Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
    210             "Content-Type: text/whatever\r\n" +
    211             "Content-Length: 10\r\n" +
    212             "\r\n" +
    213             "This is the content of the file\n" +
    214             "\r\n" +
    215             "-----1234\r\n" +
    216             "Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
    217             "Content-Type: text/whatever\r\n" +
    218             "\r\n" +
    219             "This is the content of the file\n" +
    220             "\r\n" +
    221             "-----1234--\r\n";
    222         // @formatter:on
    223
    224         final var upload = newFileUpload();
    225         upload.setFileSizeMax(-1);
    226         upload.setSizeMax(300);
    227
    228         // the first item should be within the max size limit
    229         // set the read limit to 10 to simulate a "real" stream
    230         // otherwise the buffer would be immediately filled
    231
    232         final var req = newMockHttpServletRequest(request, -1L, 10);
    233
    234         final var it = upload.getItemIterator(req);
    235         assertTrue(it.hasNext());
    236
    237         final var item = it.next();
    238         assertFalse(item.isFormField());
    239         assertEquals("file1", item.getFieldName());
    240         assertEquals("foo1.tab", item.getName());
    241
    242         {
    243             try (final var baos = new ByteArrayOutputStream();
    244                     final var stream = item.getInputStream()) {
    245                 IOUtils.copy(stream, baos);
    246             }
    247
    248         }
    249
    250         // the second item is over the size max, thus we expect an error
    251         // the header is still within size max -> this shall still succeed
    252         assertTrue(it.hasNext());
    253
    254         assertThrows(FileUploadException.class, () -> {
    255             final var item2 = it.next();
    256             try (final var baos = new ByteArrayOutputStream();
    257                     final var stream = item2.getInputStream()) {
    258                 IOUtils.copy(stream, baos);
    259             }
    260         });
    261     }
    262 }