commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From joc...@apache.org
Subject svn commit: r429474 - in /jakarta/commons/proper/fileupload/trunk: src/java/org/apache/commons/fileupload/ src/java/org/apache/commons/fileupload/util/ src/test/org/apache/commons/fileupload/ xdocs/
Date Mon, 07 Aug 2006 20:54:54 GMT
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, aristarkhov@bitechnology.ru

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
+     * {@link #fileSizeMax}. A value of -1 indicates no maximum.
      */
     private long sizeMax = -1;
 
+    /**
+     * The maximum size permitted for a single uploaded file, as opposed
+     * to {@link #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 {@link #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 {@link #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 {@link #getSizeMax()}.
+     *
+     * @see #setFileSizeMax(long)
+     */
+    public long getFileSizeMax() {
+    	return fileSizeMax;
+    }
+
+    /**
+     * Sets the maximum allowed size of a single uploaded file,
+     * as opposed to {@link #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 
      * {@link FileUploadException} in an {@link 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 {@link 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="aristarkhov@bitechnology.ru">
+        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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message