Browse Source

KERNEL-5583 feat: 升级spring到4.3.29RELEASE

research/11.0
Cloud.Liu 4 years ago
parent
commit
79cff8db0d
  1. 2
      fine-commons-fileupload/README.md
  2. BIN
      fine-commons-fileupload/lib/portlet-api-1.0.jar
  3. 7
      fine-commons-fileupload/pom.xml
  4. 25
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItem.java
  5. 27
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItemFactory.java
  6. 58
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DiskFileUpload.java
  7. 42
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItem.java
  8. 4
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemFactory.java
  9. 76
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeaders.java
  10. 50
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeadersSupport.java
  11. 8
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemIterator.java
  12. 13
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemStream.java
  13. 26
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUpload.java
  14. 637
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadBase.java
  15. 16
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadException.java
  16. 64
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/InvalidFileNameException.java
  17. 429
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/MultipartStream.java
  18. 100
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ParameterParser.java
  19. 9
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ProgressListener.java
  20. 7
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/RequestContext.java
  21. 39
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/UploadContext.java
  22. 222
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItem.java
  23. 98
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItemFactory.java
  24. 54
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/package-info.java
  25. 58
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/package.html
  26. 85
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/package-info.java
  27. 90
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/package.html
  28. 152
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java
  29. 129
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java
  30. 45
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/package-info.java
  31. 58
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java
  32. 55
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletFileUpload.java
  33. 44
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletRequestContext.java
  34. 45
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/package-info.java
  35. 49
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/package.html
  36. 7
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Closeable.java
  37. 97
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/FileItemHeadersImpl.java
  38. 28
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/LimitedInputStream.java
  39. 118
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Streams.java
  40. 152
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/Base64Decoder.java
  41. 283
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/MimeUtility.java
  42. 38
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/ParseException.java
  43. 112
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/QuotedPrintableDecoder.java
  44. 22
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/package-info.java
  45. 23
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/package-info.java
  46. 29
      fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/package.html
  47. BIN
      fine-spring/lib/bcmail-jdk14-1.38.jar
  48. BIN
      fine-spring/lib/bsh-2.0b4.jar
  49. BIN
      fine-spring/lib/bsh-2.0b5.jar
  50. BIN
      fine-spring/lib/commons-codec-1.10.jar
  51. BIN
      fine-spring/lib/commons-codec-1.6.jar
  52. BIN
      fine-spring/lib/commons-fileupload-1.3.1.jar
  53. BIN
      fine-spring/lib/commons-fileupload-1.3.3.jar
  54. BIN
      fine-spring/lib/commons-logging-1.1.3.jar
  55. BIN
      fine-spring/lib/commons-pool-1.6.jar
  56. BIN
      fine-spring/lib/commons-pool2-2.4.2.jar
  57. BIN
      fine-spring/lib/groovy-all-1.8.9.jar
  58. BIN
      fine-spring/lib/groovy-all-2.4.17.jar
  59. BIN
      fine-spring/lib/gson-2.8.5.jar
  60. BIN
      fine-spring/lib/hessian-4.0.38.jar
  61. BIN
      fine-spring/lib/hessian-4.0.7.jar
  62. BIN
      fine-spring/lib/httpasyncclient-4.0.2.jar
  63. BIN
      fine-spring/lib/httpasyncclient-4.1.4.jar
  64. BIN
      fine-spring/lib/jackson-annotations-2.3.0.jar
  65. BIN
      fine-spring/lib/jackson-annotations-2.8.0.jar
  66. BIN
      fine-spring/lib/jackson-core-2.3.4.jar
  67. BIN
      fine-spring/lib/jackson-core-2.8.10.jar
  68. BIN
      fine-spring/lib/jackson-databind-2.3.4.jar
  69. BIN
      fine-spring/lib/jackson-databind-2.8.11.3.jar
  70. BIN
      fine-spring/lib/jackson-dataformat-xml-2.8.11.jar
  71. BIN
      fine-spring/lib/jamon-2.4.jar
  72. BIN
      fine-spring/lib/jamon-2.81.jar
  73. BIN
      fine-spring/lib/jasperreports-5.5.1.jar
  74. BIN
      fine-spring/lib/javax.servlet-api-3.0.1.jar
  75. BIN
      fine-spring/lib/javax.servlet-api-3.1.0.jar
  76. BIN
      fine-spring/lib/jdom-1.0.jar
  77. BIN
      fine-spring/lib/jdom2-2.0.6.jar
  78. BIN
      fine-spring/lib/jetty-server-9.1.5.v20140505.jar
  79. BIN
      fine-spring/lib/jetty-servlet-9.1.5.v20140505.jar
  80. BIN
      fine-spring/lib/joda-time-2.5.jar
  81. BIN
      fine-spring/lib/joda-time-2.9.9.jar
  82. BIN
      fine-spring/lib/joni-2.1.3.jar
  83. BIN
      fine-spring/lib/jopt-simple-4.6.jar
  84. BIN
      fine-spring/lib/jopt-simple-5.0.3.jar
  85. BIN
      fine-spring/lib/jruby-core-1.7.17.jar
  86. BIN
      fine-spring/lib/jruby-core-1.7.27.jar
  87. BIN
      fine-spring/lib/jruby-stdlib-1.7.17.jar
  88. BIN
      fine-spring/lib/jruby-stdlib-1.7.27.jar
  89. BIN
      fine-spring/lib/money-api-1.0.1.jar
  90. BIN
      fine-spring/lib/netty-all-4.1.39.Final.jar
  91. BIN
      fine-spring/lib/poi-3.10.1.jar
  92. BIN
      fine-spring/lib/poi-3.17.jar
  93. BIN
      fine-spring/lib/rome-1.0.jar
  94. BIN
      fine-spring/lib/rome-1.7.4.jar
  95. BIN
      fine-spring/lib/snakeyaml-1.13.jar
  96. BIN
      fine-spring/lib/snakeyaml-1.17.jar
  97. BIN
      fine-spring/lib/tiles-api-2.2.2.jar
  98. BIN
      fine-spring/lib/tiles-api-3.0.8.jar
  99. BIN
      fine-spring/lib/tiles-compat-2.2.2.jar
  100. BIN
      fine-spring/lib/tiles-core-2.2.2.jar
  101. Some files were not shown because too many files have changed in this diff Show More

2
fine-commons-fileupload/README.md

@ -0,0 +1,2 @@
apache commons fileupload https://archive.apache.org/dist/commons/fileupload/source/
1.3.3

BIN
fine-commons-fileupload/lib/portlet-api-1.0.jar

Binary file not shown.

7
fine-commons-fileupload/pom.xml

@ -27,5 +27,12 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${basedir}/lib/javax.servlet-api-3.0.1.jar</systemPath> <systemPath>${basedir}/lib/javax.servlet-api-3.0.1.jar</systemPath>
</dependency> </dependency>
<dependency>
<groupId>com.fr.third</groupId>
<artifactId>portlet-api</artifactId>
<version>local</version>
<scope>system</scope>
<systemPath>${basedir}/lib/portlet-api-1.0.jar</systemPath>
</dependency>
</dependencies> </dependencies>
</project> </project>

25
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItem.java

@ -19,36 +19,33 @@ package com.fr.third.org.apache.commons.fileupload;
import java.io.File; import java.io.File;
import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItem; import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItem;
/** /**
* <p> The default implementation of the * <p> The default implementation of the
* {@link com.fr.third.org.apache.commons.fileupload.FileItem FileItem} interface. * {@link FileItem FileItem} interface.
* *
* <p> After retrieving an instance of this class from a {@link * <p> After retrieving an instance of this class from a {@link
* com.fr.third.org.apache.commons.fileupload.DiskFileUpload DiskFileUpload} instance (see * DiskFileUpload DiskFileUpload} instance (see
* {@link com.fr.third.org.apache.commons.fileupload.DiskFileUpload * {@link DiskFileUpload
* #parseRequest(javax.servlet.http.HttpServletRequest)}), you may * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may
* either request all contents of file at once using {@link #get()} or * either request all contents of file at once using {@link #get()} or
* request an {@link java.io.InputStream InputStream} with * request an {@link java.io.InputStream InputStream} with
* {@link #getInputStream()} and process the file without attempting to load * {@link #getInputStream()} and process the file without attempting to load
* it into memory, which may come handy with large files. * it into memory, which may come handy with large files.
* *
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:sean@informage.net">Sean Legassick</a>
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:jmcnally@apache.org">John McNally</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* @author Sean C. Sullivan
*
* @version $Id$ * @version $Id$
* *
* @deprecated Use <code>DiskFileItem</code> instead. * @deprecated 1.1 Use <code>DiskFileItem</code> instead.
*/ */
@Deprecated
public class DefaultFileItem public class DefaultFileItem
extends DiskFileItem { extends DiskFileItem {
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/**
* The UID to use when serializing this instance.
*/
private static final long serialVersionUID = 4088572813833518255L;
/** /**
* Constructs a new <code>DefaultFileItem</code> instance. * Constructs a new <code>DefaultFileItem</code> instance.
@ -67,8 +64,9 @@ public class DefaultFileItem
* which files will be created, should the item size * which files will be created, should the item size
* exceed the threshold. * exceed the threshold.
* *
* @deprecated Use <code>DiskFileItem</code> instead. * @deprecated 1.1 Use <code>DiskFileItem</code> instead.
*/ */
@Deprecated
public DefaultFileItem(String fieldName, String contentType, public DefaultFileItem(String fieldName, String contentType,
boolean isFormField, String fileName, int sizeThreshold, boolean isFormField, String fileName, int sizeThreshold,
File repository) { File repository) {
@ -76,5 +74,4 @@ public class DefaultFileItem
repository); repository);
} }
} }

27
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItemFactory.java

