Author: jochen
Date: Mon Aug 7 13:54:54 2006
New Revision: 429474
URL: http://svn.apache.org/viewvc?rev=429474&view=rev
Log:
It is now possible to limit a files actual size, as opposed to the request size.
PR: FILEUPLOAD-88
Permitted-by: Andrey Aristarkhov, [EMAIL PROTECTED]
Added:
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/Closeable.java
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java
Modified:
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/FileUploadBase.java
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/MultipartStream.java
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/FileUploadTestCase.java
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/SizesTest.java
jakarta/commons/proper/fileupload/trunk/xdocs/changes.xml
Modified:
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/FileUploadBase.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/FileUploadBase.java?rev=429474&r1=429473&r2=429474&view=diff
==============================================================================
---
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/FileUploadBase.java
(original)
+++
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/FileUploadBase.java
Mon Aug 7 13:54:54 2006
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2005 The Apache Software Foundation
+ * Copyright 2001-2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.apache.commons.fileupload;
-import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@@ -27,8 +26,10 @@
import javax.servlet.http.HttpServletRequest;
-import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.fileupload.servlet.ServletRequestContext;
+import org.apache.commons.fileupload.util.Closeable;
+import org.apache.commons.fileupload.util.LimitedInputStream;
/**
@@ -150,11 +151,16 @@
/**
- * The maximum size permitted for an uploaded file. A value of -1 indicates
- * no maximum.
+ * The maximum size permitted for the complete request, as opposed to
+ * [EMAIL PROTECTED] #fileSizeMax}. A value of -1 indicates no maximum.
*/
private long sizeMax = -1;
+ /**
+ * The maximum size permitted for a single uploaded file, as opposed
+ * to [EMAIL PROTECTED] #sizeMax}. A value of -1 indicates no maximum.
+ */
+ private long fileSizeMax = -1;
/**
* The content encoding to use when reading part headers.
@@ -186,9 +192,11 @@
/**
- * Returns the maximum allowed upload size.
+ * Returns the maximum allowed size of a complete request, as opposed
+ * to [EMAIL PROTECTED] #getFileSizeMax()}.
*
- * @return The maximum allowed size, in bytes.
+ * @return The maximum allowed size, in bytes. The default value of
+ * -1 indicates, that there is no limit.
*
* @see #setSizeMax(long)
*
@@ -199,9 +207,11 @@
/**
- * Sets the maximum allowed upload size. If negative, there is no maximum.
+ * Sets the maximum allowed size of a complete request, as opposed
+ * to [EMAIL PROTECTED] #setFileSizeMax(long)}.
*
- * @param sizeMax The maximum allowed size, in bytes, or -1 for no maximum.
+ * @param sizeMax The maximum allowed size, in bytes. The default value of
+ * -1 indicates, that there is no limit.
*
* @see #getSizeMax()
*
@@ -210,6 +220,25 @@
this.sizeMax = sizeMax;
}
+ /**
+ * Returns the maximum allowed size of a single uploaded file,
+ * as opposed to [EMAIL PROTECTED] #getSizeMax()}.
+ *
+ * @see #setFileSizeMax(long)
+ */
+ public long getFileSizeMax() {
+ return fileSizeMax;
+ }
+
+ /**
+ * Sets the maximum allowed size of a single uploaded file,
+ * as opposed to [EMAIL PROTECTED] #getSizeMax()}.
+ *
+ * @see #getFileSizeMax()
+ */
+ public void setFileSizeMax(long fileSizeMax) {
+ this.fileSizeMax = fileSizeMax;
+ }
/**
* Retrieves the character encoding used when reading the headers of an
@@ -520,7 +549,7 @@
private class FileItemStreamImpl implements FileItemStream {
private final String contentType, fieldName, name;
private final boolean formField;
- private final MultipartStream.ItemInputStream stream;
+ private final InputStream stream;
private boolean opened;
FileItemStreamImpl(String pName, String pFieldName,
@@ -529,7 +558,20 @@
fieldName = pFieldName;
contentType = pContentType;
formField = pFormField;
- stream = multi.newInputStream();
+ InputStream istream = multi.newInputStream();
+ if (fileSizeMax != -1) {
+ istream = new LimitedInputStream(istream, fileSizeMax){
+ protected void raiseError(long pSizeMax, long
pCount) throws IOException {
+ FileUploadException e = new
FileSizeLimitExceededException(
+ "The field " +
fieldName + " exceeds its maximum permitted "
+ + " size of " +
pSizeMax + " characters.",
+ pCount, pSizeMax);
+ throw new FileUploadIOException(e);
+
+ }
+ };
+ }
+ stream = istream;
}
public String getContentType() {
@@ -552,7 +594,7 @@
if (opened) {
throw new IllegalStateException("The stream was already
opened.");
}
- if (stream.isClosed()) {
+ if (((Closeable) stream).isClosed()) {
throw new FileItemStream.ItemSkippedException();
}
return stream;
@@ -594,7 +636,15 @@
if (sizeMax >= 0) {
int requestSize = ctx.getContentLength();
if (requestSize == -1) {
- input = new LimitedInputStream(input, sizeMax);
+ input = new LimitedInputStream(input, sizeMax){
+ protected void raiseError(long
pSizeMax, long pCount) throws IOException {
+ FileUploadException ex = new
SizeLimitExceededException(
+ "the request was rejected
because its size (" + pCount
+ + ") exceeds the configured
maximum (" + pSizeMax + ")",
+ pCount, pSizeMax);
+ throw new FileUploadIOException(ex);
+ }
+ };
} else {
if (sizeMax >= 0 && requestSize > sizeMax) {
throw new SizeLimitExceededException(
@@ -709,48 +759,6 @@
}
/**
- * An input stream, which limits its data size. This stream is
- * used, if the content length is unknown.
- */
- private static class LimitedInputStream extends FilterInputStream {
- private long sizeMax;
- private long count;
-
- private void checkLimit() throws IOException {
- if (count > sizeMax) {
- FileUploadException ex = new SizeLimitExceededException(
- "the request was rejected because its size (" + count
- + ") exceeds the configured maximum (" + sizeMax + ")",
- count, sizeMax);
- throw new FileUploadIOException(ex);
- }
- }
-
- public int read() throws IOException {
- int res = super.read();
- if (res != -1) {
- count++;
- checkLimit();
- }
- return res;
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- int res = super.read(b, off, len);
- if (res > 0) {
- count += res;
- checkLimit();
- }
- return res;
- }
-
- LimitedInputStream(InputStream pIn, long pSizeMax) {
- super(pIn);
- sizeMax = pSizeMax;
- }
- }
-
- /**
* This exception is thrown for hiding an inner
* [EMAIL PROTECTED] FileUploadException} in an [EMAIL PROTECTED]
IOException}.
*/
@@ -818,40 +826,48 @@
}
}
- /**
- * Thrown to indicate that the request size exceeds the configured maximum.
- */
- public static class SizeLimitExceededException
- extends FileUploadException {
- private static final long serialVersionUID = -2474893167098052828L;
-
+ protected abstract static class SizeException extends FileUploadException {
/**
* The actual size of the request.
*/
- private long actual;
+ private final long actual;
/**
* The maximum permitted size of the request.
*/
- private long permitted;
+ private final long permitted;
+
+ protected SizeException(String message, long actual, long permitted) {
+ super(message);
+ this.actual = actual;
+ this.permitted = permitted;
+ }
/**
- * Constructs a <code>SizeExceededException</code> with no
- * detail message.
+ * Retrieves the actual size of the request.
+ *
+ * @return The actual size of the request.
*/
- public SizeLimitExceededException() {
- super();
+ public long getActualSize() {
+ return actual;
}
/**
- * Constructs a <code>SizeExceededException</code> with
- * the specified detail message.
+ * Retrieves the permitted size of the request.
*
- * @param message The detail message.
+ * @return The permitted size of the request.
*/
- public SizeLimitExceededException(String message) {
- super(message);
+ public long getPermittedSize() {
+ return permitted;
}
+ }
+
+ /**
+ * Thrown to indicate that the request size exceeds the configured maximum.
+ */
+ public static class SizeLimitExceededException
+ extends SizeException {
+ private static final long serialVersionUID = -2474893167098052828L;
/**
* Constructs a <code>SizeExceededException</code> with
@@ -863,27 +879,28 @@
*/
public SizeLimitExceededException(String message, long actual,
long permitted) {
- super(message);
- this.actual = actual;
- this.permitted = permitted;
+ super(message, actual, permitted);
}
+ }
- /**
- * Retrieves the actual size of the request.
- *
- * @return The actual size of the request.
- */
- public long getActualSize() {
- return actual;
- }
+ /**
+ * Thrown to indicate that A files size exceeds the configured maximum.
+ */
+ public static class FileSizeLimitExceededException
+ extends SizeException {
+ private static final long serialVersionUID =
8150776562029630058L;
- /**
- * Retrieves the permitted size of the request.
+ /**
+ * Constructs a <code>SizeExceededException</code> with
+ * the specified detail message, and actual and permitted sizes.
*
- * @return The permitted size of the request.
+ * @param message The detail message.
+ * @param actual The actual request size.
+ * @param permitted The maximum permitted request size.
*/
- public long getPermittedSize() {
- return permitted;
+ public FileSizeLimitExceededException(String message, long actual,
+ long permitted) {
+ super(message, actual, permitted);
}
}
Modified:
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/MultipartStream.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/MultipartStream.java?rev=429474&r1=429473&r2=429474&view=diff
==============================================================================
---
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/MultipartStream.java
(original)
+++
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/MultipartStream.java
Mon Aug 7 13:54:54 2006
@@ -21,6 +21,8 @@
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
+import org.apache.commons.fileupload.util.Closeable;
+
/**
* <p> Low level API for processing file uploads.
*
@@ -704,7 +706,7 @@
/**
* An [EMAIL PROTECTED] InputStream} for reading an items contents.
*/
- public class ItemInputStream extends InputStream {
+ public class ItemInputStream extends InputStream implements Closeable {
private long total;
private int pad, pos;
private boolean closed;
@@ -734,9 +736,8 @@
public int available() throws IOException {
if (pos == -1) {
return tail - head - pad;
- } else {
- return pos - head;
}
+ return pos - head;
}
public int read() throws IOException {
Added:
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/Closeable.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/Closeable.java?rev=429474&view=auto
==============================================================================
---
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/Closeable.java
(added)
+++
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/Closeable.java
Mon Aug 7 13:54:54 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.fileupload.util;
+
+import java.io.IOException;
+
+
+/**
+ * Interface of an object, which may be closed.
+ */
+public interface Closeable {
+ /**
+ * Closes the object.
+ */
+ public void close() throws IOException;
+
+ /**
+ * Returns, whether the object is already closed.
+ */
+ public boolean isClosed() throws IOException;
+}
Added:
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java?rev=429474&view=auto
==============================================================================
---
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java
(added)
+++
jakarta/commons/proper/fileupload/trunk/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java
Mon Aug 7 13:54:54 2006
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.fileupload.util;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * An input stream, which limits its data size. This stream is
+ * used, if the content length is unknown.
+ */
+public abstract class LimitedInputStream extends FilterInputStream
+ implements Closeable {
+ private long sizeMax;
+ private long count;
+ private boolean closed;
+
+ /**
+ * Creates a new instance.
+ * @param pIn The input stream, which shall be limited.
+ * @param pSizeMax The limit; no more than this number of bytes
+ * shall be returned by the source stream.
+ */
+ public LimitedInputStream(InputStream pIn, long pSizeMax) {
+ super(pIn);
+ sizeMax = pSizeMax;
+ }
+
+ protected abstract void raiseError(long pSizeMax, long pCount) throws
IOException;
+
+ private void checkLimit() throws IOException {
+ if (count > sizeMax) {
+ raiseError(sizeMax, count);
+ }
+ }
+
+ public int read() throws IOException {
+ int res = super.read();
+ if (res != -1) {
+ count++;
+ checkLimit();
+ }
+ return res;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ int res = super.read(b, off, len);
+ if (res > 0) {
+ count += res;
+ checkLimit();
+ }
+ return res;
+ }
+
+ public boolean isClosed() throws IOException {
+ return closed;
+ }
+
+ public void close() throws IOException {
+ closed = true;
+ super.close();
+ }
+}
Modified:
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/FileUploadTestCase.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/FileUploadTestCase.java?rev=429474&r1=429473&r2=429474&view=diff
==============================================================================
---
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/FileUploadTestCase.java
(original)
+++
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/FileUploadTestCase.java
Mon Aug 7 13:54:54 2006
@@ -15,9 +15,10 @@
* Base class for deriving test cases.
*/
public abstract class FileUploadTestCase extends TestCase {
- protected List parseUpload(byte[] bytes) throws FileUploadException {
- String contentType = "multipart/form-data; boundary=---1234";
- return parseUpload(bytes, contentType);
+ protected static final String CONTENT_TYPE = "multipart/form-data;
boundary=---1234";
+
+ protected List parseUpload(byte[] bytes) throws FileUploadException {
+ return parseUpload(bytes, CONTENT_TYPE);
}
protected List parseUpload(byte[] bytes, String contentType) throws
FileUploadException {
@@ -32,6 +33,6 @@
throws UnsupportedEncodingException, FileUploadException
{
byte[] bytes = content.getBytes("US-ASCII");
- return parseUpload(bytes, "multipart/form-data;
boundary=---1234");
+ return parseUpload(bytes, CONTENT_TYPE);
}
}
Modified:
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/SizesTest.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/SizesTest.java?rev=429474&r1=429473&r2=429474&view=diff
==============================================================================
---
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/SizesTest.java
(original)
+++
jakarta/commons/proper/fileupload/trunk/src/test/org/apache/commons/fileupload/SizesTest.java
Mon Aug 7 13:54:54 2006
@@ -72,4 +72,45 @@
}
assertTrue(!fileIter.hasNext());
}
+
+ /** Checks, whether limiting the file size works.
+ */
+ 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"), CONTENT_TYPE);
+ List fileItems = upload.parseRequest(req);
+ assertEquals(1, fileItems.size());
+ FileItem item = (FileItem) 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"),
CONTENT_TYPE);
+ fileItems = upload.parseRequest(req);
+ assertEquals(1, fileItems.size());
+ item = (FileItem) 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"),
CONTENT_TYPE);
+ try {
+ upload.parseRequest(req);
+ fail("Expected exception.");
+ } catch (FileUploadBase.FileSizeLimitExceededException e) {
+ assertEquals(30, e.getPermittedSize());
+ }
+ }
}
Modified: jakarta/commons/proper/fileupload/trunk/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/fileupload/trunk/xdocs/changes.xml?rev=429474&r1=429473&r2=429474&view=diff
==============================================================================
--- jakarta/commons/proper/fileupload/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/fileupload/trunk/xdocs/changes.xml Mon Aug 7
13:54:54 2006
@@ -71,6 +71,11 @@
Added support for header continuation lines.
</action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-88"
+ due-to="Andrey Aristarkhov" due-to-email="[EMAIL PROTECTED]">
+ It is now possible to limit the actual file size and not
+ the request size.
+ </action>
</release>
<release version="1.1.1" date="2006-06-08" description="Bugfix release">
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]