Refactor into Maven modules
This commit is contained in:
parent
ed002cb037
commit
e654cc4b13
|
@ -1,13 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
|
||||
<local-check-config name="maven-checkstyle-plugin validate-main" location="file:/Users/garydgregory/git/commons-fileupload/src/checkstyle/fileupload_checks.xml" type="remote" description="maven-checkstyle-plugin configuration validate-main">
|
||||
<property name="checkstyle.header.file" value="/Users/garydgregory/eclipse-workspace/apache-commons/.metadata/.plugins/org.eclipse.core.resources/.projects/commons-fileupload2/com.basistech.m2e.code.quality.checkstyleConfigurator/checkstyle-header-validate-main.txt"/>
|
||||
<local-check-config name="maven-checkstyle-plugin validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/src/checkstyle/fileupload_checks.xml" type="remote" description="maven-checkstyle-plugin configuration validate-main">
|
||||
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
|
||||
<property name="checkstyle.cache.file" value="${project_loc}/target/checkstyle-cachefile"/>
|
||||
<property name="checkstyle.suppressions.file" value="/Users/garydgregory/eclipse-workspace/apache-commons/.metadata/.plugins/org.eclipse.core.resources/.projects/commons-fileupload2/com.basistech.m2e.code.quality.checkstyleConfigurator/checkstyle-suppressions-validate-main.xml"/>
|
||||
<property name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
|
||||
</local-check-config>
|
||||
<fileset name="java-sources-validate-main" enabled="true" check-config-name="maven-checkstyle-plugin validate-main" local="true">
|
||||
<file-match-pattern match-pattern="^src/main/java/.*\/.*\.java" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/main/resources.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/test/resources.*\.properties" include-pattern="true"/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/target/
|
||||
/.settings/
|
||||
/.classpath
|
||||
/.project
|
||||
site-content/
|
||||
**/target/
|
||||
**/.settings/
|
||||
**/.classpath
|
||||
**/.project
|
||||
**/site-content/
|
||||
/commons-fileupload2.iml
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
|
||||
<local-check-config name="maven-checkstyle-plugin validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-core/../src/checkstyle/fileupload_checks.xml" type="remote" description="maven-checkstyle-plugin configuration validate-main">
|
||||
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-core\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
|
||||
<property name="checkstyle.cache.file" value="${project_loc}/target/checkstyle-cachefile"/>
|
||||
<property name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-core\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
|
||||
</local-check-config>
|
||||
<fileset name="java-sources-validate-main" enabled="true" check-config-name="maven-checkstyle-plugin validate-main" local="true">
|
||||
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/main/resources.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/test/resources.*\.properties" include-pattern="true"/>
|
||||
</fileset>
|
||||
</fileset-config>
|
|
@ -0,0 +1 @@
|
|||
/target/
|
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
|
||||
<name>Apache Commons FileUpload Core</name>
|
||||
<description>
|
||||
The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart
|
||||
file upload functionality to servlets and web applications.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<commons.parent.dir>${basedir}/..</commons.parent.dir>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons.lang3.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.moditect</groupId>
|
||||
<artifactId>moditect-maven-plugin</artifactId>
|
||||
<version>${moditect-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-module-infos</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>add-module-info</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<jvmVersion>9</jvmVersion>
|
||||
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||
<overwriteExistingFiles>true</overwriteExistingFiles>
|
||||
<module>
|
||||
<moduleInfo>
|
||||
<name>org.apache.commons.fileupload2</name>
|
||||
<exports>
|
||||
!org.apache.commons.fileupload2.impl;
|
||||
*;
|
||||
</exports>
|
||||
</moduleInfo>
|
||||
</module>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -36,17 +35,12 @@ import org.apache.commons.io.IOUtils;
|
|||
/**
|
||||
* High level API for processing file uploads.
|
||||
* <p>
|
||||
* This class handles multiple files per single HTML widget, sent using
|
||||
* {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
|
||||
* #parseRequest(RequestContext)} to acquire a list of {@link
|
||||
* org.apache.commons.fileupload2.FileItem}s associated with a given HTML
|
||||
* widget.
|
||||
* This class handles multiple files per single HTML widget, sent using {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link #parseRequest(RequestContext)} to acquire a list of
|
||||
* {@link org.apache.commons.fileupload2.FileItem}s 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.
|
||||
* 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>
|
||||
*/
|
||||
public abstract class AbstractFileUpload {
|
||||
|
@ -92,17 +86,14 @@ public abstract class AbstractFileUpload {
|
|||
public static final String MULTIPART_MIXED = "multipart/mixed";
|
||||
|
||||
/**
|
||||
* Utility method that determines whether the request contains multipart
|
||||
* content.
|
||||
* Utility method that determines whether the request contains multipart content.
|
||||
* <p>
|
||||
* <strong>NOTE:</strong> This method will be moved to the
|
||||
* {@code ServletFileUpload} class after the FileUpload 1.1 release.
|
||||
* Unfortunately, since this method is static, it is not possible to
|
||||
* provide its replacement until this method is removed.
|
||||
* <strong>NOTE:</strong> This method will be moved to the {@code ServletFileUpload} class after the FileUpload 1.1 release. Unfortunately, since this
|
||||
* method is static, it is not possible to provide its replacement until this method is removed.
|
||||
* </p>
|
||||
*
|
||||
* @param ctx The request context to be evaluated. Must be non-null.
|
||||
* @return {@code true} if the request is multipart;
|
||||
* {@code false} otherwise.
|
||||
* @return {@code true} if the request is multipart; {@code false} otherwise.
|
||||
*/
|
||||
public static final boolean isMultipartContent(final RequestContext ctx) {
|
||||
final String contentType = ctx.getContentType();
|
||||
|
@ -113,20 +104,17 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* The maximum size permitted for the complete request, as opposed to
|
||||
* {@link #fileSizeMax}. A value of -1 indicates no maximum.
|
||||
* The maximum size permitted for the complete request, as opposed to {@link #fileSizeMax}. A value of -1 indicates no maximum.
|
||||
*/
|
||||
private long sizeMax = -1;
|
||||
|
||||
/**
|
||||
* The maximum size permitted for a single uploaded file, as opposed
|
||||
* to {@link #sizeMax}. A value of -1 indicates no maximum.
|
||||
* The maximum size permitted for a single uploaded file, as opposed to {@link #sizeMax}. A value of -1 indicates no maximum.
|
||||
*/
|
||||
private long fileSizeMax = -1;
|
||||
|
||||
/**
|
||||
* The maximum permitted number of files that may be uploaded in a single
|
||||
* request. A value of -1 indicates no maximum.
|
||||
* The maximum permitted number of files that may be uploaded in a single request. A value of -1 indicates no maximum.
|
||||
*/
|
||||
private long fileCountMax = -1;
|
||||
|
||||
|
@ -143,15 +131,14 @@ public abstract class AbstractFileUpload {
|
|||
/**
|
||||
* Gets the boundary from the {@code Content-type} header.
|
||||
*
|
||||
* @param contentType The value of the content type header from which to
|
||||
* extract the boundary value.
|
||||
* @param contentType The value of the content type header from which to extract the boundary value.
|
||||
* @return The boundary, as a byte array.
|
||||
*/
|
||||
public byte[] getBoundary(final String contentType) {
|
||||
final ParameterParser parser = new ParameterParser();
|
||||
parser.setLowerCaseNames(true);
|
||||
// Parameter parser can handle null input
|
||||
final Map<String, String> params = parser.parse(contentType, new char[] {';', ','});
|
||||
final Map<String, String> params = parser.parse(contentType, new char[] { ';', ',' });
|
||||
final String boundaryStr = params.get("boundary");
|
||||
|
||||
if (boundaryStr == null) {
|
||||
|
@ -163,8 +150,7 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the field name from the {@code Content-disposition}
|
||||
* header.
|
||||
* Gets the field name from the {@code Content-disposition} header.
|
||||
*
|
||||
* @param headers A {@code Map} containing the HTTP request headers.
|
||||
* @return The field name for the current {@code encapsulation}.
|
||||
|
@ -174,16 +160,14 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the field name, which is given by the content-disposition
|
||||
* header.
|
||||
* Gets the field name, which is given by the content-disposition header.
|
||||
*
|
||||
* @param contentDisposition The content-dispositions header value.
|
||||
* @return The field jake
|
||||
*/
|
||||
private String getFieldName(final String contentDisposition) {
|
||||
String fieldName = null;
|
||||
if (contentDisposition != null
|
||||
&& contentDisposition.toLowerCase(Locale.ENGLISH).startsWith(FORM_DATA)) {
|
||||
if (contentDisposition != null && contentDisposition.toLowerCase(Locale.ENGLISH).startsWith(FORM_DATA)) {
|
||||
final ParameterParser parser = new ParameterParser();
|
||||
parser.setLowerCaseNames(true);
|
||||
// Parameter parser can handle null input
|
||||
|
@ -213,8 +197,7 @@ public abstract class AbstractFileUpload {
|
|||
public abstract FileItemFactory getFileItemFactory();
|
||||
|
||||
/**
|
||||
* Gets the file name from the {@code Content-disposition}
|
||||
* header.
|
||||
* Gets the file name from the {@code Content-disposition} header.
|
||||
*
|
||||
* @param headers The HTTP headers object.
|
||||
*
|
||||
|
@ -226,6 +209,7 @@ public abstract class AbstractFileUpload {
|
|||
|
||||
/**
|
||||
* Gets the given content-disposition headers file name.
|
||||
*
|
||||
* @param contentDisposition The content-disposition headers value.
|
||||
* @return The file name
|
||||
*/
|
||||
|
@ -255,8 +239,7 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum allowed size of a single uploaded file,
|
||||
* as opposed to {@link #getSizeMax()}.
|
||||
* Gets the maximum allowed size of a single uploaded file, as opposed to {@link #getSizeMax()}.
|
||||
*
|
||||
* @see #setFileSizeMax(long)
|
||||
* @return Maximum size of a single uploaded file.
|
||||
|
@ -266,10 +249,8 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding used when reading the headers of an
|
||||
* individual part. When not specified, or {@code null}, the request
|
||||
* encoding is used. If that is also not specified, or {@code null},
|
||||
* the platform default encoding is used.
|
||||
* Gets the character encoding used when reading the headers of an individual part. When not specified, or {@code null}, the request encoding is used. If
|
||||
* that is also not specified, or {@code null}, the platform default encoding is used.
|
||||
*
|
||||
* @return The encoding used to read part headers.
|
||||
*/
|
||||
|
@ -278,32 +259,25 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param ctx The context for the request to be parsed.
|
||||
* @return An iterator to instances of {@code FileItemStream}
|
||||
* 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.
|
||||
* @return An iterator to instances of {@code FileItemStream} 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(final RequestContext ctx) throws FileUploadException, IOException {
|
||||
return new FileItemIteratorImpl(this, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@code header-part} and returns as key/value
|
||||
* pairs.
|
||||
* Parses the {@code header-part} and returns as key/value pairs.
|
||||
* <p>
|
||||
* If there are multiple headers of the same names, the name
|
||||
* will map to a comma-separated list containing the values.
|
||||
* If there are multiple headers of the same names, the name will map to a comma-separated list containing the values.
|
||||
* </p>
|
||||
* @param headerPart The {@code header-part} of the current
|
||||
* {@code encapsulation}.
|
||||
*
|
||||
* @param headerPart The {@code header-part} of the current {@code encapsulation}.
|
||||
* @return A {@code Map} containing the parsed HTTP request headers.
|
||||
*/
|
||||
public FileItemHeaders getParsedHeaders(final String headerPart) {
|
||||
|
@ -321,7 +295,7 @@ public abstract class AbstractFileUpload {
|
|||
int nonWs = start;
|
||||
while (nonWs < len) {
|
||||
final char c = headerPart.charAt(nonWs);
|
||||
if (c != ' ' && c != '\t') {
|
||||
if (c != ' ' && c != '\t') {
|
||||
break;
|
||||
}
|
||||
++nonWs;
|
||||
|
@ -349,11 +323,9 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum allowed size of a complete request, as opposed
|
||||
* to {@link #getFileSizeMax()}.
|
||||
* Gets the maximum allowed size of a complete request, as opposed to {@link #getFileSizeMax()}.
|
||||
*
|
||||
* @return The maximum allowed size, in bytes. The default value of
|
||||
* -1 indicates, that there is no limit.
|
||||
* @return The maximum allowed size, in bytes. The default value of -1 indicates, that there is no limit.
|
||||
* @see #setSizeMax(long)
|
||||
*
|
||||
*/
|
||||
|
@ -363,6 +335,7 @@ public abstract class AbstractFileUpload {
|
|||
|
||||
/**
|
||||
* Creates a new instance of {@link FileItemHeaders}.
|
||||
*
|
||||
* @return The new instance.
|
||||
*/
|
||||
protected FileItemHeadersImpl newFileItemHeaders() {
|
||||
|
@ -373,18 +346,15 @@ public abstract class AbstractFileUpload {
|
|||
* Skips bytes until the end of the current line.
|
||||
*
|
||||
* @param headerPart The headers, which are being parsed.
|
||||
* @param end Index of the last byte, which has yet been
|
||||
* processed.
|
||||
* @return Index of the \r\n sequence, which indicates
|
||||
* end of line.
|
||||
* @param end Index of the last byte, which has yet been processed.
|
||||
* @return Index of the \r\n sequence, which indicates end of line.
|
||||
*/
|
||||
private int parseEndOfLine(final String headerPart, final int end) {
|
||||
int index = end;
|
||||
for (;;) {
|
||||
final int offset = headerPart.indexOf('\r', index);
|
||||
if (offset == -1 || offset + 1 >= headerPart.length()) {
|
||||
throw new IllegalStateException(
|
||||
"Expected headers to be terminated by an empty line.");
|
||||
if (offset == -1 || offset + 1 >= headerPart.length()) {
|
||||
throw new IllegalStateException("Expected headers to be terminated by an empty line.");
|
||||
}
|
||||
if (headerPart.charAt(offset + 1) == '\n') {
|
||||
return offset;
|
||||
|
@ -397,7 +367,7 @@ public abstract class AbstractFileUpload {
|
|||
* Parses the next header line.
|
||||
*
|
||||
* @param headers String with all headers.
|
||||
* @param header Map where to store the current header.
|
||||
* @param header Map where to store the current header.
|
||||
*/
|
||||
private void parseHeaderLine(final FileItemHeadersImpl headers, final String header) {
|
||||
final int colonOffset = header.indexOf(':');
|
||||
|
@ -406,23 +376,19 @@ public abstract class AbstractFileUpload {
|
|||
return;
|
||||
}
|
||||
final String headerName = header.substring(0, colonOffset).trim();
|
||||
final String headerValue =
|
||||
header.substring(colonOffset + 1).trim();
|
||||
final String headerValue = header.substring(colonOffset + 1).trim();
|
||||
headers.addHeader(headerName, headerValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param ctx The context for the request to be parsed.
|
||||
* @return A map of {@code FileItem} instances parsed from the request.
|
||||
* @throws FileUploadException if there are problems reading/parsing
|
||||
* the request or storing files.
|
||||
* @throws FileUploadException if there are problems reading/parsing the request or storing files.
|
||||
* @since 1.3
|
||||
*/
|
||||
public Map<String, List<FileItem>> parseParameterMap(final RequestContext ctx)
|
||||
throws FileUploadException {
|
||||
public Map<String, List<FileItem>> parseParameterMap(final RequestContext ctx) throws FileUploadException {
|
||||
final List<FileItem> items = parseRequest(ctx);
|
||||
final Map<String, List<FileItem>> itemsMap = new HashMap<>(items.size());
|
||||
|
||||
|
@ -437,17 +403,13 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param ctx The context for the request to be parsed.
|
||||
* @return A list of {@code FileItem} 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.
|
||||
* @return A list of {@code FileItem} 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(final RequestContext ctx)
|
||||
throws FileUploadException {
|
||||
public List<FileItem> parseRequest(final RequestContext ctx) throws FileUploadException {
|
||||
final List<FileItem> items = new ArrayList<>();
|
||||
boolean successful = false;
|
||||
try {
|
||||
|
@ -510,8 +472,7 @@ public abstract class AbstractFileUpload {
|
|||
public abstract void setFileItemFactory(FileItemFactory factory);
|
||||
|
||||
/**
|
||||
* Sets the maximum allowed size of a single uploaded file,
|
||||
* as opposed to {@link #getSizeMax()}.
|
||||
* Sets the maximum allowed size of a single uploaded file, as opposed to {@link #getSizeMax()}.
|
||||
*
|
||||
* @see #getFileSizeMax()
|
||||
* @param fileSizeMax Maximum size of a single uploaded file.
|
||||
|
@ -521,10 +482,8 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Specifies the character encoding to be used when reading the headers of
|
||||
* individual part. When not specified, or {@code null}, the request
|
||||
* encoding is used. If that is also not specified, or {@code null},
|
||||
* the platform default encoding is used.
|
||||
* Specifies the character encoding to be used when reading the headers of individual part. When not specified, or {@code null}, the request encoding is
|
||||
* used. If that is also not specified, or {@code null}, the platform default encoding is used.
|
||||
*
|
||||
* @param encoding The encoding used to read part headers.
|
||||
*/
|
||||
|
@ -542,11 +501,9 @@ public abstract class AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum allowed size of a complete request, as opposed
|
||||
* to {@link #setFileSizeMax(long)}.
|
||||
* Sets the maximum allowed size of a complete request, as opposed to {@link #setFileSizeMax(long)}.
|
||||
*
|
||||
* @param sizeMax The maximum allowed size, in bytes. The default value of
|
||||
* -1 indicates, that there is no limit.
|
||||
* @param sizeMax The maximum allowed size, in bytes. The default value of -1 indicates, that there is no limit.
|
||||
* @see #getSizeMax()
|
||||
*/
|
||||
public void setSizeMax(final long sizeMax) {
|
|
@ -39,7 +39,6 @@ public abstract class AbstractRequestContext implements RequestContext {
|
|||
* @param contentLengthDefault How to get the content length default.
|
||||
*/
|
||||
protected AbstractRequestContext(final Function<String, String> contentLengthString, final LongSupplier contentLengthDefault) {
|
||||
super();
|
||||
this.contentLengthString = contentLengthString;
|
||||
this.contentLengthDefault = contentLengthDefault;
|
||||
}
|
|
@ -29,7 +29,7 @@ import java.io.UnsupportedEncodingException;
|
|||
* </p>
|
||||
* <p>
|
||||
* After retrieving an instance of this class from a {@link org.apache.commons.fileupload2.FileUpload FileUpload} instance (see
|
||||
* {@link org.apache.commons.fileupload2.servlet.ServletFileUpload #parseRequest(javax.servlet.http.HttpServletRequest)}), you may either request all contents
|
||||
* {@code org.apache.commons.fileupload2.servlet.ServletFileUpload #parseRequest(javax.servlet.http.HttpServletRequest)}), you may either request all contents
|
||||
* of the file at once using {@link #get()} or request an {@link java.io.InputStream InputStream} with {@link #getInputStream()} and process the file without
|
||||
* attempting to load it into memory, which may come handy with large files.
|
||||
* </p>
|
||||
|
@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
|
|||
* specifically defined with the same signatures as methods in that interface. This allows an implementation of this interface to also implement
|
||||
* {@code javax.activation.DataSource} with minimal additional work.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.3 additionally implements FileItemHeadersSupport
|
||||
*/
|
||||
public interface FileItem extends FileItemHeadersSupport {
|
||||
|
@ -165,6 +166,7 @@ public interface FileItem extends FileItemHeadersSupport {
|
|||
* This method is not guaranteed to succeed if called more than once for the same item. This allows a particular implementation to use, for example, file
|
||||
* renaming, where possible, rather than copying all of the underlying data, thus gaining a significant performance benefit.
|
||||
* </p>
|
||||
*
|
||||
* @param file The {@code File} into which the uploaded item should be stored.
|
||||
* @throws IOException if an error occurs.
|
||||
*/
|
|
@ -33,13 +33,10 @@ public interface FileItemHeadersSupport {
|
|||
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.
|
||||
* 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.
|
||||
* @param headers the instance that holds onto the headers for this instance.
|
||||
*/
|
||||
void setHeaders(FileItemHeaders headers);
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.SizeLimitExceededException;
|
||||
|
||||
import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
|
||||
|
||||
/**
|
||||
* An iterator, as returned by {@link AbstractFileUpload#getItemIterator(RequestContext)}.
|
||||
*/
|
||||
public interface FileItemIterator {
|
||||
|
||||
List<FileItem> getFileItems() throws FileUploadException, IOException;
|
||||
|
||||
/**
|
||||
* Gets the maximum size of a single file. An {@link FileUploadByteCountLimitException} will be thrown, if there is an uploaded file, which is exceeding
|
||||
* this value. By default, this value will be copied from the {@link AbstractFileUpload#getFileSizeMax() FileUploadBase} object, however, the user may
|
||||
* replace the default value with a request specific value by invoking {@link #setFileSizeMax(long)} on this object.
|
||||
*
|
||||
* @return The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
|
||||
*/
|
||||
long getFileSizeMax();
|
||||
|
||||
/**
|
||||
* Gets the maximum size of the complete HTTP request. A {@link SizeLimitExceededException} will be thrown, if the HTTP request will exceed this value. By
|
||||
* default, this value will be copied from the {@link AbstractFileUpload#getSizeMax() FileUploadBase} object, however, the user may replace the default
|
||||
* value with a request specific value by invoking {@link #setSizeMax(long)} on this object.
|
||||
*
|
||||
* @return The maximum size of the complete HTTP request. The value -1 indicates "unlimited".
|
||||
*/
|
||||
long getSizeMax();
|
||||
|
||||
/**
|
||||
* Tests whether another instance of {@link FileItemStream} is available.
|
||||
*
|
||||
* @throws FileUploadException Parsing or processing the file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return True, if one or more additional file items are available, otherwise false.
|
||||
*/
|
||||
boolean hasNext() throws FileUploadException, IOException;
|
||||
|
||||
/**
|
||||
* Returns the next available {@link FileItemStream}.
|
||||
*
|
||||
* @throws java.util.NoSuchElementException No more items are available. Use {@link #hasNext()} to prevent this exception.
|
||||
* @throws FileUploadException Parsing or processing the file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return FileItemStream instance, which provides access to the next file item.
|
||||
*/
|
||||
FileItemStream next() throws FileUploadException, IOException;
|
||||
|
||||
/**
|
||||
* Sets the maximum size of a single file. An {@link FileUploadByteCountLimitException} will be thrown, if there is an uploaded file, which is exceeding
|
||||
* this value. By default, this value will be copied from the {@link AbstractFileUpload#getFileSizeMax() FileUploadBase} object, however, the user may
|
||||
* replace the default value with a request specific value by invoking {@link #setFileSizeMax(long)} on this object, so there is no need to configure it
|
||||
* here.
|
||||
* <p>
|
||||
* <em>Note:</em> Changing this value doesn't affect files, that have already been uploaded.
|
||||
* </p>
|
||||
*
|
||||
* @param fileSizeMax The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
|
||||
*/
|
||||
void setFileSizeMax(long fileSizeMax);
|
||||
|
||||
/**
|
||||
* Sets the maximum size of the complete HTTP request. A {@link SizeLimitExceededException} will be thrown, if the HTTP request will exceed this value. By
|
||||
* default, this value will be copied from the {@link AbstractFileUpload#getSizeMax() FileUploadBase} object, however, the user may replace the default
|
||||
* value with a request specific value by invoking {@link #setSizeMax(long)} on this object.
|
||||
* <p>
|
||||
* <em>Note:</em> Setting the maximum size on this object will work only, if the iterator is not yet initialized. In other words: If the methods
|
||||
* {@link #hasNext()}, {@link #next()} have not yet been invoked.
|
||||
* </p>
|
||||
*
|
||||
* @param sizeMax The maximum size of the complete HTTP request. The value -1 indicates "unlimited".
|
||||
*/
|
||||
void setSizeMax(long sizeMax);
|
||||
}
|
|
@ -20,85 +20,69 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Provides access to a file or form item that was
|
||||
* received within a {@code multipart/form-data} POST request.
|
||||
* Provides access to a file or form item that was received within a {@code multipart/form-data} POST request.
|
||||
* <p>
|
||||
* The items contents are retrieved by calling {@link #openStream()}.
|
||||
* </p>
|
||||
* <p>Instances of this class are created by accessing the
|
||||
* iterator, returned by
|
||||
* {@link AbstractFileUpload#getItemIterator(RequestContext)}.
|
||||
* <p>
|
||||
* Instances of this class are created by accessing the iterator, returned by {@link AbstractFileUpload#getItemIterator(RequestContext)}.
|
||||
* </p>
|
||||
* <p><em>Note</em>: There is an interaction between the iterator and
|
||||
* its associated instances of {@link FileItemStream}: By invoking
|
||||
* {@link java.util.Iterator#hasNext()} on the iterator, you discard all data,
|
||||
* which hasn't been read so far from the previous data.
|
||||
* <p>
|
||||
* <em>Note</em>: There is an interaction between the iterator and its associated instances of {@link FileItemStream}: By invoking
|
||||
* {@link java.util.Iterator#hasNext()} on the iterator, you discard all data, which hasn't been read so far from the previous data.
|
||||
* </p>
|
||||
*/
|
||||
public interface FileItemStream extends FileItemHeadersSupport {
|
||||
|
||||
/**
|
||||
* This exception is thrown, if an attempt is made to read
|
||||
* data from the {@link InputStream}, which has been returned
|
||||
* by {@link FileItemStream#openStream()}, after
|
||||
* {@link java.util.Iterator#hasNext()} has been invoked on the
|
||||
* iterator, which created the {@link FileItemStream}.
|
||||
* This exception is thrown, if an attempt is made to read data from the {@link InputStream}, which has been returned by
|
||||
* {@link FileItemStream#openStream()}, after {@link java.util.Iterator#hasNext()} has been invoked on the iterator, which created the
|
||||
* {@link FileItemStream}.
|
||||
*/
|
||||
class ItemSkippedException extends IOException {
|
||||
|
||||
/**
|
||||
* The exceptions serial version UID, which is being used
|
||||
* when serializing an exception instance.
|
||||
* The exceptions serial version UID, which is being used when serializing an exception instance.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type passed by the browser or {@code null} if
|
||||
* not defined.
|
||||
* Gets the content type passed by the browser or {@code null} if not defined.
|
||||
*
|
||||
* @return The content type passed by the browser or {@code null} if
|
||||
* not defined.
|
||||
* @return The content type passed by the browser or {@code null} if not defined.
|
||||
*/
|
||||
String getContentType();
|
||||
|
||||
/**
|
||||
* Gets the name of the field in the multipart form corresponding to
|
||||
* this file item.
|
||||
* Gets the name of the field in the multipart form corresponding to this file item.
|
||||
*
|
||||
* @return The name of the form field.
|
||||
*/
|
||||
String getFieldName();
|
||||
|
||||
/**
|
||||
* Gets the original file name in the client's file system, as provided by
|
||||
* the browser (or other client software). In most cases, this will be the
|
||||
* base file name, without path information. However, some clients, such as
|
||||
* the Opera browser, do include path information.
|
||||
* Gets the original file name in the client's file system, as provided by the browser (or other client software). In most cases, this will be the base file
|
||||
* name, without path information. However, some clients, such as the Opera browser, do include path information.
|
||||
*
|
||||
* @return The original file name in the client's file system.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Tests whether or not a {@code FileItem} instance represents
|
||||
* a simple form field.
|
||||
* Tests whether or not a {@code FileItem} instance represents a simple form field.
|
||||
*
|
||||
* @return {@code true} if the instance represents a simple form
|
||||
* field; {@code false} if it represents an uploaded file.
|
||||
* @return {@code true} if the instance represents a simple form field; {@code false} if it represents an uploaded file.
|
||||
*/
|
||||
boolean isFormField();
|
||||
|
||||
/**
|
||||
* Opens an {@link InputStream}, which allows to read the
|
||||
* items contents.
|
||||
* Opens an {@link InputStream}, which allows to read the items contents.
|
||||
*
|
||||
* @return The input stream, from which the items data may
|
||||
* be read.
|
||||
* @throws IllegalStateException The method was already invoked on
|
||||
* this item. It is not possible to recreate the data stream.
|
||||
* @throws IOException An I/O error occurred.
|
||||
* @return The input stream, from which the items data may be read.
|
||||
* @throws IllegalStateException The method was already invoked on this item. It is not possible to recreate the data stream.
|
||||
* @throws IOException An I/O error occurred.
|
||||
* @see ItemSkippedException
|
||||
*/
|
||||
InputStream openStream() throws IOException;
|
|
@ -17,18 +17,19 @@
|
|||
package org.apache.commons.fileupload2;
|
||||
|
||||
/**
|
||||
* <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
|
||||
* {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
|
||||
* #parseRequest(RequestContext)} to acquire a list
|
||||
* of {@link org.apache.commons.fileupload2.FileItem FileItems} associated
|
||||
* with a given HTML widget.</p>
|
||||
* <p>
|
||||
* This class handles multiple files per single HTML widget, sent using {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link #parseRequest(RequestContext)} to acquire a list of
|
||||
* {@link org.apache.commons.fileupload2.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>
|
||||
* <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>
|
||||
*/
|
||||
public class FileUpload extends AbstractFileUpload {
|
||||
|
||||
|
@ -40,9 +41,7 @@ public class FileUpload extends AbstractFileUpload {
|
|||
/**
|
||||
* Constructs an uninitialized instance of this class.
|
||||
*
|
||||
* A factory must be
|
||||
* configured, using {@code setFileItemFactory()}, before attempting
|
||||
* to parse requests.
|
||||
* A factory must be configured, using {@code setFileItemFactory()}, before attempting to parse requests.
|
||||
*
|
||||
* @see #FileUpload(FileItemFactory)
|
||||
*/
|
||||
|
@ -50,8 +49,7 @@ public class FileUpload extends AbstractFileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class which uses the supplied factory to
|
||||
* create {@code FileItem} instances.
|
||||
* Constructs an instance of this class which uses the supplied factory to create {@code FileItem} instances.
|
||||
*
|
||||
* @see #FileUpload()
|
||||
* @param fileItemFactory The factory to use for creating file items.
|
|
@ -17,20 +17,14 @@
|
|||
package org.apache.commons.fileupload2;
|
||||
|
||||
/**
|
||||
* Signals 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.
|
||||
* Signals 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.
|
||||
*/
|
||||
public class InvalidFileNameException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Serial version UID, being used, if the exception
|
||||
* is serialized.
|
||||
* Serial version UID, being used, if the exception is serialized.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
|
@ -42,7 +36,7 @@ public class InvalidFileNameException extends RuntimeException {
|
|||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param name The file name causing the exception.
|
||||
* @param name The file name causing the exception.
|
||||
* @param message A human readable error message.
|
||||
*/
|
||||
public InvalidFileNameException(final String name, final String message) {
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -59,6 +58,7 @@ import org.apache.commons.io.output.NullOutputStream;
|
|||
* <p>
|
||||
* Here is an example of usage of this class:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* try {
|
||||
* MultipartStream multipartStream = new MultipartStream(input, boundary);
|
||||
|
@ -398,8 +398,8 @@ public class MultipartStream {
|
|||
/**
|
||||
* Creates a new instance with the given listener and content length.
|
||||
*
|
||||
* @param progressListener The listener to invoke.
|
||||
* @param contentLength The expected content length.
|
||||
* @param progressListener The listener to invoke.
|
||||
* @param contentLength The expected content length.
|
||||
*/
|
||||
public ProgressNotifier(final ProgressListener progressListener, final long contentLength) {
|
||||
this.progressListener = progressListener;
|
||||
|
@ -557,18 +557,17 @@ public class MultipartStream {
|
|||
*/
|
||||
private final ProgressNotifier notifier;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a {@code MultipartStream} with a custom size buffer.
|
||||
* <p>
|
||||
* Note that the buffer must be at least big enough to contain the boundary string, plus 4 characters for CR/LF and double dash, plus at least one byte of
|
||||
* data. Too small a buffer size setting will degrade performance.
|
||||
* </p>
|
||||
* @param input The {@code InputStream} to serve as a data source.
|
||||
* @param boundary The token used for dividing the stream into {@code encapsulations}.
|
||||
* @param bufferSize The size of the buffer to be used, in bytes.
|
||||
* @param notifier The notifier, which is used for calling the progress listener, if any.
|
||||
*
|
||||
* @param input The {@code InputStream} to serve as a data source.
|
||||
* @param boundary The token used for dividing the stream into {@code encapsulations}.
|
||||
* @param bufferSize The size of the buffer to be used, in bytes.
|
||||
* @param notifier The notifier, which is used for calling the progress listener, if any.
|
||||
* @throws IllegalArgumentException If the buffer size is too small.
|
||||
* @since 1.3.1
|
||||
*/
|
||||
|
@ -604,8 +603,8 @@ public class MultipartStream {
|
|||
/**
|
||||
* Constructs a {@code MultipartStream} with a default size buffer.
|
||||
*
|
||||
* @param input The {@code InputStream} to serve as a data source.
|
||||
* @param boundary The token used for dividing the stream into {@code encapsulations}.
|
||||
* @param input The {@code InputStream} to serve as a data source.
|
||||
* @param boundary The token used for dividing the stream into {@code encapsulations}.
|
||||
* @param progressNotifier An object for calling the progress listener, if any.
|
||||
* @see #MultipartStream(InputStream, byte[], int, ProgressNotifier)
|
||||
*/
|
||||
|
@ -642,6 +641,7 @@ public class MultipartStream {
|
|||
* <p>
|
||||
* Use this method to skip encapsulations you don't need or don't understand.
|
||||
* </p>
|
||||
*
|
||||
* @return The amount of data discarded.
|
||||
* @throws MalformedStreamException if the stream ends unexpectedly.
|
||||
* @throws IOException if an i/o error occurs.
|
||||
|
@ -692,8 +692,8 @@ public class MultipartStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding used when reading the headers of an individual part. When not specified, or {@code null}, the platform default encoding
|
||||
* is used.
|
||||
* Gets the character encoding used when reading the headers of an individual part. When not specified, or {@code null}, the platform default encoding is
|
||||
* used.
|
||||
*
|
||||
* @return The encoding used to read part headers.
|
||||
*/
|
||||
|
@ -716,6 +716,7 @@ public class MultipartStream {
|
|||
* Arbitrary large amounts of data can be processed by this method using a constant size buffer. (see
|
||||
* {@link #MultipartStream(InputStream,byte[],int, MultipartStream.ProgressNotifier) constructor}).
|
||||
* </p>
|
||||
*
|
||||
* @param output The {@code Stream} to write data into. May be null, in which case this method is equivalent to {@link #discardBodyData()}.
|
||||
* @return the amount of data written.
|
||||
* @throws MalformedStreamException if the stream ends unexpectedly.
|
||||
|
@ -798,6 +799,7 @@ public class MultipartStream {
|
|||
* <p>
|
||||
* <strong>TODO</strong> allow limiting maximum header size to protect against abuse.
|
||||
* </p>
|
||||
*
|
||||
* @return The {@code header-part} of the current encapsulation.
|
||||
* @throws FileUploadSizeException if the bytes read from the stream exceeded the size limits.
|
||||
* @throws MalformedStreamException if the stream ends unexpectedly.
|
||||
|
@ -856,6 +858,7 @@ public class MultipartStream {
|
|||
* <p>
|
||||
* Restoring the parent stream boundary token after processing of a nested stream is left to the application.
|
||||
* </p>
|
||||
*
|
||||
* @param boundary The boundary to be used for parsing of the nested stream.
|
||||
* @throws FileUploadBoundaryException if the {@code boundary} has a different length than the one being currently parsed.
|
||||
*/
|
||||
|
@ -868,8 +871,8 @@ public class MultipartStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the character encoding to be used when reading the headers of individual parts. When not specified, or {@code null}, the platform default
|
||||
* encoding is used.
|
||||
* Sets the character encoding to be used when reading the headers of individual parts. When not specified, or {@code null}, the platform default encoding
|
||||
* is used.
|
||||
*
|
||||
* @param encoding The encoding used to read part headers.
|
||||
*/
|
|
@ -27,9 +27,8 @@ import org.apache.commons.fileupload2.util.mime.RFC2231Utility;
|
|||
/**
|
||||
* A simple parser intended to parse sequences of name/value pairs.
|
||||
* <p>
|
||||
* Parameter values are expected to be enclosed in quotes if they
|
||||
* contain unsafe characters, such as '=' characters or separators.
|
||||
* Parameter values are optional and can be omitted.
|
||||
* Parameter values are expected to be enclosed in quotes if they contain unsafe characters, such as '=' characters or separators. Parameter values are optional
|
||||
* and can be omitted.
|
||||
* </p>
|
||||
* <p>
|
||||
* {@code param1 = value; param2 = "anything goes; really"; param3}
|
||||
|
@ -74,12 +73,9 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* A helper method to process the parsed token. This method removes
|
||||
* leading and trailing blanks as well as enclosing quotation marks,
|
||||
* when necessary.
|
||||
* A helper method to process the parsed token. This method removes leading and trailing blanks as well as enclosing quotation marks, when necessary.
|
||||
*
|
||||
* @param quoted {@code true} if quotation marks are expected,
|
||||
* {@code false} otherwise.
|
||||
* @param quoted {@code true} if quotation marks are expected, {@code false} otherwise.
|
||||
* @return the token
|
||||
*/
|
||||
private String getToken(final boolean quoted) {
|
||||
|
@ -92,10 +88,7 @@ public class ParameterParser {
|
|||
i2--;
|
||||
}
|
||||
// Strip away quotation marks if necessary
|
||||
if (quoted
|
||||
&& ((i2 - i1) >= 2)
|
||||
&& (chars[i1] == '"')
|
||||
&& (chars[i2 - 1] == '"')) {
|
||||
if (quoted && ((i2 - i1) >= 2) && (chars[i1] == '"') && (chars[i2 - 1] == '"')) {
|
||||
i1++;
|
||||
i2--;
|
||||
}
|
||||
|
@ -109,20 +102,16 @@ public class ParameterParser {
|
|||
/**
|
||||
* Tests if there any characters left to parse.
|
||||
*
|
||||
* @return {@code true} if there are unparsed characters,
|
||||
* {@code false} otherwise.
|
||||
* @return {@code true} if there are unparsed characters, {@code false} otherwise.
|
||||
*/
|
||||
private boolean hasChar() {
|
||||
return this.pos < this.len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@code true} if parameter names are to be converted to lower
|
||||
* case when name/value pairs are parsed.
|
||||
* Tests {@code true} if parameter names are to be converted to lower case when name/value pairs are parsed.
|
||||
*
|
||||
* @return {@code true} if parameter names are to be
|
||||
* converted to lower case when name/value pairs are parsed.
|
||||
* Otherwise returns {@code false}
|
||||
* @return {@code true} if parameter names are to be converted to lower case when name/value pairs are parsed. Otherwise returns {@code false}
|
||||
*/
|
||||
public boolean isLowerCaseNames() {
|
||||
return this.lowerCaseNames;
|
||||
|
@ -131,10 +120,9 @@ public class ParameterParser {
|
|||
/**
|
||||
* Tests if the given character is present in the array of characters.
|
||||
*
|
||||
* @param ch the character to test for presence in the array of characters
|
||||
* @param ch the character to test for presence in the array of characters
|
||||
* @param charray the array of characters to test against
|
||||
* @return {@code true} if the character is present in the array of
|
||||
* characters, {@code false} otherwise.
|
||||
* @return {@code true} if the character is present in the array of characters, {@code false} otherwise.
|
||||
*/
|
||||
private boolean isOneOf(final char ch, final char[] charray) {
|
||||
boolean result = false;
|
||||
|
@ -148,11 +136,9 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Extracts a map of name/value pairs from the given array of
|
||||
* characters. Names are expected to be unique.
|
||||
* Extracts a map of name/value pairs from the given array of characters. Names are expected to be unique.
|
||||
*
|
||||
* @param charArray the array of characters that contains a sequence of
|
||||
* name/value pairs
|
||||
* @param charArray the array of characters that contains a sequence of name/value pairs
|
||||
* @param separator the name/value pairs separator
|
||||
* @return a map of name/value pairs
|
||||
*/
|
||||
|
@ -164,21 +150,15 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Extracts a map of name/value pairs from the given array of
|
||||
* characters. Names are expected to be unique.
|
||||
* Extracts a map of name/value pairs from the given array of characters. Names are expected to be unique.
|
||||
*
|
||||
* @param charArray the array of characters that contains a sequence of
|
||||
* name/value pairs
|
||||
* @param offset - the initial offset.
|
||||
* @param length - the length.
|
||||
* @param charArray the array of characters that contains a sequence of name/value pairs
|
||||
* @param offset - the initial offset.
|
||||
* @param length - the length.
|
||||
* @param separator the name/value pairs separator
|
||||
* @return a map of name/value pairs
|
||||
*/
|
||||
public Map<String, String> parse(
|
||||
final char[] charArray,
|
||||
final int offset,
|
||||
final int length,
|
||||
final char separator) {
|
||||
public Map<String, String> parse(final char[] charArray, final int offset, final int length, final char separator) {
|
||||
|
||||
if (charArray == null) {
|
||||
return new HashMap<>();
|
||||
|
@ -191,18 +171,15 @@ public class ParameterParser {
|
|||
String paramName;
|
||||
String paramValue;
|
||||
while (hasChar()) {
|
||||
paramName = parseToken(new char[] {
|
||||
'=', separator });
|
||||
paramName = parseToken(new char[] { '=', separator });
|
||||
paramValue = null;
|
||||
if (hasChar() && (charArray[pos] == '=')) {
|
||||
pos++; // skip '='
|
||||
paramValue = parseQuotedToken(new char[] {
|
||||
separator });
|
||||
paramValue = parseQuotedToken(new char[] { separator });
|
||||
|
||||
if (paramValue != null) {
|
||||
try {
|
||||
paramValue = RFC2231Utility.hasEncodedValue(paramName) ? RFC2231Utility.decodeText(paramValue)
|
||||
: MimeUtility.decodeText(paramValue);
|
||||
paramValue = RFC2231Utility.hasEncodedValue(paramName) ? RFC2231Utility.decodeText(paramValue) : MimeUtility.decodeText(paramValue);
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
// let's keep the original value in this case
|
||||
}
|
||||
|
@ -223,10 +200,9 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Extracts a map of name/value pairs from the given string. Names are
|
||||
* expected to be unique.
|
||||
* Extracts a map of name/value pairs from the given string. Names are expected to be unique.
|
||||
*
|
||||
* @param str the string that contains a sequence of name/value pairs
|
||||
* @param str the string that contains a sequence of name/value pairs
|
||||
* @param separator the name/value pairs separator
|
||||
* @return a map of name/value pairs
|
||||
*/
|
||||
|
@ -238,11 +214,10 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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 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
|
||||
*/
|
||||
|
@ -265,12 +240,9 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses out a token until any of the given terminators
|
||||
* is encountered outside the quotation marks.
|
||||
* Parses out a token until any of the given terminators is encountered outside the quotation marks.
|
||||
*
|
||||
* @param terminators the array of terminating characters. Any of these
|
||||
* characters when encountered outside the quotation marks signify the end
|
||||
* of the token
|
||||
* @param terminators the array of terminating characters. Any of these characters when encountered outside the quotation marks signify the end of the token
|
||||
* @return the token
|
||||
*/
|
||||
private String parseQuotedToken(final char[] terminators) {
|
||||
|
@ -296,11 +268,9 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses out a token until any of the given terminators
|
||||
* is encountered.
|
||||
* Parses out a token until any of the given terminators is encountered.
|
||||
*
|
||||
* @param terminators the array of terminating characters. Any of these
|
||||
* characters when encountered signify the end of the token
|
||||
* @param terminators the array of terminating characters. Any of these characters when encountered signify the end of the token
|
||||
* @return the token
|
||||
*/
|
||||
private String parseToken(final char[] terminators) {
|
||||
|
@ -319,12 +289,9 @@ public class ParameterParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the flag if parameter names are to be converted to lower case when
|
||||
* name/value pairs are parsed.
|
||||
* Sets the flag if parameter names are to be converted to lower case when name/value pairs are parsed.
|
||||
*
|
||||
* @param b {@code true} if parameter names are to be
|
||||
* converted to lower case when name/value pairs are parsed.
|
||||
* {@code false} otherwise.
|
||||
* @param b {@code true} if parameter names are to be converted to lower case when name/value pairs are parsed. {@code false} otherwise.
|
||||
*/
|
||||
public void setLowerCaseNames(final boolean b) {
|
||||
this.lowerCaseNames = b;
|
|
@ -24,6 +24,7 @@ import java.io.InputStream;
|
|||
* <p>
|
||||
* This interface should be implemented for each type of request that may be handled by FileUpload, such as servlets and portlets.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface RequestContext {
|
File diff suppressed because it is too large
Load Diff
|
@ -1,240 +1,199 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.disk;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileItemFactory;
|
||||
import org.apache.commons.io.FileCleaningTracker;
|
||||
|
||||
/**
|
||||
* The default {@link org.apache.commons.fileupload2.FileItemFactory}
|
||||
* implementation.
|
||||
* <p>
|
||||
* This implementation creates
|
||||
* {@link org.apache.commons.fileupload2.FileItem} instances which keep their
|
||||
* 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
|
||||
* disk, is configurable, as is the directory in which temporary files will be
|
||||
* created.
|
||||
* </p>
|
||||
* <p>
|
||||
* If not otherwise configured, the default configuration values are as
|
||||
* follows:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Size threshold is 10KB.</li>
|
||||
* <li>Repository is the system default temp directory, as returned by
|
||||
* {@code System.getProperty("java.io.tmpdir")}.</li>
|
||||
* </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}
|
||||
* may be used.
|
||||
* </p>
|
||||
* <p>
|
||||
* Temporary files, which are created for file items, should be
|
||||
* deleted later on. The best way to do this is using a
|
||||
* {@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.)
|
||||
* This is done by the so-called reaper thread, which is started and stopped
|
||||
* automatically by the {@link FileCleaningTracker} when there are files to be
|
||||
* tracked.
|
||||
* 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>
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class DiskFileItemFactory implements FileItemFactory {
|
||||
|
||||
/**
|
||||
* The default threshold above which uploads will be stored on disk.
|
||||
*/
|
||||
public static final int DEFAULT_SIZE_THRESHOLD = 10240;
|
||||
|
||||
/**
|
||||
* The directory in which uploaded files will be stored, if stored on disk.
|
||||
*/
|
||||
private File repository;
|
||||
|
||||
/**
|
||||
* The threshold above which uploads will be stored on disk.
|
||||
*/
|
||||
private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
|
||||
|
||||
/**
|
||||
* The instance of {@link FileCleaningTracker}, which is responsible
|
||||
* for deleting temporary files.
|
||||
* <p>
|
||||
* May be null, if tracking files is not required.
|
||||
* </p>
|
||||
*/
|
||||
private FileCleaningTracker fileCleaningTracker;
|
||||
|
||||
/**
|
||||
* Default content charset to be used when no explicit charset
|
||||
* parameter is provided by the sender.
|
||||
*/
|
||||
private String defaultCharset = DiskFileItem.DEFAULT_CHARSET;
|
||||
|
||||
/**
|
||||
* Constructs an unconfigured instance of this class. The resulting factory
|
||||
* may be configured by calling the appropriate setter methods.
|
||||
*/
|
||||
public DiskFileItemFactory() {
|
||||
this(DEFAULT_SIZE_THRESHOLD, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a preconfigured instance of this class.
|
||||
*
|
||||
* @param sizeThreshold The threshold, in bytes, below which items will be
|
||||
* retained in memory and above which they will be
|
||||
* stored as a file.
|
||||
* @param repository The data repository, which is the directory in
|
||||
* which files will be created, should the item size
|
||||
* exceed the threshold.
|
||||
*/
|
||||
public DiskFileItemFactory(final int sizeThreshold, final File repository) {
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link org.apache.commons.fileupload2.disk.DiskFileItem}
|
||||
* instance from the supplied parameters and the local factory
|
||||
* configuration.
|
||||
*
|
||||
* @param fieldName The name of the form field.
|
||||
* @param contentType The content type of the form field.
|
||||
* @param isFormField {@code true} if this is a plain form field;
|
||||
* {@code false} otherwise.
|
||||
* @param fileName The name of the uploaded file, if any, as supplied
|
||||
* by the browser or other client.
|
||||
* @return The newly created file item.
|
||||
*/
|
||||
@Override
|
||||
public FileItem createItem(final String fieldName, final String contentType,
|
||||
final boolean isFormField, final String fileName) {
|
||||
final DiskFileItem result = new DiskFileItem(fieldName, contentType,
|
||||
isFormField, fileName, sizeThreshold, repository);
|
||||
result.setDefaultCharset(defaultCharset);
|
||||
final FileCleaningTracker tracker = getFileCleaningTracker();
|
||||
if (tracker != null) {
|
||||
tracker.track(result.getTempFile(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default charset for use when no explicit charset
|
||||
* parameter is provided by the sender.
|
||||
*
|
||||
* @return the default charset
|
||||
*/
|
||||
public String getDefaultCharset() {
|
||||
return defaultCharset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory used to temporarily store files that are larger
|
||||
* than the configured size threshold.
|
||||
*
|
||||
* @return The directory in which temporary files will be located.
|
||||
* @see #setRepository(java.io.File)
|
||||
*/
|
||||
public File getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size threshold beyond which files are written directly to
|
||||
* disk. The default value is 10240 bytes.
|
||||
*
|
||||
* @return The size threshold, in bytes.
|
||||
* @see #setSizeThreshold(int)
|
||||
*/
|
||||
public int getSizeThreshold() {
|
||||
return sizeThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default charset for use when no explicit charset
|
||||
* parameter is provided by the sender.
|
||||
* @param charset the default charset
|
||||
*/
|
||||
public void setDefaultCharset(final String charset) {
|
||||
defaultCharset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tracker, which is responsible for deleting temporary
|
||||
* files.
|
||||
*
|
||||
* @param tracker An instance of {@link FileCleaningTracker},
|
||||
* which will from now on track the created files, or null
|
||||
* (default), to disable tracking.
|
||||
*/
|
||||
public void setFileCleaningTracker(final FileCleaningTracker tracker) {
|
||||
fileCleaningTracker = tracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory used to temporarily store files that are larger
|
||||
* than the configured size threshold.
|
||||
*
|
||||
* @param repository The directory in which temporary files will be located.
|
||||
* @see #getRepository()
|
||||
*/
|
||||
public void setRepository(final File repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size threshold beyond which files are written directly to disk.
|
||||
*
|
||||
* @param sizeThreshold The size threshold, in bytes.
|
||||
* @see #getSizeThreshold()
|
||||
*/
|
||||
public void setSizeThreshold(final int sizeThreshold) {
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.disk;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileItemFactory;
|
||||
import org.apache.commons.io.FileCleaningTracker;
|
||||
|
||||
/**
|
||||
* The default {@link org.apache.commons.fileupload2.FileItemFactory} implementation.
|
||||
* <p>
|
||||
* This implementation creates {@link org.apache.commons.fileupload2.FileItem} instances which keep their 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 disk, is configurable, as is the directory in which
|
||||
* temporary files will be created.
|
||||
* </p>
|
||||
* <p>
|
||||
* If not otherwise configured, the default configuration values are as follows:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Size threshold is 10KB.</li>
|
||||
* <li>Repository is the system default temp directory, as returned by {@code System.getProperty("java.io.tmpdir")}.</li>
|
||||
* </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} may be used.
|
||||
* </p>
|
||||
* <p>
|
||||
* Temporary files, which are created for file items, should be deleted later on. The best way to do this is using a {@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.) This is done by
|
||||
* the so-called reaper thread, which is started and stopped automatically by the {@link FileCleaningTracker} when there are files to be tracked. 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>
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class DiskFileItemFactory implements FileItemFactory {
|
||||
|
||||
/**
|
||||
* The default threshold above which uploads will be stored on disk.
|
||||
*/
|
||||
public static final int DEFAULT_SIZE_THRESHOLD = 10240;
|
||||
|
||||
/**
|
||||
* The directory in which uploaded files will be stored, if stored on disk.
|
||||
*/
|
||||
private File repository;
|
||||
|
||||
/**
|
||||
* The threshold above which uploads will be stored on disk.
|
||||
*/
|
||||
private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
|
||||
|
||||
/**
|
||||
* The instance of {@link FileCleaningTracker}, which is responsible for deleting temporary files.
|
||||
* <p>
|
||||
* May be null, if tracking files is not required.
|
||||
* </p>
|
||||
*/
|
||||
private FileCleaningTracker fileCleaningTracker;
|
||||
|
||||
/**
|
||||
* Default content charset to be used when no explicit charset parameter is provided by the sender.
|
||||
*/
|
||||
private String defaultCharset = DiskFileItem.DEFAULT_CHARSET;
|
||||
|
||||
/**
|
||||
* Constructs an unconfigured instance of this class. The resulting factory may be configured by calling the appropriate setter methods.
|
||||
*/
|
||||
public DiskFileItemFactory() {
|
||||
this(DEFAULT_SIZE_THRESHOLD, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a preconfigured instance of this class.
|
||||
*
|
||||
* @param sizeThreshold The threshold, in bytes, below which items will be retained in memory and above which they will be stored as a file.
|
||||
* @param repository The data repository, which is the directory in which files will be created, should the item size exceed the threshold.
|
||||
*/
|
||||
public DiskFileItemFactory(final int sizeThreshold, final File repository) {
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link org.apache.commons.fileupload2.disk.DiskFileItem} instance from the supplied parameters and the local factory configuration.
|
||||
*
|
||||
* @param fieldName The name of the form field.
|
||||
* @param contentType The content type of the form field.
|
||||
* @param isFormField {@code true} if this is a plain form field; {@code false} otherwise.
|
||||
* @param fileName The name of the uploaded file, if any, as supplied by the browser or other client.
|
||||
* @return The newly created file item.
|
||||
*/
|
||||
@Override
|
||||
public FileItem createItem(final String fieldName, final String contentType, final boolean isFormField, final String fileName) {
|
||||
final DiskFileItem result = new DiskFileItem(fieldName, contentType, isFormField, fileName, sizeThreshold, repository);
|
||||
result.setDefaultCharset(defaultCharset);
|
||||
final FileCleaningTracker tracker = getFileCleaningTracker();
|
||||
if (tracker != null) {
|
||||
tracker.track(result.getTempFile(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default charset for use when no explicit charset parameter is provided by the sender.
|
||||
*
|
||||
* @return the default charset
|
||||
*/
|
||||
public String getDefaultCharset() {
|
||||
return defaultCharset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory used to temporarily store files that are larger than the configured size threshold.
|
||||
*
|
||||
* @return The directory in which temporary files will be located.
|
||||
* @see #setRepository(java.io.File)
|
||||
*/
|
||||
public File getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size threshold beyond which files are written directly to disk. The default value is 10240 bytes.
|
||||
*
|
||||
* @return The size threshold, in bytes.
|
||||
* @see #setSizeThreshold(int)
|
||||
*/
|
||||
public int getSizeThreshold() {
|
||||
return sizeThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default charset for use when no explicit charset parameter is provided by the sender.
|
||||
*
|
||||
* @param charset the default charset
|
||||
*/
|
||||
public void setDefaultCharset(final String charset) {
|
||||
defaultCharset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tracker, which is responsible for deleting temporary files.
|
||||
*
|
||||
* @param tracker An instance of {@link FileCleaningTracker}, which will from now on track the created files, or null (default), to disable tracking.
|
||||
*/
|
||||
public void setFileCleaningTracker(final FileCleaningTracker tracker) {
|
||||
fileCleaningTracker = tracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory used to temporarily store files that are larger than the configured size threshold.
|
||||
*
|
||||
* @param repository The directory in which temporary files will be located.
|
||||
* @see #getRepository()
|
||||
*/
|
||||
public void setRepository(final File repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size threshold beyond which files are written directly to disk.
|
||||
*
|
||||
* @param sizeThreshold The size threshold, in bytes.
|
||||
* @see #getSizeThreshold()
|
||||
*/
|
||||
public void setSizeThreshold(final int sizeThreshold) {
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 org.apache.commons.fileupload2.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 org.apache.commons.fileupload2.disk.DiskFileItemFactory DiskFileItemFactory} would be created, configured, and then
|
||||
* passed to a {@link org.apache.commons.fileupload2.FileUpload FileUpload} implementation such as
|
||||
* {@code org.apache.commons.fileupload2.servlet.ServletFileUpload ServletFileUpload} or
|
||||
* {@code org.apache.commons.fileupload2.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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> for further details and examples of how to
|
||||
* use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.disk;
|
|
@ -1,332 +1,331 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.impl;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUpload;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileItemHeaders;
|
||||
import org.apache.commons.fileupload2.FileItemIterator;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.MultipartStream;
|
||||
import org.apache.commons.fileupload2.ProgressListener;
|
||||
import org.apache.commons.fileupload2.RequestContext;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadContentTypeException;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadSizeException;
|
||||
import org.apache.commons.fileupload2.util.LimitedInputStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* The iterator, which is returned by {@link AbstractFileUpload#getItemIterator(RequestContext)}.
|
||||
*/
|
||||
public class FileItemIteratorImpl implements FileItemIterator {
|
||||
|
||||
/**
|
||||
* The file uploads processing utility.
|
||||
*
|
||||
* @see AbstractFileUpload
|
||||
*/
|
||||
private final AbstractFileUpload fileUploadBase;
|
||||
|
||||
/**
|
||||
* The request context.
|
||||
*
|
||||
* @see RequestContext
|
||||
*/
|
||||
private final RequestContext ctx;
|
||||
|
||||
/**
|
||||
* The maximum allowed size of a complete request.
|
||||
*/
|
||||
private long sizeMax;
|
||||
|
||||
/**
|
||||
* The maximum allowed size of a single uploaded file.
|
||||
*/
|
||||
private long fileSizeMax;
|
||||
|
||||
/**
|
||||
* The multi part stream to process.
|
||||
*/
|
||||
private MultipartStream multiPartStream;
|
||||
|
||||
/**
|
||||
* The notifier, which used for triggering the {@link ProgressListener}.
|
||||
*/
|
||||
private MultipartStream.ProgressNotifier progressNotifier;
|
||||
|
||||
/**
|
||||
* The boundary, which separates the various parts.
|
||||
*/
|
||||
private byte[] multiPartBoundary;
|
||||
|
||||
/**
|
||||
* The item, which we currently process.
|
||||
*/
|
||||
private FileItemStreamImpl currentItem;
|
||||
|
||||
/**
|
||||
* The current items field name.
|
||||
*/
|
||||
private String currentFieldName;
|
||||
|
||||
/**
|
||||
* Whether we are currently skipping the preamble.
|
||||
*/
|
||||
private boolean skipPreamble;
|
||||
|
||||
/**
|
||||
* Whether the current item may still be read.
|
||||
*/
|
||||
private boolean itemValid;
|
||||
|
||||
/**
|
||||
* Whether we have seen the end of the file.
|
||||
*/
|
||||
private boolean eof;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param fileUploadBase Main processor.
|
||||
* @param requestContext The request context.
|
||||
* @throws FileUploadException An error occurred while parsing the request.
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
public FileItemIteratorImpl(final AbstractFileUpload fileUploadBase, final RequestContext requestContext) throws FileUploadException, IOException {
|
||||
this.fileUploadBase = fileUploadBase;
|
||||
this.sizeMax = fileUploadBase.getSizeMax();
|
||||
this.fileSizeMax = fileUploadBase.getFileSizeMax();
|
||||
this.ctx = Objects.requireNonNull(requestContext, "requestContext");
|
||||
this.skipPreamble = true;
|
||||
findNextItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the next item, if any.
|
||||
*
|
||||
* @return True, if an next item was found, otherwise false.
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
private boolean findNextItem() throws FileUploadException, IOException {
|
||||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
if (currentItem != null) {
|
||||
currentItem.close();
|
||||
currentItem = null;
|
||||
}
|
||||
final MultipartStream multi = getMultiPartStream();
|
||||
for (;;) {
|
||||
final boolean nextPart;
|
||||
if (skipPreamble) {
|
||||
nextPart = multi.skipPreamble();
|
||||
} else {
|
||||
nextPart = multi.readBoundary();
|
||||
}
|
||||
if (!nextPart) {
|
||||
if (currentFieldName == null) {
|
||||
// Outer multipart terminated -> No more data
|
||||
eof = true;
|
||||
return false;
|
||||
}
|
||||
// Inner multipart terminated -> Return to parsing the outer
|
||||
multi.setBoundary(multiPartBoundary);
|
||||
currentFieldName = null;
|
||||
continue;
|
||||
}
|
||||
final FileItemHeaders headers = fileUploadBase.getParsedHeaders(multi.readHeaders());
|
||||
if (currentFieldName == null) {
|
||||
// We're parsing the outer multipart
|
||||
final String fieldName = fileUploadBase.getFieldName(headers);
|
||||
if (fieldName != null) {
|
||||
final String subContentType = headers.getHeader(AbstractFileUpload.CONTENT_TYPE);
|
||||
if (subContentType != null && subContentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART_MIXED)) {
|
||||
currentFieldName = fieldName;
|
||||
// Multiple files associated with this field name
|
||||
final byte[] subBoundary = fileUploadBase.getBoundary(subContentType);
|
||||
multi.setBoundary(subBoundary);
|
||||
skipPreamble = true;
|
||||
continue;
|
||||
}
|
||||
final String fileName = fileUploadBase.getFileName(headers);
|
||||
currentItem = new FileItemStreamImpl(this, fileName, fieldName, headers.getHeader(AbstractFileUpload.CONTENT_TYPE), fileName == null,
|
||||
getContentLength(headers));
|
||||
currentItem.setHeaders(headers);
|
||||
progressNotifier.noteItem();
|
||||
itemValid = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
final String fileName = fileUploadBase.getFileName(headers);
|
||||
if (fileName != null) {
|
||||
currentItem = new FileItemStreamImpl(this, fileName, currentFieldName, headers.getHeader(AbstractFileUpload.CONTENT_TYPE), false,
|
||||
getContentLength(headers));
|
||||
currentItem.setHeaders(headers);
|
||||
progressNotifier.noteItem();
|
||||
itemValid = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
multi.discardBodyData();
|
||||
}
|
||||
}
|
||||
|
||||
private long getContentLength(final FileItemHeaders headers) {
|
||||
try {
|
||||
return Long.parseLong(headers.getHeader(AbstractFileUpload.CONTENT_LENGTH));
|
||||
} catch (final Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItem> getFileItems() throws FileUploadException, IOException {
|
||||
final List<FileItem> items = new ArrayList<>();
|
||||
while (hasNext()) {
|
||||
final FileItemStream fis = next();
|
||||
items.add(fileUploadBase.getFileItemFactory().createItem(fis.getFieldName(), fis.getContentType(), fis.isFormField(), fis.getName()));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFileSizeMax() {
|
||||
return fileSizeMax;
|
||||
}
|
||||
|
||||
public MultipartStream getMultiPartStream() throws FileUploadException, IOException {
|
||||
if (multiPartStream == null) {
|
||||
init(fileUploadBase, ctx);
|
||||
}
|
||||
return multiPartStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeMax() {
|
||||
return sizeMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether another instance of {@link FileItemStream} is available.
|
||||
*
|
||||
* @throws FileUploadException Parsing or processing the file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return True, if one or more additional file items are available, otherwise false.
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() throws FileUploadException, IOException {
|
||||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
if (itemValid) {
|
||||
return true;
|
||||
}
|
||||
return findNextItem();
|
||||
}
|
||||
|
||||
protected void init(final AbstractFileUpload fileUploadBase, final RequestContext requestContext) throws FileUploadException, IOException {
|
||||
final String contentType = ctx.getContentType();
|
||||
if ((null == contentType) || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART))) {
|
||||
throw new FileUploadContentTypeException(String.format("the request doesn't contain a %s or %s stream, content type header is %s",
|
||||
AbstractFileUpload.MULTIPART_FORM_DATA, AbstractFileUpload.MULTIPART_MIXED, contentType), contentType);
|
||||
}
|
||||
final long contentLengthInt = ctx.getContentLength();
|
||||
// @formatter:off
|
||||
final long requestSize = RequestContext.class.isAssignableFrom(ctx.getClass())
|
||||
// Inline conditional is OK here CHECKSTYLE:OFF
|
||||
? ctx.getContentLength()
|
||||
: contentLengthInt;
|
||||
// CHECKSTYLE:ON
|
||||
// @formatter:on
|
||||
final InputStream input; // N.B. this is eventually closed in MultipartStream processing
|
||||
if (sizeMax >= 0) {
|
||||
if (requestSize != -1 && requestSize > sizeMax) {
|
||||
throw new FileUploadSizeException(
|
||||
String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)", requestSize, sizeMax), sizeMax,
|
||||
requestSize);
|
||||
}
|
||||
// N.B. this is eventually closed in MultipartStream processing
|
||||
input = new LimitedInputStream(ctx.getInputStream(), sizeMax) {
|
||||
@Override
|
||||
protected void raiseError(final long maxLen, final long count) throws IOException {
|
||||
throw new FileUploadSizeException(
|
||||
String.format("The request was rejected because its size (%s) exceeds the configured maximum (%s)", count, maxLen), maxLen, count);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
input = ctx.getInputStream();
|
||||
}
|
||||
|
||||
String charEncoding = fileUploadBase.getHeaderEncoding();
|
||||
if (charEncoding == null) {
|
||||
charEncoding = ctx.getCharacterEncoding();
|
||||
}
|
||||
|
||||
multiPartBoundary = fileUploadBase.getBoundary(contentType);
|
||||
if (multiPartBoundary == null) {
|
||||
IOUtils.closeQuietly(input); // avoid possible resource leak
|
||||
throw new FileUploadException("the request was rejected because no multipart boundary was found");
|
||||
}
|
||||
|
||||
progressNotifier = new MultipartStream.ProgressNotifier(fileUploadBase.getProgressListener(), requestSize);
|
||||
try {
|
||||
multiPartStream = new MultipartStream(input, multiPartBoundary, progressNotifier);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
IOUtils.closeQuietly(input); // avoid possible resource leak
|
||||
throw new FileUploadContentTypeException(String.format("The boundary specified in the %s header is too long", AbstractFileUpload.CONTENT_TYPE), e);
|
||||
}
|
||||
multiPartStream.setHeaderEncoding(charEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available {@link FileItemStream}.
|
||||
*
|
||||
* @throws java.util.NoSuchElementException No more items are available. Use {@link #hasNext()} to prevent this exception.
|
||||
* @throws FileUploadException Parsing or processing the file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return FileItemStream instance, which provides access to the next file item.
|
||||
*/
|
||||
@Override
|
||||
public FileItemStream next() throws FileUploadException, IOException {
|
||||
if (eof || (!itemValid && !hasNext())) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
itemValid = false;
|
||||
return currentItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFileSizeMax(final long fileSizeMax) {
|
||||
this.fileSizeMax = fileSizeMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeMax(final long sizeMax) {
|
||||
this.sizeMax = sizeMax;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUpload;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileItemHeaders;
|
||||
import org.apache.commons.fileupload2.FileItemIterator;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.MultipartStream;
|
||||
import org.apache.commons.fileupload2.ProgressListener;
|
||||
import org.apache.commons.fileupload2.RequestContext;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadContentTypeException;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadSizeException;
|
||||
import org.apache.commons.fileupload2.util.LimitedInputStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* The iterator, which is returned by {@link AbstractFileUpload#getItemIterator(RequestContext)}.
|
||||
*/
|
||||
public class FileItemIteratorImpl implements FileItemIterator {
|
||||
|
||||
/**
|
||||
* The file uploads processing utility.
|
||||
*
|
||||
* @see AbstractFileUpload
|
||||
*/
|
||||
private final AbstractFileUpload fileUploadBase;
|
||||
|
||||
/**
|
||||
* The request context.
|
||||
*
|
||||
* @see RequestContext
|
||||
*/
|
||||
private final RequestContext ctx;
|
||||
|
||||
/**
|
||||
* The maximum allowed size of a complete request.
|
||||
*/
|
||||
private long sizeMax;
|
||||
|
||||
/**
|
||||
* The maximum allowed size of a single uploaded file.
|
||||
*/
|
||||
private long fileSizeMax;
|
||||
|
||||
/**
|
||||
* The multi part stream to process.
|
||||
*/
|
||||
private MultipartStream multiPartStream;
|
||||
|
||||
/**
|
||||
* The notifier, which used for triggering the {@link ProgressListener}.
|
||||
*/
|
||||
private MultipartStream.ProgressNotifier progressNotifier;
|
||||
|
||||
/**
|
||||
* The boundary, which separates the various parts.
|
||||
*/
|
||||
private byte[] multiPartBoundary;
|
||||
|
||||
/**
|
||||
* The item, which we currently process.
|
||||
*/
|
||||
private FileItemStreamImpl currentItem;
|
||||
|
||||
/**
|
||||
* The current items field name.
|
||||
*/
|
||||
private String currentFieldName;
|
||||
|
||||
/**
|
||||
* Whether we are currently skipping the preamble.
|
||||
*/
|
||||
private boolean skipPreamble;
|
||||
|
||||
/**
|
||||
* Whether the current item may still be read.
|
||||
*/
|
||||
private boolean itemValid;
|
||||
|
||||
/**
|
||||
* Whether we have seen the end of the file.
|
||||
*/
|
||||
private boolean eof;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param fileUploadBase Main processor.
|
||||
* @param requestContext The request context.
|
||||
* @throws FileUploadException An error occurred while parsing the request.
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
public FileItemIteratorImpl(final AbstractFileUpload fileUploadBase, final RequestContext requestContext) throws FileUploadException, IOException {
|
||||
this.fileUploadBase = fileUploadBase;
|
||||
this.sizeMax = fileUploadBase.getSizeMax();
|
||||
this.fileSizeMax = fileUploadBase.getFileSizeMax();
|
||||
this.ctx = Objects.requireNonNull(requestContext, "requestContext");
|
||||
this.skipPreamble = true;
|
||||
findNextItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the next item, if any.
|
||||
*
|
||||
* @return True, if an next item was found, otherwise false.
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
private boolean findNextItem() throws FileUploadException, IOException {
|
||||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
if (currentItem != null) {
|
||||
currentItem.close();
|
||||
currentItem = null;
|
||||
}
|
||||
final MultipartStream multi = getMultiPartStream();
|
||||
for (;;) {
|
||||
final boolean nextPart;
|
||||
if (skipPreamble) {
|
||||
nextPart = multi.skipPreamble();
|
||||
} else {
|
||||
nextPart = multi.readBoundary();
|
||||
}
|
||||
if (!nextPart) {
|
||||
if (currentFieldName == null) {
|
||||
// Outer multipart terminated -> No more data
|
||||
eof = true;
|
||||
return false;
|
||||
}
|
||||
// Inner multipart terminated -> Return to parsing the outer
|
||||
multi.setBoundary(multiPartBoundary);
|
||||
currentFieldName = null;
|
||||
continue;
|
||||
}
|
||||
final FileItemHeaders headers = fileUploadBase.getParsedHeaders(multi.readHeaders());
|
||||
if (currentFieldName == null) {
|
||||
// We're parsing the outer multipart
|
||||
final String fieldName = fileUploadBase.getFieldName(headers);
|
||||
if (fieldName != null) {
|
||||
final String subContentType = headers.getHeader(AbstractFileUpload.CONTENT_TYPE);
|
||||
if (subContentType != null && subContentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART_MIXED)) {
|
||||
currentFieldName = fieldName;
|
||||
// Multiple files associated with this field name
|
||||
final byte[] subBoundary = fileUploadBase.getBoundary(subContentType);
|
||||
multi.setBoundary(subBoundary);
|
||||
skipPreamble = true;
|
||||
continue;
|
||||
}
|
||||
final String fileName = fileUploadBase.getFileName(headers);
|
||||
currentItem = new FileItemStreamImpl(this, fileName, fieldName, headers.getHeader(AbstractFileUpload.CONTENT_TYPE), fileName == null,
|
||||
getContentLength(headers));
|
||||
currentItem.setHeaders(headers);
|
||||
progressNotifier.noteItem();
|
||||
itemValid = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
final String fileName = fileUploadBase.getFileName(headers);
|
||||
if (fileName != null) {
|
||||
currentItem = new FileItemStreamImpl(this, fileName, currentFieldName, headers.getHeader(AbstractFileUpload.CONTENT_TYPE), false,
|
||||
getContentLength(headers));
|
||||
currentItem.setHeaders(headers);
|
||||
progressNotifier.noteItem();
|
||||
itemValid = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
multi.discardBodyData();
|
||||
}
|
||||
}
|
||||
|
||||
private long getContentLength(final FileItemHeaders headers) {
|
||||
try {
|
||||
return Long.parseLong(headers.getHeader(AbstractFileUpload.CONTENT_LENGTH));
|
||||
} catch (final Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItem> getFileItems() throws FileUploadException, IOException {
|
||||
final List<FileItem> items = new ArrayList<>();
|
||||
while (hasNext()) {
|
||||
final FileItemStream fis = next();
|
||||
items.add(fileUploadBase.getFileItemFactory().createItem(fis.getFieldName(), fis.getContentType(), fis.isFormField(), fis.getName()));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFileSizeMax() {
|
||||
return fileSizeMax;
|
||||
}
|
||||
|
||||
public MultipartStream getMultiPartStream() throws FileUploadException, IOException {
|
||||
if (multiPartStream == null) {
|
||||
init(fileUploadBase, ctx);
|
||||
}
|
||||
return multiPartStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeMax() {
|
||||
return sizeMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether another instance of {@link FileItemStream} is available.
|
||||
*
|
||||
* @throws FileUploadException Parsing or processing the file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return True, if one or more additional file items are available, otherwise false.
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() throws FileUploadException, IOException {
|
||||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
if (itemValid) {
|
||||
return true;
|
||||
}
|
||||
return findNextItem();
|
||||
}
|
||||
|
||||
protected void init(final AbstractFileUpload fileUploadBase, final RequestContext requestContext) throws FileUploadException, IOException {
|
||||
final String contentType = ctx.getContentType();
|
||||
if ((null == contentType) || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART))) {
|
||||
throw new FileUploadContentTypeException(String.format("the request doesn't contain a %s or %s stream, content type header is %s",
|
||||
AbstractFileUpload.MULTIPART_FORM_DATA, AbstractFileUpload.MULTIPART_MIXED, contentType), contentType);
|
||||
}
|
||||
final long contentLengthInt = ctx.getContentLength();
|
||||
// @formatter:off
|
||||
final long requestSize = RequestContext.class.isAssignableFrom(ctx.getClass())
|
||||
// Inline conditional is OK here CHECKSTYLE:OFF
|
||||
? ctx.getContentLength()
|
||||
: contentLengthInt;
|
||||
// CHECKSTYLE:ON
|
||||
// @formatter:on
|
||||
final InputStream input; // N.B. this is eventually closed in MultipartStream processing
|
||||
if (sizeMax >= 0) {
|
||||
if (requestSize != -1 && requestSize > sizeMax) {
|
||||
throw new FileUploadSizeException(
|
||||
String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)", requestSize, sizeMax), sizeMax,
|
||||
requestSize);
|
||||
}
|
||||
// N.B. this is eventually closed in MultipartStream processing
|
||||
input = new LimitedInputStream(ctx.getInputStream(), sizeMax) {
|
||||
@Override
|
||||
protected void raiseError(final long maxLen, final long count) throws IOException {
|
||||
throw new FileUploadSizeException(
|
||||
String.format("The request was rejected because its size (%s) exceeds the configured maximum (%s)", count, maxLen), maxLen, count);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
input = ctx.getInputStream();
|
||||
}
|
||||
|
||||
String charEncoding = fileUploadBase.getHeaderEncoding();
|
||||
if (charEncoding == null) {
|
||||
charEncoding = ctx.getCharacterEncoding();
|
||||
}
|
||||
|
||||
multiPartBoundary = fileUploadBase.getBoundary(contentType);
|
||||
if (multiPartBoundary == null) {
|
||||
IOUtils.closeQuietly(input); // avoid possible resource leak
|
||||
throw new FileUploadException("the request was rejected because no multipart boundary was found");
|
||||
}
|
||||
|
||||
progressNotifier = new MultipartStream.ProgressNotifier(fileUploadBase.getProgressListener(), requestSize);
|
||||
try {
|
||||
multiPartStream = new MultipartStream(input, multiPartBoundary, progressNotifier);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
IOUtils.closeQuietly(input); // avoid possible resource leak
|
||||
throw new FileUploadContentTypeException(String.format("The boundary specified in the %s header is too long", AbstractFileUpload.CONTENT_TYPE), e);
|
||||
}
|
||||
multiPartStream.setHeaderEncoding(charEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available {@link FileItemStream}.
|
||||
*
|
||||
* @throws java.util.NoSuchElementException No more items are available. Use {@link #hasNext()} to prevent this exception.
|
||||
* @throws FileUploadException Parsing or processing the file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return FileItemStream instance, which provides access to the next file item.
|
||||
*/
|
||||
@Override
|
||||
public FileItemStream next() throws FileUploadException, IOException {
|
||||
if (eof || (!itemValid && !hasNext())) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
itemValid = false;
|
||||
return currentItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFileSizeMax(final long fileSizeMax) {
|
||||
this.fileSizeMax = fileSizeMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeMax(final long sizeMax) {
|
||||
this.sizeMax = sizeMax;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,206 +1,205 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.impl;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.fileupload2.FileItemHeaders;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.InvalidFileNameException;
|
||||
import org.apache.commons.fileupload2.MultipartStream.ItemInputStream;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItem;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
|
||||
import org.apache.commons.fileupload2.util.LimitedInputStream;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link FileItemStream}.
|
||||
*/
|
||||
public class FileItemStreamImpl implements FileItemStream {
|
||||
|
||||
/**
|
||||
* The File Item iterator implementation.
|
||||
*
|
||||
* @see FileItemIteratorImpl
|
||||
*/
|
||||
private final FileItemIteratorImpl fileItemIteratorImpl;
|
||||
|
||||
/**
|
||||
* The file items content type.
|
||||
*/
|
||||
private final String contentType;
|
||||
|
||||
/**
|
||||
* The file items field name.
|
||||
*/
|
||||
private final String fieldName;
|
||||
|
||||
/**
|
||||
* The file items file name.
|
||||
*/
|
||||
private final String fileName;
|
||||
|
||||
/**
|
||||
* Whether the file item is a form field.
|
||||
*/
|
||||
private final boolean formField;
|
||||
|
||||
/**
|
||||
* The file items input stream.
|
||||
*/
|
||||
private final InputStream inputStream;
|
||||
|
||||
/**
|
||||
* The file items input stream closed flag.
|
||||
*/
|
||||
private boolean inputStreamClosed;
|
||||
|
||||
/**
|
||||
* The headers, if any.
|
||||
*/
|
||||
private FileItemHeaders headers;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param fileItemIterator The {@link FileItemIteratorImpl iterator}, which returned this file item.
|
||||
* @param fileName The items file name, or null.
|
||||
* @param fieldName The items field name.
|
||||
* @param contentType The items content type, or null.
|
||||
* @param formField Whether the item is a form field.
|
||||
* @param contentLength The items content length, if known, or -1
|
||||
* @throws IOException Creating the file item failed.
|
||||
* @throws FileUploadException Parsing the incoming data stream failed.
|
||||
*/
|
||||
public FileItemStreamImpl(final FileItemIteratorImpl fileItemIterator, final String fileName, final String fieldName, final String contentType,
|
||||
final boolean formField, final long contentLength) throws FileUploadException, IOException {
|
||||
this.fileItemIteratorImpl = fileItemIterator;
|
||||
this.fileName = fileName;
|
||||
this.fieldName = fieldName;
|
||||
this.contentType = contentType;
|
||||
this.formField = formField;
|
||||
final long fileSizeMax = fileItemIteratorImpl.getFileSizeMax();
|
||||
if (fileSizeMax != -1 && contentLength != -1 && contentLength > fileSizeMax) {
|
||||
throw new FileUploadByteCountLimitException(String.format("The field %s exceeds its maximum permitted size of %s bytes.", fieldName, fileSizeMax),
|
||||
contentLength, fileSizeMax, fileName, fieldName);
|
||||
}
|
||||
// OK to construct stream now
|
||||
final ItemInputStream itemInputStream = fileItemIteratorImpl.getMultiPartStream().newInputStream();
|
||||
InputStream istream = itemInputStream;
|
||||
if (fileSizeMax != -1) {
|
||||
istream = new LimitedInputStream(istream, fileSizeMax) {
|
||||
@Override
|
||||
protected void raiseError(final long sizeMax, final long count) throws IOException {
|
||||
itemInputStream.close(true);
|
||||
throw new FileUploadByteCountLimitException(
|
||||
String.format("The field %s exceeds its maximum permitted size of %s bytes.", fieldName, sizeMax), count, sizeMax, fileName,
|
||||
fieldName);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.inputStream = istream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the file item.
|
||||
*
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
inputStreamClosed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items content type, or null.
|
||||
*
|
||||
* @return Content type, if known, or null.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items field name.
|
||||
*
|
||||
* @return Field name.
|
||||
*/
|
||||
@Override
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file item headers.
|
||||
*
|
||||
* @return The items header object
|
||||
*/
|
||||
@Override
|
||||
public FileItemHeaders getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items file name.
|
||||
*
|
||||
* @return File name, if known, or null.
|
||||
* @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().
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return DiskFileItem.checkFileName(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this is a form field.
|
||||
*
|
||||
* @return True, if the item is a form field, otherwise false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isFormField() {
|
||||
return formField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream, which may be used to read the items contents.
|
||||
*
|
||||
* @return Opened input stream.
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
@Override
|
||||
public InputStream openStream() throws IOException {
|
||||
if (inputStreamClosed) {
|
||||
throw new FileItemStream.ItemSkippedException();
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file item headers.
|
||||
*
|
||||
* @param headers The items header object
|
||||
*/
|
||||
@Override
|
||||
public void setHeaders(final FileItemHeaders headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.fileupload2.FileItemHeaders;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.InvalidFileNameException;
|
||||
import org.apache.commons.fileupload2.MultipartStream.ItemInputStream;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItem;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
|
||||
import org.apache.commons.fileupload2.util.LimitedInputStream;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link FileItemStream}.
|
||||
*/
|
||||
public class FileItemStreamImpl implements FileItemStream {
|
||||
|
||||
/**
|
||||
* The File Item iterator implementation.
|
||||
*
|
||||
* @see FileItemIteratorImpl
|
||||
*/
|
||||
private final FileItemIteratorImpl fileItemIteratorImpl;
|
||||
|
||||
/**
|
||||
* The file items content type.
|
||||
*/
|
||||
private final String contentType;
|
||||
|
||||
/**
|
||||
* The file items field name.
|
||||
*/
|
||||
private final String fieldName;
|
||||
|
||||
/**
|
||||
* The file items file name.
|
||||
*/
|
||||
private final String fileName;
|
||||
|
||||
/**
|
||||
* Whether the file item is a form field.
|
||||
*/
|
||||
private final boolean formField;
|
||||
|
||||
/**
|
||||
* The file items input stream.
|
||||
*/
|
||||
private final InputStream inputStream;
|
||||
|
||||
/**
|
||||
* The file items input stream closed flag.
|
||||
*/
|
||||
private boolean inputStreamClosed;
|
||||
|
||||
/**
|
||||
* The headers, if any.
|
||||
*/
|
||||
private FileItemHeaders headers;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param fileItemIterator The {@link FileItemIteratorImpl iterator}, which returned this file item.
|
||||
* @param fileName The items file name, or null.
|
||||
* @param fieldName The items field name.
|
||||
* @param contentType The items content type, or null.
|
||||
* @param formField Whether the item is a form field.
|
||||
* @param contentLength The items content length, if known, or -1
|
||||
* @throws IOException Creating the file item failed.
|
||||
* @throws FileUploadException Parsing the incoming data stream failed.
|
||||
*/
|
||||
public FileItemStreamImpl(final FileItemIteratorImpl fileItemIterator, final String fileName, final String fieldName, final String contentType,
|
||||
final boolean formField, final long contentLength) throws FileUploadException, IOException {
|
||||
this.fileItemIteratorImpl = fileItemIterator;
|
||||
this.fileName = fileName;
|
||||
this.fieldName = fieldName;
|
||||
this.contentType = contentType;
|
||||
this.formField = formField;
|
||||
final long fileSizeMax = fileItemIteratorImpl.getFileSizeMax();
|
||||
if (fileSizeMax != -1 && contentLength != -1 && contentLength > fileSizeMax) {
|
||||
throw new FileUploadByteCountLimitException(String.format("The field %s exceeds its maximum permitted size of %s bytes.", fieldName, fileSizeMax),
|
||||
contentLength, fileSizeMax, fileName, fieldName);
|
||||
}
|
||||
// OK to construct stream now
|
||||
final ItemInputStream itemInputStream = fileItemIteratorImpl.getMultiPartStream().newInputStream();
|
||||
InputStream istream = itemInputStream;
|
||||
if (fileSizeMax != -1) {
|
||||
istream = new LimitedInputStream(istream, fileSizeMax) {
|
||||
@Override
|
||||
protected void raiseError(final long sizeMax, final long count) throws IOException {
|
||||
itemInputStream.close(true);
|
||||
throw new FileUploadByteCountLimitException(
|
||||
String.format("The field %s exceeds its maximum permitted size of %s bytes.", fieldName, sizeMax), count, sizeMax, fileName,
|
||||
fieldName);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.inputStream = istream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the file item.
|
||||
*
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
inputStreamClosed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items content type, or null.
|
||||
*
|
||||
* @return Content type, if known, or null.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items field name.
|
||||
*
|
||||
* @return Field name.
|
||||
*/
|
||||
@Override
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file item headers.
|
||||
*
|
||||
* @return The items header object
|
||||
*/
|
||||
@Override
|
||||
public FileItemHeaders getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items file name.
|
||||
*
|
||||
* @return File name, if known, or null.
|
||||
* @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().
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return DiskFileItem.checkFileName(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this is a form field.
|
||||
*
|
||||
* @return True, if the item is a form field, otherwise false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isFormField() {
|
||||
return formField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream, which may be used to read the items contents.
|
||||
*
|
||||
* @return Opened input stream.
|
||||
* @throws IOException An I/O error occurred.
|
||||
*/
|
||||
@Override
|
||||
public InputStream openStream() throws IOException {
|
||||
if (inputStreamClosed) {
|
||||
throw new FileItemStream.ItemSkippedException();
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file item headers.
|
||||
*
|
||||
* @param headers The items header object
|
||||
*/
|
||||
@Override
|
||||
public void setHeaders(final FileItemHeaders headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,29 +17,23 @@
|
|||
|
||||
/**
|
||||
* <p>
|
||||
* A component for handling HTML file uploads as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC 1867</a>.
|
||||
* This component provides support for uploads within both servlets (JSR 53)
|
||||
* and portlets (JSR 168).
|
||||
* A component for handling HTML file uploads as specified by <a href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC 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 org.apache.commons.fileupload2.FileUpload FileUpload} such as
|
||||
* {@link org.apache.commons.fileupload2.servlet.ServletFileUpload ServletFileUpload}
|
||||
* or
|
||||
* {@link org.apache.commons.fileupload2.portlet.PortletFileUpload PortletFileUpload},
|
||||
* together with a factory for
|
||||
* {@link org.apache.commons.fileupload2.FileItem FileItem} instances,
|
||||
* such as
|
||||
* {@link org.apache.commons.fileupload2.disk.DiskFileItemFactory DiskFileItemFactory}.
|
||||
* 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 org.apache.commons.fileupload2.FileUpload FileUpload} such as
|
||||
* {@code org.apache.commons.fileupload2.servlet.ServletFileUpload ServletFileUpload} or
|
||||
* {@code org.apache.commons.fileupload2.portlet.PortletFileUpload PortletFileUpload}, together with a factory for
|
||||
* {@link org.apache.commons.fileupload2.FileItem FileItem} instances, such as {@link org.apache.commons.fileupload2.disk.DiskFileItemFactory
|
||||
* DiskFileItemFactory}.
|
||||
* </p>
|
||||
* <p>
|
||||
* The following is a brief example of typical usage in a servlet, storing
|
||||
* the uploaded files on disk.
|
||||
* 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) {
|
||||
*
|
||||
* <pre>
|
||||
* public void doPost(HttpServletRequest req, HttpServletResponse res) {
|
||||
* DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||
* // maximum size that will be stored in memory
|
||||
* factory.setSizeThreshold(4096);
|
||||
|
@ -66,20 +60,14 @@
|
|||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In the example above, the first file is loaded into memory as a
|
||||
* {@code String}. Before calling the {@code getString} 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.
|
||||
* In the example above, the first file is loaded into memory as a {@code String}. Before calling the {@code getString} 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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
|
||||
* for further details and examples of how to use this package.
|
||||
* Please see the FileUpload <a href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> for further details and examples of how to
|
||||
* use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
|
@ -1,72 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
||||
|
||||
/**
|
||||
* Signals that a file size exceeds the configured maximum.
|
||||
*/
|
||||
public class FileUploadByteCountLimitException extends FileUploadSizeException {
|
||||
|
||||
/**
|
||||
* The exceptions UID, for serializing an instance.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* File name of the item, which caused the exception.
|
||||
*/
|
||||
private final String fileName;
|
||||
|
||||
/**
|
||||
* Field name of the item, which caused the exception.
|
||||
*/
|
||||
private final String fieldName;
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified detail message, and actual and permitted sizes.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param actual The actual request size.
|
||||
* @param permitted The maximum permitted request size.
|
||||
* @param fileName File name of the item, which caused the exception.
|
||||
* @param fieldName Field name of the item, which caused the exception.
|
||||
*/
|
||||
public FileUploadByteCountLimitException(final String message, final long actual, final long permitted, final String fileName, final String fieldName) {
|
||||
super(message, permitted, actual);
|
||||
this.fileName = fileName;
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field name of the item, which caused the exception.
|
||||
*
|
||||
* @return Field name, if known, or null.
|
||||
*/
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file name of the item, which caused the exception.
|
||||
*
|
||||
* @return File name, if known, or null.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
||||
|
||||
/**
|
||||
* Signals that a file size exceeds the configured maximum.
|
||||
*/
|
||||
public class FileUploadByteCountLimitException extends FileUploadSizeException {
|
||||
|
||||
/**
|
||||
* The exceptions UID, for serializing an instance.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* File name of the item, which caused the exception.
|
||||
*/
|
||||
private final String fileName;
|
||||
|
||||
/**
|
||||
* Field name of the item, which caused the exception.
|
||||
*/
|
||||
private final String fieldName;
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified detail message, and actual and permitted sizes.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param actual The actual request size.
|
||||
* @param permitted The maximum permitted request size.
|
||||
* @param fileName File name of the item, which caused the exception.
|
||||
* @param fieldName Field name of the item, which caused the exception.
|
||||
*/
|
||||
public FileUploadByteCountLimitException(final String message, final long actual, final long permitted, final String fileName, final String fieldName) {
|
||||
super(message, permitted, actual);
|
||||
this.fileName = fileName;
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field name of the item, which caused the exception.
|
||||
*
|
||||
* @return Field name, if known, or null.
|
||||
*/
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file name of the item, which caused the exception.
|
||||
*
|
||||
* @return File name, if known, or null.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +1,60 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
||||
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
|
||||
/**
|
||||
* Signals that a request is not a multipart request.
|
||||
*/
|
||||
public class FileUploadContentTypeException extends FileUploadException {
|
||||
|
||||
/**
|
||||
* The exceptions UID, for serializing an instance.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* The guilty content type.
|
||||
*/
|
||||
private String contentType;
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified detail message.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param contentType The guilty content type.
|
||||
*/
|
||||
public FileUploadContentTypeException(final String message, final String contentType) {
|
||||
super(message);
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified detail message and cause.
|
||||
*
|
||||
* @param message
|
||||
* The detail message (which is saved for later retrieval
|
||||
* by the {@link #getMessage()} method)
|
||||
* @param cause the original cause
|
||||
*/
|
||||
public FileUploadContentTypeException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
||||
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
|
||||
/**
|
||||
* Signals that a request is not a multipart request.
|
||||
*/
|
||||
public class FileUploadContentTypeException extends FileUploadException {
|
||||
|
||||
/**
|
||||
* The exceptions UID, for serializing an instance.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* The guilty content type.
|
||||
*/
|
||||
private String contentType;
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified detail message.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param contentType The guilty content type.
|
||||
*/
|
||||
public FileUploadContentTypeException(final String message, final String contentType) {
|
||||
super(message);
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified detail message and cause.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param cause the original cause
|
||||
*/
|
||||
public FileUploadContentTypeException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
}
|
|
@ -1,72 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
||||
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
|
||||
/**
|
||||
* Signals that a requests permitted size is exceeded.
|
||||
*/
|
||||
public class FileUploadSizeException extends FileUploadException {
|
||||
|
||||
/**
|
||||
* Serial version UID, being used, if serialized.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* The actual size of the request.
|
||||
*/
|
||||
private final long actual;
|
||||
|
||||
/**
|
||||
* The maximum permitted size of the request.
|
||||
*/
|
||||
private final long permitted;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param permitted The requests size limit.
|
||||
* @param actual The actual values for the request.
|
||||
*/
|
||||
public FileUploadSizeException(final String message, final long permitted, final long actual) {
|
||||
super(message);
|
||||
this.permitted = permitted;
|
||||
this.actual = actual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the actual size of the request.
|
||||
*
|
||||
* @return The actual size of the request.
|
||||
*/
|
||||
public long getActualSize() {
|
||||
return actual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the limit size of the request.
|
||||
*
|
||||
* @return The limit size of the request.
|
||||
*/
|
||||
public long getPermitted() {
|
||||
return permitted;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
||||
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
|
||||
/**
|
||||
* Signals that a requests permitted size is exceeded.
|
||||
*/
|
||||
public class FileUploadSizeException extends FileUploadException {
|
||||
|
||||
/**
|
||||
* Serial version UID, being used, if serialized.
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* The actual size of the request.
|
||||
*/
|
||||
private final long actual;
|
||||
|
||||
/**
|
||||
* The maximum permitted size of the request.
|
||||
*/
|
||||
private final long permitted;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
|
||||
* @param permitted The requests size limit.
|
||||
* @param actual The actual values for the request.
|
||||
*/
|
||||
public FileUploadSizeException(final String message, final long permitted, final long actual) {
|
||||
super(message);
|
||||
this.permitted = permitted;
|
||||
this.actual = actual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the actual size of the request.
|
||||
*
|
||||
* @return The actual size of the request.
|
||||
*/
|
||||
public long getActualSize() {
|
||||
return actual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the limit size of the request.
|
||||
*
|
||||
* @return The limit size of the request.
|
||||
*/
|
||||
public long getPermitted() {
|
||||
return permitted;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Exceptions, and other classes, that are known to be used outside
|
||||
* of FileUpload.
|
||||
* Exceptions, and other classes, that are known to be used outside of FileUpload.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.pub;
|
|
@ -21,8 +21,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* An input stream, which limits its data size. This stream is
|
||||
* used, if the content length is unknown.
|
||||
* An input stream, which limits its data size. This stream is used, if the content length is unknown.
|
||||
*/
|
||||
public abstract class LimitedInputStream extends FilterInputStream {
|
||||
|
||||
|
@ -40,8 +39,7 @@ public abstract class LimitedInputStream extends FilterInputStream {
|
|||
* Creates a new instance.
|
||||
*
|
||||
* @param inputStream The input stream, which shall be limited.
|
||||
* @param sizeMax The limit; no more than this number of bytes
|
||||
* shall be returned by the source stream.
|
||||
* @param sizeMax The limit; no more than this number of bytes shall be returned by the source stream.
|
||||
*/
|
||||
public LimitedInputStream(final InputStream inputStream, final long sizeMax) {
|
||||
super(inputStream);
|
||||
|
@ -49,8 +47,7 @@ public abstract class LimitedInputStream extends FilterInputStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called to check, whether the input streams
|
||||
* limit is reached.
|
||||
* Called to check, whether the input streams limit is reached.
|
||||
*
|
||||
* @throws IOException The given limit is exceeded.
|
||||
*/
|
||||
|
@ -61,13 +58,10 @@ public abstract class LimitedInputStream extends FilterInputStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* Closes this input stream and releases any system resources
|
||||
* associated with the stream.
|
||||
* This
|
||||
* method simply performs {@code in.close()}.
|
||||
* Closes this input stream and releases any system resources associated with the stream. This method simply performs {@code in.close()}.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterInputStream#in
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterInputStream#in
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
@ -75,33 +69,25 @@ public abstract class LimitedInputStream extends FilterInputStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called to indicate, that the input streams limit has
|
||||
* been exceeded.
|
||||
* Called to indicate, that the input streams limit has been exceeded.
|
||||
*
|
||||
* @param sizeMax The input streams limit, in bytes.
|
||||
* @param count The actual number of bytes.
|
||||
* @throws IOException The called method is expected
|
||||
* to raise an IOException.
|
||||
* @param count The actual number of bytes.
|
||||
* @throws IOException The called method is expected to raise an IOException.
|
||||
*/
|
||||
protected abstract void raiseError(long sizeMax, long count)
|
||||
throws IOException;
|
||||
protected abstract void raiseError(long sizeMax, long count) throws IOException;
|
||||
|
||||
/**
|
||||
* Reads the next byte of data from this input stream. The value
|
||||
* byte is returned as an {@code int} in the range
|
||||
* {@code 0} to {@code 255}. If no byte is available
|
||||
* because the end of the stream has been reached, the value
|
||||
* {@code -1} is returned. This method blocks until input data
|
||||
* is available, the end of the stream is detected, or an exception
|
||||
* is thrown.
|
||||
* Reads the next byte of data from this input stream. The value byte is returned as an {@code int} in the range {@code 0} to {@code 255}. If no byte is
|
||||
* available because the end of the stream has been reached, the value {@code -1} is returned. This method blocks until input data is available, the end of
|
||||
* the stream is detected, or an exception is thrown.
|
||||
* <p>
|
||||
* This method
|
||||
* simply performs {@code in.read()} and returns the result.
|
||||
* This method simply performs {@code in.read()} and returns the result.
|
||||
* </p>
|
||||
* @return the next byte of data, or {@code -1} if the end of the
|
||||
* stream is reached.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterInputStream#in
|
||||
*
|
||||
* @return the next byte of data, or {@code -1} if the end of the stream is reached.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterInputStream#in
|
||||
*/
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
|
@ -114,27 +100,20 @@ public abstract class LimitedInputStream extends FilterInputStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* Reads up to {@code len} bytes of data from this input stream
|
||||
* into an array of bytes. If {@code len} is not zero, the method
|
||||
* blocks until some input is available; otherwise, no
|
||||
* bytes are read and {@code 0} is returned.
|
||||
* Reads up to {@code len} bytes of data from this input stream into an array of bytes. If {@code len} is not zero, the method blocks until some input is
|
||||
* available; otherwise, no bytes are read and {@code 0} is returned.
|
||||
* <p>
|
||||
* This method simply performs {@code in.read(b, off, len)}
|
||||
* and returns the result.
|
||||
* This method simply performs {@code in.read(b, off, len)} and returns the result.
|
||||
* </p>
|
||||
* @param b the buffer into which the data is read.
|
||||
* @param off The start offset in the destination array
|
||||
* {@code b}.
|
||||
* @param len the maximum number of bytes read.
|
||||
* @return the total number of bytes read into the buffer, or
|
||||
* {@code -1} if there is no more data because the end of
|
||||
* the stream has been reached.
|
||||
* @throws NullPointerException If {@code b} is {@code null}.
|
||||
* @throws IndexOutOfBoundsException If {@code off} is negative,
|
||||
* {@code len} is negative, or {@code len} is greater than
|
||||
* {@code b.length - off}
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterInputStream#in
|
||||
*
|
||||
* @param b the buffer into which the data is read.
|
||||
* @param off The start offset in the destination array {@code b}.
|
||||
* @param len the maximum number of bytes read.
|
||||
* @return the total number of bytes read into the buffer, or {@code -1} if there is no more data because the end of the stream has been reached.
|
||||
* @throws NullPointerException If {@code b} is {@code null}.
|
||||
* @throws IndexOutOfBoundsException If {@code off} is negative, {@code len} is negative, or {@code len} is greater than {@code b.length - off}
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterInputStream#in
|
||||
*/
|
||||
@Override
|
||||
public int read(final byte[] b, final int off, final int len) throws IOException {
|
|
@ -76,18 +76,16 @@ public final class MimeUtility {
|
|||
}
|
||||
|
||||
/**
|
||||
* Decodes 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.
|
||||
* Decodes 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.
|
||||
* @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(final String text) throws UnsupportedEncodingException {
|
||||
// if the text contains any encoded tokens, those tokens will be marked with "=?". If the
|
||||
// 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.contains(ENCODED_TOKEN_MARKER)) {
|
||||
return text;
|
||||
|
@ -121,7 +119,7 @@ public final class MimeUtility {
|
|||
offset++;
|
||||
}
|
||||
} else {
|
||||
// we have a word token. We need to scan over the word and then try to parse it.
|
||||
// we have a word token. We need to scan over the word and then try to parse it.
|
||||
final int wordStart = offset;
|
||||
|
||||
while (offset < endOffset) {
|
||||
|
@ -132,17 +130,17 @@ public final class MimeUtility {
|
|||
}
|
||||
offset++;
|
||||
|
||||
//NB: Trailing whitespace on these header strings will just be discarded.
|
||||
// NB: Trailing whitespace on these header strings will just be discarded.
|
||||
}
|
||||
// pull out the word token.
|
||||
final String word = text.substring(wordStart, offset);
|
||||
// is the token encoded? decode the word
|
||||
// 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.
|
||||
final String decodedWord = decodeWord(word);
|
||||
|
||||
// are any whitespace characters significant? Append 'em if we've got 'em.
|
||||
// are any whitespace characters significant? Append 'em if we've got 'em.
|
||||
if (!previousTokenEncoded && startWhiteSpace != -1) {
|
||||
decodedText.append(text, startWhiteSpace, endWhiteSpace);
|
||||
startWhiteSpace = -1;
|
||||
|
@ -159,7 +157,7 @@ public final class MimeUtility {
|
|||
// 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
|
||||
// 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, startWhiteSpace, endWhiteSpace);
|
||||
|
@ -175,19 +173,18 @@ public final class MimeUtility {
|
|||
}
|
||||
|
||||
/**
|
||||
* Decodes a string using the RFC 2047 rules for an "encoded-word"
|
||||
* type. This encoding has the syntax:
|
||||
* Decodes 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.
|
||||
* @param word The possibly encoded word value.
|
||||
*
|
||||
* @return The decoded word.
|
||||
* @throws ParseException in case of a parse error of the RFC 2047
|
||||
* @throws ParseException in case of a parse error of the RFC 2047
|
||||
* @throws UnsupportedEncodingException Thrown when Invalid RFC 2047 encoding was found
|
||||
*/
|
||||
private static String decodeWord(final String word) throws ParseException, UnsupportedEncodingException {
|
||||
// encoded words start with the characters "=?". If this not an encoded word, we throw a
|
||||
// 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)) {
|
||||
|
@ -246,8 +243,7 @@ public final class MimeUtility {
|
|||
}
|
||||
|
||||
/**
|
||||
* Translate a MIME standard character set name into the Java
|
||||
* equivalent.
|
||||
* Translate a MIME standard character set name into the Java equivalent.
|
||||
*
|
||||
* @param charset The MIME standard name.
|
||||
*
|
||||
|
@ -260,8 +256,8 @@ public final class MimeUtility {
|
|||
}
|
||||
|
||||
final 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 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;
|
||||
}
|
|
@ -25,16 +25,15 @@ import java.io.OutputStream;
|
|||
final class QuotedPrintableDecoder {
|
||||
|
||||
/**
|
||||
* The shift value required to create the upper nibble
|
||||
* from the first of 2 byte values converted from ascii hex.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Decodes 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.
|
||||
* @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.
|
||||
* @throws IOException if an IO error occurs
|
||||
|
@ -52,7 +51,7 @@ final class QuotedPrintableDecoder {
|
|||
if (ch == '_') {
|
||||
out.write(' ');
|
||||
} else if (ch == '=') {
|
||||
// we found an encoded character. Reduce the 3 char sequence to one.
|
||||
// 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");
|
||||
|
@ -61,12 +60,12 @@ final class QuotedPrintableDecoder {
|
|||
final byte b1 = data[off++];
|
||||
final byte b2 = data[off++];
|
||||
|
||||
// we've found an encoded carriage return. The next char needs to be a newline
|
||||
// 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
|
||||
// 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.
|
|
@ -18,14 +18,15 @@ package org.apache.commons.fileupload2.util.mime;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* Utility class to decode/encode character set on HTTP Header fields based on RFC 2231.
|
||||
* This implementation adheres to RFC 5987 in particular, which was defined for HTTP headers
|
||||
* Utility class to decode/encode character set on HTTP Header fields based on RFC 2231. This implementation adheres to RFC 5987 in particular, which was
|
||||
* defined for HTTP headers
|
||||
* <p>
|
||||
* RFC 5987 builds on RFC 2231, but has lesser scope like
|
||||
* <a href="https://tools.ietf.org/html/rfc5987#section-3.2">mandatory charset definition</a>
|
||||
* and <a href="https://tools.ietf.org/html/rfc5987#section-4">no parameter continuation</a>
|
||||
* RFC 5987 builds on RFC 2231, but has lesser scope like <a href="https://tools.ietf.org/html/rfc5987#section-3.2">mandatory charset definition</a> and
|
||||
* <a href="https://tools.ietf.org/html/rfc5987#section-4">no parameter continuation</a>
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc2231">RFC 2231</a>
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5987">RFC 5987</a>
|
||||
*/
|
||||
|
@ -59,17 +60,13 @@ public final class RFC2231Utility {
|
|||
/**
|
||||
* Decodes a string of text obtained from a HTTP header as per RFC 2231
|
||||
*
|
||||
* <b>Eg 1.</b> {@code us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A}
|
||||
* will be decoded to {@code This is ***fun***}
|
||||
* <b>Eg 1.</b> {@code us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A} will be decoded to {@code This is ***fun***}
|
||||
*
|
||||
* <b>Eg 2.</b> {@code iso-8859-1'en'%A3%20rate}
|
||||
* will be decoded to {@code £ rate}.
|
||||
* <b>Eg 2.</b> {@code iso-8859-1'en'%A3%20rate} will be decoded to {@code £ rate}.
|
||||
*
|
||||
* <b>Eg 3.</b> {@code UTF-8''%c2%a3%20and%20%e2%82%ac%20rates}
|
||||
* will be decoded to {@code £ and € rates}.
|
||||
* <b>Eg 3.</b> {@code UTF-8''%c2%a3%20and%20%e2%82%ac%20rates} will be decoded to {@code £ and € rates}.
|
||||
*
|
||||
* @param encodedText - Text to be decoded has a format of {@code <charset>'<language>'<encoded_value>}
|
||||
* and ASCII only
|
||||
* @param encodedText - Text to be decoded has a format of {@code <charset>'<language>'<encoded_value>} and ASCII only
|
||||
* @return Decoded text based on charset encoding
|
||||
* @throws UnsupportedEncodingException The requested character set wasn't found.
|
||||
*/
|
||||
|
@ -120,8 +117,8 @@ public final class RFC2231Utility {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests if asterisk (*) at the end of parameter name to indicate,
|
||||
* if it has charset and language information to decode the value.
|
||||
* Tests if asterisk (*) at the end of parameter name to indicate, if it has charset and language information to decode the value.
|
||||
*
|
||||
* @param paramName The parameter, which is being checked.
|
||||
* @return {@code true}, if encoded as per RFC 2231, {@code false} otherwise
|
||||
*/
|
||||
|
@ -133,8 +130,8 @@ public final class RFC2231Utility {
|
|||
}
|
||||
|
||||
/**
|
||||
* If {@code paramName} has Asterisk (*) at the end, it will be stripped off,
|
||||
* else the passed value will be returned.
|
||||
* If {@code paramName} has Asterisk (*) at the end, it will be stripped off, else the passed value will be returned.
|
||||
*
|
||||
* @param paramName The parameter, which is being inspected.
|
||||
* @return stripped {@code paramName} of Asterisk (*), if RFC2231 encoded
|
||||
*/
|
||||
|
@ -148,8 +145,7 @@ public final class RFC2231Utility {
|
|||
}
|
||||
|
||||
/**
|
||||
* Private constructor so that no instances can be created. This class
|
||||
* contains only static utility methods.
|
||||
* Private constructor so that no instances can be created. This class contains only static utility methods.
|
||||
*/
|
||||
private RFC2231Utility() {
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* 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>.
|
||||
* 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 org.apache.commons.fileupload2.util.mime;
|
|
@ -16,8 +16,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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 org.apache.commons.fileupload2.util;
|
|
@ -24,33 +24,22 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.fileupload2.portlet.PortletFileUploadTest;
|
||||
import org.apache.commons.fileupload2.servlet.ServletFileUploadTest;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Common tests for implementations of {@link FileUpload}. This is a parameterized test.
|
||||
* Tests must be valid and common to all implementations of FileUpload added as parameter
|
||||
* in this class.
|
||||
* Common tests for implementations of {@link FileUpload}. This is a parameterized test. Tests must be valid and common to all implementations of FileUpload
|
||||
* added as parameter in this class.
|
||||
*
|
||||
* @see ServletFileUploadTest
|
||||
* @see PortletFileUploadTest
|
||||
* @since 1.4
|
||||
*/
|
||||
public class FileUploadTest {
|
||||
public abstract class AbstractFileUploadTest extends AbstractFileUploadWrapper {
|
||||
|
||||
/**
|
||||
* @return {@link FileUpload} classes under test.
|
||||
*/
|
||||
public static Stream<FileUpload> data() {
|
||||
return Util.fileUploadImplementations().stream();
|
||||
protected AbstractFileUploadTest(final FileUpload fileUpload) {
|
||||
super(fileUpload);
|
||||
}
|
||||
|
||||
private void assertHeaders(final String[] headerNames, final String[] headerValues,
|
||||
final FileItem fileItems, final int index) {
|
||||
private void assertHeaders(final String[] headerNames, final String[] headerValues, final FileItem fileItems, final int index) {
|
||||
for (int i = 0; i < headerNames.length; i++) {
|
||||
final String value = fileItems.getHeaders().getHeader(headerNames[i]);
|
||||
if (i == index) {
|
||||
|
@ -64,11 +53,10 @@ public class FileUploadTest {
|
|||
/**
|
||||
* Test for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-239">FILEUPLOAD-239</a>
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testContentTypeAttachment(final FileUpload upload)
|
||||
throws IOException, FileUploadException {
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload,
|
||||
@Test
|
||||
public void testContentTypeAttachment() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final List<FileItem> fileItems = parseUpload(upload,
|
||||
"-----1234\r\n" +
|
||||
"content-disposition: form-data; name=\"field1\"\r\n" +
|
||||
"\r\n" +
|
||||
|
@ -84,6 +72,7 @@ public class FileUploadTest {
|
|||
"... contents of file1.txt ...\r\n" +
|
||||
"-----9876--\r\n" +
|
||||
"-----1234--\r\n");
|
||||
// @formatter:on
|
||||
assertEquals(2, fileItems.size());
|
||||
|
||||
final FileItem field = fileItems.get(0);
|
||||
|
@ -102,16 +91,16 @@ public class FileUploadTest {
|
|||
/**
|
||||
* This is what the browser does if you submit the form without choosing a file.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testEmptyFile(final FileUpload upload)
|
||||
throws FileUploadException {
|
||||
final List<FileItem> fileItems = Util.parseUpload (upload,
|
||||
@Test
|
||||
public void testEmptyFile() throws FileUploadException {
|
||||
// @formatter:off
|
||||
final List<FileItem> fileItems = parseUpload (upload,
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"\"\r\n" +
|
||||
"\r\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n");
|
||||
// @formatter:on
|
||||
assertEquals(1, fileItems.size());
|
||||
|
||||
final FileItem file = fileItems.get(0);
|
||||
|
@ -120,11 +109,10 @@ public class FileUploadTest {
|
|||
assertEquals("", file.getName());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testFilenameCaseSensitivity(final FileUpload upload)
|
||||
throws IOException, FileUploadException {
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload,
|
||||
@Test
|
||||
public void testFilenameCaseSensitivity() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final List<FileItem> fileItems = parseUpload(upload,
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; "
|
||||
+ "name=\"FiLe\"; filename=\"FOO.tab\"\r\n" +
|
||||
|
@ -133,6 +121,7 @@ public class FileUploadTest {
|
|||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n");
|
||||
// @formatter:on
|
||||
assertEquals(1, fileItems.size());
|
||||
|
||||
final FileItem file = fileItems.get(0);
|
||||
|
@ -140,11 +129,10 @@ public class FileUploadTest {
|
|||
assertEquals("FOO.tab", file.getName());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testFileUpload(final FileUpload upload)
|
||||
throws IOException, FileUploadException {
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload,
|
||||
@Test
|
||||
public void testFileUpload() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final List<FileItem> fileItems = parseUpload(upload,
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: "
|
||||
+ "form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
|
@ -165,6 +153,7 @@ public class FileUploadTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n");
|
||||
// @formatter:on
|
||||
assertEquals(4, fileItems.size());
|
||||
|
||||
final FileItem file = fileItems.get(0);
|
||||
|
@ -193,17 +182,12 @@ public class FileUploadTest {
|
|||
/**
|
||||
* Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-130">
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testFileUpload130(final FileUpload upload)
|
||||
throws Exception {
|
||||
final String[] headerNames = {
|
||||
"SomeHeader", "OtherHeader", "YetAnotherHeader", "WhatAHeader"
|
||||
};
|
||||
final String[] headerValues = {
|
||||
"present", "Is there", "Here", "Is That"
|
||||
};
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload,
|
||||
@Test
|
||||
public void testFileUpload130() throws Exception {
|
||||
final String[] headerNames = { "SomeHeader", "OtherHeader", "YetAnotherHeader", "WhatAHeader" };
|
||||
final String[] headerValues = { "present", "Is there", "Here", "Is That" };
|
||||
// @formatter:off
|
||||
final List<FileItem> fileItems = parseUpload(upload,
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; "
|
||||
+ "filename=\"foo.tab\"\r\n" +
|
||||
|
@ -230,6 +214,7 @@ public class FileUploadTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n");
|
||||
// @formatter:on
|
||||
assertEquals(4, fileItems.size());
|
||||
|
||||
final FileItem file = fileItems.get(0);
|
||||
|
@ -248,9 +233,9 @@ public class FileUploadTest {
|
|||
/**
|
||||
* Test for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-62">FILEUPLOAD-62</a>
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testFILEUPLOAD62(final FileUpload upload) throws Exception {
|
||||
@Test
|
||||
public void testFILEUPLOAD62() throws Exception {
|
||||
// @formatter:off
|
||||
final String contentType = "multipart/form-data; boundary=AaB03x";
|
||||
final String request =
|
||||
"--AaB03x\r\n" +
|
||||
|
@ -274,8 +259,8 @@ public class FileUploadTest {
|
|||
"...contents of file2.gif...\r\n" +
|
||||
"--BbC04y--\r\n" +
|
||||
"--AaB03x--";
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload, request.getBytes(StandardCharsets.US_ASCII),
|
||||
contentType);
|
||||
// @formatter:on
|
||||
final List<FileItem> fileItems = parseUpload(upload, request.getBytes(StandardCharsets.US_ASCII), contentType);
|
||||
assertEquals(3, fileItems.size());
|
||||
final FileItem item0 = fileItems.get(0);
|
||||
assertEquals("field1", item0.getFieldName());
|
||||
|
@ -294,11 +279,10 @@ public class FileUploadTest {
|
|||
/**
|
||||
* Test for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-111">FILEUPLOAD-111</a>
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testFoldedHeaders(final FileUpload upload)
|
||||
throws IOException, FileUploadException {
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload, "-----1234\r\n" +
|
||||
@Test
|
||||
public void testFoldedHeaders() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final List<FileItem> fileItems = parseUpload(upload, "-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
|
@ -319,6 +303,7 @@ public class FileUploadTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n");
|
||||
// @formatter:on
|
||||
assertEquals(4, fileItems.size());
|
||||
|
||||
final FileItem file = fileItems.get(0);
|
||||
|
@ -345,32 +330,31 @@ public class FileUploadTest {
|
|||
}
|
||||
|
||||
/**
|
||||
* Internet Explorer 5 for the Mac has a bug where the carriage
|
||||
* return is missing on any boundary line immediately preceding
|
||||
* an input with type=image. (type=submit does not have the bug.)
|
||||
* Internet Explorer 5 for the Mac has a bug where the carriage return is missing on any boundary line immediately preceding an input with type=image.
|
||||
* (type=submit does not have the bug.)
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testIE5MacBug(final FileUpload upload)
|
||||
throws FileUploadException {
|
||||
final List<FileItem> fileItems = Util.parseUpload(upload,
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"field1\"\r\n" +
|
||||
"\r\n" +
|
||||
"fieldValue\r\n" +
|
||||
"-----1234\n" + // NOTE \r missing
|
||||
"Content-Disposition: form-data; name=\"submitName.x\"\r\n" +
|
||||
"\r\n" +
|
||||
"42\r\n" +
|
||||
"-----1234\n" + // NOTE \r missing
|
||||
"Content-Disposition: form-data; name=\"submitName.y\"\r\n" +
|
||||
"\r\n" +
|
||||
"21\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"field2\"\r\n" +
|
||||
"\r\n" +
|
||||
"fieldValue2\r\n" +
|
||||
"-----1234--\r\n");
|
||||
@Test
|
||||
public void testIE5MacBug() throws FileUploadException {
|
||||
final List<FileItem> fileItems = parseUpload(upload,
|
||||
// @formatter:off
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"field1\"\r\n" +
|
||||
"\r\n" +
|
||||
"fieldValue\r\n" +
|
||||
"-----1234\n" + // NOTE \r missing
|
||||
"Content-Disposition: form-data; name=\"submitName.x\"\r\n" +
|
||||
"\r\n" +
|
||||
"42\r\n" +
|
||||
"-----1234\n" + // NOTE \r missing
|
||||
"Content-Disposition: form-data; name=\"submitName.y\"\r\n" +
|
||||
"\r\n" +
|
||||
"21\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"field2\"\r\n" +
|
||||
"\r\n" +
|
||||
"fieldValue2\r\n" +
|
||||
"-----1234--\r\n");
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(4, fileItems.size());
|
||||
|
|
@ -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.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Common tests for implementations of {@link FileUpload}. This is a parameterized test. Tests must be valid and common to all implementations of FileUpload
|
||||
* added as parameter in this class.
|
||||
*/
|
||||
public abstract class AbstractFileUploadWrapper {
|
||||
|
||||
protected final FileUpload upload;
|
||||
|
||||
protected AbstractFileUploadWrapper(final FileUpload fileUpload) {
|
||||
this.upload = fileUpload;
|
||||
}
|
||||
|
||||
public List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes) throws FileUploadException {
|
||||
return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
public abstract List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes, final String contentType) throws FileUploadException;
|
||||
|
||||
public List<FileItem> parseUpload(final FileUpload upload, final String content) throws FileUploadException {
|
||||
final byte[] bytes = content.getBytes(StandardCharsets.US_ASCII);
|
||||
return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,5 +28,6 @@ public final class Constants {
|
|||
*/
|
||||
public static final String CONTENT_TYPE = "multipart/form-data; boundary=---1234";
|
||||
|
||||
private Constants() { }
|
||||
private Constants() {
|
||||
}
|
||||
}
|
|
@ -27,8 +27,7 @@ import org.apache.commons.fileupload2.util.FileItemHeadersImpl;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests {@link FileItemHeaders} and
|
||||
* {@link FileItemHeadersImpl}.
|
||||
* Unit tests {@link FileItemHeaders} and {@link FileItemHeadersImpl}.
|
||||
*/
|
||||
public class FileItemHeadersTest {
|
||||
|
||||
|
@ -38,8 +37,7 @@ public class FileItemHeadersTest {
|
|||
@Test
|
||||
public void testFileItemHeaders() throws Exception {
|
||||
final FileItemHeadersImpl aMutableFileItemHeaders = new FileItemHeadersImpl();
|
||||
aMutableFileItemHeaders.addHeader("Content-Disposition",
|
||||
"form-data; name=\"FileItem\"; filename=\"file1.txt\"");
|
||||
aMutableFileItemHeaders.addHeader("Content-Disposition", "form-data; name=\"FileItem\"; filename=\"file1.txt\"");
|
||||
aMutableFileItemHeaders.addHeader("Content-Type", "text/plain");
|
||||
|
||||
aMutableFileItemHeaders.addHeader("TestHeader", "headerValue1");
|
||||
|
@ -53,8 +51,7 @@ public class FileItemHeadersTest {
|
|||
assertEquals("testheader", headerNameEnumeration.next());
|
||||
assertFalse(headerNameEnumeration.hasNext());
|
||||
|
||||
assertEquals(aMutableFileItemHeaders.getHeader("Content-Disposition"),
|
||||
"form-data; name=\"FileItem\"; filename=\"file1.txt\"");
|
||||
assertEquals(aMutableFileItemHeaders.getHeader("Content-Disposition"), "form-data; name=\"FileItem\"; filename=\"file1.txt\"");
|
||||
assertEquals(aMutableFileItemHeaders.getHeader("Content-Type"), "text/plain");
|
||||
assertEquals(aMutableFileItemHeaders.getHeader("content-type"), "text/plain");
|
||||
assertEquals(aMutableFileItemHeaders.getHeader("TestHeader"), "headerValue1");
|
|
@ -39,11 +39,7 @@ public class MultipartStreamTest {
|
|||
final byte[] boundary = BOUNDARY_TEXT.getBytes();
|
||||
final int iBufSize = 1;
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new MultipartStream(
|
||||
input,
|
||||
boundary,
|
||||
iBufSize,
|
||||
new MultipartStream.ProgressNotifier(null, contents.length)));
|
||||
() -> new MultipartStream(input, boundary, iBufSize, new MultipartStream.ProgressNotifier(null, contents.length)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -52,13 +48,8 @@ public class MultipartStreamTest {
|
|||
final byte[] contents = strData.getBytes();
|
||||
final InputStream input = new ByteArrayInputStream(contents);
|
||||
final byte[] boundary = BOUNDARY_TEXT.getBytes();
|
||||
final int iBufSize =
|
||||
boundary.length + MultipartStream.BOUNDARY_PREFIX.length + 1;
|
||||
final MultipartStream ms = new MultipartStream(
|
||||
input,
|
||||
boundary,
|
||||
iBufSize,
|
||||
new MultipartStream.ProgressNotifier(null, contents.length));
|
||||
final int iBufSize = boundary.length + MultipartStream.BOUNDARY_PREFIX.length + 1;
|
||||
final MultipartStream ms = new MultipartStream(input, boundary, iBufSize, new MultipartStream.ProgressNotifier(null, contents.length));
|
||||
assertNotNull(ms);
|
||||
}
|
||||
|
||||
|
@ -68,10 +59,7 @@ public class MultipartStreamTest {
|
|||
final byte[] contents = strData.getBytes();
|
||||
final InputStream input = new ByteArrayInputStream(contents);
|
||||
final byte[] boundary = BOUNDARY_TEXT.getBytes();
|
||||
final MultipartStream ms = new MultipartStream(
|
||||
input,
|
||||
boundary,
|
||||
new MultipartStream.ProgressNotifier(null, contents.length));
|
||||
final MultipartStream ms = new MultipartStream(input, boundary, new MultipartStream.ProgressNotifier(null, contents.length));
|
||||
assertNotNull(ms);
|
||||
}
|
||||
|
|
@ -42,15 +42,15 @@ public class ParameterParserTest {
|
|||
public void testFileUpload139() {
|
||||
final ParameterParser parser = new ParameterParser();
|
||||
String s = "Content-type: multipart/form-data , boundary=AaB03x";
|
||||
Map<String, String> params = parser.parse(s, new char[] {',', ';' });
|
||||
Map<String, String> params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("AaB03x", params.get("boundary"));
|
||||
|
||||
s = "Content-type: multipart/form-data, boundary=AaB03x";
|
||||
params = parser.parse(s, new char[] {';', ',' });
|
||||
params = parser.parse(s, new char[] { ';', ',' });
|
||||
assertEquals("AaB03x", params.get("boundary"));
|
||||
|
||||
s = "Content-type: multipart/mixed, boundary=BbC04y";
|
||||
params = parser.parse(s, new char[] {',', ';' });
|
||||
params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("BbC04y", params.get("boundary"));
|
||||
}
|
||||
|
||||
|
@ -74,36 +74,34 @@ public class ParameterParserTest {
|
|||
final ParameterParser parser = new ParameterParser();
|
||||
|
||||
// Should parse a UTF-8 charset
|
||||
String s = "Content-Disposition: form-data; "
|
||||
+ "name=\"file\"; filename*=UTF-8''%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF\r\n";
|
||||
String s = "Content-Disposition: form-data; " + "name=\"file\"; filename*=UTF-8''%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF\r\n";
|
||||
Map<String, String> params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("\u3053\u3093\u306B\u3061\u306F", params.get("filename")); //filename = "こんにちは" in japanese
|
||||
assertEquals("\u3053\u3093\u306B\u3061\u306F", params.get("filename")); // filename = "こんにちは" in japanese
|
||||
|
||||
// Should parse ISO-8859-1 charset
|
||||
s = "Content-Disposition: form-data; name=\"file\"; filename*=UTF-8''%70%C3%A2%74%C3%A9\r\n";
|
||||
params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("\u0070\u00e2\u0074\u00e9", params.get("filename")); //filename = "pâté" in french
|
||||
assertEquals("\u0070\u00e2\u0074\u00e9", params.get("filename")); // filename = "pâté" in french
|
||||
|
||||
// Should not decode if '*' is not at the end of param-name
|
||||
s = "Content-Disposition: form-data; name=\"file\"; file*name=UTF-8''%61%62%63\r\n";
|
||||
params = parser.parse(s, new char[] {',', ';' });
|
||||
params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("UTF-8''%61%62%63", params.get("file*name"));
|
||||
|
||||
// Should not decode if param-value does not follow <charset>'<lang>'<encoded>
|
||||
s = "Content-Disposition: form-data; name=\"file\"; filename*=a'bc\r\n";
|
||||
params = parser.parse(s, new char[] {',', ';' });
|
||||
params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("a'bc", params.get("filename"));
|
||||
|
||||
// Should not decode if param-name doesn't have '*' at end
|
||||
s = "Content-Disposition: form-data; name=\"file\"; filename=a'b'c\r\n";
|
||||
params = parser.parse(s, new char[] {',', ';' });
|
||||
params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertEquals("a'b'c", params.get("filename"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsing() {
|
||||
String s =
|
||||
"test; test1 = stuff ; test2 = \"stuff; stuff\"; test3=\"stuff";
|
||||
String s = "test; test1 = stuff ; test2 = \"stuff; stuff\"; test3=\"stuff";
|
||||
final ParameterParser parser = new ParameterParser();
|
||||
Map<String, String> params = parser.parse(s, ';');
|
||||
assertNull(params.get("test"));
|
||||
|
@ -111,7 +109,7 @@ public class ParameterParserTest {
|
|||
assertEquals("stuff; stuff", params.get("test2"));
|
||||
assertEquals("\"stuff", params.get("test3"));
|
||||
|
||||
params = parser.parse(s, new char[] {',', ';' });
|
||||
params = parser.parse(s, new char[] { ',', ';' });
|
||||
assertNull(params.get("test"));
|
||||
assertEquals("stuff", params.get("test1"));
|
||||
assertEquals("stuff; stuff", params.get("test2"));
|
|
@ -24,8 +24,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Use the online <a href="http://dogmamix.com/MimeHeadersDecoder/">MimeHeadersDecoder</a>
|
||||
* to validate expected values.
|
||||
* Use the online <a href="http://dogmamix.com/MimeHeadersDecoder/">MimeHeadersDecoder</a> to validate expected values.
|
||||
*
|
||||
* @since 1.3
|
||||
*/
|
||||
|
@ -43,15 +42,13 @@ public final class MimeUtilityTestCase {
|
|||
@Test
|
||||
public void decodeIso88591Base64Encoded() throws Exception {
|
||||
assertEncoded("If you can read this you understand the example.",
|
||||
"=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= "
|
||||
+ "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");
|
||||
"=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= " + "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decodeIso88591Base64EncodedWithWhiteSpace() throws Exception {
|
||||
assertEncoded("If you can read this you understand the example.",
|
||||
"=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\t \r\n =?ISO-8859-"
|
||||
+ "2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");
|
||||
"=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\t \r\n =?ISO-8859-" + "2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");
|
||||
}
|
||||
|
||||
@Test
|
|
@ -100,9 +100,8 @@ public final class QuotedPrintableDecoderTestCase {
|
|||
*/
|
||||
@Test
|
||||
public void softLineBreakDecode() throws Exception {
|
||||
assertEncoded("If you believe that truth=beauty, then surely mathematics is the most "
|
||||
+ "beautiful branch of philosophy.", "If you believe that truth=3Dbeauty, then "
|
||||
+ "surely=20=\r\nmathematics is the most beautiful branch of philosophy.");
|
||||
assertEncoded("If you believe that truth=beauty, then surely mathematics is the most " + "beautiful branch of philosophy.",
|
||||
"If you believe that truth=3Dbeauty, then " + "surely=20=\r\nmathematics is the most beautiful branch of philosophy.");
|
||||
}
|
||||
|
||||
@Test
|
|
@ -28,8 +28,7 @@ import org.junit.jupiter.api.Test;
|
|||
/**
|
||||
* The expected characters are encoded in UTF16, while the actual characters may be encoded in UTF-8/ISO-8859-1
|
||||
*
|
||||
* RFC 5987 recommends to support both UTF-8 & ISO 8859-1. Test values are taken
|
||||
* from https://tools.ietf.org/html/rfc5987#section-3.2.2
|
||||
* RFC 5987 recommends to support both UTF-8 & ISO 8859-1. Test values are taken from https://tools.ietf.org/html/rfc5987#section-3.2.2
|
||||
*/
|
||||
public final class RFC2231UtilityTestCase {
|
||||
|
||||
|
@ -44,13 +43,12 @@ public final class RFC2231UtilityTestCase {
|
|||
|
||||
@Test
|
||||
public void decodeIso88591() throws Exception {
|
||||
assertEncoded("\u00A3 rate", "iso-8859-1'en'%A3%20rate"); //"£ rate"
|
||||
assertEncoded("\u00A3 rate", "iso-8859-1'en'%A3%20rate"); // "£ rate"
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decodeUtf8() throws Exception {
|
||||
assertEncoded("\u00a3 \u0061\u006e\u0064 \u20ac \u0072\u0061\u0074\u0065\u0073",
|
||||
"UTF-8''%c2%a3%20and%20%e2%82%ac%20rates"); //"£ and € rates"
|
||||
assertEncoded("\u00a3 \u0061\u006e\u0064 \u20ac \u0072\u0061\u0074\u0065\u0073", "UTF-8''%c2%a3%20and%20%e2%82%ac%20rates"); // "£ and € rates"
|
||||
}
|
||||
|
||||
@Test
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
|
||||
<local-check-config name="maven-checkstyle-plugin validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-jakarta/../src/checkstyle/fileupload_checks.xml" type="remote" description="maven-checkstyle-plugin configuration validate-main">
|
||||
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-jakarta\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
|
||||
<property name="checkstyle.cache.file" value="${project_loc}/target/checkstyle-cachefile"/>
|
||||
<property name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-jakarta\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
|
||||
</local-check-config>
|
||||
<fileset name="java-sources-validate-main" enabled="true" check-config-name="maven-checkstyle-plugin validate-main" local="true">
|
||||
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/main/resources.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/test/resources.*\.properties" include-pattern="true"/>
|
||||
</fileset>
|
||||
</fileset-config>
|
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>commons-fileupload2-jakarta</artifactId>
|
||||
|
||||
<name>Apache Commons FileUpload Jakarta Servlet</name>
|
||||
<description>
|
||||
The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart
|
||||
file upload functionality to servlets and web applications.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<commons.parent.dir>${basedir}/..</commons.parent.dir>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<classifier>tests</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<!-- Version 6.0.0 requires Java 11 -->
|
||||
<version>5.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons.lang3.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jaksrvlt;
|
||||
package org.apache.commons.fileupload2.jakarta;
|
||||
|
||||
import org.apache.commons.io.FileCleaningTracker;
|
||||
|
||||
|
@ -23,50 +23,39 @@ import jakarta.servlet.ServletContextEvent;
|
|||
import jakarta.servlet.ServletContextListener;
|
||||
|
||||
/**
|
||||
* A servlet context listener, which ensures that the
|
||||
* {@link FileCleaningTracker}'s reaper thread is terminated,
|
||||
* when the web application is destroyed.
|
||||
* A servlet context listener, which ensures that the {@link FileCleaningTracker}'s reaper thread is terminated, when the web application is destroyed.
|
||||
*/
|
||||
public class JakSrvltFileCleaner implements ServletContextListener {
|
||||
public class JakartaServletFileCleaner implements ServletContextListener {
|
||||
|
||||
/**
|
||||
* Attribute name, which is used for storing an instance of
|
||||
* {@link FileCleaningTracker} in the web application.
|
||||
* Attribute name, which is used for storing an instance of {@link FileCleaningTracker} in the web application.
|
||||
*/
|
||||
public static final String FILE_CLEANING_TRACKER_ATTRIBUTE
|
||||
= JakSrvltFileCleaner.class.getName() + ".FileCleaningTracker";
|
||||
public static final String FILE_CLEANING_TRACKER_ATTRIBUTE = JakartaServletFileCleaner.class.getName() + ".FileCleaningTracker";
|
||||
|
||||
/**
|
||||
* Gets the instance of {@link FileCleaningTracker}, which is
|
||||
* associated with the given {@link ServletContext}.
|
||||
* Gets the instance of {@link FileCleaningTracker}, which is associated with the given {@link ServletContext}.
|
||||
*
|
||||
* @param servletContext The servlet context to query
|
||||
* @return The contexts tracker
|
||||
*/
|
||||
public static FileCleaningTracker
|
||||
getFileCleaningTracker(final ServletContext servletContext) {
|
||||
return (FileCleaningTracker)
|
||||
servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
|
||||
public static FileCleaningTracker getFileCleaningTracker(final ServletContext servletContext) {
|
||||
return (FileCleaningTracker) servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instance of {@link FileCleaningTracker}, which is
|
||||
* associated with the given {@link ServletContext}.
|
||||
* Sets the instance of {@link FileCleaningTracker}, which is associated with the given {@link ServletContext}.
|
||||
*
|
||||
* @param servletContext The servlet context to modify
|
||||
* @param tracker The tracker to set
|
||||
* @param tracker The tracker to set
|
||||
*/
|
||||
public static void setFileCleaningTracker(final ServletContext servletContext,
|
||||
final FileCleaningTracker tracker) {
|
||||
public static void setFileCleaningTracker(final ServletContext servletContext, final FileCleaningTracker tracker) {
|
||||
servletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, tracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the web application is being destroyed.
|
||||
* Calls {@link FileCleaningTracker#exitWhenFinished()}.
|
||||
* Called when the web application is being destroyed. Calls {@link FileCleaningTracker#exitWhenFinished()}.
|
||||
*
|
||||
* @param sce The servlet context, used for calling
|
||||
* {@link #getFileCleaningTracker(ServletContext)}.
|
||||
* @param sce The servlet context, used for calling {@link #getFileCleaningTracker(ServletContext)}.
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(final ServletContextEvent sce) {
|
||||
|
@ -74,15 +63,12 @@ public class JakSrvltFileCleaner implements ServletContextListener {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called when the web application is initialized. Does
|
||||
* nothing.
|
||||
* Called when the web application is initialized. Does nothing.
|
||||
*
|
||||
* @param sce The servlet context, used for calling
|
||||
* {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
|
||||
* @param sce The servlet context, used for calling {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(final ServletContextEvent sce) {
|
||||
setFileCleaningTracker(sce.getServletContext(),
|
||||
new FileCleaningTracker());
|
||||
setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker());
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jaksrvlt;
|
||||
package org.apache.commons.fileupload2.jakarta;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -32,20 +32,15 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
/**
|
||||
* High level API for processing file uploads.
|
||||
* <p>
|
||||
* This class handles multiple files per single HTML widget, sent using
|
||||
* {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
|
||||
* #parseRequest(HttpServletRequest)} to acquire a list of {@link
|
||||
* org.apache.commons.fileupload2.FileItem}s associated with a given HTML
|
||||
* widget.
|
||||
* This class handles multiple files per single HTML widget, sent using {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link #parseRequest(HttpServletRequest)} to acquire a list of
|
||||
* {@link org.apache.commons.fileupload2.FileItem}s 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.
|
||||
* 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>
|
||||
*/
|
||||
public class JakSrvltFileUpload extends FileUpload {
|
||||
public class JakartaServletFileUpload extends FileUpload {
|
||||
|
||||
/**
|
||||
* Constant for HTTP POST method.
|
||||
|
@ -53,86 +48,70 @@ public class JakSrvltFileUpload extends FileUpload {
|
|||
private static final String POST_METHOD = "POST";
|
||||
|
||||
/**
|
||||
* Utility method that determines whether the request contains multipart
|
||||
* content.
|
||||
* Utility method that determines whether the request contains multipart content.
|
||||
*
|
||||
* @param request The servlet request to be evaluated. Must be non-null.
|
||||
*
|
||||
* @return {@code true} if the request is multipart;
|
||||
* {@code false} otherwise.
|
||||
* @return {@code true} if the request is multipart; {@code false} otherwise.
|
||||
*/
|
||||
public static final boolean isMultipartContent(final HttpServletRequest request) {
|
||||
return POST_METHOD.equalsIgnoreCase(request.getMethod()) && AbstractFileUpload.isMultipartContent(new JakSrvltRequestContext(request));
|
||||
return POST_METHOD.equalsIgnoreCase(request.getMethod()) && AbstractFileUpload.isMultipartContent(new JakartaServletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized instance of this class. A factory must be
|
||||
* configured, using {@code setFileItemFactory()}, before attempting
|
||||
* to parse requests.
|
||||
* Constructs an uninitialized instance of this class. A factory must be configured, using {@code setFileItemFactory()}, before attempting to parse
|
||||
* requests.
|
||||
*
|
||||
* @see FileUpload#FileUpload(FileItemFactory)
|
||||
*/
|
||||
public JakSrvltFileUpload() {
|
||||
public JakartaServletFileUpload() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class which uses the supplied factory to
|
||||
* create {@code FileItem} instances.
|
||||
* Constructs an instance of this class which uses the supplied factory to create {@code FileItem} instances.
|
||||
*
|
||||
* @see FileUpload#FileUpload()
|
||||
* @param fileItemFactory The factory to use for creating file items.
|
||||
*/
|
||||
public JakSrvltFileUpload(final FileItemFactory fileItemFactory) {
|
||||
public JakartaServletFileUpload(final FileItemFactory fileItemFactory) {
|
||||
super(fileItemFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} file item iterator.
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} file item iterator.
|
||||
*
|
||||
* @param request The servlet request to be parsed.
|
||||
* @return An iterator to instances of {@code FileItemStream}
|
||||
* 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.
|
||||
* @return An iterator to instances of {@code FileItemStream} 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(final HttpServletRequest request)
|
||||
throws FileUploadException, IOException {
|
||||
return super.getItemIterator(new JakSrvltRequestContext(request));
|
||||
public FileItemIterator getItemIterator(final HttpServletRequest request) throws FileUploadException, IOException {
|
||||
return super.getItemIterator(new JakartaServletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param request The servlet request to be parsed.
|
||||
* @return A map of {@code FileItem} instances parsed from the request.
|
||||
* @throws FileUploadException if there are problems reading/parsing
|
||||
* the request or storing files.
|
||||
* @throws FileUploadException if there are problems reading/parsing the request or storing files.
|
||||
*
|
||||
* @since 1.3
|
||||
*/
|
||||
public Map<String, List<FileItem>> parseParameterMap(final HttpServletRequest request)
|
||||
throws FileUploadException {
|
||||
return parseParameterMap(new JakSrvltRequestContext(request));
|
||||
public Map<String, List<FileItem>> parseParameterMap(final HttpServletRequest request) throws FileUploadException {
|
||||
return parseParameterMap(new JakartaServletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param request The servlet request to be parsed.
|
||||
* @return A list of {@code FileItem} 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.
|
||||
* @return A list of {@code FileItem} 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(final HttpServletRequest request) throws FileUploadException {
|
||||
return parseRequest(new JakSrvltRequestContext(request));
|
||||
return parseRequest(new JakartaServletRequestContext(request));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,81 +1,80 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jaksrvlt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractRequestContext;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Provides access to the request information needed for a request made to
|
||||
* an HTTP servlet.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class JakSrvltRequestContext extends AbstractRequestContext {
|
||||
|
||||
/**
|
||||
* The request for which the context is being provided.
|
||||
*/
|
||||
private final HttpServletRequest request;
|
||||
|
||||
/**
|
||||
* Construct a context for this request.
|
||||
*
|
||||
* @param request The request to which this context applies.
|
||||
*/
|
||||
public JakSrvltRequestContext(final HttpServletRequest request) {
|
||||
super(request::getHeader, request::getContentLength);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding for the request.
|
||||
*
|
||||
* @return The character encoding for the request.
|
||||
*/
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type of the request.
|
||||
*
|
||||
* @return The content type of the request.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return request.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream for the request.
|
||||
*
|
||||
* @return The input stream for the request.
|
||||
*
|
||||
* @throws IOException if a problem occurs.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return request.getInputStream();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jakarta;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractRequestContext;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Provides access to the request information needed for a request made to an HTTP servlet.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class JakartaServletRequestContext extends AbstractRequestContext {
|
||||
|
||||
/**
|
||||
* The request for which the context is being provided.
|
||||
*/
|
||||
private final HttpServletRequest request;
|
||||
|
||||
/**
|
||||
* Construct a context for this request.
|
||||
*
|
||||
* @param request The request to which this context applies.
|
||||
*/
|
||||
public JakartaServletRequestContext(final HttpServletRequest request) {
|
||||
super(request::getHeader, request::getContentLength);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding for the request.
|
||||
*
|
||||
* @return The character encoding for the request.
|
||||
*/
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type of the request.
|
||||
*
|
||||
* @return The content type of the request.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return request.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream for the request.
|
||||
*
|
||||
* @return The input stream for the request.
|
||||
*
|
||||
* @throws IOException if a problem occurs.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return request.getInputStream();
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of {@link org.apache.commons.fileupload2.FileUpload FileUpload} for use in servlets conforming to the namespace {@code jakarta.servlet}.
|
||||
*
|
||||
* </p>
|
||||
* <p>
|
||||
* The following code fragment demonstrates typical usage.
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||
* // Configure the factory here, if desired.
|
||||
* JakSrvltFileUpload upload = new JakSrvltFileUpload(factory);
|
||||
* // Configure the uploader here, if desired.
|
||||
* List fileItems = upload.parseRequest(request);
|
||||
* </pre>
|
||||
* <p>
|
||||
* Please see the FileUpload <a href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> for further details and examples of how to
|
||||
* use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jakarta;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jaksrvlt;
|
||||
package org.apache.commons.fileupload2.jakarta;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
@ -23,9 +23,9 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUploadTest;
|
||||
import org.apache.commons.fileupload2.Constants;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileUploadTest;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -34,40 +34,40 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
/**
|
||||
* Test for {@link org.apache.commons.fileupload2.servlet.ServletFileUpload}.
|
||||
*
|
||||
* @see FileUploadTest
|
||||
* @see AbstractFileUploadTest
|
||||
* @since 1.4
|
||||
*/
|
||||
public class JakSrvltFileUploadTest {
|
||||
public class JakartaServletFileUploadTest {
|
||||
|
||||
@Test
|
||||
public void parseImpliedUtf8()
|
||||
throws Exception {
|
||||
public void parseImpliedUtf8() throws Exception {
|
||||
// utf8 encoded form-data without explicit content-type encoding
|
||||
// @formatter:off
|
||||
final String text = "-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"utf8Html\"\r\n" +
|
||||
"\r\n" +
|
||||
"Thís ís the coñteñt of the fíle\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
|
||||
final byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
|
||||
final HttpServletRequest request = new MockJakSrvltHttpRequest(bytes, Constants.CONTENT_TYPE);
|
||||
final HttpServletRequest request = new MockJakartaServletHttpRequest(bytes, Constants.CONTENT_TYPE);
|
||||
|
||||
final DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
|
||||
fileItemFactory.setDefaultCharset("UTF-8");
|
||||
final JakSrvltFileUpload upload = new JakSrvltFileUpload(fileItemFactory);
|
||||
final JakartaServletFileUpload upload = new JakartaServletFileUpload(fileItemFactory);
|
||||
final List<FileItem> fileItems = upload.parseRequest(request);
|
||||
final FileItem fileItem = fileItems.get(0);
|
||||
assertTrue(fileItem.getString().contains("coñteñt"), fileItem.getString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-210">
|
||||
*/
|
||||
@Test
|
||||
public void parseParameterMap()
|
||||
throws Exception {
|
||||
public void parseParameterMap() throws Exception {
|
||||
// @formatter:off
|
||||
final String text = "-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
|
@ -87,10 +87,11 @@ public class JakSrvltFileUploadTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
|
||||
final HttpServletRequest request = new MockJakSrvltHttpRequest(bytes, Constants.CONTENT_TYPE);
|
||||
final HttpServletRequest request = new MockJakartaServletHttpRequest(bytes, Constants.CONTENT_TYPE);
|
||||
|
||||
final JakSrvltFileUpload upload = new JakSrvltFileUpload(new DiskFileItemFactory());
|
||||
final JakartaServletFileUpload upload = new JakartaServletFileUpload(new DiskFileItemFactory());
|
||||
final Map<String, List<FileItem>> mappedParameters = upload.parseParameterMap(request);
|
||||
assertTrue(mappedParameters.containsKey("file"));
|
||||
assertEquals(1, mappedParameters.get("file").size());
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jaksrvlt;
|
||||
package org.apache.commons.fileupload2.jakarta;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -45,17 +45,15 @@ import jakarta.servlet.http.HttpSession;
|
|||
import jakarta.servlet.http.HttpUpgradeHandler;
|
||||
import jakarta.servlet.http.Part;
|
||||
|
||||
public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
||||
public class MockJakartaServletHttpRequest implements HttpServletRequest {
|
||||
|
||||
private static class MyServletInputStream
|
||||
extends jakarta.servlet.ServletInputStream {
|
||||
private static class MyServletInputStream extends jakarta.servlet.ServletInputStream {
|
||||
|
||||
private final InputStream inputStream;
|
||||
private final int readLimit;
|
||||
|
||||
/**
|
||||
* Creates a new instance, which returns the given
|
||||
* streams data.
|
||||
* Creates a new instance, which returns the given streams data.
|
||||
*/
|
||||
public MyServletInputStream(final InputStream inputStream, final int readLimit) {
|
||||
this.inputStream = inputStream;
|
||||
|
@ -103,24 +101,16 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
private final Map<String, String> mHeaders = new java.util.HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance with the given request data
|
||||
* and content type.
|
||||
* Creates a new instance with the given request data and content type.
|
||||
*/
|
||||
public MockJakSrvltHttpRequest(
|
||||
final byte[] requestData,
|
||||
final String strContentType) {
|
||||
this(new ByteArrayInputStream(requestData),
|
||||
requestData.length, strContentType);
|
||||
public MockJakartaServletHttpRequest(final byte[] requestData, final String strContentType) {
|
||||
this(new ByteArrayInputStream(requestData), requestData.length, strContentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the given request data
|
||||
* and content type.
|
||||
* Creates a new instance with the given request data and content type.
|
||||
*/
|
||||
public MockJakSrvltHttpRequest(
|
||||
final InputStream requestData,
|
||||
final long requestLength,
|
||||
final String strContentType) {
|
||||
public MockJakartaServletHttpRequest(final InputStream requestData, final long requestLength, final String strContentType) {
|
||||
mRequestData = requestData;
|
||||
length = requestLength;
|
||||
mStrContentType = strContentType;
|
||||
|
@ -393,6 +383,10 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
return null;
|
||||
}
|
||||
|
||||
public String getProtocolRequestId() {
|
||||
throw new IllegalStateException("Not implemented 6.0.0");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletRequest#getQueryString()
|
||||
*/
|
||||
|
@ -463,6 +457,10 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
return null;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
throw new IllegalStateException("Not implemented 6.0.0");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletRequest#getRequestURI()
|
||||
*/
|
||||
|
@ -509,7 +507,7 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
return session.getServletContext();
|
||||
return session.getServletContext();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -632,8 +630,7 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
* @see javax.servlet.ServletRequest#setCharacterEncoding(String)
|
||||
*/
|
||||
@Override
|
||||
public void setCharacterEncoding(final String arg0)
|
||||
throws UnsupportedEncodingException {
|
||||
public void setCharacterEncoding(final String arg0) throws UnsupportedEncodingException {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -658,8 +655,7 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AsyncContext startAsync(final ServletRequest servletRequest, final ServletResponse servletResponse)
|
||||
throws IllegalStateException {
|
||||
public AsyncContext startAsync(final ServletRequest servletRequest, final ServletResponse servletResponse) throws IllegalStateException {
|
||||
throw new IllegalStateException("Not implemented");
|
||||
}
|
||||
|
||||
|
@ -667,4 +663,9 @@ public class MockJakSrvltHttpRequest implements HttpServletRequest {
|
|||
public <T extends HttpUpgradeHandler> T upgrade(final Class<T> handlerClass) throws IOException, ServletException {
|
||||
throw new IllegalStateException("Not implemented");
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public ServletConnection getServletConnection() {
|
||||
// throw new IllegalStateException("Not implemented 6.0.0");
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
|
||||
<local-check-config name="maven-checkstyle-plugin validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-javax/../src/checkstyle/fileupload_checks.xml" type="remote" description="maven-checkstyle-plugin configuration validate-main">
|
||||
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-javax\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
|
||||
<property name="checkstyle.cache.file" value="${project_loc}/target/checkstyle-cachefile"/>
|
||||
<property name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-javax\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
|
||||
</local-check-config>
|
||||
<fileset name="java-sources-validate-main" enabled="true" check-config-name="maven-checkstyle-plugin validate-main" local="true">
|
||||
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/main/resources.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/test/resources.*\.properties" include-pattern="true"/>
|
||||
</fileset>
|
||||
</fileset-config>
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>commons-fileupload2-javax</artifactId>
|
||||
|
||||
<name>Apache Commons FileUpload Javax Servlet</name>
|
||||
<description>
|
||||
The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart
|
||||
file upload functionality to servlets and web applications.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<commons.parent.dir>${basedir}/..</commons.parent.dir>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<classifier>tests</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${commons.servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.servlet;
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
|
@ -23,50 +23,39 @@ import javax.servlet.ServletContextListener;
|
|||
import org.apache.commons.io.FileCleaningTracker;
|
||||
|
||||
/**
|
||||
* A servlet context listener, which ensures that the
|
||||
* {@link FileCleaningTracker}'s reaper thread is terminated,
|
||||
* when the web application is destroyed.
|
||||
* A servlet context listener, which ensures that the {@link FileCleaningTracker}'s reaper thread is terminated, when the web application is destroyed.
|
||||
*/
|
||||
public class FileCleanerCleanup implements ServletContextListener {
|
||||
|
||||
/**
|
||||
* Attribute name, which is used for storing an instance of
|
||||
* {@link FileCleaningTracker} in the web application.
|
||||
* 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";
|
||||
public static final String FILE_CLEANING_TRACKER_ATTRIBUTE = FileCleanerCleanup.class.getName() + ".FileCleaningTracker";
|
||||
|
||||
/**
|
||||
* Gets the instance of {@link FileCleaningTracker}, which is
|
||||
* associated with the given {@link ServletContext}.
|
||||
* Gets the instance of {@link FileCleaningTracker}, which is associated with the given {@link ServletContext}.
|
||||
*
|
||||
* @param servletContext The servlet context to query
|
||||
* @return The contexts tracker
|
||||
*/
|
||||
public static FileCleaningTracker
|
||||
getFileCleaningTracker(final ServletContext servletContext) {
|
||||
return (FileCleaningTracker)
|
||||
servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
|
||||
public static FileCleaningTracker getFileCleaningTracker(final ServletContext servletContext) {
|
||||
return (FileCleaningTracker) servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instance of {@link FileCleaningTracker}, which is
|
||||
* associated with the given {@link ServletContext}.
|
||||
* Sets the instance of {@link FileCleaningTracker}, which is associated with the given {@link ServletContext}.
|
||||
*
|
||||
* @param servletContext The servlet context to modify
|
||||
* @param tracker The tracker to set
|
||||
* @param tracker The tracker to set
|
||||
*/
|
||||
public static void setFileCleaningTracker(final ServletContext servletContext,
|
||||
final FileCleaningTracker tracker) {
|
||||
public static void setFileCleaningTracker(final ServletContext servletContext, final FileCleaningTracker tracker) {
|
||||
servletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, tracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the web application is being destroyed.
|
||||
* Calls {@link FileCleaningTracker#exitWhenFinished()}.
|
||||
* Called when the web application is being destroyed. Calls {@link FileCleaningTracker#exitWhenFinished()}.
|
||||
*
|
||||
* @param sce The servlet context, used for calling
|
||||
* {@link #getFileCleaningTracker(ServletContext)}.
|
||||
* @param sce The servlet context, used for calling {@link #getFileCleaningTracker(ServletContext)}.
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(final ServletContextEvent sce) {
|
||||
|
@ -74,16 +63,13 @@ public class FileCleanerCleanup implements ServletContextListener {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called when the web application is initialized. Does
|
||||
* nothing.
|
||||
* Called when the web application is initialized. Does nothing.
|
||||
*
|
||||
* @param sce The servlet context, used for calling
|
||||
* {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
|
||||
* @param sce The servlet context, used for calling {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(final ServletContextEvent sce) {
|
||||
setFileCleaningTracker(sce.getServletContext(),
|
||||
new FileCleaningTracker());
|
||||
setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker());
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.servlet;
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -32,17 +32,12 @@ import org.apache.commons.fileupload2.FileUploadException;
|
|||
/**
|
||||
* High level API for processing file uploads.
|
||||
* <p>
|
||||
* This class handles multiple files per single HTML widget, sent using
|
||||
* {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
|
||||
* #parseRequest(HttpServletRequest)} to acquire a list of {@link
|
||||
* org.apache.commons.fileupload2.FileItem}s associated with a given HTML
|
||||
* widget.
|
||||
* This class handles multiple files per single HTML widget, sent using {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link #parseRequest(HttpServletRequest)} to acquire a list of
|
||||
* {@link org.apache.commons.fileupload2.FileItem}s 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.
|
||||
* 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>
|
||||
*/
|
||||
public class ServletFileUpload extends FileUpload {
|
||||
|
@ -53,22 +48,19 @@ public class ServletFileUpload extends FileUpload {
|
|||
private static final String POST_METHOD = "POST";
|
||||
|
||||
/**
|
||||
* Tests whether the request contains multipart
|
||||
* content.
|
||||
* Tests whether the request contains multipart content.
|
||||
*
|
||||
* @param request The servlet request to be evaluated. Must be non-null.
|
||||
*
|
||||
* @return {@code true} if the request is multipart;
|
||||
* {@code false} otherwise.
|
||||
* @return {@code true} if the request is multipart; {@code false} otherwise.
|
||||
*/
|
||||
public static final boolean isMultipartContent(final HttpServletRequest request) {
|
||||
return POST_METHOD.equalsIgnoreCase(request.getMethod()) && AbstractFileUpload.isMultipartContent(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized instance of this class. A factory must be
|
||||
* configured, using {@code setFileItemFactory()}, before attempting
|
||||
* to parse requests.
|
||||
* Constructs an uninitialized instance of this class. A factory must be configured, using {@code setFileItemFactory()}, before attempting to parse
|
||||
* requests.
|
||||
*
|
||||
* @see FileUpload#FileUpload(FileItemFactory)
|
||||
*/
|
||||
|
@ -76,8 +68,7 @@ public class ServletFileUpload extends FileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class which uses the supplied factory to
|
||||
* create {@code FileItem} instances.
|
||||
* Constructs an instance of this class which uses the supplied factory to create {@code FileItem} instances.
|
||||
*
|
||||
* @see FileUpload#FileUpload()
|
||||
* @param fileItemFactory The factory to use for creating file items.
|
||||
|
@ -87,31 +78,24 @@ public class ServletFileUpload extends FileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} file item iterator.
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} file item iterator.
|
||||
*
|
||||
* @param request The servlet request to be parsed.
|
||||
* @return An iterator to instances of {@code FileItemStream}
|
||||
* 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.
|
||||
* @return An iterator to instances of {@code FileItemStream} 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(final HttpServletRequest request) throws FileUploadException, IOException {
|
||||
return super.getItemIterator(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param request The servlet request to be parsed.
|
||||
* @return A map of {@code FileItem} instances parsed from the request.
|
||||
* @throws FileUploadException if there are problems reading/parsing
|
||||
* the request or storing files.
|
||||
* @throws FileUploadException if there are problems reading/parsing the request or storing files.
|
||||
* @since 1.3
|
||||
*/
|
||||
public Map<String, List<FileItem>> parseParameterMap(final HttpServletRequest request) throws FileUploadException {
|
||||
|
@ -119,14 +103,11 @@ public class ServletFileUpload extends FileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param request The servlet request to be parsed.
|
||||
* @return A list of {@code FileItem} 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.
|
||||
* @return A list of {@code FileItem} 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(final HttpServletRequest request) throws FileUploadException {
|
||||
return parseRequest(new ServletRequestContext(request));
|
|
@ -1,81 +1,80 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractRequestContext;
|
||||
|
||||
/**
|
||||
* Provides access to the request information needed for a request made to
|
||||
* an HTTP servlet.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class ServletRequestContext extends AbstractRequestContext {
|
||||
|
||||
/**
|
||||
* The request for which the context is being provided.
|
||||
*/
|
||||
private final HttpServletRequest request;
|
||||
|
||||
/**
|
||||
* Constructs a context for this request.
|
||||
*
|
||||
* @param request The request to which this context applies.
|
||||
*/
|
||||
public ServletRequestContext(final HttpServletRequest request) {
|
||||
super(request::getHeader, request::getContentLength);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding for the request.
|
||||
*
|
||||
* @return The character encoding for the request.
|
||||
*/
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type of the request.
|
||||
*
|
||||
* @return The content type of the request.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return request.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream for the request.
|
||||
*
|
||||
* @return The input stream for the request.
|
||||
*
|
||||
* @throws IOException if a problem occurs.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return request.getInputStream();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractRequestContext;
|
||||
|
||||
/**
|
||||
* Provides access to the request information needed for a request made to an HTTP servlet.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class ServletRequestContext extends AbstractRequestContext {
|
||||
|
||||
/**
|
||||
* The request for which the context is being provided.
|
||||
*/
|
||||
private final HttpServletRequest request;
|
||||
|
||||
/**
|
||||
* Constructs a context for this request.
|
||||
*
|
||||
* @param request The request to which this context applies.
|
||||
*/
|
||||
public ServletRequestContext(final HttpServletRequest request) {
|
||||
super(request::getHeader, request::getContentLength);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding for the request.
|
||||
*
|
||||
* @return The character encoding for the request.
|
||||
*/
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type of the request.
|
||||
*
|
||||
* @return The content type of the request.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return request.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream for the request.
|
||||
*
|
||||
* @return The input stream for the request.
|
||||
*
|
||||
* @throws IOException if a problem occurs.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return request.getInputStream();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 org.apache.commons.fileupload2.FileUpload FileUpload} for use in servlets conforming to JSR 53. This implementation requires only
|
||||
* access to the servlet's current {@code HttpServletRequest} instance, and a suitable {@link org.apache.commons.fileupload2.FileItemFactory FileItemFactory}
|
||||
* implementation, such as {@link org.apache.commons.fileupload2.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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> for further details and examples of how to
|
||||
* use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.javax;
|
|
@ -14,29 +14,26 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUpload;
|
||||
|
||||
final class HttpServletRequestFactory {
|
||||
|
||||
public static HttpServletRequest createHttpServletRequestWithNullContentType() {
|
||||
final byte[] requestData = "foobar".getBytes();
|
||||
return new MockHttpServletRequest(
|
||||
requestData,
|
||||
null);
|
||||
return new MockHttpServletRequest(requestData, null);
|
||||
}
|
||||
|
||||
static public HttpServletRequest createInvalidHttpServletRequest() {
|
||||
final byte[] requestData = "foobar".getBytes();
|
||||
return new MockHttpServletRequest(
|
||||
requestData,
|
||||
AbstractFileUpload.MULTIPART_FORM_DATA);
|
||||
return new MockHttpServletRequest(requestData, AbstractFileUpload.MULTIPART_FORM_DATA);
|
||||
}
|
||||
|
||||
public static HttpServletRequest createValidHttpServletRequest(
|
||||
final String[] strFileNames) {
|
||||
// todo - provide a real implementation
|
||||
public static HttpServletRequest createValidHttpServletRequest(final String[] strFileNames) {
|
||||
// TODO Provide a real implementation.
|
||||
|
||||
final StringBuilder sbRequestData = new StringBuilder();
|
||||
|
||||
|
@ -46,9 +43,7 @@ final class HttpServletRequestFactory {
|
|||
|
||||
final byte[] requestData = sbRequestData.toString().getBytes();
|
||||
|
||||
return new MockHttpServletRequest(
|
||||
requestData,
|
||||
AbstractFileUpload.MULTIPART_FORM_DATA);
|
||||
return new MockHttpServletRequest(requestData, AbstractFileUpload.MULTIPART_FORM_DATA);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -32,17 +32,17 @@ import javax.servlet.http.Cookie;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUpload;
|
||||
|
||||
public class MockHttpServletRequest implements HttpServletRequest {
|
||||
|
||||
private static class MyServletInputStream
|
||||
extends javax.servlet.ServletInputStream {
|
||||
private static class MyServletInputStream extends javax.servlet.ServletInputStream {
|
||||
|
||||
private final InputStream inputStream;
|
||||
private final int readLimit;
|
||||
|
||||
/**
|
||||
* Creates a new instance, which returns the given
|
||||
* streams data.
|
||||
* Creates a new instance, which returns the given streams data.
|
||||
*/
|
||||
public MyServletInputStream(final InputStream inputStream, final int readLimit) {
|
||||
this.inputStream = inputStream;
|
||||
|
@ -75,24 +75,16 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
|||
private final Map<String, String> mHeaders = new java.util.HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance with the given request data
|
||||
* and content type.
|
||||
* Creates a new instance with the given request data and content type.
|
||||
*/
|
||||
public MockHttpServletRequest(
|
||||
final byte[] requestData,
|
||||
final String strContentType) {
|
||||
this(new ByteArrayInputStream(requestData),
|
||||
requestData.length, strContentType);
|
||||
public MockHttpServletRequest(final byte[] requestData, final String strContentType) {
|
||||
this(new ByteArrayInputStream(requestData), requestData.length, strContentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the given request data
|
||||
* and content type.
|
||||
* Creates a new instance with the given request data and content type.
|
||||
*/
|
||||
public MockHttpServletRequest(
|
||||
final InputStream requestData,
|
||||
final long requestLength,
|
||||
final String strContentType) {
|
||||
public MockHttpServletRequest(final InputStream requestData, final long requestLength, final String strContentType) {
|
||||
mmRequestData = requestData;
|
||||
length = requestLength;
|
||||
mStrContentType = strContentType;
|
||||
|
@ -545,8 +537,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
|||
* @see javax.servlet.ServletRequest#setCharacterEncoding(String)
|
||||
*/
|
||||
@Override
|
||||
public void setCharacterEncoding(final String arg0)
|
||||
throws UnsupportedEncodingException {
|
||||
public void setCharacterEncoding(final String arg0) throws UnsupportedEncodingException {
|
||||
}
|
||||
|
||||
/**
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
@ -25,7 +25,11 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.fileupload2.servlet.ServletFileUpload;
|
||||
import org.apache.commons.fileupload2.Constants;
|
||||
import org.apache.commons.fileupload2.FileItemIterator;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.ProgressListener;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
|
@ -55,13 +59,13 @@ public class ProgressListenerTest {
|
|||
|
||||
@Override
|
||||
public void update(final long actualBytesRead, final long actualContentLength, final int actualItems) {
|
||||
assertTrue(actualBytesRead >= 0 && actualBytesRead <= expectedContentLength);
|
||||
assertTrue(actualContentLength == -1 || actualContentLength == expectedContentLength);
|
||||
assertTrue(actualItems >= 0 && actualItems <= expectedItems);
|
||||
assertTrue(actualBytesRead >= 0 && actualBytesRead <= expectedContentLength);
|
||||
assertTrue(actualContentLength == -1 || actualContentLength == expectedContentLength);
|
||||
assertTrue(actualItems >= 0 && actualItems <= expectedItems);
|
||||
|
||||
assertTrue(bytesRead == null || actualBytesRead >= bytesRead.longValue());
|
||||
assertTrue(bytesRead == null || actualBytesRead >= bytesRead.longValue());
|
||||
bytesRead = Long.valueOf(actualBytesRead);
|
||||
assertTrue(items == null || actualItems >= items.intValue());
|
||||
assertTrue(items == null || actualItems >= items.intValue());
|
||||
items = Integer.valueOf(actualItems);
|
||||
}
|
||||
|
||||
|
@ -100,12 +104,10 @@ public class ProgressListenerTest {
|
|||
public void testProgressListener() throws Exception {
|
||||
final int NUM_ITEMS = 512;
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
final String header = "-----1234\r\n"
|
||||
+ "Content-Disposition: form-data; name=\"field" + (i + 1) + "\"\r\n"
|
||||
+ "\r\n";
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
final String header = "-----1234\r\n" + "Content-Disposition: form-data; name=\"field" + (i + 1) + "\"\r\n" + "\r\n";
|
||||
baos.write(header.getBytes(StandardCharsets.US_ASCII));
|
||||
for (int j = 0; j < 16384 + i; j++) {
|
||||
for (int j = 0; j < 16384 + i; j++) {
|
||||
baos.write((byte) j);
|
||||
}
|
||||
baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
|
|
@ -14,42 +14,46 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.servlet;
|
||||
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUploadTest;
|
||||
import org.apache.commons.fileupload2.Constants;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileUploadTest;
|
||||
import org.apache.commons.fileupload2.MockHttpServletRequest;
|
||||
import org.apache.commons.fileupload2.FileUpload;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test for {@link ServletFileUpload}.
|
||||
*
|
||||
* @see FileUploadTest
|
||||
* @since 1.4
|
||||
*/
|
||||
public class ServletFileUploadTest {
|
||||
public class ServletFileUploadTest extends AbstractFileUploadTest {
|
||||
|
||||
public ServletFileUploadTest() {
|
||||
super(new ServletFileUpload(new DiskFileItemFactory()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseImpliedUtf8()
|
||||
throws Exception {
|
||||
public void parseImpliedUtf8() throws Exception {
|
||||
// utf8 encoded form-data without explicit content-type encoding
|
||||
// @formatter:off
|
||||
final String text = "-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"utf8Html\"\r\n" +
|
||||
"\r\n" +
|
||||
"Thís ís the coñteñt of the fíle\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
|
||||
final byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
|
||||
final HttpServletRequest request = new MockHttpServletRequest(bytes, Constants.CONTENT_TYPE);
|
||||
|
@ -62,13 +66,12 @@ public class ServletFileUploadTest {
|
|||
assertTrue(fileItem.getString().contains("coñteñt"), fileItem.getString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-210">
|
||||
*/
|
||||
@Test
|
||||
public void parseParameterMap()
|
||||
throws Exception {
|
||||
public void parseParameterMap() throws Exception {
|
||||
// @formatter:off
|
||||
final String text = "-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
|
@ -88,6 +91,7 @@ public class ServletFileUploadTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
|
||||
final HttpServletRequest request = new MockHttpServletRequest(bytes, Constants.CONTENT_TYPE);
|
||||
|
||||
|
@ -102,4 +106,52 @@ public class ServletFileUploadTest {
|
|||
assertTrue(mappedParameters.containsKey("multi"));
|
||||
assertEquals(2, mappedParameters.get("multi").size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes, final String contentType) throws FileUploadException {
|
||||
final HttpServletRequest request = new MockHttpServletRequest(bytes, contentType);
|
||||
return upload.parseRequest(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a test with varying file sizes.
|
||||
*/
|
||||
@Override
|
||||
@Test
|
||||
public void testFileUpload() throws IOException, FileUploadException {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int add = 16;
|
||||
int num = 0;
|
||||
for (int i = 0; i < 16384; i += add) {
|
||||
if (++add == 32) {
|
||||
add = 16;
|
||||
}
|
||||
final String header = "-----1234\r\n" + "Content-Disposition: form-data; name=\"field" + (num++) + "\"\r\n" + "\r\n";
|
||||
baos.write(header.getBytes(StandardCharsets.US_ASCII));
|
||||
for (int j = 0; j < i; j++) {
|
||||
baos.write((byte) j);
|
||||
}
|
||||
baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
|
||||
}
|
||||
baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
final List<FileItem> fileItems = parseUpload(new ServletFileUpload(new DiskFileItemFactory()), baos.toByteArray());
|
||||
final Iterator<FileItem> fileIter = fileItems.iterator();
|
||||
add = 16;
|
||||
num = 0;
|
||||
for (int i = 0; i < 16384; i += add) {
|
||||
if (++add == 32) {
|
||||
add = 16;
|
||||
}
|
||||
final FileItem item = fileIter.next();
|
||||
assertEquals("field" + (num++), item.getFieldName());
|
||||
final byte[] bytes = item.get();
|
||||
assertEquals(i, bytes.length);
|
||||
for (int j = 0; j < i; j++) {
|
||||
assertEquals((byte) j, bytes[j]);
|
||||
}
|
||||
}
|
||||
assertTrue(!fileIter.hasNext());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,282 +1,244 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadSizeException;
|
||||
import org.apache.commons.fileupload2.servlet.ServletFileUpload;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit test for items with varying sizes.
|
||||
*/
|
||||
public class SizesTest {
|
||||
|
||||
/** Checks, whether limiting the file size works.
|
||||
*/
|
||||
@Test
|
||||
public void testFileSizeLimit()
|
||||
throws IOException, FileUploadException {
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
|
||||
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
HttpServletRequest req = new MockHttpServletRequest(
|
||||
request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
List<FileItem> fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
FileItem item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(40);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(30);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadByteCountLimitException e) {
|
||||
assertEquals(30, e.getPermitted());
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks, whether a faked Content-Length header is detected.
|
||||
*/
|
||||
@Test
|
||||
public void testFileSizeLimitWithFakedContentLength()
|
||||
throws IOException, FileUploadException {
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
|
||||
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
HttpServletRequest req = new MockHttpServletRequest(
|
||||
request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
List<FileItem> fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
FileItem item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(40);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
// provided Content-Length is larger than the FileSizeMax -> handled by ctor
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(5);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadByteCountLimitException e) {
|
||||
assertEquals(5, e.getPermitted());
|
||||
}
|
||||
|
||||
// provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(15);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadByteCountLimitException e) {
|
||||
assertEquals(15, e.getPermitted());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a test with varying file sizes.
|
||||
*/
|
||||
@Test
|
||||
public void testFileUpload()
|
||||
throws IOException, FileUploadException {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int add = 16;
|
||||
int num = 0;
|
||||
for (int i = 0; i < 16384; i += add) {
|
||||
if (++add == 32) {
|
||||
add = 16;
|
||||
}
|
||||
final String header = "-----1234\r\n"
|
||||
+ "Content-Disposition: form-data; name=\"field" + (num++) + "\"\r\n"
|
||||
+ "\r\n";
|
||||
baos.write(header.getBytes(StandardCharsets.US_ASCII));
|
||||
for (int j = 0; j < i; j++) {
|
||||
baos.write((byte) j);
|
||||
}
|
||||
baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
|
||||
}
|
||||
baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
final List<FileItem> fileItems =
|
||||
Util.parseUpload(new ServletFileUpload(new DiskFileItemFactory()), baos.toByteArray());
|
||||
final Iterator<FileItem> fileIter = fileItems.iterator();
|
||||
add = 16;
|
||||
num = 0;
|
||||
for (int i = 0; i < 16384; i += add) {
|
||||
if (++add == 32) {
|
||||
add = 16;
|
||||
}
|
||||
final FileItem item = fileIter.next();
|
||||
assertEquals("field" + (num++), item.getFieldName());
|
||||
final byte[] bytes = item.get();
|
||||
assertEquals(i, bytes.length);
|
||||
for (int j = 0; j < i; j++) {
|
||||
assertEquals((byte) j, bytes[j]);
|
||||
}
|
||||
}
|
||||
assertTrue(!fileIter.hasNext());
|
||||
}
|
||||
|
||||
/** Checks, whether the maxSize works.
|
||||
*/
|
||||
@Test
|
||||
public void testMaxSizeLimit()
|
||||
throws IOException, FileUploadException {
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
|
||||
final ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
upload.setSizeMax(200);
|
||||
|
||||
final MockHttpServletRequest req = new MockHttpServletRequest(
|
||||
request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadSizeException e) {
|
||||
assertEquals(200, e.getPermitted());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxSizeLimitUnknownContentLength()
|
||||
throws IOException, FileUploadException {
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
|
||||
final ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
upload.setSizeMax(300);
|
||||
|
||||
// the first item should be within the max size limit
|
||||
// set the read limit to 10 to simulate a "real" stream
|
||||
// otherwise the buffer would be immediately filled
|
||||
|
||||
final MockHttpServletRequest req = new MockHttpServletRequest(
|
||||
request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
req.setContentLength(-1);
|
||||
req.setReadLimit(10);
|
||||
|
||||
final FileItemIterator it = upload.getItemIterator(req);
|
||||
assertTrue(it.hasNext());
|
||||
|
||||
final FileItemStream item = it.next();
|
||||
assertFalse(item.isFormField());
|
||||
assertEquals("file1", item.getFieldName());
|
||||
assertEquals("foo1.tab", item.getName());
|
||||
|
||||
{
|
||||
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final InputStream stream = item.openStream()) {
|
||||
IOUtils.copy(stream, baos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// the second item is over the size max, thus we expect an error
|
||||
// the header is still within size max -> this shall still succeed
|
||||
assertTrue(it.hasNext());
|
||||
|
||||
assertThrows(FileUploadException.class, () -> {
|
||||
final FileItemStream item2 = it.next();
|
||||
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final InputStream stream = item2.openStream()) {
|
||||
IOUtils.copy(stream, baos);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.Constants;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileItemIterator;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
|
||||
import org.apache.commons.fileupload2.pub.FileUploadSizeException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit test for items with varying sizes.
|
||||
*/
|
||||
public class SizesTest {
|
||||
|
||||
/**
|
||||
* Checks, whether limiting the file size works.
|
||||
*/
|
||||
@Test
|
||||
public void testFileSizeLimit() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
|
||||
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
HttpServletRequest req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
List<FileItem> fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
FileItem item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(40);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(30);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadByteCountLimitException e) {
|
||||
assertEquals(30, e.getPermitted());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, whether a faked Content-Length header is detected.
|
||||
*/
|
||||
@Test
|
||||
public void testFileSizeLimitWithFakedContentLength() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
|
||||
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
HttpServletRequest req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
List<FileItem> fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
FileItem item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(40);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
fileItems = upload.parseRequest(req);
|
||||
assertEquals(1, fileItems.size());
|
||||
item = fileItems.get(0);
|
||||
assertEquals("This is the content of the file\n", new String(item.get()));
|
||||
|
||||
// provided Content-Length is larger than the FileSizeMax -> handled by ctor
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(5);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadByteCountLimitException e) {
|
||||
assertEquals(5, e.getPermitted());
|
||||
}
|
||||
|
||||
// provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
|
||||
upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(15);
|
||||
req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadByteCountLimitException e) {
|
||||
assertEquals(15, e.getPermitted());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether maxSize works.
|
||||
*/
|
||||
@Test
|
||||
public void testMaxSizeLimit() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
|
||||
final ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
upload.setSizeMax(200);
|
||||
|
||||
final MockHttpServletRequest req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
try {
|
||||
upload.parseRequest(req);
|
||||
fail("Expected exception.");
|
||||
} catch (final FileUploadSizeException e) {
|
||||
assertEquals(200, e.getPermitted());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxSizeLimitUnknownContentLength() throws IOException, FileUploadException {
|
||||
// @formatter:off
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
"\r\n" +
|
||||
"This is the content of the file\n" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
|
||||
final ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
upload.setFileSizeMax(-1);
|
||||
upload.setSizeMax(300);
|
||||
|
||||
// the first item should be within the max size limit
|
||||
// set the read limit to 10 to simulate a "real" stream
|
||||
// otherwise the buffer would be immediately filled
|
||||
|
||||
final MockHttpServletRequest req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), Constants.CONTENT_TYPE);
|
||||
req.setContentLength(-1);
|
||||
req.setReadLimit(10);
|
||||
|
||||
final FileItemIterator it = upload.getItemIterator(req);
|
||||
assertTrue(it.hasNext());
|
||||
|
||||
final FileItemStream item = it.next();
|
||||
assertFalse(item.isFormField());
|
||||
assertEquals("file1", item.getFieldName());
|
||||
assertEquals("foo1.tab", item.getName());
|
||||
|
||||
{
|
||||
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final InputStream stream = item.openStream()) {
|
||||
IOUtils.copy(stream, baos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// the second item is over the size max, thus we expect an error
|
||||
// the header is still within size max -> this shall still succeed
|
||||
assertTrue(it.hasNext());
|
||||
|
||||
assertThrows(FileUploadException.class, () -> {
|
||||
final FileItemStream item2 = it.next();
|
||||
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final InputStream stream = item2.openStream()) {
|
||||
IOUtils.copy(stream, baos);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
package org.apache.commons.fileupload2.javax;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
@ -32,9 +32,14 @@ import java.util.List;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUpload;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileItemIterator;
|
||||
import org.apache.commons.fileupload2.FileItemStream;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.InvalidFileNameException;
|
||||
import org.apache.commons.fileupload2.MultipartStream;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.servlet.ServletFileUpload;
|
||||
import org.apache.commons.fileupload2.servlet.ServletRequestContext;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
|
@ -47,10 +52,11 @@ public class StreamingTest {
|
|||
}
|
||||
|
||||
private String getHeader(final String value) {
|
||||
// @formatter:off
|
||||
return "-----1234\r\n"
|
||||
+ "Content-Disposition: form-data; name=\"" + value + "\"\r\n"
|
||||
+ "\r\n";
|
||||
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private byte[] newRequest() throws IOException {
|
||||
|
@ -89,26 +95,22 @@ public class StreamingTest {
|
|||
return parseUpload(new ByteArrayInputStream(bytes), bytes.length);
|
||||
}
|
||||
|
||||
private List<FileItem> parseUpload(final InputStream inputStream, final int length)
|
||||
throws FileUploadException {
|
||||
private List<FileItem> parseUpload(final InputStream inputStream, final int length) throws FileUploadException {
|
||||
final String contentType = "multipart/form-data; boundary=---1234";
|
||||
|
||||
final AbstractFileUpload upload = new ServletFileUpload();
|
||||
upload.setFileItemFactory(new DiskFileItemFactory());
|
||||
final HttpServletRequest request = new MockHttpServletRequest(inputStream,
|
||||
length, contentType);
|
||||
final HttpServletRequest request = new MockHttpServletRequest(inputStream, length, contentType);
|
||||
|
||||
return upload.parseRequest(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
private FileItemIterator parseUpload(final int length, final InputStream inputStream)
|
||||
throws FileUploadException, IOException {
|
||||
private FileItemIterator parseUpload(final int length, final InputStream inputStream) throws FileUploadException, IOException {
|
||||
final String contentType = "multipart/form-data; boundary=---1234";
|
||||
|
||||
final AbstractFileUpload upload = new ServletFileUpload();
|
||||
upload.setFileItemFactory(new DiskFileItemFactory());
|
||||
final HttpServletRequest request = new MockHttpServletRequest(inputStream,
|
||||
length, contentType);
|
||||
final HttpServletRequest request = new MockHttpServletRequest(inputStream, length, contentType);
|
||||
|
||||
return upload.getItemIterator(new ServletRequestContext(request));
|
||||
}
|
||||
|
@ -117,14 +119,13 @@ public class StreamingTest {
|
|||
* Tests a file upload with varying file sizes.
|
||||
*/
|
||||
@Test
|
||||
public void testFileUpload()
|
||||
throws IOException, FileUploadException {
|
||||
public void testFileUpload() throws IOException, FileUploadException {
|
||||
final byte[] request = newRequest();
|
||||
final List<FileItem> fileItems = parseUpload(request);
|
||||
final Iterator<FileItem> fileIter = fileItems.iterator();
|
||||
int add = 16;
|
||||
int num = 0;
|
||||
for (int i = 0; i < 16384; i += add) {
|
||||
for (int i = 0; i < 16384; i += add) {
|
||||
if (++add == 32) {
|
||||
add = 16;
|
||||
}
|
||||
|
@ -132,7 +133,7 @@ public class StreamingTest {
|
|||
assertEquals("field" + (num++), item.getFieldName());
|
||||
final byte[] bytes = item.get();
|
||||
assertEquals(i, bytes.length);
|
||||
for (int j = 0; j < i; j++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
assertEquals((byte) j, bytes[j]);
|
||||
}
|
||||
}
|
||||
|
@ -143,20 +144,17 @@ public class StreamingTest {
|
|||
* Test for FILEUPLOAD-135
|
||||
*/
|
||||
@Test
|
||||
public void testFILEUPLOAD135()
|
||||
throws IOException, FileUploadException {
|
||||
public void testFILEUPLOAD135() throws IOException, FileUploadException {
|
||||
final byte[] request = newShortRequest();
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(request);
|
||||
final List<FileItem> fileItems = parseUpload(new InputStream() {
|
||||
@Override
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
public int read() throws IOException {
|
||||
return bais.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] b, final int off, final int len) throws IOException
|
||||
{
|
||||
public int read(final byte[] b, final int off, final int len) throws IOException {
|
||||
return bais.read(b, off, Math.min(len, 3));
|
||||
}
|
||||
|
||||
|
@ -167,19 +165,17 @@ public class StreamingTest {
|
|||
assertEquals("field", item.getFieldName());
|
||||
final byte[] bytes = item.get();
|
||||
assertEquals(3, bytes.length);
|
||||
assertEquals((byte)'1', bytes[0]);
|
||||
assertEquals((byte)'2', bytes[1]);
|
||||
assertEquals((byte)'3', bytes[2]);
|
||||
assertEquals((byte) '1', bytes[0]);
|
||||
assertEquals((byte) '2', bytes[1]);
|
||||
assertEquals((byte) '3', bytes[2]);
|
||||
assertTrue(!fileIter.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests, whether an invalid request throws a proper
|
||||
* exception.
|
||||
* Tests, whether an invalid request throws a proper exception.
|
||||
*/
|
||||
@Test
|
||||
public void testFileUploadException()
|
||||
throws IOException, FileUploadException {
|
||||
public void testFileUploadException() throws IOException, FileUploadException {
|
||||
final byte[] request = newRequest();
|
||||
final byte[] invalidRequest = new byte[request.length - 11];
|
||||
System.arraycopy(request, 0, invalidRequest, 0, request.length - 11);
|
||||
|
@ -197,6 +193,7 @@ public class StreamingTest {
|
|||
@Test
|
||||
public void testInvalidFileNameException() throws Exception {
|
||||
final String fileName = "foo.exe\u0000.png";
|
||||
// @formatter:off
|
||||
final String request =
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n" +
|
||||
|
@ -217,6 +214,7 @@ public class StreamingTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
final byte[] reqBytes = request.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
final FileItemIterator fileItemIter = parseUpload(reqBytes.length, new ByteArrayInputStream(reqBytes));
|
||||
|
@ -244,11 +242,11 @@ public class StreamingTest {
|
|||
* Tests, whether an IOException is properly delegated.
|
||||
*/
|
||||
@Test
|
||||
public void testIOException()
|
||||
throws IOException {
|
||||
public void testIOException() throws IOException {
|
||||
final byte[] request = newRequest();
|
||||
final InputStream stream = new FilterInputStream(new ByteArrayInputStream(request)) {
|
||||
private int num;
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (++num > 123) {
|
||||
|
@ -256,10 +254,10 @@ public class StreamingTest {
|
|||
}
|
||||
return super.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] buffer, final int offset, final int length)
|
||||
throws IOException {
|
||||
for (int i = 0; i < length; i++) {
|
||||
public int read(final byte[] buffer, final int offset, final int length) throws IOException {
|
||||
for (int i = 0; i < length; i++) {
|
||||
final int res = read();
|
||||
if (res == -1) {
|
||||
return i == 0 ? -1 : i;
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
|
||||
<local-check-config name="maven-checkstyle-plugin validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-portlet/../src/checkstyle/fileupload_checks.xml" type="remote" description="maven-checkstyle-plugin configuration validate-main">
|
||||
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-portlet\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
|
||||
<property name="checkstyle.cache.file" value="${project_loc}/target/checkstyle-cachefile"/>
|
||||
<property name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.projects\commons-fileupload2-portlet\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
|
||||
</local-check-config>
|
||||
<fileset name="java-sources-validate-main" enabled="true" check-config-name="maven-checkstyle-plugin validate-main" local="true">
|
||||
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/main/resources.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^.*\.properties" include-pattern="true"/>
|
||||
<file-match-pattern match-pattern="^src/test/resources.*\.properties" include-pattern="true"/>
|
||||
</fileset>
|
||||
</fileset-config>
|
|
@ -0,0 +1 @@
|
|||
/target/
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>commons-fileupload2-portlet</artifactId>
|
||||
|
||||
<name>Apache Commons FileUpload Portlet</name>
|
||||
<description>
|
||||
The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart
|
||||
file upload functionality to servlets and web applications.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<commons.parent.dir>${basedir}/..</commons.parent.dir>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<classifier>tests</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-javax</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-javax</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<classifier>tests</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${commons.servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>portlet-api</groupId>
|
||||
<artifactId>portlet-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -32,40 +32,32 @@ import org.apache.commons.fileupload2.FileUploadException;
|
|||
/**
|
||||
* High level API for processing file uploads.
|
||||
* <p>
|
||||
* This class handles multiple files per single HTML widget, sent using
|
||||
* {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use
|
||||
* {@link org.apache.commons.fileupload2.servlet.ServletFileUpload
|
||||
* #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list
|
||||
* of {@link org.apache.commons.fileupload2.FileItem FileItems} associated
|
||||
* with a given HTML widget.
|
||||
* This class handles multiple files per single HTML widget, sent using {@code multipart/mixed} encoding type, as specified by
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link org.apache.commons.fileupload2.javax.ServletFileUpload
|
||||
* #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list of {@link org.apache.commons.fileupload2.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.
|
||||
* 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 1.1
|
||||
*/
|
||||
public class PortletFileUpload extends FileUpload {
|
||||
|
||||
/**
|
||||
* Tests whether the request contains multipart
|
||||
* content.
|
||||
* Tests whether the request contains multipart content.
|
||||
*
|
||||
* @param request The portlet request to be evaluated. Must be non-null.
|
||||
* @return {@code true} if the request is multipart;
|
||||
* {@code false} otherwise.
|
||||
* @return {@code true} if the request is multipart; {@code false} otherwise.
|
||||
*/
|
||||
public static final boolean isMultipartContent(final ActionRequest request) {
|
||||
return AbstractFileUpload.isMultipartContent(
|
||||
new PortletRequestContext(request));
|
||||
return AbstractFileUpload.isMultipartContent(new PortletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized instance of this class. A factory must be
|
||||
* configured, using {@code setFileItemFactory()}, before attempting
|
||||
* to parse requests.
|
||||
* Constructs an uninitialized instance of this class. A factory must be configured, using {@code setFileItemFactory()}, before attempting to parse
|
||||
* requests.
|
||||
*
|
||||
* @see FileUpload#FileUpload(FileItemFactory)
|
||||
*/
|
||||
|
@ -73,8 +65,7 @@ public class PortletFileUpload extends FileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class which uses the supplied factory to
|
||||
* create {@code FileItem} instances.
|
||||
* Constructs an instance of this class which uses the supplied factory to create {@code FileItem} instances.
|
||||
*
|
||||
* @see FileUpload#FileUpload()
|
||||
* @param fileItemFactory The factory to use for creating file items.
|
||||
|
@ -84,51 +75,38 @@ public class PortletFileUpload extends FileUpload {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} file item iterator.
|
||||
* Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} file item iterator.
|
||||
*
|
||||
* @param request The portlet request to be parsed.
|
||||
* @return An iterator to instances of {@code FileItemStream}
|
||||
* 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.
|
||||
* @return An iterator to instances of {@code FileItemStream} 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(final ActionRequest request)
|
||||
throws FileUploadException, IOException {
|
||||
public FileItemIterator getItemIterator(final ActionRequest request) throws FileUploadException, IOException {
|
||||
return super.getItemIterator(new PortletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param request The portlet request to be parsed.
|
||||
* @return A map of {@code FileItem} instances parsed from the request.
|
||||
* @throws FileUploadException if there are problems reading/parsing
|
||||
* the request or storing files.
|
||||
* @throws FileUploadException if there are problems reading/parsing the request or storing files.
|
||||
* @since 1.3
|
||||
*/
|
||||
public Map<String, List<FileItem>> parseParameterMap(final ActionRequest request)
|
||||
throws FileUploadException {
|
||||
public Map<String, List<FileItem>> parseParameterMap(final ActionRequest request) throws FileUploadException {
|
||||
return parseParameterMap(new PortletRequestContext(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
|
||||
* compliant {@code multipart/form-data} stream.
|
||||
* Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant {@code multipart/form-data} stream.
|
||||
*
|
||||
* @param request The portlet request to be parsed.
|
||||
* @return A list of {@code FileItem} 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.
|
||||
* @return A list of {@code FileItem} 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(final ActionRequest request)
|
||||
throws FileUploadException {
|
||||
public List<FileItem> parseRequest(final ActionRequest request) throws FileUploadException {
|
||||
return parseRequest(new PortletRequestContext(request));
|
||||
}
|
||||
|
|
@ -1,79 +1,79 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractRequestContext;
|
||||
|
||||
/**
|
||||
* Provides access to the request information needed for a request made to a portlet.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class PortletRequestContext extends AbstractRequestContext {
|
||||
|
||||
/**
|
||||
* The request for which the context is being provided.
|
||||
*/
|
||||
private final ActionRequest request;
|
||||
|
||||
/**
|
||||
* Construct a context for this request.
|
||||
*
|
||||
* @param request The request to which this context applies.
|
||||
*/
|
||||
public PortletRequestContext(final ActionRequest request) {
|
||||
super(request::getProperty, request::getContentLength);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding for the request.
|
||||
*
|
||||
* @return The character encoding for the request.
|
||||
*/
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type of the request.
|
||||
*
|
||||
* @return The content type of the request.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return request.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream for the request.
|
||||
*
|
||||
* @return The input stream for the request.
|
||||
* @throws IOException if a problem occurs.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return request.getPortletInputStream();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.fileupload2.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractRequestContext;
|
||||
|
||||
/**
|
||||
* Provides access to the request information needed for a request made to a portlet.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class PortletRequestContext extends AbstractRequestContext {
|
||||
|
||||
/**
|
||||
* The request for which the context is being provided.
|
||||
*/
|
||||
private final ActionRequest request;
|
||||
|
||||
/**
|
||||
* Construct a context for this request.
|
||||
*
|
||||
* @param request The request to which this context applies.
|
||||
*/
|
||||
public PortletRequestContext(final ActionRequest request) {
|
||||
super(request::getProperty, request::getContentLength);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the character encoding for the request.
|
||||
*
|
||||
* @return The character encoding for the request.
|
||||
*/
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content type of the request.
|
||||
*
|
||||
* @return The content type of the request.
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return request.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream for the request.
|
||||
*
|
||||
* @return The input stream for the request.
|
||||
* @throws IOException if a problem occurs.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return request.getPortletInputStream();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 org.apache.commons.fileupload2.FileUpload FileUpload} for use in portlets conforming to JSR 168. This implementation requires
|
||||
* only access to the portlet's current {@code ActionRequest} instance, and a suitable {@link org.apache.commons.fileupload2.FileItemFactory FileItemFactory}
|
||||
* implementation, such as {@link org.apache.commons.fileupload2.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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> for further details and examples of how to
|
||||
* use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.portlet;
|
|
@ -61,8 +61,7 @@ public class MockPortletActionRequest implements ActionRequest {
|
|||
this(new ByteArrayInputStream(requestData), requestData.length, contentType);
|
||||
}
|
||||
|
||||
public MockPortletActionRequest(final ByteArrayInputStream byteArrayInputStream,
|
||||
final int requestLength, final String contentType) {
|
||||
public MockPortletActionRequest(final ByteArrayInputStream byteArrayInputStream, final int requestLength, final String contentType) {
|
||||
this.requestData = byteArrayInputStream;
|
||||
length = requestLength;
|
||||
this.contentType = contentType;
|
|
@ -24,27 +24,33 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.AbstractFileUploadTest;
|
||||
import org.apache.commons.fileupload2.Constants;
|
||||
import org.apache.commons.fileupload2.FileItem;
|
||||
import org.apache.commons.fileupload2.FileUploadTest;
|
||||
import org.apache.commons.fileupload2.FileUpload;
|
||||
import org.apache.commons.fileupload2.FileUploadException;
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.apache.commons.fileupload2.javax.MockHttpServletRequest;
|
||||
import org.apache.commons.fileupload2.javax.ServletRequestContext;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test for {@link PortletFileUpload}.
|
||||
*
|
||||
* @see FileUploadTest
|
||||
* @see AbstractFileUploadTest
|
||||
* @since 1.4
|
||||
*/
|
||||
public class PortletFileUploadTest {
|
||||
public class PortletFileUploadTest extends AbstractFileUploadTest {
|
||||
|
||||
private PortletFileUpload upload;
|
||||
public PortletFileUploadTest() {
|
||||
super(new PortletFileUpload(new DiskFileItemFactory()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseParameterMap()
|
||||
throws Exception {
|
||||
public void parseParameterMap() throws Exception {
|
||||
// @formatter:off
|
||||
final String text = "-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
|
||||
"Content-Type: text/whatever\r\n" +
|
||||
|
@ -64,10 +70,11 @@ public class PortletFileUploadTest {
|
|||
"\r\n" +
|
||||
"value2\r\n" +
|
||||
"-----1234--\r\n";
|
||||
// @formatter:on
|
||||
final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
|
||||
final ActionRequest request = new MockPortletActionRequest(bytes, Constants.CONTENT_TYPE);
|
||||
|
||||
final Map<String, List<FileItem>> mappedParameters = upload.parseParameterMap(request);
|
||||
final Map<String, List<FileItem>> mappedParameters = ((PortletFileUpload) upload).parseParameterMap(request);
|
||||
assertTrue(mappedParameters.containsKey("file"));
|
||||
assertEquals(1, mappedParameters.get("file").size());
|
||||
|
||||
|
@ -78,9 +85,10 @@ public class PortletFileUploadTest {
|
|||
assertEquals(2, mappedParameters.get("multi").size());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
upload = new PortletFileUpload(new DiskFileItemFactory());
|
||||
@Override
|
||||
public List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes, final String contentType) throws FileUploadException {
|
||||
final HttpServletRequest request = new MockHttpServletRequest(bytes, contentType);
|
||||
return upload.parseRequest(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
}
|
84
pom.xml
84
pom.xml
|
@ -25,9 +25,10 @@
|
|||
</parent>
|
||||
|
||||
<artifactId>commons-fileupload2</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Apache Commons FileUpload</name>
|
||||
<name>Apache Commons FileUpload Parent</name>
|
||||
<description>
|
||||
The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart
|
||||
file upload functionality to servlets and web applications.
|
||||
|
@ -223,6 +224,7 @@
|
|||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<commons.parent.dir>${basedir}</commons.parent.dir>
|
||||
<commons.componentid>fileupload</commons.componentid>
|
||||
<commons.module.name>org.apache.commons.fileupload</commons.module.name>
|
||||
<commons.release.version>2.0</commons.release.version>
|
||||
|
@ -235,6 +237,9 @@
|
|||
<commons.osgi.export>!org.apache.commons.fileupload.util.mime,org.apache.commons.*;version=${project.version};-noimport:=true</commons.osgi.export>
|
||||
<commons.osgi.import>!javax.portlet,*</commons.osgi.import>
|
||||
<commons.osgi.dynamicImport>javax.portlet</commons.osgi.dynamicImport>
|
||||
<commons.servlet-api.version>2.5</commons.servlet-api.version>
|
||||
<commons.io.version>2.11.0</commons.io.version>
|
||||
<commons.lang3.version>3.12.0</commons.lang3.version>
|
||||
<japicmp.skip>true</japicmp.skip>
|
||||
<clirr.skip>true</clirr.skip>
|
||||
<moditect-maven-plugin.version>1.0.0.RC2</moditect-maven-plugin.version>
|
||||
|
@ -249,43 +254,6 @@
|
|||
<commons.releaseManagerKey>B6E73D84EA4FCC47166087253FAAD2CD5ECBB314</commons.releaseManagerKey>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>portlet-api</groupId>
|
||||
<artifactId>portlet-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>5.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -296,8 +264,8 @@
|
|||
<id>validate-main</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<configLocation>${commons.parent.dir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${commons.parent.dir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<includeTestSourceDirectory>false</includeTestSourceDirectory>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
|
@ -314,8 +282,8 @@
|
|||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${basedir}/src/main/assembly/bin.xml</descriptor>
|
||||
<descriptor>${basedir}/src/main/assembly/src.xml</descriptor>
|
||||
<descriptor>${commons.parent.dir}/src/main/assembly/bin.xml</descriptor>
|
||||
<descriptor>${commons.parent.dir}/src/main/assembly/src.xml</descriptor>
|
||||
</descriptors>
|
||||
<tarLongFileMode>gnu</tarLongFileMode>
|
||||
</configuration>
|
||||
|
@ -429,12 +397,19 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<configLocation>${commons.parent.dir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${commons.parent.dir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<includeTestSourceDirectory>false</includeTestSourceDirectory>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludeFilterFile>${commons.parent.dir}/spotbugs-exclude-filter.xml</excludeFilterFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<defaultGoal>clean verify apache-rat:check checkstyle:check javadoc:javadoc spotbugs:check</defaultGoal>
|
||||
|
@ -462,8 +437,8 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<configLocation>${commons.parent.dir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${commons.parent.dir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<includeTestSourceDirectory>false</includeTestSourceDirectory>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
</configuration>
|
||||
|
@ -474,7 +449,7 @@
|
|||
<configuration>
|
||||
<targetJdk>${maven.compiler.target}</targetJdk>
|
||||
<rulesets>
|
||||
<ruleset>${basedir}/src/checkstyle/fileupload_basic.xml</ruleset>
|
||||
<ruleset>${commons.parent.dir}/src/checkstyle/fileupload_basic.xml</ruleset>
|
||||
</rulesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
@ -567,13 +542,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludeFilterFile>${basedir}/spotbugs-exclude-filter.xml</excludeFilterFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
@ -595,4 +563,10 @@
|
|||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
<modules>
|
||||
<module>commons-fileupload2-core</module>
|
||||
<module>commons-fileupload2-jakarta</module>
|
||||
<module>commons-fileupload2-javax</module>
|
||||
<module>commons-fileupload2-portlet</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -1,107 +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.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.SizeLimitExceededException;
|
||||
|
||||
import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
|
||||
|
||||
/**
|
||||
* An iterator, as returned by
|
||||
* {@link AbstractFileUpload#getItemIterator(RequestContext)}.
|
||||
*/
|
||||
public interface FileItemIterator {
|
||||
|
||||
List<FileItem> getFileItems() throws FileUploadException, IOException;
|
||||
|
||||
/**
|
||||
* Gets the maximum size of a single file. An {@link FileUploadByteCountLimitException}
|
||||
* will be thrown, if there is an uploaded file, which is exceeding this value.
|
||||
* By default, this value will be copied from the {@link AbstractFileUpload#getFileSizeMax()
|
||||
* FileUploadBase} object, however, the user may replace the default value with a
|
||||
* request specific value by invoking {@link #setFileSizeMax(long)} on this object.
|
||||
* @return The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
|
||||
*/
|
||||
long getFileSizeMax();
|
||||
|
||||
/**
|
||||
* Gets the maximum size of the complete HTTP request. A {@link SizeLimitExceededException}
|
||||
* will be thrown, if the HTTP request will exceed this value.
|
||||
* By default, this value will be copied from the {@link AbstractFileUpload#getSizeMax()
|
||||
* FileUploadBase} object, however, the user may replace the default value with a
|
||||
* request specific value by invoking {@link #setSizeMax(long)} on this object.
|
||||
* @return The maximum size of the complete HTTP request. The value -1 indicates "unlimited".
|
||||
*/
|
||||
long getSizeMax();
|
||||
|
||||
/**
|
||||
* Tests whether another instance of {@link FileItemStream}
|
||||
* is available.
|
||||
*
|
||||
* @throws FileUploadException Parsing or processing the
|
||||
* file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return True, if one or more additional file items
|
||||
* are available, otherwise false.
|
||||
*/
|
||||
boolean hasNext() throws FileUploadException, IOException;
|
||||
|
||||
/**
|
||||
* Returns the next available {@link FileItemStream}.
|
||||
*
|
||||
* @throws java.util.NoSuchElementException No more items are available. Use
|
||||
* {@link #hasNext()} to prevent this exception.
|
||||
* @throws FileUploadException Parsing or processing the
|
||||
* file item failed.
|
||||
* @throws IOException Reading the file item failed.
|
||||
* @return FileItemStream instance, which provides
|
||||
* access to the next file item.
|
||||
*/
|
||||
FileItemStream next() throws FileUploadException, IOException;
|
||||
|
||||
/**
|
||||
* Sets the maximum size of a single file. An {@link FileUploadByteCountLimitException}
|
||||
* will be thrown, if there is an uploaded file, which is exceeding this value.
|
||||
* By default, this value will be copied from the {@link AbstractFileUpload#getFileSizeMax()
|
||||
* FileUploadBase} object, however, the user may replace the default value with a
|
||||
* request specific value by invoking {@link #setFileSizeMax(long)} on this object, so
|
||||
* there is no need to configure it here.
|
||||
* <p>
|
||||
* <em>Note:</em> Changing this value doesn't affect files, that have already been uploaded.
|
||||
* </p>
|
||||
* @param fileSizeMax The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
|
||||
*/
|
||||
void setFileSizeMax(long fileSizeMax);
|
||||
|
||||
/**
|
||||
* Sets the maximum size of the complete HTTP request. A {@link SizeLimitExceededException}
|
||||
* will be thrown, if the HTTP request will exceed this value.
|
||||
* By default, this value will be copied from the {@link AbstractFileUpload#getSizeMax()
|
||||
* FileUploadBase} object, however, the user may replace the default value with a
|
||||
* request specific value by invoking {@link #setSizeMax(long)} on this object.
|
||||
* <p>
|
||||
* <em>Note:</em> Setting the maximum size on this object will work only, if the iterator is not
|
||||
* yet initialized. In other words: If the methods {@link #hasNext()}, {@link #next()} have not
|
||||
* yet been invoked.
|
||||
* </p>
|
||||
* @param sizeMax The maximum size of the complete HTTP request. The value -1 indicates "unlimited".
|
||||
*/
|
||||
void setSizeMax(long sizeMax);
|
||||
}
|
|
@ -1,54 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A disk-based implementation of the
|
||||
* {@link org.apache.commons.fileupload2.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 org.apache.commons.fileupload2.disk.DiskFileItemFactory DiskFileItemFactory}
|
||||
* would be created, configured, and then passed to a
|
||||
* {@link org.apache.commons.fileupload2.FileUpload FileUpload}
|
||||
* implementation such as
|
||||
* {@link org.apache.commons.fileupload2.servlet.ServletFileUpload ServletFileUpload}
|
||||
* or
|
||||
* {@link org.apache.commons.fileupload2.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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
|
||||
* for further details and examples of how to use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.disk;
|
|
@ -1,41 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of
|
||||
* {@link org.apache.commons.fileupload2.FileUpload FileUpload}
|
||||
* for use in servlets conforming to the namespace {@code jakarta.servlet}.
|
||||
*
|
||||
* </p>
|
||||
* <p>
|
||||
* The following code fragment demonstrates typical usage.
|
||||
* </p>
|
||||
* <pre>
|
||||
* DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||
* // Configure the factory here, if desired.
|
||||
* JakSrvltFileUpload upload = new JakSrvltFileUpload(factory);
|
||||
* // Configure the uploader here, if desired.
|
||||
* List fileItems = upload.parseRequest(request);
|
||||
* </pre>
|
||||
* <p>
|
||||
* Please see the FileUpload
|
||||
* <a href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
|
||||
* for further details and examples of how to use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.jaksrvlt;
|
|
@ -1,45 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of
|
||||
* {@link org.apache.commons.fileupload2.FileUpload FileUpload}
|
||||
* for use in portlets conforming to JSR 168. This implementation requires
|
||||
* only access to the portlet's current {@code ActionRequest} instance,
|
||||
* and a suitable
|
||||
* {@link org.apache.commons.fileupload2.FileItemFactory FileItemFactory}
|
||||
* implementation, such as
|
||||
* {@link org.apache.commons.fileupload2.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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
|
||||
* for further details and examples of how to use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.portlet;
|
|
@ -1,45 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of
|
||||
* {@link org.apache.commons.fileupload2.FileUpload FileUpload}
|
||||
* for use in servlets conforming to JSR 53. This implementation requires
|
||||
* only access to the servlet's current {@code HttpServletRequest}
|
||||
* instance, and a suitable
|
||||
* {@link org.apache.commons.fileupload2.FileItemFactory FileItemFactory}
|
||||
* implementation, such as
|
||||
* {@link org.apache.commons.fileupload2.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="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
|
||||
* for further details and examples of how to use this package.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.commons.fileupload2.servlet;
|
|
@ -1,62 +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.
|
||||
*/
|
||||
package org.apache.commons.fileupload2;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.portlet.PortletFileUpload;
|
||||
import org.apache.commons.fileupload2.servlet.ServletFileUpload;
|
||||
import org.apache.commons.fileupload2.servlet.ServletRequestContext;
|
||||
|
||||
/**
|
||||
* Test utility methods.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
/**
|
||||
* Return a list of {@link FileUpload} implementations for parameterized tests.
|
||||
* @return a list of {@link FileUpload} implementations
|
||||
*/
|
||||
public static List<FileUpload> fileUploadImplementations() {
|
||||
return Arrays.asList(
|
||||
new ServletFileUpload(new DiskFileItemFactory()),
|
||||
new PortletFileUpload(new DiskFileItemFactory()));
|
||||
}
|
||||
|
||||
public static List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes) throws FileUploadException {
|
||||
return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
public static List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes, final String contentType)
|
||||
throws FileUploadException {
|
||||
final HttpServletRequest request = new MockHttpServletRequest(bytes, contentType);
|
||||
return upload.parseRequest(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
public static List<FileItem> parseUpload(final FileUpload upload, final String content)
|
||||
throws FileUploadException {
|
||||
final byte[] bytes = content.getBytes(StandardCharsets.US_ASCII);
|
||||
return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue