001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.fileupload; 018 019 import java.io.ByteArrayInputStream; 020 import java.io.ByteArrayOutputStream; 021 import java.io.FilterInputStream; 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.io.OutputStreamWriter; 025 import java.util.Iterator; 026 import java.util.List; 027 import javax.servlet.http.HttpServletRequest; 028 029 import org.apache.commons.fileupload.FileUploadBase.IOFileUploadException; 030 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 031 import org.apache.commons.fileupload.servlet.ServletFileUpload; 032 import org.apache.commons.fileupload.servlet.ServletRequestContext; 033 034 import junit.framework.TestCase; 035 036 037 /** 038 * Unit test for items with varying sizes. 039 */ 040 public class StreamingTest extends TestCase 041 { 042 /** 043 * Tests a file upload with varying file sizes. 044 */ 045 public void testFileUpload() 046 throws IOException, FileUploadException 047 { 048 byte[] request = newRequest(); 049 List fileItems = parseUpload(request); 050 Iterator fileIter = fileItems.iterator(); 051 int add = 16; 052 int num = 0; 053 for (int i = 0; i < 16384; i += add) { 054 if (++add == 32) { 055 add = 16; 056 } 057 FileItem item = (FileItem) fileIter.next(); 058 assertEquals("field" + (num++), item.getFieldName()); 059 byte[] bytes = item.get(); 060 assertEquals(i, bytes.length); 061 for (int j = 0; j < i; j++) { 062 assertEquals((byte) j, bytes[j]); 063 } 064 } 065 assertTrue(!fileIter.hasNext()); 066 } 067 068 069 /** 070 * Tests, whether an invalid request throws a proper 071 * exception. 072 */ 073 public void testFileUploadException() 074 throws IOException, FileUploadException { 075 byte[] request = newRequest(); 076 byte[] invalidRequest = new byte[request.length-11]; 077 System.arraycopy(request, 0, invalidRequest, 0, request.length-11); 078 try { 079 parseUpload(invalidRequest); 080 fail("Expected EndOfStreamException"); 081 } catch (IOFileUploadException e) { 082 assertTrue(e.getCause() instanceof MultipartStream.MalformedStreamException); 083 } 084 } 085 086 /** 087 * Tests, whether an IOException is properly delegated. 088 */ 089 public void testIOException() 090 throws IOException { 091 byte[] request = newRequest(); 092 InputStream stream = new FilterInputStream(new ByteArrayInputStream(request)){ 093 private int num; 094 public int read() throws IOException { 095 if (++num > 123) { 096 throw new IOException("123"); 097 } 098 return super.read(); 099 } 100 public int read(byte[] pB, int pOff, int pLen) 101 throws IOException { 102 for (int i = 0; i < pLen; i++) { 103 int res = read(); 104 if (res == -1) { 105 return i == 0 ? -1 : i; 106 } 107 pB[pOff+i] = (byte) res; 108 } 109 return pLen; 110 } 111 }; 112 try { 113 parseUpload(stream, request.length); 114 fail("Expected IOException"); 115 } catch (FileUploadException e) { 116 assertTrue(e.getCause() instanceof IOException); 117 assertEquals("123", e.getCause().getMessage()); 118 } 119 } 120 121 /** 122 * Test for FILEUPLOAD-135 123 */ 124 public void testFILEUPLOAD135() 125 throws IOException, FileUploadException 126 { 127 byte[] request = newShortRequest(); 128 final ByteArrayInputStream bais = new ByteArrayInputStream(request); 129 List fileItems = parseUpload(new InputStream() { 130 public int read() 131 throws IOException 132 { 133 return bais.read(); 134 } 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 fileIter = fileItems.iterator(); 142 assertTrue(fileIter.hasNext()); 143 FileItem item = (FileItem) 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 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 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 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 fileItems = parseUpload(reqBytes); 264 final FileItem 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 }