blob: ca005e99e26986f092ff2ff368c8ceed3ad24f62 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload2.FileItem;
import org.apache.commons.fileupload2.FileItemIterator;
import org.apache.commons.fileupload2.FileItemStream;
import org.apache.commons.fileupload2.FileUploadException;
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
import org.apache.commons.fileupload2.impl.FileSizeLimitExceededException;
import org.apache.commons.fileupload2.impl.FileUploadIOException;
import org.apache.commons.fileupload2.impl.SizeLimitExceededException;
import org.apache.commons.fileupload2.servlet.ServletFileUpload;
import org.apache.commons.fileupload2.util.Streams;
import org.junit.jupiter.api.Test;
/**
* Unit test for items with varying sizes.
*/
public class SizesTest {
/**
* Runs a test with varying file sizes.
*/
@Test
public void testFileUpload()
throws IOException, FileUploadException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int add = 16;
int num = 0;
for (int i = 0; i < 16384; i += add) {
if (++add == 32) {
add = 16;
}
String header = "-----1234\r\n"
+ "Content-Disposition: form-data; name=\"field" + (num++) + "\"\r\n"
+ "\r\n";
baos.write(header.getBytes("US-ASCII"));
for (int j = 0; j < i; j++) {
baos.write((byte) j);
}
baos.write("\r\n".getBytes("US-ASCII"));
}
baos.write("-----1234--\r\n".getBytes("US-ASCII"));
List<FileItem> fileItems =
Util.parseUpload(new ServletFileUpload(new DiskFileItemFactory()), baos.toByteArray());
Iterator<FileItem> fileIter = fileItems.iterator();
add = 16;
num = 0;
for (int i = 0; i < 16384; i += add) {
if (++add == 32) {
add = 16;
}
FileItem item = fileIter.next();
assertEquals("field" + (num++), item.getFieldName());
byte[] bytes = item.get();
assertEquals(i, bytes.length);
for (int j = 0; j < i; j++) {
assertEquals((byte) j, bytes[j]);
}
}
assertTrue(!fileIter.hasNext());
}
/** Checks, whether limiting the file size works.
*/
@Test
public void testFileSizeLimit()
throws IOException, FileUploadException {
final String request =
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"\r\n" +
"This is the content of the file\n" +
"\r\n" +
"-----1234--\r\n";
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(-1);
HttpServletRequest req = new MockHttpServletRequest(
request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
List<FileItem> fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
FileItem item = fileItems.get(0);
assertEquals("This is the content of the file\n", new String(item.get()));
upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(40);
req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
item = fileItems.get(0);
assertEquals("This is the content of the file\n", new String(item.get()));
upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(30);
req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (FileSizeLimitExceededException e) {
assertEquals(30, e.getPermittedSize());
}
}
/** Checks, whether a faked Content-Length header is detected.
*/
@Test
public void testFileSizeLimitWithFakedContentLength()
throws IOException, FileUploadException {
final String request =
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"Content-Length: 10\r\n" +
"\r\n" +
"This is the content of the file\n" +
"\r\n" +
"-----1234--\r\n";
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(-1);
HttpServletRequest req = new MockHttpServletRequest(
request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
List<FileItem> fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
FileItem item = fileItems.get(0);
assertEquals("This is the content of the file\n", new String(item.get()));
upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(40);
req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
item = fileItems.get(0);
assertEquals("This is the content of the file\n", new String(item.get()));
// provided Content-Length is larger than the FileSizeMax -> handled by ctor
upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(5);
req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (FileSizeLimitExceededException e) {
assertEquals(5, e.getPermittedSize());
}
// provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(15);
req = new MockHttpServletRequest(request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (FileSizeLimitExceededException e) {
assertEquals(15, e.getPermittedSize());
}
}
/** Checks, whether the maxSize works.
*/
@Test
public void testMaxSizeLimit()
throws IOException, FileUploadException {
final String request =
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"Content-Length: 10\r\n" +
"\r\n" +
"This is the content of the file\n" +
"\r\n" +
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"\r\n" +
"This is the content of the file\n" +
"\r\n" +
"-----1234--\r\n";
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(-1);
upload.setSizeMax(200);
MockHttpServletRequest req = new MockHttpServletRequest(
request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (SizeLimitExceededException e) {
assertEquals(200, e.getPermittedSize());
}
}
@Test
public void testMaxSizeLimitUnknownContentLength()
throws IOException, FileUploadException {
final String request =
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"Content-Length: 10\r\n" +
"\r\n" +
"This is the content of the file\n" +
"\r\n" +
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"\r\n" +
"This is the content of the file\n" +
"\r\n" +
"-----1234--\r\n";
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setFileSizeMax(-1);
upload.setSizeMax(300);
// the first item should be within the max size limit
// set the read limit to 10 to simulate a "real" stream
// otherwise the buffer would be immediately filled
MockHttpServletRequest req = new MockHttpServletRequest(
request.getBytes("US-ASCII"), Constants.CONTENT_TYPE);
req.setContentLength(-1);
req.setReadLimit(10);
FileItemIterator it = upload.getItemIterator(req);
assertTrue(it.hasNext());
FileItemStream item = it.next();
assertFalse(item.isFormField());
assertEquals("file1", item.getFieldName());
assertEquals("foo1.tab", item.getName());
{
InputStream stream = item.openStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Streams.copy(stream, baos, true);
}
// the second item is over the size max, thus we expect an error
try {
// the header is still within size max -> this shall still succeed
assertTrue(it.hasNext());
} catch (SizeLimitExceededException e) {
fail();
}
item = it.next();
try {
InputStream stream = item.openStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Streams.copy(stream, baos, true);
fail();
} catch (FileUploadIOException e) {
// expected
}
}
}