@ -20,45 +20,42 @@ import java.io.File;
import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory; import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory;
/** /**
* <p>The default {@link com.fr.third.org.apache.commons.fileupload.FileItemFactory} * <p>The default {@link FileItemFactory}
* implementation. This implementation creates * implementation. This implementation creates
* {@link com.fr.third.org.apache.commons.fileupload.FileItem} instances which keep their * {@link FileItem} instances which keep their
* content either in memory, for smaller items, or in a temporary file on disk, * content either in memory, for smaller items, or in a temporary file on disk,
* for larger items. The size threshold, above which content will be stored on * for larger items. The size threshold, above which content will be stored on
* disk, is configurable, as is the directory in which temporary files will be * disk, is configurable, as is the directory in which temporary files will be
* created.</p> * created.</p>
* *
* <p>If not otherwise configured, the default configuration values are as * If not otherwise configured, the default configuration values are as
* follows: * follows:
* <ul> * <ul>
* <li>Size threshold is 10KB.</li> * <li>Size threshold is 10KB.</li>
* <li>Repository is the system default temp directory, as returned by * <li>Repository is the system default temp directory, as returned by
* <code>System.getProperty("java.io.tmpdir")</code>.</li> * <code>System.getProperty("java.io.tmpdir")</code>.</li>
* </ul> * </ul>
* </p>
*
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* *
* @version $Id$ * @version $Id$
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public class DefaultFileItemFactory extends DiskFileItemFactory { public class DefaultFileItemFactory extends DiskFileItemFactory {
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/** /**
* Constructs an unconfigured instance of this class. The resulting factory * Constructs an unconfigured instance of this class. The resulting factory
* may be configured by calling the appropriate setter methods. * may be configured by calling the appropriate setter methods.
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public DefaultFileItemFactory() { public DefaultFileItemFactory() {
super(); super();
} }
/** /**
* Constructs a preconfigured instance of this class. * Constructs a preconfigured instance of this class.
* *
@ -69,17 +66,17 @@ public class DefaultFileItemFactory extends DiskFileItemFactory {
* which files will be created, should the item size * which files will be created, should the item size
* exceed the threshold. * exceed the threshold.
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public DefaultFileItemFactory(int sizeThreshold, File repository) { public DefaultFileItemFactory(int sizeThreshold, File repository) {
super(sizeThreshold, repository); super(sizeThreshold, repository);
} }
// --------------------------------------------------------- Public Methods // --------------------------------------------------------- Public Methods
/** /**
* Create a new {@link com.fr.third.org.apache.commons.fileupload.DefaultFileItem} * Create a new {@link DefaultFileItem}
* instance from the supplied parameters and the local factory * instance from the supplied parameters and the local factory
* configuration. * configuration.
* *
@ -92,8 +89,10 @@ public class DefaultFileItemFactory extends DiskFileItemFactory {
* *
* @return The newly created file item. * @return The newly created file item.
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Override
@Deprecated
public FileItem createItem( public FileItem createItem(
String fieldName, String fieldName,
String contentType, String contentType,

58
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DiskFileUpload.java

@ -27,54 +27,45 @@ import javax.servlet.http.HttpServletRequest;
* <code>multipart/mixed</code> encoding type, as specified by * <code>multipart/mixed</code> encoding type, as specified by
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
* #parseRequest(HttpServletRequest)} to acquire a list of {@link * #parseRequest(HttpServletRequest)} to acquire a list of {@link
* com.fr.third.org.apache.commons.fileupload.FileItem}s associated with a given HTML * FileItem}s associated with a given HTML
* widget.</p> * widget.</p>
* *
* <p>Individual parts will be stored in temporary disk storage or in memory, * <p>Individual parts will be stored in temporary disk storage or in memory,
* depending on their size, and will be available as {@link * depending on their size, and will be available as {@link
* com.fr.third.org.apache.commons.fileupload.FileItem}s.</p> * FileItem}s.</p>
*
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:jmcnally@collab.net">John McNally</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* @author Sean C. Sullivan
* *
* @version $Id$ * @version $Id$
* *
* @deprecated Use <code>ServletFileUpload</code> together with * @deprecated 1.1 Use <code>ServletFileUpload</code> together with
* <code>DiskFileItemFactory</code> instead. * <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public class DiskFileUpload public class DiskFileUpload
extends FileUploadBase { extends FileUploadBase {
// ----------------------------------------------------------- Data members // ----------------------------------------------------------- Data members
/** /**
* The factory to use to create new form items. * The factory to use to create new form items.
*/ */
private DefaultFileItemFactory fileItemFactory; private DefaultFileItemFactory fileItemFactory;
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/** /**
* Constructs an instance of this class which uses the default factory to * Constructs an instance of this class which uses the default factory to
* create <code>FileItem</code> instances. * create <code>FileItem</code> instances.
* *
* @see #DiskFileUpload(DefaultFileItemFactory fileItemFactory) * @see #DiskFileUpload(DefaultFileItemFactory fileItemFactory)
* *
* @deprecated Use <code>FileUpload</code> instead. * @deprecated 1.1 Use <code>FileUpload</code> instead.
*/ */
@Deprecated
public DiskFileUpload() { public DiskFileUpload() {
super(); super();
this.fileItemFactory = new DefaultFileItemFactory(); this.fileItemFactory = new DefaultFileItemFactory();
} }
/** /**
* Constructs an instance of this class which uses the supplied factory to * Constructs an instance of this class which uses the supplied factory to
* create <code>FileItem</code> instances. * create <code>FileItem</code> instances.
@ -82,29 +73,29 @@ public class DiskFileUpload
* @see #DiskFileUpload() * @see #DiskFileUpload()
* @param fileItemFactory The file item factory to use. * @param fileItemFactory The file item factory to use.
* *
* @deprecated Use <code>FileUpload</code> instead. * @deprecated 1.1 Use <code>FileUpload</code> instead.
*/ */
@Deprecated
public DiskFileUpload(DefaultFileItemFactory fileItemFactory) { public DiskFileUpload(DefaultFileItemFactory fileItemFactory) {
super(); super();
this.fileItemFactory = fileItemFactory; this.fileItemFactory = fileItemFactory;
} }
// ----------------------------------------------------- Property accessors // ----------------------------------------------------- Property accessors
/** /**
* Returns the factory class used when creating file items. * Returns the factory class used when creating file items.
* *
* @return The factory class for new file items. * @return The factory class for new file items.
* *
* @deprecated Use <code>FileUpload</code> instead. * @deprecated 1.1 Use <code>FileUpload</code> instead.
*/ */
@Override
@Deprecated
public FileItemFactory getFileItemFactory() { public FileItemFactory getFileItemFactory() {
return fileItemFactory; return fileItemFactory;
} }
/** /**
* Sets the factory class to use when creating file items. The factory must * Sets the factory class to use when creating file items. The factory must
* be an instance of <code>DefaultFileItemFactory</code> or a subclass * be an instance of <code>DefaultFileItemFactory</code> or a subclass
@ -112,13 +103,14 @@ public class DiskFileUpload
* *
* @param factory The factory class for new file items. * @param factory The factory class for new file items.
* *
* @deprecated Use <code>FileUpload</code> instead. * @deprecated 1.1 Use <code>FileUpload</code> instead.
*/ */
@Override
@Deprecated
public void setFileItemFactory(FileItemFactory factory) { public void setFileItemFactory(FileItemFactory factory) {
this.fileItemFactory = (DefaultFileItemFactory) factory; this.fileItemFactory = (DefaultFileItemFactory) factory;
} }
/** /**
* Returns the size threshold beyond which files are written directly to * Returns the size threshold beyond which files are written directly to
* disk. * disk.
@ -127,13 +119,13 @@ public class DiskFileUpload
* *
* @see #setSizeThreshold(int) * @see #setSizeThreshold(int)
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public int getSizeThreshold() { public int getSizeThreshold() {
return fileItemFactory.getSizeThreshold(); return fileItemFactory.getSizeThreshold();
} }
/** /**
* Sets the size threshold beyond which files are written directly to disk. * Sets the size threshold beyond which files are written directly to disk.
* *
@ -141,13 +133,13 @@ public class DiskFileUpload
* *
* @see #getSizeThreshold() * @see #getSizeThreshold()
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public void setSizeThreshold(int sizeThreshold) { public void setSizeThreshold(int sizeThreshold) {
fileItemFactory.setSizeThreshold(sizeThreshold); fileItemFactory.setSizeThreshold(sizeThreshold);
} }
/** /**
* Returns the location used to temporarily store files that are larger * Returns the location used to temporarily store files that are larger
* than the configured size threshold. * than the configured size threshold.
@ -156,13 +148,13 @@ public class DiskFileUpload
* *
* @see #setRepositoryPath(String) * @see #setRepositoryPath(String)
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public String getRepositoryPath() { public String getRepositoryPath() {
return fileItemFactory.getRepository().getPath(); return fileItemFactory.getRepository().getPath();
} }
/** /**
* Sets the location used to temporarily store files that are larger * Sets the location used to temporarily store files that are larger
* than the configured size threshold. * than the configured size threshold.
@ -171,16 +163,15 @@ public class DiskFileUpload
* *
* @see #getRepositoryPath() * @see #getRepositoryPath()
* *
* @deprecated Use <code>DiskFileItemFactory</code> instead. * @deprecated 1.1 Use <code>DiskFileItemFactory</code> instead.
*/ */
@Deprecated
public void setRepositoryPath(String repositoryPath) { public void setRepositoryPath(String repositoryPath) {
fileItemFactory.setRepository(new File(repositoryPath)); fileItemFactory.setRepository(new File(repositoryPath));
} }
// --------------------------------------------------------- Public methods // --------------------------------------------------------- Public methods
/** /**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
* compliant <code>multipart/form-data</code> stream. If files are stored * compliant <code>multipart/form-data</code> stream. If files are stored
@ -197,9 +188,10 @@ public class DiskFileUpload
* @throws FileUploadException if there are problems reading/parsing * @throws FileUploadException if there are problems reading/parsing
* the request or storing files. * the request or storing files.
* *
* @deprecated Use <code>ServletFileUpload</code> instead. * @deprecated 1.1 Use <code>ServletFileUpload</code> instead.
*/ */
public List /* FileItem */ parseRequest(HttpServletRequest req, @Deprecated
public List<FileItem> parseRequest(HttpServletRequest req,
int sizeThreshold, int sizeThreshold,
long sizeMax, String path) long sizeMax, String path)
throws FileUploadException { throws FileUploadException {

42
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItem.java

@ -16,6 +16,8 @@
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -28,8 +30,8 @@ import java.io.UnsupportedEncodingException;
* <code>multipart/form-data</code> POST request. * <code>multipart/form-data</code> POST request.
* *
* <p> After retrieving an instance of this class from a {@link * <p> After retrieving an instance of this class from a {@link
* com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload} instance (see * FileUpload FileUpload} instance (see
* {@link com.fr.third.org.apache.commons.fileupload.FileUpload * {@link ServletFileUpload
* #parseRequest(javax.servlet.http.HttpServletRequest)}), you may * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may
* either request all contents of the file at once using {@link #get()} or * either request all contents of the file at once using {@link #get()} or
* request an {@link java.io.InputStream InputStream} with * request an {@link java.io.InputStream InputStream} with
@ -43,20 +45,13 @@ import java.io.UnsupportedEncodingException;
* implementation of this interface to also implement * implementation of this interface to also implement
* <code>javax.activation.DataSource</code> with minimal additional work. * <code>javax.activation.DataSource</code> with minimal additional work.
* *
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:sean@informage.net">Sean Legassick</a>
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
*
* @version $Id$ * @version $Id$
* @since 1.3 additionally implements FileItemHeadersSupport
*/ */
public interface FileItem public interface FileItem extends Serializable, FileItemHeadersSupport {
extends Serializable {
// ------------------------------- Methods from javax.activation.DataSource // ------------------------------- Methods from javax.activation.DataSource
/** /**
* Returns an {@link java.io.InputStream InputStream} that can be * Returns an {@link java.io.InputStream InputStream} that can be
* used to retrieve the contents of the file. * used to retrieve the contents of the file.
@ -66,9 +61,7 @@ public interface FileItem
* *
* @throws IOException if an error occurs. * @throws IOException if an error occurs.
*/ */
InputStream getInputStream() InputStream getInputStream() throws IOException;
throws IOException;
/** /**
* Returns the content type passed by the browser or <code>null</code> if * Returns the content type passed by the browser or <code>null</code> if
@ -79,7 +72,6 @@ public interface FileItem
*/ */
String getContentType(); String getContentType();
/** /**
* Returns the original filename in the client's filesystem, as provided by * Returns the original filename in the client's filesystem, as provided by
* the browser (or other client software). In most cases, this will be the * the browser (or other client software). In most cases, this will be the
@ -87,13 +79,15 @@ public interface FileItem
* the Opera browser, do include path information. * the Opera browser, do include path information.
* *
* @return The original filename in the client's filesystem. * @return The original filename in the client's filesystem.
* @throws InvalidFileNameException The file name contains a NUL character,
* which might be an indicator of a security attack. If you intend to
* use the file name anyways, catch the exception and use
* InvalidFileNameException#getName().
*/ */
String getName(); String getName();
// ------------------------------------------------------- FileItem methods // ------------------------------------------------------- FileItem methods
/** /**
* Provides a hint as to whether or not the file contents will be read * Provides a hint as to whether or not the file contents will be read
* from memory. * from memory.
@ -103,7 +97,6 @@ public interface FileItem
*/ */
boolean isInMemory(); boolean isInMemory();
/** /**
* Returns the size of the file item. * Returns the size of the file item.
* *
@ -111,7 +104,6 @@ public interface FileItem
*/ */
long getSize(); long getSize();
/** /**
* Returns the contents of the file item as an array of bytes. * Returns the contents of the file item as an array of bytes.
* *
@ -119,7 +111,6 @@ public interface FileItem
*/ */
byte[] get(); byte[] get();
/** /**
* Returns the contents of the file item as a String, using the specified * Returns the contents of the file item as a String, using the specified
* encoding. This method uses {@link #get()} to retrieve the * encoding. This method uses {@link #get()} to retrieve the
@ -132,9 +123,7 @@ public interface FileItem
* @throws UnsupportedEncodingException if the requested character * @throws UnsupportedEncodingException if the requested character
* encoding is not available. * encoding is not available.
*/ */
String getString(String encoding) String getString(String encoding) throws UnsupportedEncodingException;
throws UnsupportedEncodingException;
/** /**
* Returns the contents of the file item as a String, using the default * Returns the contents of the file item as a String, using the default
@ -145,7 +134,6 @@ public interface FileItem
*/ */
String getString(); String getString();
/** /**
* A convenience method to write an uploaded item to disk. The client code * A convenience method to write an uploaded item to disk. The client code
* is not concerned with whether or not the item is stored in memory, or on * is not concerned with whether or not the item is stored in memory, or on
@ -164,7 +152,6 @@ public interface FileItem
*/ */
void write(File file) throws Exception; void write(File file) throws Exception;
/** /**
* Deletes the underlying storage for a file item, including deleting any * Deletes the underlying storage for a file item, including deleting any
* associated temporary disk file. Although this storage will be deleted * associated temporary disk file. Although this storage will be deleted
@ -174,7 +161,6 @@ public interface FileItem
*/ */
void delete(); void delete();
/** /**
* Returns the name of the field in the multipart form corresponding to * Returns the name of the field in the multipart form corresponding to
* this file item. * this file item.
@ -183,7 +169,6 @@ public interface FileItem
*/ */
String getFieldName(); String getFieldName();
/** /**
* Sets the field name used to reference this file item. * Sets the field name used to reference this file item.
* *
@ -191,7 +176,6 @@ public interface FileItem
*/ */
void setFieldName(String name); void setFieldName(String name);
/** /**
* Determines whether or not a <code>FileItem</code> instance represents * Determines whether or not a <code>FileItem</code> instance represents
* a simple form field. * a simple form field.
@ -201,7 +185,6 @@ public interface FileItem
*/ */
boolean isFormField(); boolean isFormField();
/** /**
* Specifies whether or not a <code>FileItem</code> instance represents * Specifies whether or not a <code>FileItem</code> instance represents
* a simple form field. * a simple form field.
@ -211,7 +194,6 @@ public interface FileItem
*/ */
void setFormField(boolean state); void setFormField(boolean state);
/** /**
* Returns an {@link java.io.OutputStream OutputStream} that can * Returns an {@link java.io.OutputStream OutputStream} that can
* be used for storing the contents of the file. * be used for storing the contents of the file.

4
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemFactory.java

@ -16,14 +16,11 @@
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
/** /**
* <p>A factory interface for creating {@link FileItem} instances. Factories * <p>A factory interface for creating {@link FileItem} instances. Factories
* can provide their own custom configuration, over and above that provided * can provide their own custom configuration, over and above that provided
* by the default file upload implementation.</p> * by the default file upload implementation.</p>
* *
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
*
* @version $Id$ * @version $Id$
*/ */
public interface FileItemFactory { public interface FileItemFactory {
@ -47,4 +44,5 @@ public interface FileItemFactory {
boolean isFormField, boolean isFormField,
String fileName String fileName
); );
} }

76
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeaders.java

@ -0,0 +1,76 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload;
import java.util.Iterator;
/**
* <p> This class provides support for accessing the headers for a file or form
* item that was received within a <code>multipart/form-data</code> POST
* request.</p>
*
* @since 1.2.1
*
* @version $Id$
*/
public interface FileItemHeaders {
/**
* Returns the value of the specified part header as a <code>String</code>.
*
* If the part did not include a header of the specified name, this method
* return <code>null</code>. If there are multiple headers with the same
* name, this method returns the first header in the item. The header
* name is case insensitive.
*
* @param name a <code>String</code> specifying the header name
* @return a <code>String</code> containing the value of the requested
* header, or <code>null</code> if the item does not have a header
* of that name
*/
String getHeader(String name);
/**
* <p>
* Returns all the values of the specified item header as an
* <code>Iterator</code> of <code>String</code> objects.
* </p>
* <p>
* If the item did not include any headers of the specified name, this
* method returns an empty <code>Iterator</code>. The header name is
* case insensitive.
* </p>
*
* @param name a <code>String</code> specifying the header name
* @return an <code>Iterator</code> containing the values of the
* requested header. If the item does not have any headers of
* that name, return an empty <code>Iterator</code>
*/
Iterator<String> getHeaders(String name);
/**
* <p>
* Returns an <code>Iterator</code> of all the header names.
* </p>
*
* @return an <code>Iterator</code> containing all of the names of
* headers provided with this file item. If the item does not have
* any headers return an empty <code>Iterator</code>
*/
Iterator<String> getHeaderNames();
}

50
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeadersSupport.java

@ -0,0 +1,50 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload;
/**
* Interface that will indicate that {@link FileItem} or {@link FileItemStream}
* implementations will accept the headers read for the item.
*
* @since 1.2.1
*
* @see FileItem
* @see FileItemStream
*
* @version $Id$
*/
public interface FileItemHeadersSupport {
/**
* Returns the collection of headers defined locally within this item.
*
* @return the {@link FileItemHeaders} present for this item.
*/
FileItemHeaders getHeaders();
/**
* Sets the headers read from within an item. Implementations of
* {@link FileItem} or {@link FileItemStream} should implement this
* interface to be able to get the raw headers found within the item
* header block.
*
* @param headers the instance that holds onto the headers
* for this instance.
*/
void setHeaders(FileItemHeaders headers);
}

8
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemIterator.java

@ -15,17 +15,21 @@
* limitations under the License. * limitations under the License.
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
import java.io.IOException;
import java.io.IOException;
/** /**
* An iterator, as returned by * An iterator, as returned by
* {@link FileUploadBase#getItemIterator(RequestContext)}. * {@link FileUploadBase#getItemIterator(RequestContext)}.
*
* @version $Id$
*/ */
public interface FileItemIterator { public interface FileItemIterator {
/** /**
* Returns, whether another instance of {@link FileItemStream} * Returns, whether another instance of {@link FileItemStream}
* is available. * is available.
*
* @throws FileUploadException Parsing or processing the * @throws FileUploadException Parsing or processing the
* file item failed. * file item failed.
* @throws IOException Reading the file item failed. * @throws IOException Reading the file item failed.
@ -36,6 +40,7 @@ public interface FileItemIterator {
/** /**
* Returns the next available {@link FileItemStream}. * Returns the next available {@link FileItemStream}.
*
* @throws java.util.NoSuchElementException No more items are available. Use * @throws java.util.NoSuchElementException No more items are available. Use
* {@link #hasNext()} to prevent this exception. * {@link #hasNext()} to prevent this exception.
* @throws FileUploadException Parsing or processing the * @throws FileUploadException Parsing or processing the
@ -45,4 +50,5 @@ public interface FileItemIterator {
* access to the next file item. * access to the next file item.
*/ */
FileItemStream next() throws FileUploadException, IOException; FileItemStream next() throws FileUploadException, IOException;
} }

13
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemStream.java

@ -19,7 +19,6 @@ package com.fr.third.org.apache.commons.fileupload;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
/** /**
* <p> This interface provides access to a file or form item that was * <p> This interface provides access to a file or form item that was
* received within a <code>multipart/form-data</code> POST request. * received within a <code>multipart/form-data</code> POST request.
@ -31,8 +30,11 @@ import java.io.InputStream;
* its associated instances of {@link FileItemStream}: By invoking * its associated instances of {@link FileItemStream}: By invoking
* {@link java.util.Iterator#hasNext()} on the iterator, you discard all data, * {@link java.util.Iterator#hasNext()} on the iterator, you discard all data,
* which hasn't been read so far from the previous data.</p> * which hasn't been read so far from the previous data.</p>
*
* @version $Id$
*/ */
public interface FileItemStream { public interface FileItemStream extends FileItemHeadersSupport {
/** /**
* This exception is thrown, if an attempt is made to read * This exception is thrown, if an attempt is made to read
* data from the {@link InputStream}, which has been returned * data from the {@link InputStream}, which has been returned
@ -41,15 +43,19 @@ public interface FileItemStream {
* iterator, which created the {@link FileItemStream}. * iterator, which created the {@link FileItemStream}.
*/ */
public static class ItemSkippedException extends IOException { public static class ItemSkippedException extends IOException {
/** /**
* The exceptions serial version UID, which is being used * The exceptions serial version UID, which is being used
* when serializing an exception instance. * when serializing an exception instance.
*/ */
private static final long serialVersionUID = -7280778431581963740L; private static final long serialVersionUID = -7280778431581963740L;
} }
/** Creates an {@link InputStream}, which allows to read the /**
* Creates an {@link InputStream}, which allows to read the
* items contents. * items contents.
*
* @return The input stream, from which the items data may * @return The input stream, from which the items data may
* be read. * be read.
* @throws IllegalStateException The method was already invoked on * @throws IllegalStateException The method was already invoked on
@ -94,4 +100,5 @@ public interface FileItemStream {
* field; <code>false</code> if it represents an uploaded file. * field; <code>false</code> if it represents an uploaded file.
*/ */
boolean isFormField(); boolean isFormField();
} }

26
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUpload.java

@ -16,28 +16,20 @@
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
/** /**
* <p>High level API for processing file uploads.</p> * <p>High level API for processing file uploads.</p>
* *
* <p>This class handles multiple files per single HTML widget, sent using * <p>This class handles multiple files per single HTML widget, sent using
* <code>multipart/mixed</code> encoding type, as specified by * <code>multipart/mixed</code> encoding type, as specified by
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
* #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list * #parseRequest(RequestContext)} to acquire a list
* of {@link com.fr.third.org.apache.commons.fileupload.FileItem FileItems} associated * of {@link FileItem FileItems} associated
* with a given HTML widget.</p> * with a given HTML widget.</p>
* *
* <p>How the data for individual parts is stored is determined by the factory * <p>How the data for individual parts is stored is determined by the factory
* used to create them; a given part may be in memory, on disk, or somewhere * used to create them; a given part may be in memory, on disk, or somewhere
* else.</p> * else.</p>
* *
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:jmcnally@collab.net">John McNally</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* @author Sean C. Sullivan
*
* @version $Id$ * @version $Id$
*/ */
public class FileUpload public class FileUpload
@ -45,18 +37,17 @@ public class FileUpload
// ----------------------------------------------------------- Data members // ----------------------------------------------------------- Data members
/** /**
* The factory to use to create new form items. * The factory to use to create new form items.
*/ */
private FileItemFactory fileItemFactory; private FileItemFactory fileItemFactory;
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/** /**
* Constructs an uninitialised instance of this class. A factory must be * Constructs an uninitialised instance of this class.
*
* A factory must be
* configured, using <code>setFileItemFactory()</code>, before attempting * configured, using <code>setFileItemFactory()</code>, before attempting
* to parse requests. * to parse requests.
* *
@ -66,7 +57,6 @@ public class FileUpload
super(); super();
} }
/** /**
* Constructs an instance of this class which uses the supplied factory to * Constructs an instance of this class which uses the supplied factory to
* create <code>FileItem</code> instances. * create <code>FileItem</code> instances.
@ -79,28 +69,26 @@ public class FileUpload
this.fileItemFactory = fileItemFactory; this.fileItemFactory = fileItemFactory;
} }
// ----------------------------------------------------- Property accessors // ----------------------------------------------------- Property accessors
/** /**
* Returns the factory class used when creating file items. * Returns the factory class used when creating file items.
* *
* @return The factory class for new file items. * @return The factory class for new file items.
*/ */
@Override
public FileItemFactory getFileItemFactory() { public FileItemFactory getFileItemFactory() {
return fileItemFactory; return fileItemFactory;
} }
/** /**
* Sets the factory class to use when creating file items. * Sets the factory class to use when creating file items.
* *
* @param factory The factory class for new file items. * @param factory The factory class for new file items.
*/ */
@Override
public void setFileItemFactory(FileItemFactory factory) { public void setFileItemFactory(FileItemFactory factory) {
this.fileItemFactory = factory; this.fileItemFactory = factory;
} }
} }

637
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadBase.java

File diff suppressed because it is too large Load Diff

16
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadException.java

@ -19,19 +19,19 @@ package com.fr.third.org.apache.commons.fileupload;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
/** /**
* Exception for errors encountered while processing the request. * Exception for errors encountered while processing the request.
* *
* @author <a href="mailto:jmcnally@collab.net">John McNally</a>
* @version $Id$ * @version $Id$
*/ */
public class FileUploadException extends Exception { public class FileUploadException extends Exception {
/** /**
* Serial version UID, being used, if the exception * Serial version UID, being used, if the exception
* is serialized. * is serialized.
*/ */
private static final long serialVersionUID = 8881893724388807504L; private static final long serialVersionUID = 8881893724388807504L;
/** /**
* The exceptions cause. We overwrite the cause of * The exceptions cause. We overwrite the cause of
* the super class, which isn't available in Java 1.3. * the super class, which isn't available in Java 1.3.
@ -58,6 +58,7 @@ public class FileUploadException extends Exception {
/** /**
* Creates a new <code>FileUploadException</code> with the given * Creates a new <code>FileUploadException</code> with the given
* detail message and cause. * detail message and cause.
*
* @param msg The exceptions detail message. * @param msg The exceptions detail message.
* @param cause The exceptions cause. * @param cause The exceptions cause.
*/ */
@ -71,6 +72,7 @@ public class FileUploadException extends Exception {
* *
* @param stream <code>PrintStream</code> to use for output * @param stream <code>PrintStream</code> to use for output
*/ */
@Override
public void printStackTrace(PrintStream stream) { public void printStackTrace(PrintStream stream) {
super.printStackTrace(stream); super.printStackTrace(stream);
if (cause != null) { if (cause != null) {
@ -85,6 +87,7 @@ public class FileUploadException extends Exception {
* *
* @param writer <code>PrintWriter</code> to use for output * @param writer <code>PrintWriter</code> to use for output
*/ */
@Override
public void printStackTrace(PrintWriter writer) { public void printStackTrace(PrintWriter writer) {
super.printStackTrace(writer); super.printStackTrace(writer);
if (cause != null) { if (cause != null) {
@ -92,4 +95,13 @@ public class FileUploadException extends Exception {
cause.printStackTrace(writer); cause.printStackTrace(writer);
} }
} }
/**
* {@inheritDoc}
*/
@Override
public Throwable getCause() {
return cause;
}
} }

64
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/InvalidFileNameException.java

@ -0,0 +1,64 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload;
/**
* This exception is thrown in case of an invalid file name.
* A file name is invalid, if it contains a NUL character.
* Attackers might use this to circumvent security checks:
* For example, a malicious user might upload a file with the name
* "foo.exe\0.png". This file name might pass security checks (i.e.
* checks for the extension ".png"), while, depending on the underlying
* C library, it might create a file named "foo.exe", as the NUL
* character is the string terminator in C.
*
* @version $Id$
*/
public class InvalidFileNameException extends RuntimeException {
/**
* Serial version UID, being used, if the exception
* is serialized.
*/
private static final long serialVersionUID = 7922042602454350470L;
/**
* The file name causing the exception.
*/
private final String name;
/**
* Creates a new instance.
*
* @param pName The file name causing the exception.
* @param pMessage A human readable error message.
*/
public InvalidFileNameException(String pName, String pMessage) {
super(pMessage);
name = pName;
}
/**
* Returns the invalid file name.
*
* @return the invalid file name.
*/
public String getName() {
return name;
}
}

429
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/MultipartStream.java

@ -16,12 +16,15 @@
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
import static java.lang.String.format;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import com.fr.third.org.apache.commons.fileupload.FileUploadBase.FileUploadIOException;
import com.fr.third.org.apache.commons.fileupload.util.Closeable; import com.fr.third.org.apache.commons.fileupload.util.Closeable;
import com.fr.third.org.apache.commons.fileupload.util.Streams; import com.fr.third.org.apache.commons.fileupload.util.Streams;
@ -40,14 +43,14 @@ import com.fr.third.org.apache.commons.fileupload.util.Streams;
* multipart-body := preamble 1*encapsulation close-delimiter epilogue<br> * multipart-body := preamble 1*encapsulation close-delimiter epilogue<br>
* encapsulation := delimiter body CRLF<br> * encapsulation := delimiter body CRLF<br>
* delimiter := "--" boundary CRLF<br> * delimiter := "--" boundary CRLF<br>
* close-delimiter := "--" boudary "--"<br> * close-delimiter := "--" boundary "--"<br>
* preamble := &lt;ignore&gt;<br> * preamble := &lt;ignore&gt;<br>
* epilogue := &lt;ignore&gt;<br> * epilogue := &lt;ignore&gt;<br>
* body := header-part CRLF body-part<br> * body := header-part CRLF body-part<br>
* header-part := 1*header CRLF<br> * header-part := 1*header CRLF<br>
* header := header-name ":" header-value<br> * header := header-name ":" header-value<br>
* header-name := &lt;printable ascii characters except ":"&gt;<br> * header-name := &lt;printable ascii characters except ":"&gt;<br>
* header-value := &lt;any ascii characters except CR & LF&gt;<br> * header-value := &lt;any ascii characters except CR &amp; LF&gt;<br>
* body-data := &lt;arbitrary data&gt;<br> * body-data := &lt;arbitrary data&gt;<br>
* </code> * </code>
* *
@ -60,52 +63,58 @@ import com.fr.third.org.apache.commons.fileupload.util.Streams;
* <p>Here is an example of usage of this class.<br> * <p>Here is an example of usage of this class.<br>
* *
* <pre> * <pre>
* try { * try {
* MultipartStream multipartStream = new MultipartStream(input, * MultipartStream multipartStream = new MultipartStream(input, boundary);
* boundary); * boolean nextPart = multipartStream.skipPreamble();
* boolean nextPart = multipartStream.skipPreamble(); * OutputStream output;
* OutputStream output; * while(nextPart) {
* while(nextPart) { * String header = multipartStream.readHeaders();
* header = chunks.readHeader(); * // process headers
* // process headers * // create some output stream
* // create some output stream * multipartStream.readBodyData(output);
* multipartStream.readBodyPart(output); * nextPart = multipartStream.readBoundary();
* nextPart = multipartStream.readBoundary(); * }
* } * } catch(MultipartStream.MalformedStreamException e) {
* } catch(MultipartStream.MalformedStreamException e) { * // the stream failed to follow required syntax
* // the stream failed to follow required syntax * } catch(IOException e) {
* } catch(IOException) { * // a read or write error occurred
* // a read or write error occurred * }
* }
*
* </pre> * </pre>
* *
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* @author Sean C. Sullivan
*
* @version $Id$ * @version $Id$
*/ */
public class MultipartStream { public class MultipartStream {
/** /**
* Internal class, which is used to invoke the * Internal class, which is used to invoke the
* {@link ProgressListener}. * {@link ProgressListener}.
*/ */
static class ProgressNotifier { public static class ProgressNotifier {
/** The listener to invoke.
/**
* The listener to invoke.
*/ */
private final ProgressListener listener; private final ProgressListener listener;
/** Number of expected bytes, if known, or -1.
/**
* Number of expected bytes, if known, or -1.
*/ */
private final long contentLength; private final long contentLength;
/** Number of bytes, which have been read so far.
/**
* Number of bytes, which have been read so far.
*/ */
private long bytesRead; private long bytesRead;
/** Number of items, which have been read so far.
/**
* Number of items, which have been read so far.
*/ */
private int items; private int items;
/** Creates a new instance with the given listener
/**
* Creates a new instance with the given listener
* and content length. * and content length.
*
* @param pListener The listener to invoke. * @param pListener The listener to invoke.
* @param pContentLength The expected content length. * @param pContentLength The expected content length.
*/ */
@ -113,7 +122,10 @@ public class MultipartStream {
listener = pListener; listener = pListener;
contentLength = pContentLength; contentLength = pContentLength;
} }
/** Called to indicate that bytes have been read.
/**
* Called to indicate that bytes have been read.
*
* @param pBytes Number of bytes, which have been read. * @param pBytes Number of bytes, which have been read.
*/ */
void noteBytesRead(int pBytes) { void noteBytesRead(int pBytes) {
@ -123,132 +135,110 @@ public class MultipartStream {
bytesRead += pBytes; bytesRead += pBytes;
notifyListener(); notifyListener();
} }
/** Called to indicate, that a new file item has been detected.
/**
* Called to indicate, that a new file item has been detected.
*/ */
void noteItem() { void noteItem() {
++items; ++items;
notifyListener();
} }
/** Called for notifying the listener.
/**
* Called for notifying the listener.
*/ */
private void notifyListener() { private void notifyListener() {
if (listener != null) { if (listener != null) {
listener.update(bytesRead, contentLength, items); listener.update(bytesRead, contentLength, items);
} }
} }
} }
// ----------------------------------------------------- Manifest constants // ----------------------------------------------------- Manifest constants
/** /**
* The Carriage Return ASCII character value. * The Carriage Return ASCII character value.
*/ */
public static final byte CR = 0x0D; public static final byte CR = 0x0D;
/** /**
* The Line Feed ASCII character value. * The Line Feed ASCII character value.
*/ */
public static final byte LF = 0x0A; public static final byte LF = 0x0A;
/** /**
* The dash (-) ASCII character value. * The dash (-) ASCII character value.
*/ */
public static final byte DASH = 0x2D; public static final byte DASH = 0x2D;
/** /**
* The maximum length of <code>header-part</code> that will be * The maximum length of <code>header-part</code> that will be
* processed (10 kilobytes = 10240 bytes.). * processed (10 kilobytes = 10240 bytes.).
*/ */
public static final int HEADER_PART_SIZE_MAX = 10240; public static final int HEADER_PART_SIZE_MAX = 10240;
/** /**
* The default length of the buffer used for processing a request. * The default length of the buffer used for processing a request.
*/ */
protected static final int DEFAULT_BUFSIZE = 4096; protected static final int DEFAULT_BUFSIZE = 4096;
/** /**
* A byte sequence that marks the end of <code>header-part</code> * A byte sequence that marks the end of <code>header-part</code>
* (<code>CRLFCRLF</code>). * (<code>CRLFCRLF</code>).
*/ */
protected static final byte[] HEADER_SEPARATOR = { protected static final byte[] HEADER_SEPARATOR = {CR, LF, CR, LF};
CR, LF, CR, LF };
/** /**
* A byte sequence that that follows a delimiter that will be * A byte sequence that that follows a delimiter that will be
* followed by an encapsulation (<code>CRLF</code>). * followed by an encapsulation (<code>CRLF</code>).
*/ */
protected static final byte[] FIELD_SEPARATOR = { protected static final byte[] FIELD_SEPARATOR = {CR, LF};
CR, LF};
/** /**
* A byte sequence that that follows a delimiter of the last * A byte sequence that that follows a delimiter of the last
* encapsulation in the stream (<code>--</code>). * encapsulation in the stream (<code>--</code>).
*/ */
protected static final byte[] STREAM_TERMINATOR = { protected static final byte[] STREAM_TERMINATOR = {DASH, DASH};
DASH, DASH};
/** /**
* A byte sequence that precedes a boundary (<code>CRLF--</code>). * A byte sequence that precedes a boundary (<code>CRLF--</code>).
*/ */
protected static final byte[] BOUNDARY_PREFIX = { protected static final byte[] BOUNDARY_PREFIX = {CR, LF, DASH, DASH};
CR, LF, DASH, DASH};
/**
* The number of bytes, over and above the boundary size, to use for the
* keep region.
*/
private static final int KEEP_REGION_PAD = 3;
// ----------------------------------------------------------- Data members // ----------------------------------------------------------- Data members
/** /**
* The input stream from which data is read. * The input stream from which data is read.
*/ */
private final InputStream input; private final InputStream input;
/** /**
* The length of the boundary token plus the leading <code>CRLF--</code>. * The length of the boundary token plus the leading <code>CRLF--</code>.
*/ */
private int boundaryLength; private int boundaryLength;
/** /**
* The amount of data, in bytes, that must be kept in the buffer in order * The amount of data, in bytes, that must be kept in the buffer in order
* to detect delimiters reliably. * to detect delimiters reliably.
*/ */
private int keepRegion; private int keepRegion;
/** /**
* The byte sequence that partitions the stream. * The byte sequence that partitions the stream.
*/ */
private byte[] boundary; private byte[] boundary;
/** /**
* The length of the buffer used for processing the request. * The length of the buffer used for processing the request.
*/ */
private final int bufSize; private final int bufSize;
/** /**
* The buffer used for processing the request. * The buffer used for processing the request.
*/ */
private final byte[] buffer; private final byte[] buffer;
/** /**
* The index of first valid character in the buffer. * The index of first valid character in the buffer.
* <br> * <br>
@ -256,21 +246,18 @@ public class MultipartStream {
*/ */
private int head; private int head;
/** /**
* The index of last valid characer in the buffer + 1. * The index of last valid character in the buffer + 1.
* <br> * <br>
* 0 <= tail <= bufSize * 0 <= tail <= bufSize
*/ */
private int tail; private int tail;
/** /**
* The content encoding to use when reading headers. * The content encoding to use when reading headers.
*/ */
private String headerEncoding; private String headerEncoding;
/** /**
* The progress notifier, if any, or null. * The progress notifier, if any, or null.
*/ */
@ -280,11 +267,11 @@ public class MultipartStream {
/** /**
* Creates a new instance. * Creates a new instance.
* @deprecated Use {@link #MultipartStream(InputStream, byte[], *
* com.fr.third.org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}, * @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[], int,
* or {@link #MultipartStream(InputStream, byte[], int, * ProgressNotifier)}
* com.fr.third.org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}
*/ */
@Deprecated
public MultipartStream() { public MultipartStream() {
this(null, null, null); this(null, null, null);
} }
@ -303,10 +290,10 @@ public class MultipartStream {
* <code>encapsulations</code>. * <code>encapsulations</code>.
* @param bufSize The size of the buffer to be used, in bytes. * @param bufSize The size of the buffer to be used, in bytes.
* *
* @see #MultipartStream(InputStream, byte[], ProgressNotifier) * @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[], int,
* @deprecated Use {@link #MultipartStream(InputStream, byte[], int, * ProgressNotifier)}.
* com.fr.third.org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}.
*/ */
@Deprecated
public MultipartStream(InputStream input, byte[] boundary, int bufSize) { public MultipartStream(InputStream input, byte[] boundary, int bufSize) {
this(input, boundary, bufSize, null); this(input, boundary, bufSize, null);
} }
@ -326,22 +313,34 @@ public class MultipartStream {
* @param pNotifier The notifier, which is used for calling the * @param pNotifier The notifier, which is used for calling the
* progress listener, if any. * progress listener, if any.
* *
* @see #MultipartStream(InputStream, byte[], ProgressNotifier) * @throws IllegalArgumentException If the buffer size is too small
*
* @since 1.3.1
*/ */
MultipartStream(InputStream input, public MultipartStream(InputStream input,
byte[] boundary, byte[] boundary,
int bufSize, int bufSize,
ProgressNotifier pNotifier) { ProgressNotifier pNotifier) {
this.input = input;
this.bufSize = bufSize;
this.buffer = new byte[bufSize];
this.notifier = pNotifier;
// We prepend CR/LF to the boundary to chop trailng CR/LF from if (boundary == null) {
throw new IllegalArgumentException("boundary may not be null");
}
// We prepend CR/LF to the boundary to chop trailing CR/LF from
// body-data tokens. // body-data tokens.
this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length];
this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length; this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;
this.keepRegion = boundary.length + KEEP_REGION_PAD; if (bufSize < this.boundaryLength + 1) {
throw new IllegalArgumentException(
"The buffer size specified for the MultipartStream is too small");
}
this.input = input;
this.bufSize = Math.max(bufSize, boundaryLength * 2);
this.buffer = new byte[this.bufSize];
this.notifier = pNotifier;
this.boundary = new byte[this.boundaryLength];
this.keepRegion = this.boundary.length;
System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0,
BOUNDARY_PREFIX.length); BOUNDARY_PREFIX.length);
System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length,
@ -351,7 +350,6 @@ public class MultipartStream {
tail = 0; tail = 0;
} }
/** /**
* <p> Constructs a <code>MultipartStream</code> with a default size buffer. * <p> Constructs a <code>MultipartStream</code> with a default size buffer.
* *
@ -376,10 +374,10 @@ public class MultipartStream {
* @param boundary The token used for dividing the stream into * @param boundary The token used for dividing the stream into
* <code>encapsulations</code>. * <code>encapsulations</code>.
* *
* @deprecated Use {@link #MultipartStream(InputStream, byte[], * @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[], int,
* ProgressNotifier)}. * ProgressNotifier)}.
* @see #MultipartStream(InputStream, byte[], int, ProgressNotifier)
*/ */
@Deprecated
public MultipartStream(InputStream input, public MultipartStream(InputStream input,
byte[] boundary) { byte[] boundary) {
this(input, boundary, DEFAULT_BUFSIZE, null); this(input, boundary, DEFAULT_BUFSIZE, null);
@ -387,12 +385,10 @@ public class MultipartStream {
// --------------------------------------------------------- Public methods // --------------------------------------------------------- Public methods
/** /**
* Retrieves the character encoding used when reading the headers of an * Retrieves the character encoding used when reading the headers of an
* individual part. When not specified, or <code>null</code>, the platform * individual part. When not specified, or <code>null</code>, the platform
* default encoding is used. * default encoding is used.
* *
* @return The encoding used to read part headers. * @return The encoding used to read part headers.
*/ */
@ -400,7 +396,6 @@ public class MultipartStream {
return headerEncoding; return headerEncoding;
} }
/** /**
* Specifies the character encoding to be used when reading the headers of * Specifies the character encoding to be used when reading the headers of
* individual parts. When not specified, or <code>null</code>, the platform * individual parts. When not specified, or <code>null</code>, the platform
@ -412,7 +407,6 @@ public class MultipartStream {
headerEncoding = encoding; headerEncoding = encoding;
} }
/** /**
* Reads a byte from the <code>buffer</code>, and refills it as * Reads a byte from the <code>buffer</code>, and refills it as
* necessary. * necessary.
@ -421,8 +415,7 @@ public class MultipartStream {
* *
* @throws IOException if there is no more data available. * @throws IOException if there is no more data available.
*/ */
public byte readByte() public byte readByte() throws IOException {
throws IOException {
// Buffer depleted ? // Buffer depleted ?
if (head == tail) { if (head == tail) {
head = 0; head = 0;
@ -432,12 +425,13 @@ public class MultipartStream {
// No more data available. // No more data available.
throw new IOException("No more data is available"); throw new IOException("No more data is available");
} }
notifier.noteBytesRead(tail); if (notifier != null) {
notifier.noteBytesRead(tail);
}
} }
return buffer[head++]; return buffer[head++];
} }
/** /**
* Skips a <code>boundary</code> token, and checks whether more * Skips a <code>boundary</code> token, and checks whether more
* <code>encapsulations</code> are contained in the stream. * <code>encapsulations</code> are contained in the stream.
@ -445,11 +439,12 @@ public class MultipartStream {
* @return <code>true</code> if there are more encapsulations in * @return <code>true</code> if there are more encapsulations in
* this stream; <code>false</code> otherwise. * this stream; <code>false</code> otherwise.
* *
* @throws MalformedStreamException if the stream ends unexpecetedly or * @throws FileUploadIOException if the bytes read from the stream exceeded the size limits
* @throws MalformedStreamException if the stream ends unexpectedly or
* fails to follow required syntax. * fails to follow required syntax.
*/ */
public boolean readBoundary() public boolean readBoundary()
throws MalformedStreamException { throws FileUploadIOException, MalformedStreamException {
byte[] marker = new byte[2]; byte[] marker = new byte[2];
boolean nextChunk = false; boolean nextChunk = false;
@ -475,13 +470,15 @@ public class MultipartStream {
throw new MalformedStreamException( throw new MalformedStreamException(
"Unexpected characters follow a boundary"); "Unexpected characters follow a boundary");
} }
} catch (FileUploadIOException e) {
// wraps a SizeException, re-throw as it will be unwrapped later
throw e;
} catch (IOException e) { } catch (IOException e) {
throw new MalformedStreamException("Stream ended unexpectedly"); throw new MalformedStreamException("Stream ended unexpectedly");
} }
return nextChunk; return nextChunk;
} }
/** /**
* <p>Changes the boundary token used for partitioning the stream. * <p>Changes the boundary token used for partitioning the stream.
* *
@ -511,7 +508,6 @@ public class MultipartStream {
boundary.length); boundary.length);
} }
/** /**
* <p>Reads the <code>header-part</code> of the current * <p>Reads the <code>header-part</code> of the current
* <code>encapsulation</code>. * <code>encapsulation</code>.
@ -525,31 +521,35 @@ public class MultipartStream {
* *
* @return The <code>header-part</code> of the current encapsulation. * @return The <code>header-part</code> of the current encapsulation.
* *
* @throws MalformedStreamException if the stream ends unexpecetedly. * @throws FileUploadIOException if the bytes read from the stream exceeded the size limits.
* @throws MalformedStreamException if the stream ends unexpectedly.
*/ */
public String readHeaders() public String readHeaders() throws FileUploadIOException, MalformedStreamException {
throws MalformedStreamException {
int i = 0; int i = 0;
byte[] b = new byte[1]; byte b;
// to support multi-byte characters // to support multi-byte characters
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
int sizeMax = HEADER_PART_SIZE_MAX;
int size = 0; int size = 0;
while (i < HEADER_SEPARATOR.length) { while (i < HEADER_SEPARATOR.length) {
try { try {
b[0] = readByte(); b = readByte();
} catch (FileUploadIOException e) {
// wraps a SizeException, re-throw as it will be unwrapped later
throw e;
} catch (IOException e) { } catch (IOException e) {
throw new MalformedStreamException("Stream ended unexpectedly"); throw new MalformedStreamException("Stream ended unexpectedly");
} }
size++; if (++size > HEADER_PART_SIZE_MAX) {
if (b[0] == HEADER_SEPARATOR[i]) { throw new MalformedStreamException(
format("Header section has more than %s bytes (maybe it is not properly terminated)",
Integer.valueOf(HEADER_PART_SIZE_MAX)));
}
if (b == HEADER_SEPARATOR[i]) {
i++; i++;
} else { } else {
i = 0; i = 0;
} }
if (size <= sizeMax) { baos.write(b);
baos.write(b[0]);
}
} }
String headers = null; String headers = null;
@ -568,7 +568,6 @@ public class MultipartStream {
return headers; return headers;
} }
/** /**
* <p>Reads <code>body-data</code> from the current * <p>Reads <code>body-data</code> from the current
* <code>encapsulation</code> and writes its contents into the * <code>encapsulation</code> and writes its contents into the
@ -576,7 +575,8 @@ public class MultipartStream {
* *
* <p>Arbitrary large amounts of data can be processed by this * <p>Arbitrary large amounts of data can be processed by this
* method using a constant size buffer. (see {@link * method using a constant size buffer. (see {@link
* #MultipartStream(InputStream,byte[],int, ProgressNotifier) constructor}). * #MultipartStream(InputStream,byte[],int,
* MultipartStream.ProgressNotifier) constructor}).
* *
* @param output The <code>Stream</code> to write data into. May * @param output The <code>Stream</code> to write data into. May
* be null, in which case this method is equivalent * be null, in which case this method is equivalent
@ -613,13 +613,10 @@ public class MultipartStream {
* @throws MalformedStreamException if the stream ends unexpectedly. * @throws MalformedStreamException if the stream ends unexpectedly.
* @throws IOException if an i/o error occurs. * @throws IOException if an i/o error occurs.
*/ */
public int discardBodyData() public int discardBodyData() throws MalformedStreamException, IOException {
throws MalformedStreamException,
IOException {
return readBodyData(null); return readBodyData(null);
} }
/** /**
* Finds the beginning of the first <code>encapsulation</code>. * Finds the beginning of the first <code>encapsulation</code>.
* *
@ -628,8 +625,7 @@ public class MultipartStream {
* *
* @throws IOException if an i/o error occurs. * @throws IOException if an i/o error occurs.
*/ */
public boolean skipPreamble() public boolean skipPreamble() throws IOException {
throws IOException {
// First delimiter may be not preceeded with a CRLF. // First delimiter may be not preceeded with a CRLF.
System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2); System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2);
boundaryLength = boundary.length - 2; boundaryLength = boundary.length - 2;
@ -637,7 +633,7 @@ public class MultipartStream {
// Discard all data up to the delimiter. // Discard all data up to the delimiter.
discardBodyData(); discardBodyData();
// Read boundary - if succeded, the stream contains an // Read boundary - if succeeded, the stream contains an
// encapsulation. // encapsulation.
return readBoundary(); return readBoundary();
} catch (MalformedStreamException e) { } catch (MalformedStreamException e) {
@ -651,7 +647,6 @@ public class MultipartStream {
} }
} }
/** /**
* Compares <code>count</code> first bytes in the arrays * Compares <code>count</code> first bytes in the arrays
* <code>a</code> and <code>b</code>. * <code>a</code> and <code>b</code>.
@ -674,7 +669,6 @@ public class MultipartStream {
return true; return true;
} }
/** /**
* Searches for a byte of specified value in the <code>buffer</code>, * Searches for a byte of specified value in the <code>buffer</code>,
* starting at the specified <code>position</code>. * starting at the specified <code>position</code>.
@ -696,7 +690,6 @@ public class MultipartStream {
return -1; return -1;
} }
/** /**
* Searches for the <code>boundary</code> in the <code>buffer</code> * Searches for the <code>boundary</code> in the <code>buffer</code>
* region delimited by <code>head</code> and <code>tail</code>. * region delimited by <code>head</code> and <code>tail</code>.
@ -709,11 +702,9 @@ public class MultipartStream {
int first; int first;
int match = 0; int match = 0;
int maxpos = tail - boundaryLength; int maxpos = tail - boundaryLength;
for (first = head; for (first = head; first <= maxpos && match != boundaryLength; first++) {
(first <= maxpos) && (match != boundaryLength);
first++) {
first = findByte(boundary[0], first); first = findByte(boundary[0], first);
if (first == -1 || (first > maxpos)) { if (first == -1 || first > maxpos) {
return -1; return -1;
} }
for (match = 1; match < boundaryLength; match++) { for (match = 1; match < boundaryLength; match++) {
@ -732,8 +723,13 @@ public class MultipartStream {
* Thrown to indicate that the input stream fails to follow the * Thrown to indicate that the input stream fails to follow the
* required syntax. * required syntax.
*/ */
public static class MalformedStreamException public static class MalformedStreamException extends IOException {
extends IOException {
/**
* The UID to use when serializing this instance.
*/
private static final long serialVersionUID = 6466926458059796677L;
/** /**
* Constructs a <code>MalformedStreamException</code> with no * Constructs a <code>MalformedStreamException</code> with no
* detail message. * detail message.
@ -751,14 +747,19 @@ public class MultipartStream {
public MalformedStreamException(String message) { public MalformedStreamException(String message) {
super(message); super(message);
} }
}
}
/** /**
* Thrown upon attempt of setting an invalid boundary token. * Thrown upon attempt of setting an invalid boundary token.
*/ */
public static class IllegalBoundaryException public static class IllegalBoundaryException extends IOException {
extends IOException {
/**
* The UID to use when serializing this instance.
*/
private static final long serialVersionUID = -161533165102632918L;
/** /**
* Constructs an <code>IllegalBoundaryException</code> with no * Constructs an <code>IllegalBoundaryException</code> with no
* detail message. * detail message.
@ -776,23 +777,32 @@ public class MultipartStream {
public IllegalBoundaryException(String message) { public IllegalBoundaryException(String message) {
super(message); super(message);
} }
} }
/** /**
* An {@link InputStream} for reading an items contents. * An {@link InputStream} for reading an items contents.
*/ */
public class ItemInputStream extends InputStream implements Closeable { public class ItemInputStream extends InputStream implements Closeable {
/** The number of bytes, which have been read so far.
/**
* The number of bytes, which have been read so far.
*/ */
private long total; private long total;
/** The number of bytes, which must be hold, because
/**
* The number of bytes, which must be hold, because
* they might be a part of the boundary. * they might be a part of the boundary.
*/ */
private int pad; private int pad;
/** The current offset in the buffer.
/**
* The current offset in the buffer.
*/ */
private int pos; private int pos;
/** Whether the stream is already closed.
/**
* Whether the stream is already closed.
*/ */
private boolean closed; private boolean closed;
@ -820,6 +830,7 @@ public class MultipartStream {
/** /**
* Returns the number of bytes, which have been read * Returns the number of bytes, which have been read
* by the stream. * by the stream.
*
* @return Number of bytes, which have been read so far. * @return Number of bytes, which have been read so far.
*/ */
public long getBytesRead() { public long getBytesRead() {
@ -829,9 +840,11 @@ public class MultipartStream {
/** /**
* Returns the number of bytes, which are currently * Returns the number of bytes, which are currently
* available, without blocking. * available, without blocking.
*
* @throws IOException An I/O error occurs. * @throws IOException An I/O error occurs.
* @return Number of bytes in the buffer. * @return Number of bytes in the buffer.
*/ */
@Override
public int available() throws IOException { public int available() throws IOException {
if (pos == -1) { if (pos == -1) {
return tail - head - pad; return tail - head - pad;
@ -839,24 +852,25 @@ public class MultipartStream {
return pos - head; return pos - head;
} }
/** Offset when converting negative bytes to integers. /**
* Offset when converting negative bytes to integers.
*/ */
private static final int BYTE_POSITIVE_OFFSET = 256; private static final int BYTE_POSITIVE_OFFSET = 256;
/** /**
* Returns the next byte in the stream. * Returns the next byte in the stream.
*
* @return The next byte in the stream, as a non-negative * @return The next byte in the stream, as a non-negative
* integer, or -1 for EOF. * integer, or -1 for EOF.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
@Override
public int read() throws IOException { public int read() throws IOException {
if (closed) { if (closed) {
throw new FileItemStream.ItemSkippedException(); throw new FileItemStream.ItemSkippedException();
} }
if (available() == 0) { if (available() == 0 && makeAvailable() == 0) {
if (makeAvailable() == 0) { return -1;
return -1;
}
} }
++total; ++total;
int b = buffer[head++]; int b = buffer[head++];
@ -868,6 +882,7 @@ public class MultipartStream {
/** /**
* Reads bytes into the given buffer. * Reads bytes into the given buffer.
*
* @param b The destination buffer, where to write to. * @param b The destination buffer, where to write to.
* @param off Offset of the first byte in the buffer. * @param off Offset of the first byte in the buffer.
* @param len Maximum number of bytes to read. * @param len Maximum number of bytes to read.
@ -875,6 +890,7 @@ public class MultipartStream {
* or -1 for EOF. * or -1 for EOF.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
@Override
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len) throws IOException {
if (closed) { if (closed) {
throw new FileItemStream.ItemSkippedException(); throw new FileItemStream.ItemSkippedException();
@ -898,32 +914,52 @@ public class MultipartStream {
/** /**
* Closes the input stream. * Closes the input stream.
*
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
@Override
public void close() throws IOException { public void close() throws IOException {
close(false);
}
/**
* Closes the input stream.
*
* @param pCloseUnderlying Whether to close the underlying stream
* (hard close)
* @throws IOException An I/O error occurred.
*/
public void close(boolean pCloseUnderlying) throws IOException {
if (closed) { if (closed) {
return; return;
} }
for (;;) { if (pCloseUnderlying) {
int av = available(); closed = true;
if (av == 0) { input.close();
av = makeAvailable(); } else {
for (;;) {
int av = available();
if (av == 0) { if (av == 0) {
break; av = makeAvailable();
if (av == 0) {
break;
}
} }
skip(av);
} }
skip(av);
} }
closed = true; closed = true;
} }
/** /**
* Skips the given number of bytes. * Skips the given number of bytes.
*
* @param bytes Number of bytes to skip. * @param bytes Number of bytes to skip.
* @return The number of bytes, which have actually been * @return The number of bytes, which have actually been
* skipped. * skipped.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
@Override
public long skip(long bytes) throws IOException { public long skip(long bytes) throws IOException {
if (closed) { if (closed) {
throw new FileItemStream.ItemSkippedException(); throw new FileItemStream.ItemSkippedException();
@ -942,6 +978,7 @@ public class MultipartStream {
/** /**
* Attempts to read more data. * Attempts to read more data.
*
* @return Number of available bytes * @return Number of available bytes
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
@ -956,92 +993,40 @@ public class MultipartStream {
// Refill buffer with new data. // Refill buffer with new data.
head = 0; head = 0;
int bytesRead = input.read(buffer, pad, bufSize - pad); tail = pad;
if (bytesRead == -1) {
// The last pad amount is left in the buffer. for (;;) {
// Boundary can't be in there so signal an error int bytesRead = input.read(buffer, tail, bufSize - tail);
// condition. if (bytesRead == -1) {
throw new MalformedStreamException( // The last pad amount is left in the buffer.
"Stream ended unexpectedly"); // Boundary can't be in there so signal an error
// condition.
final String msg = "Stream ended unexpectedly";
throw new MalformedStreamException(msg);
}
if (notifier != null) {
notifier.noteBytesRead(bytesRead);
}
tail += bytesRead;
findSeparator();
int av = available();
if (av > 0 || pos != -1) {
return av;
}
} }
notifier.noteBytesRead(bytesRead);
tail = pad + bytesRead;
findSeparator();
return available();
} }
/** /**
* Returns, whether the stream is closed. * Returns, whether the stream is closed.
*
* @return True, if the stream is closed, otherwise false. * @return True, if the stream is closed, otherwise false.
*/ */
public boolean isClosed() { public boolean isClosed() {
return closed; return closed;
} }
}
// ------------------------------------------------------ Debugging methods
// These are the methods that were used to debug this stuff.
/*
// Dump data.
protected void dump()
{
System.out.println("01234567890");
byte[] temp = new byte[buffer.length];
for(int i=0; i<buffer.length; i++)
{
if (buffer[i] == 0x0D || buffer[i] == 0x0A)
{
temp[i] = 0x21;
}
else
{
temp[i] = buffer[i];
}
}
System.out.println(new String(temp));
int i;
for (i=0; i<head; i++)
System.out.print(" ");
System.out.println("h");
for (i=0; i<tail; i++)
System.out.print(" ");
System.out.println("t");
System.out.flush();
}
// Main routine, for testing purposes only.
//
// @param args A String[] with the command line arguments.
// @throws Exception, a generic exception.
public static void main( String[] args )
throws Exception
{
File boundaryFile = new File("boundary.dat");
int boundarySize = (int)boundaryFile.length();
byte[] boundary = new byte[boundarySize];
FileInputStream input = new FileInputStream(boundaryFile);
input.read(boundary,0,boundarySize);
input = new FileInputStream("multipart.dat");
MultipartStream chunks = new MultipartStream(input, boundary);
int i = 0;
String header;
OutputStream output;
boolean nextChunk = chunks.skipPreamble();
while (nextChunk)
{
header = chunks.readHeaders();
System.out.println("!"+header+"!");
System.out.println("wrote part"+i+".dat");
output = new FileOutputStream("part"+(i++)+".dat");
chunks.readBodyData(output);
nextChunk = chunks.readBoundary();
}
} }
*/
} }

100
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ParameterParser.java

@ -16,12 +16,17 @@
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
import java.io.UnsupportedEncodingException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import com.fr.third.org.apache.commons.fileupload.util.mime.MimeUtility;
/** /**
* A simple parser intended to parse sequences of name/value pairs. * A simple parser intended to parse sequences of name/value pairs.
* Parameter values are exptected to be enclosed in quotes if they *
* Parameter values are expected to be enclosed in quotes if they
* contain unsafe characters, such as '=' characters or separators. * contain unsafe characters, such as '=' characters or separators.
* Parameter values are optional and can be omitted. * Parameter values are optional and can be omitted.
* *
@ -29,10 +34,10 @@ import java.util.Map;
* <code>param1 = value; param2 = "anything goes; really"; param3</code> * <code>param1 = value; param2 = "anything goes; really"; param3</code>
* </p> * </p>
* *
* @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a> * @version $Id$
*/ */
public class ParameterParser { public class ParameterParser {
/** /**
* String to be parsed. * String to be parsed.
*/ */
@ -99,13 +104,12 @@ public class ParameterParser {
i2--; i2--;
} }
// Strip away quotation marks if necessary // Strip away quotation marks if necessary
if (quoted) { if (quoted
if (((i2 - i1) >= 2) && ((i2 - i1) >= 2)
&& (chars[i1] == '"') && (chars[i1] == '"')
&& (chars[i2 - 1] == '"')) { && (chars[i2 - 1] == '"')) {
i1++; i1++;
i2--; i2--;
}
} }
String result = null; String result = null;
if (i2 > i1) { if (i2 > i1) {
@ -125,8 +129,8 @@ public class ParameterParser {
*/ */
private boolean isOneOf(char ch, final char[] charray) { private boolean isOneOf(char ch, final char[] charray) {
boolean result = false; boolean result = false;
for (int i = 0; i < charray.length; i++) { for (char element : charray) {
if (ch == charray[i]) { if (ch == element) {
result = true; result = true;
break; break;
} }
@ -214,6 +218,34 @@ public class ParameterParser {
this.lowerCaseNames = b; this.lowerCaseNames = b;
} }
/**
* Extracts a map of name/value pairs from the given string. Names are
* expected to be unique. Multiple separators may be specified and
* the earliest found in the input string is used.
*
* @param str the string that contains a sequence of name/value pairs
* @param separators the name/value pairs separators
*
* @return a map of name/value pairs
*/
public Map<String, String> parse(final String str, char[] separators) {
if (separators == null || separators.length == 0) {
return new HashMap<String, String>();
}
char separator = separators[0];
if (str != null) {
int idx = str.length();
for (char separator2 : separators) {
int tmp = str.indexOf(separator2);
if (tmp != -1 && tmp < idx) {
idx = tmp;
separator = separator2;
}
}
}
return parse(str, separator);
}
/** /**
* Extracts a map of name/value pairs from the given string. Names are * Extracts a map of name/value pairs from the given string. Names are
* expected to be unique. * expected to be unique.
@ -223,9 +255,9 @@ public class ParameterParser {
* *
* @return a map of name/value pairs * @return a map of name/value pairs
*/ */
public Map parse(final String str, char separator) { public Map<String, String> parse(final String str, char separator) {
if (str == null) { if (str == null) {
return new HashMap(); return new HashMap<String, String>();
} }
return parse(str.toCharArray(), separator); return parse(str.toCharArray(), separator);
} }
@ -234,24 +266,24 @@ public class ParameterParser {
* Extracts a map of name/value pairs from the given array of * Extracts a map of name/value pairs from the given array of
* characters. Names are expected to be unique. * characters. Names are expected to be unique.
* *
* @param chars the array of characters that contains a sequence of * @param charArray the array of characters that contains a sequence of
* name/value pairs * name/value pairs
* @param separator the name/value pairs separator * @param separator the name/value pairs separator
* *
* @return a map of name/value pairs * @return a map of name/value pairs
*/ */
public Map parse(final char[] chars, char separator) { public Map<String, String> parse(final char[] charArray, char separator) {
if (chars == null) { if (charArray == null) {
return new HashMap(); return new HashMap<String, String>();
} }
return parse(chars, 0, chars.length, separator); return parse(charArray, 0, charArray.length, separator);
} }
/** /**
* Extracts a map of name/value pairs from the given array of * Extracts a map of name/value pairs from the given array of
* characters. Names are expected to be unique. * characters. Names are expected to be unique.
* *
* @param chars the array of characters that contains a sequence of * @param charArray the array of characters that contains a sequence of
* name/value pairs * name/value pairs
* @param offset - the initial offset. * @param offset - the initial offset.
* @param length - the length. * @param length - the length.
@ -259,17 +291,17 @@ public class ParameterParser {
* *
* @return a map of name/value pairs * @return a map of name/value pairs
*/ */
public Map parse( public Map<String, String> parse(
final char[] chars, final char[] charArray,
int offset, int offset,
int length, int length,
char separator) { char separator) {
if (chars == null) { if (charArray == null) {
return new HashMap(); return new HashMap<String, String>();
} }
HashMap params = new HashMap(); HashMap<String, String> params = new HashMap<String, String>();
this.chars = chars; this.chars = charArray;
this.pos = offset; this.pos = offset;
this.len = length; this.len = length;
@ -279,21 +311,31 @@ public class ParameterParser {
paramName = parseToken(new char[] { paramName = parseToken(new char[] {
'=', separator }); '=', separator });
paramValue = null; paramValue = null;
if (hasChar() && (chars[pos] == '=')) { if (hasChar() && (charArray[pos] == '=')) {
pos++; // skip '=' pos++; // skip '='
paramValue = parseQuotedToken(new char[] { paramValue = parseQuotedToken(new char[] {
separator }); separator });
if (paramValue != null) {
try {
paramValue = MimeUtility.decodeText(paramValue);
} catch (UnsupportedEncodingException e) {
// let's keep the original value in this case
}
}
} }
if (hasChar() && (chars[pos] == separator)) { if (hasChar() && (charArray[pos] == separator)) {
pos++; // skip separator pos++; // skip separator
} }
if ((paramName != null) && (paramName.length() > 0)) { if ((paramName != null) && (paramName.length() > 0)) {
if (this.lowerCaseNames) { if (this.lowerCaseNames) {
paramName = paramName.toLowerCase(); paramName = paramName.toLowerCase(Locale.ENGLISH);
} }
params.put(paramName, paramValue); params.put(paramName, paramValue);
} }
} }
return params; return params;
} }
} }

9
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ProgressListener.java

@ -16,13 +16,17 @@
*/ */
package com.fr.third.org.apache.commons.fileupload; package com.fr.third.org.apache.commons.fileupload;
/** /**
* The {@link ProgressListener} may be used to display a progress bar * The {@link ProgressListener} may be used to display a progress bar
* or do stuff like that. * or do stuff like that.
*
* @version $Id$
*/ */
public interface ProgressListener { public interface ProgressListener {
/** Updates the listeners status information.
/**
* Updates the listeners status information.
*
* @param pBytesRead The total number of bytes, which have been read * @param pBytesRead The total number of bytes, which have been read
* so far. * so far.
* @param pContentLength The total number of bytes, which are being * @param pContentLength The total number of bytes, which are being
@ -31,4 +35,5 @@ public interface ProgressListener {
* read. (0 = no item so far, 1 = first item is being read, ...) * read. (0 = no item so far, 1 = first item is being read, ...)
*/ */
void update(long pBytesRead, long pContentLength, int pItems); void update(long pBytesRead, long pContentLength, int pItems);
} }

7
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/RequestContext.java

@ -21,11 +21,9 @@ import java.io.IOException;
/** /**
* <p>Abstracts access to the request information needed for file uploads. This * <p>Abstracts access to the request information needed for file uploads. This
* interfsace should be implemented for each type of request that may be * interface should be implemented for each type of request that may be
* handled by FileUpload, such as servlets and portlets.</p> * handled by FileUpload, such as servlets and portlets.</p>
* *
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
*
* @since FileUpload 1.1 * @since FileUpload 1.1
* *
* @version $Id$ * @version $Id$
@ -50,7 +48,9 @@ public interface RequestContext {
* Retrieve the content length of the request. * Retrieve the content length of the request.
* *
* @return The content length of the request. * @return The content length of the request.
* @deprecated 1.3 Use {@link UploadContext#contentLength()} instead
*/ */
@Deprecated
int getContentLength(); int getContentLength();
/** /**
@ -61,4 +61,5 @@ public interface RequestContext {
* @throws IOException if a problem occurs. * @throws IOException if a problem occurs.
*/ */
InputStream getInputStream() throws IOException; InputStream getInputStream() throws IOException;
} }

39
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/UploadContext.java

@ -0,0 +1,39 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload;
/**
* Enhanced access to the request information needed for file uploads,
* which fixes the Content Length data access in {@link RequestContext}.
*
* The reason of introducing this new interface is just for backward compatibility
* and it might vanish for a refactored 2.x version moving the new method into
* RequestContext again.
*
* @since 1.3
*/
public interface UploadContext extends RequestContext {
/**
* Retrieve the content length of the request.
*
* @return The content length of the request.
* @since 1.3
*/
long contentLength();
}

222
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItem.java

@ -16,6 +16,8 @@
*/ */
package com.fr.third.org.apache.commons.fileupload.disk; package com.fr.third.org.apache.commons.fileupload.disk;
import static java.lang.String.format;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -24,50 +26,51 @@ import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Map; import java.util.Map;
import com.fr.third.org.apache.commons.io.IOUtils; import java.util.UUID;
import com.fr.third.org.apache.commons.io.FileCleaner; import java.util.concurrent.atomic.AtomicInteger;
import com.fr.third.org.apache.commons.io.output.DeferredFileOutputStream;
import com.fr.third.org.apache.commons.fileupload.FileItem; import com.fr.third.org.apache.commons.fileupload.FileItem;
import com.fr.third.org.apache.commons.fileupload.FileItemHeaders;
import com.fr.third.org.apache.commons.fileupload.FileUploadException; import com.fr.third.org.apache.commons.fileupload.FileUploadException;
import com.fr.third.org.apache.commons.fileupload.InvalidFileNameException;
import com.fr.third.org.apache.commons.fileupload.ParameterParser; import com.fr.third.org.apache.commons.fileupload.ParameterParser;
import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.fr.third.org.apache.commons.fileupload.util.Streams;
import com.fr.third.org.apache.commons.io.IOUtils;
import com.fr.third.org.apache.commons.io.output.DeferredFileOutputStream;
/** /**
* <p> The default implementation of the * <p> The default implementation of the
* {@link com.fr.third.org.apache.commons.fileupload.FileItem FileItem} interface. * {@link FileItem FileItem} interface.
* *
* <p> After retrieving an instance of this class from a {@link * <p> After retrieving an instance of this class from a {@link
* com.fr.third.org.apache.commons.fileupload.DiskFileUpload DiskFileUpload} instance (see * DiskFileItemFactory} instance (see
* {@link com.fr.third.org.apache.commons.fileupload.DiskFileUpload * {@link ServletFileUpload
* #parseRequest(javax.servlet.http.HttpServletRequest)}), you may * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may
* either request all contents of file at once using {@link #get()} or * either request all contents of file at once using {@link #get()} or
* request an {@link java.io.InputStream InputStream} with * request an {@link java.io.InputStream InputStream} with
* {@link #getInputStream()} and process the file without attempting to load * {@link #getInputStream()} and process the file without attempting to load
* it into memory, which may come handy with large files. * it into memory, which may come handy with large files.
* *
* <p>When using the <code>DiskFileItemFactory</code>, then you should * <p>Temporary files, which are created for file items, should be
* consider the following: Temporary files are automatically deleted as * deleted later on. The best way to do this is using a
* soon as they are no longer needed. (More precisely, when the * {@link org.apache.commons.io.FileCleaningTracker}, which you can set on the
* {@link DiskFileItemFactory}. However, if you do use such a tracker,
* then you must consider the following: Temporary files are automatically
* deleted as soon as they are no longer needed. (More precisely, when the
* corresponding instance of {@link java.io.File} is garbage collected.) * corresponding instance of {@link java.io.File} is garbage collected.)
* This is done by the so-called reaper thread, which is started * This is done by the so-called reaper thread, which is started and stopped
* automatically when the class {@link FileCleaner} is loaded. * automatically by the {@link org.apache.commons.io.FileCleaningTracker} when
* there are files to be tracked.
* It might make sense to terminate that thread, for example, if * It might make sense to terminate that thread, for example, if
* your web application ends. See the section on "Resource cleanup" * your web application ends. See the section on "Resource cleanup"
* in the users guide of commons-fileupload.</p> * in the users guide of commons-fileupload.</p>
* *
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:sean@informage.net">Sean Legassick</a>
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:jmcnally@apache.org">John McNally</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* @author Sean C. Sullivan
*
* @since FileUpload 1.1 * @since FileUpload 1.1
* *
* @version $Id$ * @version $Id$
@ -75,8 +78,18 @@ import com.fr.third.org.apache.commons.fileupload.ParameterParser;
public class DiskFileItem public class DiskFileItem
implements FileItem { implements FileItem {
/**
* Although it implements {@link java.io.Serializable}, a DiskFileItem can actually only be deserialized,
* if this System property is true.
*/
public static final String SERIALIZABLE_PROPERTY = DiskFileItem.class.getName() + ".serializable";
// ----------------------------------------------------- Manifest constants // ----------------------------------------------------- Manifest constants
/**
* The UID to use when serializing this instance.
*/
private static final long serialVersionUID = 2237570099615271025L;
/** /**
* Default content charset to be used when no explicit charset * Default content charset to be used when no explicit charset
@ -86,47 +99,39 @@ public class DiskFileItem
*/ */
public static final String DEFAULT_CHARSET = "ISO-8859-1"; public static final String DEFAULT_CHARSET = "ISO-8859-1";
// ----------------------------------------------------------- Data members // ----------------------------------------------------------- Data members
/** /**
* UID used in unique file name generation. * UID used in unique file name generation.
*/ */
private static final String UID = private static final String UID =
new java.rmi.server.UID().toString() UUID.randomUUID().toString().replace('-', '_');
.replace(':', '_').replace('-', '_');
/** /**
* Counter used in unique identifier generation. * Counter used in unique identifier generation.
*/ */
private static int counter = 0; private static final AtomicInteger COUNTER = new AtomicInteger(0);
/** /**
* The name of the form field as provided by the browser. * The name of the form field as provided by the browser.
*/ */
private String fieldName; private String fieldName;
/** /**
* The content type passed by the browser, or <code>null</code> if * The content type passed by the browser, or <code>null</code> if
* not defined. * not defined.
*/ */
private String contentType; private final String contentType;
/** /**
* Whether or not this item is a simple form field. * Whether or not this item is a simple form field.
*/ */
private boolean isFormField; private boolean isFormField;
/** /**
* The original filename in the user's filesystem. * The original filename in the user's filesystem.
*/ */
private String fileName; private final String fileName;
/** /**
* The size of the item, in bytes. This is used to cache the size when a * The size of the item, in bytes. This is used to cache the size when a
@ -138,35 +143,40 @@ public class DiskFileItem
/** /**
* The threshold above which uploads will be stored on disk. * The threshold above which uploads will be stored on disk.
*/ */
private int sizeThreshold; private final int sizeThreshold;
/** /**
* The directory in which uploaded files will be stored, if stored on disk. * The directory in which uploaded files will be stored, if stored on disk.
*/ */
private File repository; private final File repository;
/** /**
* Cached contents of the file. * Cached contents of the file.
*/ */
private byte[] cachedContent; private byte[] cachedContent;
/** /**
* Output stream for this item. * Output stream for this item.
*/ */
private transient DeferredFileOutputStream dfos; private transient DeferredFileOutputStream dfos;
/**
* The temporary file to use.
*/
private transient File tempFile;
/** /**
* File to allow for serialization of the content of this item. * File to allow for serialization of the content of this item.
*/ */
private File dfosFile; private File dfosFile;
/**
* The file items headers.
*/
private FileItemHeaders headers;
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/** /**
* Constructs a new <code>DiskFileItem</code> instance. * Constructs a new <code>DiskFileItem</code> instance.
* *
@ -184,9 +194,9 @@ public class DiskFileItem
* which files will be created, should the item size * which files will be created, should the item size
* exceed the threshold. * exceed the threshold.
*/ */
public DiskFileItem(String fieldName, String contentType, public DiskFileItem(String fieldName,
boolean isFormField, String fileName, int sizeThreshold, String contentType, boolean isFormField, String fileName,
File repository) { int sizeThreshold, File repository) {
this.fieldName = fieldName; this.fieldName = fieldName;
this.contentType = contentType; this.contentType = contentType;
this.isFormField = isFormField; this.isFormField = isFormField;
@ -195,10 +205,8 @@ public class DiskFileItem
this.repository = repository; this.repository = repository;
} }
// ------------------------------- Methods from javax.activation.DataSource // ------------------------------- Methods from javax.activation.DataSource
/** /**
* Returns an {@link java.io.InputStream InputStream} that can be * Returns an {@link java.io.InputStream InputStream} that can be
* used to retrieve the contents of the file. * used to retrieve the contents of the file.
@ -220,7 +228,6 @@ public class DiskFileItem
return new ByteArrayInputStream(cachedContent); return new ByteArrayInputStream(cachedContent);
} }
/** /**
* Returns the content type passed by the agent or <code>null</code> if * Returns the content type passed by the agent or <code>null</code> if
* not defined. * not defined.
@ -232,7 +239,6 @@ public class DiskFileItem
return contentType; return contentType;
} }
/** /**
* Returns the content charset passed by the agent or <code>null</code> if * Returns the content charset passed by the agent or <code>null</code> if
* not defined. * not defined.
@ -244,24 +250,25 @@ public class DiskFileItem
ParameterParser parser = new ParameterParser(); ParameterParser parser = new ParameterParser();
parser.setLowerCaseNames(true); parser.setLowerCaseNames(true);
// Parameter parser can handle null input // Parameter parser can handle null input
Map params = parser.parse(getContentType(), ';'); Map<String, String> params = parser.parse(getContentType(), ';');
return (String) params.get("charset"); return params.get("charset");
} }
/** /**
* Returns the original filename in the client's filesystem. * Returns the original filename in the client's filesystem.
* *
* @return The original filename in the client's filesystem. * @return The original filename in the client's filesystem.
* @throws InvalidFileNameException The file name contains a NUL character,
* which might be an indicator of a security attack. If you intend to
* use the file name anyways, catch the exception and use
* {@link InvalidFileNameException#getName()}.
*/ */
public String getName() { public String getName() {
return fileName; return Streams.checkFileName(fileName);
} }
// ------------------------------------------------------- FileItem methods // ------------------------------------------------------- FileItem methods
/** /**
* Provides a hint as to whether or not the file contents will be read * Provides a hint as to whether or not the file contents will be read
* from memory. * from memory.
@ -276,7 +283,6 @@ public class DiskFileItem
return dfos.isInMemory(); return dfos.isInMemory();
} }
/** /**
* Returns the size of the file. * Returns the size of the file.
* *
@ -294,7 +300,6 @@ public class DiskFileItem
} }
} }
/** /**
* Returns the contents of the file as an array of bytes. If the * Returns the contents of the file as an array of bytes. If the
* contents of the file were not yet cached in memory, they will be * contents of the file were not yet cached in memory, they will be
@ -311,10 +316,10 @@ public class DiskFileItem
} }
byte[] fileData = new byte[(int) getSize()]; byte[] fileData = new byte[(int) getSize()];
FileInputStream fis = null; InputStream fis = null;
try { try {
fis = new FileInputStream(dfos.getFile()); fis = new BufferedInputStream(new FileInputStream(dfos.getFile()));
fis.read(fileData); fis.read(fileData);
} catch (IOException e) { } catch (IOException e) {
fileData = null; fileData = null;
@ -331,7 +336,6 @@ public class DiskFileItem
return fileData; return fileData;
} }
/** /**
* Returns the contents of the file as a String, using the specified * Returns the contents of the file as a String, using the specified
* encoding. This method uses {@link #get()} to retrieve the * encoding. This method uses {@link #get()} to retrieve the
@ -349,15 +353,14 @@ public class DiskFileItem
return new String(get(), charset); return new String(get(), charset);
} }
/** /**
* Returns the contents of the file as a String, using the default * Returns the contents of the file as a String, using the default
* character encoding. This method uses {@link #get()} to retrieve the * character encoding. This method uses {@link #get()} to retrieve the
* contents of the file. * contents of the file.
* *
* @return The contents of the file, as a string. * <b>TODO</b> Consider making this method throw UnsupportedEncodingException.
* *
* @todo Consider making this method throw UnsupportedEncodingException. * @return The contents of the file, as a string.
*/ */
public String getString() { public String getString() {
byte[] rawdata = get(); byte[] rawdata = get();
@ -372,7 +375,6 @@ public class DiskFileItem
} }
} }
/** /**
* A convenience method to write an uploaded item to disk. The client code * A convenience method to write an uploaded item to disk. The client code
* is not concerned with whether or not the item is stored in memory, or on * is not concerned with whether or not the item is stored in memory, or on
@ -451,7 +453,6 @@ public class DiskFileItem
} }
} }
/** /**
* Deletes the underlying storage for a file item, including deleting any * Deletes the underlying storage for a file item, including deleting any
* associated temporary disk file. Although this storage will be deleted * associated temporary disk file. Although this storage will be deleted
@ -467,7 +468,6 @@ public class DiskFileItem
} }
} }
/** /**
* Returns the name of the field in the multipart form corresponding to * Returns the name of the field in the multipart form corresponding to
* this file item. * this file item.
@ -481,7 +481,6 @@ public class DiskFileItem
return fieldName; return fieldName;
} }
/** /**
* Sets the field name used to reference this file item. * Sets the field name used to reference this file item.
* *
@ -494,7 +493,6 @@ public class DiskFileItem
this.fieldName = fieldName; this.fieldName = fieldName;
} }
/** /**
* Determines whether or not a <code>FileItem</code> instance represents * Determines whether or not a <code>FileItem</code> instance represents
* a simple form field. * a simple form field.
@ -509,7 +507,6 @@ public class DiskFileItem
return isFormField; return isFormField;
} }
/** /**
* Specifies whether or not a <code>FileItem</code> instance represents * Specifies whether or not a <code>FileItem</code> instance represents
* a simple form field. * a simple form field.
@ -524,7 +521,6 @@ public class DiskFileItem
isFormField = state; isFormField = state;
} }
/** /**
* Returns an {@link java.io.OutputStream OutputStream} that can * Returns an {@link java.io.OutputStream OutputStream} that can
* be used for storing the contents of the file. * be used for storing the contents of the file.
@ -543,10 +539,8 @@ public class DiskFileItem
return dfos; return dfos;
} }
// --------------------------------------------------------- Public methods // --------------------------------------------------------- Public methods
/** /**
* Returns the {@link java.io.File} object for the <code>FileItem</code>'s * Returns the {@link java.io.File} object for the <code>FileItem</code>'s
* data's temporary location on the disk. Note that for * data's temporary location on the disk. Note that for
@ -561,16 +555,18 @@ public class DiskFileItem
* memory. * memory.
*/ */
public File getStoreLocation() { public File getStoreLocation() {
if (dfos == null) {
return null;
}
return dfos.getFile(); return dfos.getFile();
} }
// ------------------------------------------------------ Protected methods // ------------------------------------------------------ Protected methods
/** /**
* Removes the file contents from the temporary storage. * Removes the file contents from the temporary storage.
*/ */
@Override
protected void finalize() { protected void finalize() {
File outputFile = dfos.getFile(); File outputFile = dfos.getFile();
@ -579,7 +575,6 @@ public class DiskFileItem
} }
} }
/** /**
* Creates and returns a {@link java.io.File File} representing a uniquely * Creates and returns a {@link java.io.File File} representing a uniquely
* named temporary file in the configured repository path. The lifetime of * named temporary file in the configured repository path. The lifetime of
@ -589,22 +584,21 @@ public class DiskFileItem
* @return The {@link java.io.File File} to be used for temporary storage. * @return The {@link java.io.File File} to be used for temporary storage.
*/ */
protected File getTempFile() { protected File getTempFile() {
File tempDir = repository; if (tempFile == null) {
if (tempDir == null) { File tempDir = repository;
tempDir = new File(System.getProperty("java.io.tmpdir")); if (tempDir == null) {
} tempDir = new File(System.getProperty("java.io.tmpdir"));
}
String tempFileName = "upload_" + UID + "_" + getUniqueId() + ".tmp"; String tempFileName = format("upload_%s_%s.tmp", UID, getUniqueId());
File f = new File(tempDir, tempFileName); tempFile = new File(tempDir, tempFileName);
FileCleaner.track(f, this); }
return f; return tempFile;
} }
// -------------------------------------------------------- Private methods // -------------------------------------------------------- Private methods
/** /**
* Returns an identifier that is unique within the class loader used to * Returns an identifier that is unique within the class loader used to
* load this class, but does not have random-like apearance. * load this class, but does not have random-like apearance.
@ -613,10 +607,7 @@ public class DiskFileItem
*/ */
private static String getUniqueId() { private static String getUniqueId() {
final int limit = 100000000; final int limit = 100000000;
int current; int current = COUNTER.getAndIncrement();
synchronized (DiskFileItem.class) {
current = counter++;
}
String id = Integer.toString(current); String id = Integer.toString(current);
// If you manage to get more than 100 million of ids, you'll // If you manage to get more than 100 million of ids, you'll
@ -627,30 +618,20 @@ public class DiskFileItem
return id; return id;
} }
/** /**
* Returns a string representation of this object. * Returns a string representation of this object.
* *
* @return a string representation of this object. * @return a string representation of this object.
*/ */
@Override
public String toString() { public String toString() {
return "name=" + this.getName() return format("name=%s, StoreLocation=%s, size=%s bytes, isFormField=%s, FieldName=%s",
+ ", StoreLocation=" getName(), getStoreLocation(), Long.valueOf(getSize()),
+ String.valueOf(this.getStoreLocation()) Boolean.valueOf(isFormField()), getFieldName());
+ ", size="
+ this.getSize()
+ "bytes, "
+ "isFormField=" + isFormField()
+ ", FieldName="
+ this.getFieldName();
} }
// -------------------------------------------------- Serialization methods // -------------------------------------------------- Serialization methods
/** /**
* Writes the state of this object during serialization. * Writes the state of this object during serialization.
* *
@ -681,15 +662,38 @@ public class DiskFileItem
*/ */
private void readObject(ObjectInputStream in) private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException {
if (!Boolean.getBoolean(SERIALIZABLE_PROPERTY)) {
throw new IllegalStateException("Property " + SERIALIZABLE_PROPERTY
+ " is not true, rejecting to deserialize a DiskFileItem.");
}
// read values // read values
in.defaultReadObject(); in.defaultReadObject();
/* One expected use of serialization is to migrate HTTP sessions
* containing a DiskFileItem between JVMs. Particularly if the JVMs are
* on different machines It is possible that the repository location is
* not valid so validate it.
*/
if (repository != null) {
if (repository.isDirectory()) {
// Check path for nulls
if (repository.getPath().contains("\0")) {
throw new IOException(format(
"The repository [%s] contains a null character",
repository.getPath()));
}
} else {
throw new IOException(format(
"The repository [%s] is not a directory",
repository.getAbsolutePath()));
}
}
OutputStream output = getOutputStream(); OutputStream output = getOutputStream();
if (cachedContent != null) { if (cachedContent != null) {
output.write(cachedContent); output.write(cachedContent);
} else { } else {
FileInputStream input = new FileInputStream(dfosFile); FileInputStream input = new FileInputStream(dfosFile);
IOUtils.copy(input, output); IOUtils.copy(input, output);
dfosFile.delete(); dfosFile.delete();
dfosFile = null; dfosFile = null;
@ -699,4 +703,20 @@ public class DiskFileItem
cachedContent = null; cachedContent = null;
} }
/**
* Returns the file item headers.
* @return The file items headers.
*/
public FileItemHeaders getHeaders() {
return headers;
}
/**
* Sets the file item headers.
* @param pHeaders The file items headers.
*/
public void setHeaders(FileItemHeaders pHeaders) {
headers = pHeaders;
}
} }

98
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItemFactory.java

@ -20,37 +20,51 @@ import java.io.File;
import com.fr.third.org.apache.commons.fileupload.FileItem; import com.fr.third.org.apache.commons.fileupload.FileItem;
import com.fr.third.org.apache.commons.fileupload.FileItemFactory; import com.fr.third.org.apache.commons.fileupload.FileItemFactory;
import com.fr.third.org.apache.commons.io.FileCleaningTracker;
/** /**
* <p>The default {@link com.fr.third.org.apache.commons.fileupload.FileItemFactory} * <p>The default {@link FileItemFactory}
* implementation. This implementation creates * implementation. This implementation creates
* {@link com.fr.third.org.apache.commons.fileupload.FileItem} instances which keep their * {@link FileItem} instances which keep their
* content either in memory, for smaller items, or in a temporary file on disk, * content either in memory, for smaller items, or in a temporary file on disk,
* for larger items. The size threshold, above which content will be stored on * for larger items. The size threshold, above which content will be stored on
* disk, is configurable, as is the directory in which temporary files will be * disk, is configurable, as is the directory in which temporary files will be
* created.</p> * created.</p>
* *
* <p>If not otherwise configured, the default configuration values are as * <p>If not otherwise configured, the default configuration values are as
* follows: * follows:</p>
* <ul> * <ul>
* <li>Size threshold is 10KB.</li> * <li>Size threshold is 10KB.</li>
* <li>Repository is the system default temp directory, as returned by * <li>Repository is the system default temp directory, as returned by
* <code>System.getProperty("java.io.tmpdir")</code>.</li> * <code>System.getProperty("java.io.tmpdir")</code>.</li>
* </ul> * </ul>
* <p>
* <b>NOTE</b>: Files are created in the system default temp directory with
* predictable names. This means that a local attacker with write access to that
* directory can perform a TOUTOC attack to replace any uploaded file with a
* file of the attackers choice. The implications of this will depend on how the
* uploaded file is used but could be significant. When using this
* implementation in an environment with local, untrusted users,
* {@link #setRepository(File)} MUST be used to configure a repository location
* that is not publicly writable. In a Servlet container the location identified
* by the ServletContext attribute <code>javax.servlet.context.tempdir</code>
* may be used.
* </p> * </p>
* *
* <p>When using the <code>DiskFileItemFactory</code>, then you should * <p>Temporary files, which are created for file items, should be
* consider the following: Temporary files are automatically deleted as * deleted later on. The best way to do this is using a
* soon as they are no longer needed. (More precisely, when the * {@link FileCleaningTracker}, which you can set on the
* {@link DiskFileItemFactory}. However, if you do use such a tracker,
* then you must consider the following: Temporary files are automatically
* deleted as soon as they are no longer needed. (More precisely, when the
* corresponding instance of {@link java.io.File} is garbage collected.) * corresponding instance of {@link java.io.File} is garbage collected.)
* This is done by the so-called reaper thread, which is started * This is done by the so-called reaper thread, which is started and stopped
* automatically when the class {@link org.apache.commons.io.FileCleaner} * automatically by the {@link FileCleaningTracker} when there are files to be
* is loaded. It might make sense to terminate that thread, for example, * tracked.
* if your web application ends. See the section on "Resource cleanup" * It might make sense to terminate that thread, for example, if
* your web application ends. See the section on "Resource cleanup"
* in the users guide of commons-fileupload.</p> * in the users guide of commons-fileupload.</p>
* *
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
*
* @since FileUpload 1.1 * @since FileUpload 1.1
* *
* @version $Id$ * @version $Id$
@ -59,40 +73,40 @@ public class DiskFileItemFactory implements FileItemFactory {
// ----------------------------------------------------- Manifest constants // ----------------------------------------------------- Manifest constants
/** /**
* The default threshold above which uploads will be stored on disk. * The default threshold above which uploads will be stored on disk.
*/ */
public static final int DEFAULT_SIZE_THRESHOLD = 10240; public static final int DEFAULT_SIZE_THRESHOLD = 10240;
// ----------------------------------------------------- Instance Variables // ----------------------------------------------------- Instance Variables
/** /**
* The directory in which uploaded files will be stored, if stored on disk. * The directory in which uploaded files will be stored, if stored on disk.
*/ */
private File repository; private File repository;
/** /**
* The threshold above which uploads will be stored on disk. * The threshold above which uploads will be stored on disk.
*/ */
private int sizeThreshold = DEFAULT_SIZE_THRESHOLD; private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
/**
* <p>The instance of {@link FileCleaningTracker}, which is responsible
* for deleting temporary files.</p>
* <p>May be null, if tracking files is not required.</p>
*/
private FileCleaningTracker fileCleaningTracker;
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/** /**
* Constructs an unconfigured instance of this class. The resulting factory * Constructs an unconfigured instance of this class. The resulting factory
* may be configured by calling the appropriate setter methods. * may be configured by calling the appropriate setter methods.
*/ */
public DiskFileItemFactory() { public DiskFileItemFactory() {
// Does nothing. this(DEFAULT_SIZE_THRESHOLD, null);
} }
/** /**
* Constructs a preconfigured instance of this class. * Constructs a preconfigured instance of this class.
* *
@ -108,10 +122,8 @@ public class DiskFileItemFactory implements FileItemFactory {
this.repository = repository; this.repository = repository;
} }
// ------------------------------------------------------------- Properties // ------------------------------------------------------------- Properties
/** /**
* Returns the directory used to temporarily store files that are larger * Returns the directory used to temporarily store files that are larger
* than the configured size threshold. * than the configured size threshold.
@ -125,7 +137,6 @@ public class DiskFileItemFactory implements FileItemFactory {
return repository; return repository;
} }
/** /**
* Sets the directory used to temporarily store files that are larger * Sets the directory used to temporarily store files that are larger
* than the configured size threshold. * than the configured size threshold.
@ -139,7 +150,6 @@ public class DiskFileItemFactory implements FileItemFactory {
this.repository = repository; this.repository = repository;
} }
/** /**
* Returns the size threshold beyond which files are written directly to * Returns the size threshold beyond which files are written directly to
* disk. The default value is 10240 bytes. * disk. The default value is 10240 bytes.
@ -152,7 +162,6 @@ public class DiskFileItemFactory implements FileItemFactory {
return sizeThreshold; return sizeThreshold;
} }
/** /**
* Sets the size threshold beyond which files are written directly to disk. * Sets the size threshold beyond which files are written directly to disk.
* *
@ -165,11 +174,10 @@ public class DiskFileItemFactory implements FileItemFactory {
this.sizeThreshold = sizeThreshold; this.sizeThreshold = sizeThreshold;
} }
// --------------------------------------------------------- Public Methods // --------------------------------------------------------- Public Methods
/** /**
* Create a new {@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItem} * Create a new {@link DiskFileItem}
* instance from the supplied parameters and the local factory * instance from the supplied parameters and the local factory
* configuration. * configuration.
* *
@ -182,14 +190,38 @@ public class DiskFileItemFactory implements FileItemFactory {
* *
* @return The newly created file item. * @return The newly created file item.
*/ */
public FileItem createItem( public FileItem createItem(String fieldName, String contentType,
String fieldName, boolean isFormField, String fileName) {
String contentType, DiskFileItem result = new DiskFileItem(fieldName, contentType,
boolean isFormField,
String fileName
) {
return new DiskFileItem(fieldName, contentType,
isFormField, fileName, sizeThreshold, repository); isFormField, fileName, sizeThreshold, repository);
FileCleaningTracker tracker = getFileCleaningTracker();
if (tracker != null) {
tracker.track(result.getTempFile(), result);
}
return result;
}
/**
* Returns the tracker, which is responsible for deleting temporary
* files.
*
* @return An instance of {@link FileCleaningTracker}, or null
* (default), if temporary files aren't tracked.
*/
public FileCleaningTracker getFileCleaningTracker() {
return fileCleaningTracker;
}
/**
* Sets the tracker, which is responsible for deleting temporary
* files.
*
* @param pTracker An instance of {@link FileCleaningTracker},
* which will from now on track the created files, or null
* (default), to disable tracking.
*/
public void setFileCleaningTracker(FileCleaningTracker pTracker) {
fileCleaningTracker = pTracker;
} }
} }

54
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/package-info.java

@ -0,0 +1,54 @@
/*
* 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.
*/
/**
* <p>
* A disk-based implementation of the
* {@link com.fr.third.org.apache.commons.fileupload.FileItem FileItem}
* interface. This implementation retains smaller items in memory, while
* writing larger ones to disk. The threshold between these two is
* configurable, as is the location of files that are written to disk.
* </p>
* <p>
* In typical usage, an instance of
* {@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}
* would be created, configured, and then passed to a
* {@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload}
* implementation such as
* {@link com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload ServletFileUpload}
* or
* {@link com.fr.third.org.apache.commons.fileupload.portlet.PortletFileUpload PortletFileUpload}.
* </p>
* <p>
* The following code fragment demonstrates this usage.
* </p>
* <pre>
* DiskFileItemFactory factory = new DiskFileItemFactory();
* // maximum size that will be stored in memory
* factory.setSizeThreshold(4096);
* // the location for saving data that is larger than getSizeThreshold()
* factory.setRepository(new File("/tmp"));
*
* ServletFileUpload upload = new ServletFileUpload(factory);
* </pre>
* <p>
* Please see the FileUpload
* <a href="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
* for further details and examples of how to use this package.
* </p>
*/
package com.fr.third.org.apache.commons.fileupload.disk;

58
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/package.html

@ -1,58 +0,0 @@
<!--
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.
-->
<!-- $Id$ -->
<html>
<head>
<title>Overview of the com.fr.third.org.apache.commons.fileupload.disk component</title>
</head>
<body>
<p>
A disk-based implementation of the
{@link com.fr.third.org.apache.commons.fileupload.FileItem FileItem}
interface. This implementation retains smaller items in memory, while
writing larger ones to disk. The threshold between these two is
configurable, as is the location of files that are written to disk.
</p>
<p>
In typical usage, an instance of
{@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}
would be created, configured, and then passed to a
{@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload}
implementation such as
{@link com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload ServletFileUpload}
or
{@link com.fr.third.org.apache.commons.fileupload.portlet.PortletFileUpload PortletFileUpload}.
</p>
<p>
The following code fragment demonstrates this usage.
</p>
<pre>
DiskFileItemFactory factory = new DiskFileItemFactory();
// maximum size that will be stored in memory
factory.setSizeThreshold(4096);
// the location for saving data that is larger than getSizeThreshold()
factory.setRepository(new File("/tmp"));
ServletFileUpload upload = new ServletFileUpload(factory);
</pre>
<p>
Please see the FileUpload
<a href="http://jakarta.apache.org/commons/fileupload/using.html" target="_top">User Guide</a>
for further details and examples of how to use this package.
</p>
</body>
</html>

85
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/package-info.java

@ -0,0 +1,85 @@
/*
* 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.
*/
/**
* <p>
* A component for handling HTML file uploads as specified by
* <a href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC&nbsp;1867</a>.
* This component provides support for uploads within both servlets (JSR 53)
* and portlets (JSR 168).
* </p>
* <p>
* While this package provides the generic functionality for file uploads,
* these classes are not typically used directly. Instead, normal usage
* involves one of the provided extensions of
* {@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload} such as
* {@link com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload ServletFileUpload}
* or
* {@link com.fr.third.org.apache.commons.fileupload.portlet.PortletFileUpload PortletFileUpload},
* together with a factory for
* {@link com.fr.third.org.apache.commons.fileupload.FileItem FileItem} instances,
* such as
* {@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}.
* </p>
* <p>
* The following is a brief example of typical usage in a servlet, storing
* the uploaded files on disk.
* </p>
* <pre>public void doPost(HttpServletRequest req, HttpServletResponse res) {
* DiskFileItemFactory factory = new DiskFileItemFactory();
* // maximum size that will be stored in memory
* factory.setSizeThreshold(4096);
* // the location for saving data that is larger than getSizeThreshold()
* factory.setRepository(new File("/tmp"));
*
* ServletFileUpload upload = new ServletFileUpload(factory);
* // maximum size before a FileUploadException will be thrown
* upload.setSizeMax(1000000);
*
* List fileItems = upload.parseRequest(req);
* // assume we know there are two files. The first file is a small
* // text file, the second is unknown and is written to a file on
* // the server
* Iterator i = fileItems.iterator();
* String comment = ((FileItem)i.next()).getString();
* FileItem fi = (FileItem)i.next();
* // filename on the client
* String fileName = fi.getName();
* // save comment and filename to database
* ...
* // write the file
* fi.write(new File("/www/uploads/", fileName));
* }
* </pre>
* <p>
* In the example above, the first file is loaded into memory as a
* <code>String</code>. Before calling the <code>getString</code> method,
* the data may have been in memory or on disk depending on its size. The
* second file we assume it will be large and therefore never explicitly
* load it into memory, though if it is less than 4096 bytes it will be
* in memory before it is written to its final location. When writing to
* the final location, if the data is larger than the threshold, an attempt
* is made to rename the temporary file to the given location. If it cannot
* be renamed, it is streamed to the new location.
* </p>
* <p>
* Please see the FileUpload
* <a href="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
* for further details and examples of how to use this package.
* </p>
*/
package com.fr.third.org.apache.commons.fileupload;

90
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/package.html

@ -1,90 +0,0 @@
<!--
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.
-->
<!-- $Id$ -->
<html>
<head>
<title>Overview of the com.fr.third.org.apache.commons.fileupload component</title>
</head>
<body>
<p>
A component for handling HTML file uploads as specified by
<a href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC&nbsp;1867</a>.
This component provides support for uploads within both servlets (JSR 53)
and portlets (JSR 168).
</p>
<p>
While this package provides the generic functionality for file uploads,
these classes are not typically used directly. Instead, normal usage
involves one of the provided extensions of
{@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload} such as
{@link com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload ServletFileUpload}
or
{@link com.fr.third.org.apache.commons.fileupload.portlet.PortletFileUpload PortletFileUpload},
together with a factory for
{@link com.fr.third.org.apache.commons.fileupload.FileItem FileItem} instances,
such as
{@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}.
</p>
<p>
The following is a brief example of typical usage in a servlet, storing
the uploaded files on disk.
</p>
<pre>
public void doPost(HttpServletRequest req, HttpServletResponse res) {
DiskFileItemFactory factory = new DiskFileItemFactory();
// maximum size that will be stored in memory
factory.setSizeThreshold(4096);
// the location for saving data that is larger than getSizeThreshold()
factory.setRepository(new File("/tmp"));
ServletFileUpload upload = new ServletFileUpload(factory);
// maximum size before a FileUploadException will be thrown
upload.setSizeMax(1000000);
List fileItems = upload.parseRequest(req);
// assume we know there are two files. The first file is a small
// text file, the second is unknown and is written to a file on
// the server
Iterator i = fileItems.iterator();
String comment = ((FileItem)i.next()).getString();
FileItem fi = (FileItem)i.next();
// filename on the client
String fileName = fi.getName();
// save comment and filename to database
...
// write the file
fi.write(new File("/www/uploads/", fileName));
}
</pre>
<p>
In the example above, the first file is loaded into memory as a
<code>String</code>. Before calling the <code>getString</code> method,
the data may have been in memory or on disk depending on its size. The
second file we assume it will be large and therefore never explicitly
load it into memory, though if it is less than 4096 bytes it will be
in memory before it is written to its final location. When writing to
the final location, if the data is larger than the threshold, an attempt
is made to rename the temporary file to the given location. If it cannot
be renamed, it is streamed to the new location.
</p>
<p>
Please see the FileUpload
<a href="http://jakarta.apache.org/commons/fileupload/using.html" target="_top">User Guide</a>
for further details and examples of how to use this package.
</p>
</body>
</html>

152
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java

@ -0,0 +1,152 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.portlet;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.portlet.ActionRequest;
import com.fr.third.org.apache.commons.fileupload.FileItem;
import com.fr.third.org.apache.commons.fileupload.FileItemFactory;
import com.fr.third.org.apache.commons.fileupload.FileItemIterator;
import com.fr.third.org.apache.commons.fileupload.FileUpload;
import com.fr.third.org.apache.commons.fileupload.FileUploadBase;
import com.fr.third.org.apache.commons.fileupload.FileUploadException;
import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* <p>High level API for processing file uploads.</p>
*
* <p>This class handles multiple files per single HTML widget, sent using
* <code>multipart/mixed</code> encoding type, as specified by
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use
* {@link ServletFileUpload
* #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list
* of {@link FileItem FileItems} associated
* with a given HTML widget.</p>
*
* <p>How the data for individual parts is stored is determined by the factory
* used to create them; a given part may be in memory, on disk, or somewhere
* else.</p>
*
* @since FileUpload 1.1
*
* @version $Id$
*/
public class PortletFileUpload extends FileUpload {
// ---------------------------------------------------------- Class methods
/**
* Utility method that determines whether the request contains multipart
* content.
*
* @param request The portlet request to be evaluated. Must be non-null.
*
* @return <code>true</code> if the request is multipart;
* <code>false</code> otherwise.
*/
public static final boolean isMultipartContent(ActionRequest request) {
return FileUploadBase.isMultipartContent(
new PortletRequestContext(request));
}
// ----------------------------------------------------------- Constructors
/**
* Constructs an uninitialised instance of this class. A factory must be
* configured, using <code>setFileItemFactory()</code>, before attempting
* to parse requests.
*
* @see FileUpload#FileUpload(FileItemFactory)
*/
public PortletFileUpload() {
super();
}
/**
* Constructs an instance of this class which uses the supplied factory to
* create <code>FileItem</code> instances.
*
* @see FileUpload#FileUpload()
* @param fileItemFactory The factory to use for creating file items.
*/
public PortletFileUpload(FileItemFactory fileItemFactory) {
super(fileItemFactory);
}
// --------------------------------------------------------- Public methods
/**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
* compliant <code>multipart/form-data</code> stream.
*
* @param request The portlet request to be parsed.
*
* @return A list of <code>FileItem</code> instances parsed from the
* request, in the order that they were transmitted.
*
* @throws FileUploadException if there are problems reading/parsing
* the request or storing files.
*/
public List<FileItem> parseRequest(ActionRequest request)
throws FileUploadException {
return parseRequest(new PortletRequestContext(request));
}
/**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
* compliant <code>multipart/form-data</code> stream.
*
* @param request The portlet request to be parsed.
*
* @return A map of <code>FileItem</code> instances parsed from the request.
*
* @throws FileUploadException if there are problems reading/parsing
* the request or storing files.
*
* @since 1.3
*/
public Map<String, List<FileItem>> parseParameterMap(ActionRequest request)
throws FileUploadException {
return parseParameterMap(new PortletRequestContext(request));
}
/**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
* compliant <code>multipart/form-data</code> stream.
*
* @param request The portlet request to be parsed.
*
* @return An iterator to instances of <code>FileItemStream</code>
* parsed from the request, in the order that they were
* transmitted.
*
* @throws FileUploadException if there are problems reading/parsing
* the request or storing files.
* @throws IOException An I/O error occurred. This may be a network
* error while communicating with the client or a problem while
* storing the uploaded content.
*/
public FileItemIterator getItemIterator(ActionRequest request)
throws FileUploadException, IOException {
return super.getItemIterator(new PortletRequestContext(request));
}
}

129
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java

@ -0,0 +1,129 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.portlet;
import static java.lang.String.format;
import java.io.IOException;
import java.io.InputStream;
import javax.portlet.ActionRequest;
import com.fr.third.org.apache.commons.fileupload.FileUploadBase;
import com.fr.third.org.apache.commons.fileupload.UploadContext;
/**
* <p>Provides access to the request information needed for a request made to
* a portlet.</p>
*
* @since FileUpload 1.1
*
* @version $Id$
*/
public class PortletRequestContext implements UploadContext {
// ----------------------------------------------------- Instance Variables
/**
* The request for which the context is being provided.
*/
private final ActionRequest request;
// ----------------------------------------------------------- Constructors
/**
* Construct a context for this request.
*
* @param request The request to which this context applies.
*/
public PortletRequestContext(ActionRequest request) {
this.request = request;
}
// --------------------------------------------------------- Public Methods
/**
* Retrieve the character encoding for the request.
*
* @return The character encoding for the request.
*/
public String getCharacterEncoding() {
return request.getCharacterEncoding();
}
/**
* Retrieve the content type of the request.
*
* @return The content type of the request.
*/
public String getContentType() {
return request.getContentType();
}
/**
* Retrieve the content length of the request.
*
* @return The content length of the request.
* @deprecated 1.3 Use {@link #contentLength()} instead
*/
@Deprecated
public int getContentLength() {
return request.getContentLength();
}
/**
* Retrieve the content length of the request.
*
* @return The content length of the request.
* @since 1.3
*/
public long contentLength() {
long size;
try {
size = Long.parseLong(request.getProperty(FileUploadBase.CONTENT_LENGTH));
} catch (NumberFormatException e) {
size = request.getContentLength();
}
return size;
}
/**
* Retrieve the input stream for the request.
*
* @return The input stream for the request.
*
* @throws IOException if a problem occurs.
*/
public InputStream getInputStream() throws IOException {
return request.getPortletInputStream();
}
/**
* Returns a string representation of this object.
*
* @return a string representation of this object.
*/
@Override
public String toString() {
return format("ContentLength=%s, ContentType=%s",
Long.valueOf(this.contentLength()),
this.getContentType());
}
}

45
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/package-info.java

@ -0,0 +1,45 @@
/*
* 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.
*/
/**
* <p>
* An implementation of
* {@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload}
* for use in portlets conforming to JSR 168. This implementation requires
* only access to the portlet's current <code>ActionRequest</code> instance,
* and a suitable
* {@link com.fr.third.org.apache.commons.fileupload.FileItemFactory FileItemFactory}
* implementation, such as
* {@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}.
* </p>
* <p>
* The following code fragment demonstrates typical usage.
* </p>
* <pre>
* DiskFileItemFactory factory = new DiskFileItemFactory();
* // Configure the factory here, if desired.
* PortletFileUpload upload = new PortletFileUpload(factory);
* // Configure the uploader here, if desired.
* List fileItems = upload.parseRequest(request);
* </pre>
* <p>
* Please see the FileUpload
* <a href="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
* for further details and examples of how to use this package.
* </p>
*/
package com.fr.third.org.apache.commons.fileupload.portlet;

58
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java

@ -16,34 +16,74 @@
*/ */
package com.fr.third.org.apache.commons.fileupload.servlet; package com.fr.third.org.apache.commons.fileupload.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener; import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextEvent;
import com.fr.third.org.apache.commons.io.FileCleaner; import com.fr.third.org.apache.commons.io.FileCleaningTracker;
/** /**
* A servlet context listener, which ensures that the * A servlet context listener, which ensures that the
* {@link com.fr.third.org.apache.commons.io.FileCleaner FileCleaner's} * {@link FileCleaningTracker}'s reaper thread is terminated,
* reaper thread is terminated,
* when the web application is destroyed. * when the web application is destroyed.
*
* @version $Id$
*/ */
public class FileCleanerCleanup implements ServletContextListener { public class FileCleanerCleanup implements ServletContextListener {
/**
* Attribute name, which is used for storing an instance of
* {@link FileCleaningTracker} in the web application.
*/
public static final String FILE_CLEANING_TRACKER_ATTRIBUTE
= FileCleanerCleanup.class.getName() + ".FileCleaningTracker";
/**
* Returns the instance of {@link FileCleaningTracker}, which is
* associated with the given {@link ServletContext}.
*
* @param pServletContext The servlet context to query
* @return The contexts tracker
*/
public static FileCleaningTracker
getFileCleaningTracker(ServletContext pServletContext) {
return (FileCleaningTracker)
pServletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
}
/**
* Sets the instance of {@link FileCleaningTracker}, which is
* associated with the given {@link ServletContext}.
*
* @param pServletContext The servlet context to modify
* @param pTracker The tracker to set
*/
public static void setFileCleaningTracker(ServletContext pServletContext,
FileCleaningTracker pTracker) {
pServletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, pTracker);
}
/** /**
* Called when the web application is initialized. Does * Called when the web application is initialized. Does
* nothing. * nothing.
* @param sce The servlet context (ignored). *
* @param sce The servlet context, used for calling
* {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
*/ */
public void contextInitialized(ServletContextEvent sce) { public void contextInitialized(ServletContextEvent sce) {
// Does nothing. setFileCleaningTracker(sce.getServletContext(),
new FileCleaningTracker());
} }
/** /**
* Called when the web application is being destroyed. * Called when the web application is being destroyed.
* Calls {@link FileCleaner#exitWhenFinished()}. * Calls {@link FileCleaningTracker#exitWhenFinished()}.
* @param sce The servlet context (ignored). *
* @param sce The servlet context, used for calling
* {@link #getFileCleaningTracker(ServletContext)}.
*/ */
public void contextDestroyed(ServletContextEvent sce) { public void contextDestroyed(ServletContextEvent sce) {
FileCleaner.exitWhenFinished(); getFileCleaningTracker(sce.getServletContext()).exitWhenFinished();
} }
} }

55
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletFileUpload.java

@ -18,12 +18,15 @@ package com.fr.third.org.apache.commons.fileupload.servlet;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.fr.third.org.apache.commons.fileupload.FileItem;
import com.fr.third.org.apache.commons.fileupload.FileItemFactory; import com.fr.third.org.apache.commons.fileupload.FileItemFactory;
import com.fr.third.org.apache.commons.fileupload.FileItemIterator; import com.fr.third.org.apache.commons.fileupload.FileItemIterator;
import com.fr.third.org.apache.commons.fileupload.FileUpload; import com.fr.third.org.apache.commons.fileupload.FileUpload;
import com.fr.third.org.apache.commons.fileupload.FileUploadBase;
import com.fr.third.org.apache.commons.fileupload.FileUploadException; import com.fr.third.org.apache.commons.fileupload.FileUploadException;
/** /**
@ -33,26 +36,23 @@ import com.fr.third.org.apache.commons.fileupload.FileUploadException;
* <code>multipart/mixed</code> encoding type, as specified by * <code>multipart/mixed</code> encoding type, as specified by
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
* #parseRequest(HttpServletRequest)} to acquire a list of {@link * #parseRequest(HttpServletRequest)} to acquire a list of {@link
* com.fr.third.org.apache.commons.fileupload.FileItem}s associated with a given HTML * FileItem}s associated with a given HTML
* widget.</p> * widget.</p>
* *
* <p>How the data for individual parts is stored is determined by the factory * <p>How the data for individual parts is stored is determined by the factory
* used to create them; a given part may be in memory, on disk, or somewhere * used to create them; a given part may be in memory, on disk, or somewhere
* else.</p> * else.</p>
* *
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:jmcnally@collab.net">John McNally</a>
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
* @author Sean C. Sullivan
*
* @version $Id$ * @version $Id$
*/ */
public class ServletFileUpload extends FileUpload { public class ServletFileUpload extends FileUpload {
// ---------------------------------------------------------- Class methods /**
* Constant for HTTP POST method.
*/
private static final String POST_METHOD = "POST";
// ---------------------------------------------------------- Class methods
/** /**
* Utility method that determines whether the request contains multipart * Utility method that determines whether the request contains multipart
@ -65,23 +65,14 @@ public class ServletFileUpload extends FileUpload {
*/ */
public static final boolean isMultipartContent( public static final boolean isMultipartContent(
HttpServletRequest request) { HttpServletRequest request) {
if (!"post".equals(request.getMethod().toLowerCase())) { if (!POST_METHOD.equalsIgnoreCase(request.getMethod())) {
return false;
}
String contentType = request.getContentType();
if (contentType == null) {
return false; return false;
} }
if (contentType.toLowerCase().startsWith(MULTIPART)) { return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
return true;
}
return false;
} }
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
/** /**
* Constructs an uninitialised instance of this class. A factory must be * Constructs an uninitialised instance of this class. A factory must be
* configured, using <code>setFileItemFactory()</code>, before attempting * configured, using <code>setFileItemFactory()</code>, before attempting
@ -93,7 +84,6 @@ public class ServletFileUpload extends FileUpload {
super(); super();
} }
/** /**
* Constructs an instance of this class which uses the supplied factory to * Constructs an instance of this class which uses the supplied factory to
* create <code>FileItem</code> instances. * create <code>FileItem</code> instances.
@ -105,10 +95,8 @@ public class ServletFileUpload extends FileUpload {
super(fileItemFactory); super(fileItemFactory);
} }
// --------------------------------------------------------- Public methods // --------------------------------------------------------- Public methods
/** /**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
* compliant <code>multipart/form-data</code> stream. * compliant <code>multipart/form-data</code> stream.
@ -121,11 +109,29 @@ public class ServletFileUpload extends FileUpload {
* @throws FileUploadException if there are problems reading/parsing * @throws FileUploadException if there are problems reading/parsing
* the request or storing files. * the request or storing files.
*/ */
public List /* FileItem */ parseRequest(HttpServletRequest request) @Override
public List<FileItem> parseRequest(HttpServletRequest request)
throws FileUploadException { throws FileUploadException {
return parseRequest(new ServletRequestContext(request)); return parseRequest(new ServletRequestContext(request));
} }
/**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
* compliant <code>multipart/form-data</code> stream.
*
* @param request The servlet request to be parsed.
*
* @return A map of <code>FileItem</code> instances parsed from the request.
*
* @throws FileUploadException if there are problems reading/parsing
* the request or storing files.
*
* @since 1.3
*/
public Map<String, List<FileItem>> parseParameterMap(HttpServletRequest request)
throws FileUploadException {
return parseParameterMap(new ServletRequestContext(request));
}
/** /**
* Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
@ -147,4 +153,5 @@ public class ServletFileUpload extends FileUpload {
throws FileUploadException, IOException { throws FileUploadException, IOException {
return super.getItemIterator(new ServletRequestContext(request)); return super.getItemIterator(new ServletRequestContext(request));
} }
} }

44
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletRequestContext.java

@ -16,30 +16,32 @@
*/ */
package com.fr.third.org.apache.commons.fileupload.servlet; package com.fr.third.org.apache.commons.fileupload.servlet;
import java.io.InputStream; import static java.lang.String.format;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.fr.third.org.apache.commons.fileupload.RequestContext;
import com.fr.third.org.apache.commons.fileupload.FileUploadBase;
import com.fr.third.org.apache.commons.fileupload.UploadContext;
/** /**
* <p>Provides access to the request information needed for a request made to * <p>Provides access to the request information needed for a request made to
* an HTTP servlet.</p> * an HTTP servlet.</p>
* *
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
*
* @since FileUpload 1.1 * @since FileUpload 1.1
* *
* @version $Id$ * @version $Id$
*/ */
public class ServletRequestContext implements RequestContext { public class ServletRequestContext implements UploadContext {
// ----------------------------------------------------- Instance Variables // ----------------------------------------------------- Instance Variables
/** /**
* The request for which the context is being provided. * The request for which the context is being provided.
*/ */
private HttpServletRequest request; private final HttpServletRequest request;
// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors
@ -52,7 +54,6 @@ public class ServletRequestContext implements RequestContext {
this.request = request; this.request = request;
} }
// --------------------------------------------------------- Public Methods // --------------------------------------------------------- Public Methods
/** /**
@ -77,11 +78,29 @@ public class ServletRequestContext implements RequestContext {
* Retrieve the content length of the request. * Retrieve the content length of the request.
* *
* @return The content length of the request. * @return The content length of the request.
* @deprecated 1.3 Use {@link #contentLength()} instead
*/ */
@Deprecated
public int getContentLength() { public int getContentLength() {
return request.getContentLength(); return request.getContentLength();
} }
/**
* Retrieve the content length of the request.
*
* @return The content length of the request.
* @since 1.3
*/
public long contentLength() {
long size;
try {
size = Long.parseLong(request.getHeader(FileUploadBase.CONTENT_LENGTH));
} catch (NumberFormatException e) {
size = request.getContentLength();
}
return size;
}
/** /**
* Retrieve the input stream for the request. * Retrieve the input stream for the request.
* *
@ -98,10 +117,11 @@ public class ServletRequestContext implements RequestContext {
* *
* @return a string representation of this object. * @return a string representation of this object.
*/ */
@Override
public String toString() { public String toString() {
return "ContentLength=" return format("ContentLength=%s, ContentType=%s",
+ this.getContentLength() Long.valueOf(this.contentLength()),
+ ", ContentType=" this.getContentType());
+ this.getContentType();
} }
} }

45
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/package-info.java

@ -0,0 +1,45 @@
/*
* 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.
*/
/**
* <p>
* An implementation of
* {@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload}
* for use in servlets conforming to JSR 53. This implementation requires
* only access to the servlet's current <code>HttpServletRequest</code>
* instance, and a suitable
* {@link com.fr.third.org.apache.commons.fileupload.FileItemFactory FileItemFactory}
* implementation, such as
* {@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}.
* </p>
* <p>
* The following code fragment demonstrates typical usage.
* </p>
* <pre>
* DiskFileItemFactory factory = new DiskFileItemFactory();
* // Configure the factory here, if desired.
* ServletFileUpload upload = new ServletFileUpload(factory);
* // Configure the uploader here, if desired.
* List fileItems = upload.parseRequest(request);
* </pre>
* <p>
* Please see the FileUpload
* <a href="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
* for further details and examples of how to use this package.
* </p>
*/
package com.fr.third.org.apache.commons.fileupload.servlet;

49
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/package.html

@ -1,49 +0,0 @@
<!--
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.
-->
<!-- $Id$ -->
<html>
<head>
<title>Overview of the com.fr.third.org.apache.commons.fileupload.servlet component</title>
</head>
<body>
<p>
An implementation of
{@link com.fr.third.org.apache.commons.fileupload.FileUpload FileUpload}
for use in servlets conforming to JSR 53. This implementation requires
only access to the servlet's current <code>HttpServletRequest</code>
instance, and a suitable
{@link com.fr.third.org.apache.commons.fileupload.FileItemFactory FileItemFactory}
implementation, such as
{@link com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}.
</p>
<p>
The following code fragment demonstrates typical usage.
</p>
<pre>
DiskFileItemFactory factory = new DiskFileItemFactory();
// Configure the factory here, if desired.
ServletFileUpload upload = new ServletFileUpload(factory);
// Configure the uploader here, if desired.
List fileItems = upload.parseRequest(request);
</pre>
<p>
Please see the FileUpload
<a href="http://jakarta.apache.org/commons/fileupload/using.html" target="_top">User Guide</a>
for further details and examples of how to use this package.
</p>
</body>
</html>

7
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Closeable.java

@ -18,21 +18,26 @@ package com.fr.third.org.apache.commons.fileupload.util;
import java.io.IOException; import java.io.IOException;
/** /**
* Interface of an object, which may be closed. * Interface of an object, which may be closed.
*
* @version $Id$
*/ */
public interface Closeable { public interface Closeable {
/** /**
* Closes the object. * Closes the object.
*
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
void close() throws IOException; void close() throws IOException;
/** /**
* Returns, whether the object is already closed. * Returns, whether the object is already closed.
*
* @return True, if the object is closed, otherwise false. * @return True, if the object is closed, otherwise false.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
boolean isClosed() throws IOException; boolean isClosed() throws IOException;
} }

97
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/FileItemHeadersImpl.java

@ -0,0 +1,97 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import com.fr.third.org.apache.commons.fileupload.FileItemHeaders;
/**
* Default implementation of the {@link FileItemHeaders} interface.
*
* @since 1.2.1
*
* @version $Id$
*/
public class FileItemHeadersImpl implements FileItemHeaders, Serializable {
/**
* Serial version UID, being used, if serialized.
*/
private static final long serialVersionUID = -4455695752627032559L;
/**
* Map of <code>String</code> keys to a <code>List</code> of
* <code>String</code> instances.
*/
private final Map<String, List<String>> headerNameToValueListMap = new LinkedHashMap<String, List<String>>();
/**
* {@inheritDoc}
*/
public String getHeader(String name) {
String nameLower = name.toLowerCase(Locale.ENGLISH);
List<String> headerValueList = headerNameToValueListMap.get(nameLower);
if (null == headerValueList) {
return null;
}
return headerValueList.get(0);
}
/**
* {@inheritDoc}
*/
public Iterator<String> getHeaderNames() {
return headerNameToValueListMap.keySet().iterator();
}
/**
* {@inheritDoc}
*/
public Iterator<String> getHeaders(String name) {
String nameLower = name.toLowerCase(Locale.ENGLISH);
List<String> headerValueList = headerNameToValueListMap.get(nameLower);
if (null == headerValueList) {
headerValueList = Collections.emptyList();
}
return headerValueList.iterator();
}
/**
* Method to add header values to this instance.
*
* @param name name of this header
* @param value value of this header
*/
public synchronized void addHeader(String name, String value) {
String nameLower = name.toLowerCase(Locale.ENGLISH);
List<String> headerValueList = headerNameToValueListMap.get(nameLower);
if (null == headerValueList) {
headerValueList = new ArrayList<String>();
headerNameToValueListMap.put(nameLower, headerValueList);
}
headerValueList.add(value);
}
}

28
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/LimitedInputStream.java

@ -20,21 +20,24 @@ import java.io.FilterInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
/** /**
* An input stream, which limits its data size. This stream is * An input stream, which limits its data size. This stream is
* used, if the content length is unknown. * used, if the content length is unknown.
*
* @version $Id$
*/ */
public abstract class LimitedInputStream public abstract class LimitedInputStream extends FilterInputStream implements Closeable {
extends FilterInputStream implements Closeable {
/** /**
* The maximum size of an item, in bytes. * The maximum size of an item, in bytes.
*/ */
private long sizeMax; private final long sizeMax;
/** /**
* The current number of bytes. * The current number of bytes.
*/ */
private long count; private long count;
/** /**
* Whether this stream is already closed. * Whether this stream is already closed.
*/ */
@ -42,18 +45,20 @@ public abstract class LimitedInputStream
/** /**
* Creates a new instance. * Creates a new instance.
* @param pIn The input stream, which shall be limited. *
* @param inputStream The input stream, which shall be limited.
* @param pSizeMax The limit; no more than this number of bytes * @param pSizeMax The limit; no more than this number of bytes
* shall be returned by the source stream. * shall be returned by the source stream.
*/ */
public LimitedInputStream(InputStream pIn, long pSizeMax) { public LimitedInputStream(InputStream inputStream, long pSizeMax) {
super(pIn); super(inputStream);
sizeMax = pSizeMax; sizeMax = pSizeMax;
} }
/** /**
* Called to indicate, that the input streams limit has * Called to indicate, that the input streams limit has
* been exceeded. * been exceeded.
*
* @param pSizeMax The input streams limit, in bytes. * @param pSizeMax The input streams limit, in bytes.
* @param pCount The actual number of bytes. * @param pCount The actual number of bytes.
* @throws IOException The called method is expected * @throws IOException The called method is expected
@ -62,8 +67,10 @@ public abstract class LimitedInputStream
protected abstract void raiseError(long pSizeMax, long pCount) protected abstract void raiseError(long pSizeMax, long pCount)
throws IOException; throws IOException;
/** Called to check, whether the input streams /**
* Called to check, whether the input streams
* limit is reached. * limit is reached.
*
* @throws IOException The given limit is exceeded. * @throws IOException The given limit is exceeded.
*/ */
private void checkLimit() throws IOException { private void checkLimit() throws IOException {
@ -89,6 +96,7 @@ public abstract class LimitedInputStream
* @exception IOException if an I/O error occurs. * @exception IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in * @see java.io.FilterInputStream#in
*/ */
@Override
public int read() throws IOException { public int read() throws IOException {
int res = super.read(); int res = super.read();
if (res != -1) { if (res != -1) {
@ -121,6 +129,7 @@ public abstract class LimitedInputStream
* @exception IOException if an I/O error occurs. * @exception IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in * @see java.io.FilterInputStream#in
*/ */
@Override
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len) throws IOException {
int res = super.read(b, off, len); int res = super.read(b, off, len);
if (res > 0) { if (res > 0) {
@ -132,6 +141,7 @@ public abstract class LimitedInputStream
/** /**
* Returns, whether this stream is already closed. * Returns, whether this stream is already closed.
*
* @return True, if the stream is closed, otherwise false. * @return True, if the stream is closed, otherwise false.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
@ -148,8 +158,10 @@ public abstract class LimitedInputStream
* @exception IOException if an I/O error occurs. * @exception IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in * @see java.io.FilterInputStream#in
*/ */
@Override
public void close() throws IOException { public void close() throws IOException {
closed = true; closed = true;
super.close(); super.close();
} }
} }

118
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Streams.java

@ -21,10 +21,17 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import com.fr.third.org.apache.commons.fileupload.FileItemStream;
import com.fr.third.org.apache.commons.fileupload.InvalidFileNameException;
import com.fr.third.org.apache.commons.io.IOUtils;
/** Utility class for working with streams. /**
* Utility class for working with streams.
*
* @version $Id$
*/ */
public final class Streams { public final class Streams {
/** /**
* Private constructor, to prevent instantiation. * Private constructor, to prevent instantiation.
* This class has only static methods. * This class has only static methods.
@ -45,65 +52,65 @@ public final class Streams {
* <pre> * <pre>
* copy(pInputStream, pOutputStream, new byte[8192]); * copy(pInputStream, pOutputStream, new byte[8192]);
* </pre> * </pre>
* @param pInputStream The input stream, which is being read. *
* @param inputStream The input stream, which is being read.
* It is guaranteed, that {@link InputStream#close()} is called * It is guaranteed, that {@link InputStream#close()} is called
* on the stream. * on the stream.
* @param pOutputStream The output stream, to which data should * @param outputStream The output stream, to which data should
* be written. May be null, in which case the input streams * be written. May be null, in which case the input streams
* contents are simply discarded. * contents are simply discarded.
* @param pClose True guarantees, that {@link OutputStream#close()} * @param closeOutputStream True guarantees, that {@link OutputStream#close()}
* is called on the stream. False indicates, that only * is called on the stream. False indicates, that only
* {@link OutputStream#flush()} should be called finally. * {@link OutputStream#flush()} should be called finally.
* *
* @return Number of bytes, which have been copied. * @return Number of bytes, which have been copied.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
public static long copy(InputStream pInputStream, public static long copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream)
OutputStream pOutputStream, boolean pClose)
throws IOException { throws IOException {
return copy(pInputStream, pOutputStream, pClose, return copy(inputStream, outputStream, closeOutputStream, new byte[DEFAULT_BUFFER_SIZE]);
new byte[DEFAULT_BUFFER_SIZE]);
} }
/** /**
* Copies the contents of the given {@link InputStream} * Copies the contents of the given {@link InputStream}
* to the given {@link OutputStream}. * to the given {@link OutputStream}.
* @param pIn The input stream, which is being read. *
* @param inputStream The input stream, which is being read.
* It is guaranteed, that {@link InputStream#close()} is called * It is guaranteed, that {@link InputStream#close()} is called
* on the stream. * on the stream.
* @param pOut The output stream, to which data should * @param outputStream The output stream, to which data should
* be written. May be null, in which case the input streams * be written. May be null, in which case the input streams
* contents are simply discarded. * contents are simply discarded.
* @param pClose True guarantees, that {@link OutputStream#close()} * @param closeOutputStream True guarantees, that {@link OutputStream#close()}
* is called on the stream. False indicates, that only * is called on the stream. False indicates, that only
* {@link OutputStream#flush()} should be called finally. * {@link OutputStream#flush()} should be called finally.
* @param pBuffer Temporary buffer, which is to be used for * @param buffer Temporary buffer, which is to be used for
* copying data. * copying data.
* @return Number of bytes, which have been copied. * @return Number of bytes, which have been copied.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
public static long copy(InputStream pIn, public static long copy(InputStream inputStream,
OutputStream pOut, boolean pClose, OutputStream outputStream, boolean closeOutputStream,
byte[] pBuffer) byte[] buffer)
throws IOException { throws IOException {
OutputStream out = pOut; OutputStream out = outputStream;
InputStream in = pIn; InputStream in = inputStream;
try { try {
long total = 0; long total = 0;
for (;;) { for (;;) {
int res = in.read(pBuffer); int res = in.read(buffer);
if (res == -1) { if (res == -1) {
break; break;
} }
if (res > 0) { if (res > 0) {
total += res; total += res;
if (out != null) { if (out != null) {
out.write(pBuffer, 0, res); out.write(buffer, 0, res);
} }
} }
} }
if (out != null) { if (out != null) {
if (pClose) { if (closeOutputStream) {
out.close(); out.close();
} else { } else {
out.flush(); out.flush();
@ -114,53 +121,76 @@ public final class Streams {
in = null; in = null;
return total; return total;
} finally { } finally {
if (in != null) { IOUtils.closeQuietly(in);
try { if (closeOutputStream) {
in.close(); IOUtils.closeQuietly(out);
} catch (Throwable t) {
/* Ignore me */
}
}
if (pClose && out != null) {
try {
out.close();
} catch (Throwable t) {
/* Ignore me */
}
} }
} }
} }
/** /**
* This convenience method allows to read a * This convenience method allows to read a
* {@link com.fr.third.org.apache.commons.fileupload.FileItemStream}'s * {@link FileItemStream}'s
* content into a string. The platform's default character encoding * content into a string. The platform's default character encoding
* is used for converting bytes into characters. * is used for converting bytes into characters.
* @param pStream The input stream to read. *
* @param inputStream The input stream to read.
* @see #asString(InputStream, String) * @see #asString(InputStream, String)
* @return The streams contents, as a string. * @return The streams contents, as a string.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
public static String asString(InputStream pStream) throws IOException { public static String asString(InputStream inputStream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(pStream, baos, true); copy(inputStream, baos, true);
return baos.toString(); return baos.toString();
} }
/** /**
* This convenience method allows to read a * This convenience method allows to read a
* {@link com.fr.third.org.apache.commons.fileupload.FileItemStream}'s * {@link FileItemStream}'s
* content into a string, using the given character encoding. * content into a string, using the given character encoding.
* @param pStream The input stream to read. *
* @param pEncoding The character encoding, typically "UTF-8". * @param inputStream The input stream to read.
* @param encoding The character encoding, typically "UTF-8".
* @see #asString(InputStream) * @see #asString(InputStream)
* @return The streams contents, as a string. * @return The streams contents, as a string.
* @throws IOException An I/O error occurred. * @throws IOException An I/O error occurred.
*/ */
public static String asString(InputStream pStream, String pEncoding) public static String asString(InputStream inputStream, String encoding) throws IOException {
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(pStream, baos, true); copy(inputStream, baos, true);
return baos.toString(pEncoding); return baos.toString(encoding);
}
/**
* Checks, whether the given file name is valid in the sense,
* that it doesn't contain any NUL characters. If the file name
* is valid, it will be returned without any modifications. Otherwise,
* an {@link InvalidFileNameException} is raised.
*
* @param fileName The file name to check
* @return Unmodified file name, if valid.
* @throws InvalidFileNameException The file name was found to be invalid.
*/
public static String checkFileName(String fileName) {
if (fileName != null && fileName.indexOf('\u0000') != -1) {
// pFileName.replace("\u0000", "\\0")
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < fileName.length(); i++) {
char c = fileName.charAt(i);
switch (c) {
case 0:
sb.append("\\0");
break;
default:
sb.append(c);
break;
}
}
throw new InvalidFileNameException(fileName,
"Invalid file name: " + sb);
}
return fileName;
} }
} }

152
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/Base64Decoder.java

@ -0,0 +1,152 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.util.mime;
import java.io.IOException;
import java.io.OutputStream;
/**
* @since 1.3
*/
final class Base64Decoder {
/**
* Decoding table value for invalid bytes.
*/
private static final int INVALID_BYTE = -1; // must be outside range 0-63
/**
* Decoding table value for padding bytes, so can detect PAD afer conversion.
*/
private static final int PAD_BYTE = -2; // must be outside range 0-63
/**
* Mask to treat byte as unsigned integer.
*/
private static final int MASK_BYTE_UNSIGNED = 0xFF;
/**
* Number of bytes per encoded chunk - 4 6bit bytes produce 3 8bit bytes on output.
*/
private static final int INPUT_BYTES_PER_CHUNK = 4;
/**
* Set up the encoding table.
*/
private static final byte[] ENCODING_TABLE = {
(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G',
(byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N',
(byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g',
(byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n',
(byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u',
(byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z',
(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
(byte) '7', (byte) '8', (byte) '9',
(byte) '+', (byte) '/'
};
/**
* The padding byte.
*/
private static final byte PADDING = (byte) '=';
/**
* Set up the decoding table; this is indexed by a byte converted to an unsigned int,
* so must be at least as large as the number of different byte values,
* positive and negative and zero.
*/
private static final byte[] DECODING_TABLE = new byte[Byte.MAX_VALUE - Byte.MIN_VALUE + 1];
static {
// Initialise as all invalid characters
for (int i = 0; i < DECODING_TABLE.length; i++) {
DECODING_TABLE[i] = INVALID_BYTE;
}
// set up valid characters
for (int i = 0; i < ENCODING_TABLE.length; i++) {
DECODING_TABLE[ENCODING_TABLE[i]] = (byte) i;
}
// Allow pad byte to be easily detected after conversion
DECODING_TABLE[PADDING] = PAD_BYTE;
}
/**
* Hidden constructor, this class must not be instantiated.
*/
private Base64Decoder() {
// do nothing
}
/**
* Decode the base 64 encoded byte data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @param data the buffer containing the Base64-encoded data
* @param out the output stream to hold the decoded bytes
*
* @return the number of bytes produced.
* @throws IOException thrown when the padding is incorrect or the input is truncated.
*/
public static int decode(byte[] data, OutputStream out) throws IOException {
int outLen = 0;
byte [] cache = new byte[INPUT_BYTES_PER_CHUNK];
int cachedBytes = 0;
for (byte b : data) {
final byte d = DECODING_TABLE[MASK_BYTE_UNSIGNED & b];
if (d == INVALID_BYTE) {
continue; // Ignore invalid bytes
}
cache[cachedBytes++] = d;
if (cachedBytes == INPUT_BYTES_PER_CHUNK) {
// CHECKSTYLE IGNORE MagicNumber FOR NEXT 4 LINES
final byte b1 = cache[0];
final byte b2 = cache[1];
final byte b3 = cache[2];
final byte b4 = cache[3];
if (b1 == PAD_BYTE || b2 == PAD_BYTE) {
throw new IOException("Invalid Base64 input: incorrect padding, first two bytes cannot be padding");
}
// Convert 4 6-bit bytes to 3 8-bit bytes
// CHECKSTYLE IGNORE MagicNumber FOR NEXT 1 LINE
out.write((b1 << 2) | (b2 >> 4)); // 6 bits of b1 plus 2 bits of b2
outLen++;
if (b3 != PAD_BYTE) {
// CHECKSTYLE IGNORE MagicNumber FOR NEXT 1 LINE
out.write((b2 << 4) | (b3 >> 2)); // 4 bits of b2 plus 4 bits of b3
outLen++;
if (b4 != PAD_BYTE) {
// CHECKSTYLE IGNORE MagicNumber FOR NEXT 1 LINE
out.write((b3 << 6) | b4); // 2 bits of b3 plus 6 bits of b4
outLen++;
}
} else if (b4 != PAD_BYTE) { // if byte 3 is pad, byte 4 must be pad too
throw new // line wrap to avoid 120 char limit
IOException("Invalid Base64 input: incorrect padding, 4th byte must be padding if 3rd byte is");
}
cachedBytes = 0;
}
}
// Check for anything left over
if (cachedBytes != 0) {
throw new IOException("Invalid Base64 input: truncated");
}
return outLen;
}
}

283
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/MimeUtility.java

@ -0,0 +1,283 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.util.mime;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* Utility class to decode MIME texts.
*
* @since 1.3
*/
public final class MimeUtility {
/**
* The {@code US-ASCII} charset identifier constant.
*/
private static final String US_ASCII_CHARSET = "US-ASCII";
/**
* The marker to indicate text is encoded with BASE64 algorithm.
*/
private static final String BASE64_ENCODING_MARKER = "B";
/**
* The marker to indicate text is encoded with QuotedPrintable algorithm.
*/
private static final String QUOTEDPRINTABLE_ENCODING_MARKER = "Q";
/**
* If the text contains any encoded tokens, those tokens will be marked with "=?".
*/
private static final String ENCODED_TOKEN_MARKER = "=?";
/**
* If the text contains any encoded tokens, those tokens will terminate with "=?".
*/
private static final String ENCODED_TOKEN_FINISHER = "?=";
/**
* The linear whitespace chars sequence.
*/
private static final String LINEAR_WHITESPACE = " \t\r\n";
/**
* Mappings between MIME and Java charset.
*/
private static final Map<String, String> MIME2JAVA = new HashMap<String, String>();
static {
MIME2JAVA.put("iso-2022-cn", "ISO2022CN");
MIME2JAVA.put("iso-2022-kr", "ISO2022KR");
MIME2JAVA.put("utf-8", "UTF8");
MIME2JAVA.put("utf8", "UTF8");
MIME2JAVA.put("ja_jp.iso2022-7", "ISO2022JP");
MIME2JAVA.put("ja_jp.eucjp", "EUCJIS");
MIME2JAVA.put("euc-kr", "KSC5601");
MIME2JAVA.put("euckr", "KSC5601");
MIME2JAVA.put("us-ascii", "ISO-8859-1");
MIME2JAVA.put("x-us-ascii", "ISO-8859-1");
}
/**
* Hidden constructor, this class must not be instantiated.
*/
private MimeUtility() {
// do nothing
}
/**
* Decode a string of text obtained from a mail header into
* its proper form. The text generally will consist of a
* string of tokens, some of which may be encoded using
* base64 encoding.
*
* @param text The text to decode.
*
* @return The decoded text string.
* @throws UnsupportedEncodingException if the detected encoding in the input text is not supported.
*/
public static String decodeText(String text) throws UnsupportedEncodingException {
// if the text contains any encoded tokens, those tokens will be marked with "=?". If the
// source string doesn't contain that sequent, no decoding is required.
if (text.indexOf(ENCODED_TOKEN_MARKER) < 0) {
return text;
}
int offset = 0;
int endOffset = text.length();
int startWhiteSpace = -1;
int endWhiteSpace = -1;
StringBuilder decodedText = new StringBuilder(text.length());
boolean previousTokenEncoded = false;
while (offset < endOffset) {
char ch = text.charAt(offset);
// is this a whitespace character?
if (LINEAR_WHITESPACE.indexOf(ch) != -1) { // whitespace found
startWhiteSpace = offset;
while (offset < endOffset) {
// step over the white space characters.
ch = text.charAt(offset);
if (LINEAR_WHITESPACE.indexOf(ch) != -1) { // whitespace found
offset++;
} else {
// record the location of the first non lwsp and drop down to process the
// token characters.
endWhiteSpace = offset;
break;
}
}
} else {
// we have a word token. We need to scan over the word and then try to parse it.
int wordStart = offset;
while (offset < endOffset) {
// step over the non white space characters.
ch = text.charAt(offset);
if (LINEAR_WHITESPACE.indexOf(ch) == -1) { // not white space
offset++;
} else {
break;
}
//NB: Trailing whitespace on these header strings will just be discarded.
}
// pull out the word token.
String word = text.substring(wordStart, offset);
// is the token encoded? decode the word
if (word.startsWith(ENCODED_TOKEN_MARKER)) {
try {
// if this gives a parsing failure, treat it like a non-encoded word.
String decodedWord = decodeWord(word);
// are any whitespace characters significant? Append 'em if we've got 'em.
if (!previousTokenEncoded && startWhiteSpace != -1) {
decodedText.append(text.substring(startWhiteSpace, endWhiteSpace));
startWhiteSpace = -1;
}
// this is definitely a decoded token.
previousTokenEncoded = true;
// and add this to the text.
decodedText.append(decodedWord);
// we continue parsing from here...we allow parsing errors to fall through
// and get handled as normal text.
continue;
} catch (ParseException e) {
// just ignore it, skip to next word
}
}
// this is a normal token, so it doesn't matter what the previous token was. Add the white space
// if we have it.
if (startWhiteSpace != -1) {
decodedText.append(text.substring(startWhiteSpace, endWhiteSpace));
startWhiteSpace = -1;
}
// this is not a decoded token.
previousTokenEncoded = false;
decodedText.append(word);
}
}
return decodedText.toString();
}
/**
* Parse a string using the RFC 2047 rules for an "encoded-word"
* type. This encoding has the syntax:
*
* encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
*
* @param word The possibly encoded word value.
*
* @return The decoded word.
* @throws ParseException
* @throws UnsupportedEncodingException
*/
private static String decodeWord(String word) throws ParseException, UnsupportedEncodingException {
// encoded words start with the characters "=?". If this not an encoded word, we throw a
// ParseException for the caller.
if (!word.startsWith(ENCODED_TOKEN_MARKER)) {
throw new ParseException("Invalid RFC 2047 encoded-word: " + word);
}
int charsetPos = word.indexOf('?', 2);
if (charsetPos == -1) {
throw new ParseException("Missing charset in RFC 2047 encoded-word: " + word);
}
// pull out the character set information (this is the MIME name at this point).
String charset = word.substring(2, charsetPos).toLowerCase();
// now pull out the encoding token the same way.
int encodingPos = word.indexOf('?', charsetPos + 1);
if (encodingPos == -1) {
throw new ParseException("Missing encoding in RFC 2047 encoded-word: " + word);
}
String encoding = word.substring(charsetPos + 1, encodingPos);
// and finally the encoded text.
int encodedTextPos = word.indexOf(ENCODED_TOKEN_FINISHER, encodingPos + 1);
if (encodedTextPos == -1) {
throw new ParseException("Missing encoded text in RFC 2047 encoded-word: " + word);
}
String encodedText = word.substring(encodingPos + 1, encodedTextPos);
// seems a bit silly to encode a null string, but easy to deal with.
if (encodedText.length() == 0) {
return "";
}
try {
// the decoder writes directly to an output stream.
ByteArrayOutputStream out = new ByteArrayOutputStream(encodedText.length());
byte[] encodedData = encodedText.getBytes(US_ASCII_CHARSET);
// Base64 encoded?
if (encoding.equals(BASE64_ENCODING_MARKER)) {
Base64Decoder.decode(encodedData, out);
} else if (encoding.equals(QUOTEDPRINTABLE_ENCODING_MARKER)) { // maybe quoted printable.
QuotedPrintableDecoder.decode(encodedData, out);
} else {
throw new UnsupportedEncodingException("Unknown RFC 2047 encoding: " + encoding);
}
// get the decoded byte data and convert into a string.
byte[] decodedData = out.toByteArray();
return new String(decodedData, javaCharset(charset));
} catch (IOException e) {
throw new UnsupportedEncodingException("Invalid RFC 2047 encoding");
}
}
/**
* Translate a MIME standard character set name into the Java
* equivalent.
*
* @param charset The MIME standard name.
*
* @return The Java equivalent for this name.
*/
private static String javaCharset(String charset) {
// nothing in, nothing out.
if (charset == null) {
return null;
}
String mappedCharset = MIME2JAVA.get(charset.toLowerCase(Locale.ENGLISH));
// if there is no mapping, then the original name is used. Many of the MIME character set
// names map directly back into Java. The reverse isn't necessarily true.
if (mappedCharset == null) {
return charset;
}
return mappedCharset;
}
}

38
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/ParseException.java

@ -0,0 +1,38 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.util.mime;
/**
* @since 1.3
*/
final class ParseException extends Exception {
/**
* The UID to use when serializing this instance.
*/
private static final long serialVersionUID = 5355281266579392077L;
/**
* Constructs a new exception with the specified detail message.
*
* @param message the detail message.
*/
public ParseException(String message) {
super(message);
}
}

112
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/QuotedPrintableDecoder.java

@ -0,0 +1,112 @@
/*
* 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 com.fr.third.org.apache.commons.fileupload.util.mime;
import java.io.IOException;
import java.io.OutputStream;
/**
* @since 1.3
*/
final class QuotedPrintableDecoder {
/**
* The shift value required to create the upper nibble
* from the first of 2 byte values converted from ascii hex.
*/
private static final int UPPER_NIBBLE_SHIFT = Byte.SIZE / 2;
/**
* Hidden constructor, this class must not be instantiated.
*/
private QuotedPrintableDecoder() {
// do nothing
}
/**
* Decode the encoded byte data writing it to the given output stream.
*
* @param data The array of byte data to decode.
* @param out The output stream used to return the decoded data.
*
* @return the number of bytes produced.
* @exception IOException
*/
public static int decode(byte[] data, OutputStream out) throws IOException {
int off = 0;
int length = data.length;
int endOffset = off + length;
int bytesWritten = 0;
while (off < endOffset) {
byte ch = data[off++];
// space characters were translated to '_' on encode, so we need to translate them back.
if (ch == '_') {
out.write(' ');
} else if (ch == '=') {
// we found an encoded character. Reduce the 3 char sequence to one.
// but first, make sure we have two characters to work with.
if (off + 1 >= endOffset) {
throw new IOException("Invalid quoted printable encoding; truncated escape sequence");
}
byte b1 = data[off++];
byte b2 = data[off++];
// we've found an encoded carriage return. The next char needs to be a newline
if (b1 == '\r') {
if (b2 != '\n') {
throw new IOException("Invalid quoted printable encoding; CR must be followed by LF");
}
// this was a soft linebreak inserted by the encoding. We just toss this away
// on decode.
} else {
// this is a hex pair we need to convert back to a single byte.
int c1 = hexToBinary(b1);
int c2 = hexToBinary(b2);
out.write((c1 << UPPER_NIBBLE_SHIFT) | c2);
// 3 bytes in, one byte out
bytesWritten++;
}
} else {
// simple character, just write it out.
out.write(ch);
bytesWritten++;
}
}
return bytesWritten;
}
/**
* Convert a hex digit to the binary value it represents.
*
* @param b the ascii hex byte to convert (0-0, A-F, a-f)
* @return the int value of the hex byte, 0-15
* @throws IOException if the byte is not a valid hex digit.
*/
private static int hexToBinary(final byte b) throws IOException {
// CHECKSTYLE IGNORE MagicNumber FOR NEXT 1 LINE
final int i = Character.digit((char) b, 16);
if (i == -1) {
throw new IOException("Invalid quoted printable encoding: not a valid hex digit: " + b);
}
return i;
}
}

22
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/package-info.java

@ -0,0 +1,22 @@
/*
* 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.
*/
/**
* MIME decoder implementation, imported and retailed from
* <a href="http://svn.apache.org/repos/asf/geronimo/specs/tags/geronimo-javamail_1.4_spec-1.4/">Apache Geronimo</a>.
*/
package com.fr.third.org.apache.commons.fileupload.util.mime;

23
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/package-info.java

@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* This package contains various IO related utility classes
* or methods, which are basically reusable and not necessarily
* restricted to the scope of a file upload.
*/
package com.fr.third.org.apache.commons.fileupload.util;

29
fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/package.html

@ -1,29 +0,0 @@
<!--
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.
-->
<!-- $Id: package.html 479262 2006-11-26 03:09:24Z niallp $ -->
<html>
<head>
<title>Overview of the com.fr.third.org.apache.commons.fileupload.util component</title>
</head>
<body>
<p>
This package contains various IO related utility classes
or methods, which are basically reusable and not necessarily
restricted to the scope of a file upload.
</p>
</body>
</html>

BIN
fine-spring/lib/bcmail-jdk14-1.38.jar

Binary file not shown.

BIN
fine-spring/lib/bsh-2.0b4.jar

Binary file not shown.

BIN
fine-spring/lib/bsh-2.0b5.jar

Binary file not shown.

BIN
fine-spring/lib/commons-codec-1.10.jar

Binary file not shown.

BIN
fine-spring/lib/commons-codec-1.6.jar

Binary file not shown.

BIN
fine-spring/lib/commons-fileupload-1.3.1.jar

Binary file not shown.

BIN
fine-spring/lib/commons-fileupload-1.3.3.jar

Binary file not shown.

BIN
fine-spring/lib/commons-logging-1.1.3.jar

Binary file not shown.

BIN
fine-spring/lib/commons-pool-1.6.jar

Binary file not shown.

BIN
fine-spring/lib/commons-pool2-2.4.2.jar

Binary file not shown.

BIN
fine-spring/lib/groovy-all-1.8.9.jar

Binary file not shown.

BIN
fine-spring/lib/groovy-all-2.4.17.jar

Binary file not shown.

BIN
fine-spring/lib/gson-2.8.5.jar

Binary file not shown.

BIN
fine-spring/lib/hessian-4.0.38.jar

Binary file not shown.

BIN
fine-spring/lib/hessian-4.0.7.jar

Binary file not shown.

BIN
fine-spring/lib/httpasyncclient-4.0.2.jar

Binary file not shown.

BIN
fine-spring/lib/httpasyncclient-4.1.4.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-annotations-2.3.0.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-annotations-2.8.0.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-core-2.3.4.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-core-2.8.10.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-databind-2.3.4.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-databind-2.8.11.3.jar

Binary file not shown.

BIN
fine-spring/lib/jackson-dataformat-xml-2.8.11.jar

Binary file not shown.

BIN
fine-spring/lib/jamon-2.4.jar

Binary file not shown.

BIN
fine-spring/lib/jamon-2.81.jar

Binary file not shown.

BIN
fine-spring/lib/jasperreports-5.5.1.jar

Binary file not shown.

BIN
fine-spring/lib/javax.servlet-api-3.0.1.jar

Binary file not shown.

BIN
fine-spring/lib/javax.servlet-api-3.1.0.jar

Binary file not shown.

BIN
fine-spring/lib/jdom-1.0.jar

Binary file not shown.

BIN
fine-spring/lib/jdom2-2.0.6.jar

Binary file not shown.

BIN
fine-spring/lib/jetty-server-9.1.5.v20140505.jar

Binary file not shown.

BIN
fine-spring/lib/jetty-servlet-9.1.5.v20140505.jar

Binary file not shown.

BIN
fine-spring/lib/joda-time-2.5.jar

Binary file not shown.

BIN
fine-spring/lib/joda-time-2.9.9.jar

Binary file not shown.

BIN
fine-spring/lib/joni-2.1.3.jar

Binary file not shown.

BIN
fine-spring/lib/jopt-simple-4.6.jar

Binary file not shown.

BIN
fine-spring/lib/jopt-simple-5.0.3.jar

Binary file not shown.

BIN
fine-spring/lib/jruby-core-1.7.17.jar

Binary file not shown.

BIN
fine-spring/lib/jruby-core-1.7.27.jar

Binary file not shown.

BIN
fine-spring/lib/jruby-stdlib-1.7.17.jar

Binary file not shown.

BIN
fine-spring/lib/jruby-stdlib-1.7.27.jar

Binary file not shown.

BIN
fine-spring/lib/money-api-1.0.1.jar

Binary file not shown.

BIN
fine-spring/lib/netty-all-4.1.39.Final.jar

Binary file not shown.

BIN
fine-spring/lib/poi-3.10.1.jar

Binary file not shown.

BIN
fine-spring/lib/poi-3.17.jar

Binary file not shown.

BIN
fine-spring/lib/rome-1.0.jar

Binary file not shown.

BIN
fine-spring/lib/rome-1.7.4.jar

Binary file not shown.

BIN
fine-spring/lib/snakeyaml-1.13.jar

Binary file not shown.

BIN
fine-spring/lib/snakeyaml-1.17.jar

Binary file not shown.

BIN
fine-spring/lib/tiles-api-2.2.2.jar

Binary file not shown.

BIN
fine-spring/lib/tiles-api-3.0.8.jar

Binary file not shown.

BIN
fine-spring/lib/tiles-compat-2.2.2.jar

Binary file not shown.

BIN
fine-spring/lib/tiles-core-2.2.2.jar

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save