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 }