This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/master by this push: new 38cc914 Update Commons FileUpload to latest 38cc914 is described below commit 38cc9148a9e0614330a71d247bd97ffdf523797f Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Aug 26 11:27:45 2020 +0100 Update Commons FileUpload to latest --- MERGE.txt | 2 +- .../tomcat/util/http/fileupload/FileItem.java | 30 ++--- .../util/http/fileupload/FileItemFactory.java | 4 +- .../util/http/fileupload/FileItemHeaders.java | 28 ++--- .../util/http/fileupload/FileItemStream.java | 12 +- .../tomcat/util/http/fileupload/FileUpload.java | 6 +- .../util/http/fileupload/FileUploadBase.java | 63 +++++----- .../util/http/fileupload/FileUploadException.java | 34 +++++- .../util/http/fileupload/MultipartStream.java | 96 +++++++-------- .../util/http/fileupload/ParameterParser.java | 8 +- .../util/http/fileupload/disk/DiskFileItem.java | 46 +++---- .../http/fileupload/disk/DiskFileItemFactory.java | 8 +- .../http/fileupload/impl/FileItemIteratorImpl.java | 18 ++- .../http/fileupload/impl/FileItemStreamImpl.java | 8 +- .../impl/FileSizeLimitExceededException.java | 2 +- .../fileupload/impl/FileUploadIOException.java | 2 +- .../impl/InvalidContentTypeException.java | 6 +- .../impl/SizeLimitExceededException.java | 2 +- .../tomcat/util/http/fileupload/package-info.java | 2 +- .../http/fileupload/servlet/ServletFileUpload.java | 18 +-- .../util/http/fileupload/servlet/package-info.java | 2 +- .../http/fileupload/util/FileItemHeadersImpl.java | 8 +- .../http/fileupload/util/LimitedInputStream.java | 32 ++--- .../tomcat/util/http/fileupload/util/Streams.java | 9 +- .../http/fileupload/util/mime/RFC2231Utility.java | 133 +++++++++++++++++++++ webapps/docs/changelog.xml | 4 + 26 files changed, 370 insertions(+), 213 deletions(-) diff --git a/MERGE.txt b/MERGE.txt index fd084e5..088393b 100644 --- a/MERGE.txt +++ b/MERGE.txt @@ -51,7 +51,7 @@ FileUpload Sub-tree: src/main/java/org/apache/commons/fileupload2 The SHA1 ID for the most recent commit to be merged to Tomcat is: -2317552993fd5180a84083d599b8cbdb05a07bab (2019-12-06) +c25a4e33553a5f098ab6065a54e1ae7985025d26 (2020-08-26) Note: Tomcat's copy of fileupload also includes classes copied manually from Commons IO. diff --git a/java/org/apache/tomcat/util/http/fileupload/FileItem.java b/java/org/apache/tomcat/util/http/fileupload/FileItem.java index b69a51e..b7bdb55 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileItem.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileItem.java @@ -24,7 +24,7 @@ import java.io.UnsupportedEncodingException; /** * <p> This class represents a file or form item that was received within a - * <code>multipart/form-data</code> POST request. + * {@code multipart/form-data} POST request. * * <p> After retrieving an instance of this class from a {@link * org.apache.tomcat.util.http.fileupload.FileUpload FileUpload} instance (see @@ -36,11 +36,11 @@ import java.io.UnsupportedEncodingException; * it into memory, which may come handy with large files. * * <p> While this interface does not extend - * <code>javax.activation.DataSource</code> per se (to avoid a seldom used + * {@code javax.activation.DataSource} per se (to avoid a seldom used * dependency), several of the defined methods are 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</code> with minimal additional work. + * {@code javax.activation.DataSource} with minimal additional work. * * @since 1.3 additionally implements FileItemHeadersSupport */ @@ -60,10 +60,10 @@ public interface FileItem extends FileItemHeadersSupport { InputStream getInputStream() throws IOException; /** - * Returns the content type passed by the browser or <code>null</code> if + * Returns the content type passed by the browser or {@code null} if * not defined. * - * @return The content type passed by the browser or <code>null</code> if + * @return The content type passed by the browser or {@code null} if * not defined. */ String getContentType(); @@ -88,8 +88,8 @@ public interface FileItem extends FileItemHeadersSupport { * Provides a hint as to whether or not the file contents will be read * from memory. * - * @return <code>true</code> if the file contents will be read from memory; - * <code>false</code> otherwise. + * @return {@code true} if the file contents will be read from memory; + * {@code false} otherwise. */ boolean isInMemory(); @@ -141,7 +141,7 @@ public interface FileItem extends FileItemHeadersSupport { * example, file renaming, where possible, rather than copying all of the * underlying data, thus gaining a significant performance benefit. * - * @param file The <code>File</code> into which the uploaded item should + * @param file The {@code File} into which the uploaded item should * be stored. * * @throws Exception if an error occurs. @@ -151,7 +151,7 @@ public interface FileItem extends FileItemHeadersSupport { /** * Deletes the underlying storage for a file item, including deleting any * associated temporary disk file. Although this storage will be deleted - * automatically when the <code>FileItem</code> instance is garbage + * automatically when the {@code FileItem} instance is garbage * collected, this method can be used to ensure that this is done at an * earlier time, thus preserving system resources. */ @@ -173,20 +173,20 @@ public interface FileItem extends FileItemHeadersSupport { void setFieldName(String name); /** - * Determines whether or not a <code>FileItem</code> instance represents + * Determines whether or not a {@code FileItem} instance represents * a simple form field. * - * @return <code>true</code> if the instance represents a simple form - * field; <code>false</code> 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(); /** - * Specifies whether or not a <code>FileItem</code> instance represents + * Specifies whether or not a {@code FileItem} instance represents * a simple form field. * - * @param state <code>true</code> if the instance represents a simple form - * field; <code>false</code> if it represents an uploaded file. + * @param state {@code true} if the instance represents a simple form + * field; {@code false} if it represents an uploaded file. */ void setFormField(boolean state); diff --git a/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java b/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java index 9c7fd19..9d4accf 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java @@ -29,8 +29,8 @@ public interface FileItemFactory { * * @param fieldName The name of the form field. * @param contentType The content type of the form field. - * @param isFormField <code>true</code> if this is a plain form field; - * <code>false</code> otherwise. + * @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. * diff --git a/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java b/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java index 25441d3..bcfd40c 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java @@ -20,7 +20,7 @@ import java.util.Iterator; /** * <p> This class provides support for accessing the headers for a file or form - * item that was received within a <code>multipart/form-data</code> POST + * item that was received within a {@code multipart/form-data} POST * request.</p> * * @since 1.2.1 @@ -28,16 +28,16 @@ import java.util.Iterator; public interface FileItemHeaders { /** - * Returns the value of the specified part header as a <code>String</code>. + * Returns the value of the specified part header as a {@code String}. * * If the part did not include a header of the specified name, this method - * return <code>null</code>. If there are multiple headers with the same + * return {@code null}. If there are multiple headers with the same * name, this method returns the first header in the item. The header * name is case insensitive. * - * @param name a <code>String</code> specifying the header name - * @return a <code>String</code> containing the value of the requested - * header, or <code>null</code> if the item does not have a header + * @param name a {@code String} specifying the header name + * @return a {@code String} containing the value of the requested + * header, or {@code null} if the item does not have a header * of that name */ String getHeader(String name); @@ -45,29 +45,29 @@ public interface FileItemHeaders { /** * <p> * Returns all the values of the specified item header as an - * <code>Iterator</code> of <code>String</code> objects. + * {@code Iterator} of {@code String} objects. * </p> * <p> * If the item did not include any headers of the specified name, this - * method returns an empty <code>Iterator</code>. The header name is + * method returns an empty {@code Iterator}. The header name is * case insensitive. * </p> * - * @param name a <code>String</code> specifying the header name - * @return an <code>Iterator</code> containing the values of the + * @param name a {@code String} specifying the header name + * @return an {@code Iterator} containing the values of the * requested header. If the item does not have any headers of - * that name, return an empty <code>Iterator</code> + * that name, return an empty {@code Iterator} */ Iterator<String> getHeaders(String name); /** * <p> - * Returns an <code>Iterator</code> of all the header names. + * Returns an {@code Iterator} of all the header names. * </p> * - * @return an <code>Iterator</code> containing all of the names of + * @return an {@code Iterator} containing all of the names of * headers provided with this file item. If the item does not have - * any headers return an empty <code>Iterator</code> + * any headers return an empty {@code Iterator} */ Iterator<String> getHeaderNames(); diff --git a/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java b/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java index 2df072b..0dc5804 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java @@ -21,7 +21,7 @@ import java.io.InputStream; /** * <p> This interface provides access to a file or form item that was - * received within a <code>multipart/form-data</code> POST request. + * received within a {@code multipart/form-data} POST request. * The items contents are retrieved by calling {@link #openStream()}.</p> * <p>Instances of this class are created by accessing the * iterator, returned by @@ -64,10 +64,10 @@ public interface FileItemStream extends FileItemHeadersSupport { InputStream openStream() throws IOException; /** - * Returns the content type passed by the browser or <code>null</code> if + * Returns the content type passed by the browser or {@code null} if * not defined. * - * @return The content type passed by the browser or <code>null</code> if + * @return The content type passed by the browser or {@code null} if * not defined. */ String getContentType(); @@ -91,11 +91,11 @@ public interface FileItemStream extends FileItemHeadersSupport { String getFieldName(); /** - * Determines whether or not a <code>FileItem</code> instance represents + * Determines whether or not a {@code FileItem} instance represents * a simple form field. * - * @return <code>true</code> if the instance represents a simple form - * field; <code>false</code> 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(); diff --git a/java/org/apache/tomcat/util/http/fileupload/FileUpload.java b/java/org/apache/tomcat/util/http/fileupload/FileUpload.java index dad41ff..eb3305d 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileUpload.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileUpload.java @@ -20,7 +20,7 @@ package org.apache.tomcat.util.http.fileupload; * <p>High level API for processing file uploads.</p> * * <p>This class handles multiple files per single HTML widget, sent using - * <code>multipart/mixed</code> encoding type, as specified by + * {@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.tomcat.util.http.fileupload.FileItem FileItems} associated @@ -46,7 +46,7 @@ public class FileUpload * Constructs an uninitialised instance of this class. * * A factory must be - * configured, using <code>setFileItemFactory()</code>, before attempting + * configured, using {@code setFileItemFactory()}, before attempting * to parse requests. * * @see #FileUpload(FileItemFactory) @@ -57,7 +57,7 @@ public class FileUpload /** * Constructs an instance of this class which uses the supplied factory to - * create <code>FileItem</code> instances. + * create {@code FileItem} instances. * * @see #FileUpload() * @param fileItemFactory The factory to use for creating file items. diff --git a/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java b/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java index 9af3772..d68192a 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl; import org.apache.tomcat.util.http.fileupload.impl.FileItemStreamImpl; @@ -36,7 +37,7 @@ import org.apache.tomcat.util.http.fileupload.util.Streams; * <p>High level API for processing file uploads.</p> * * <p>This class handles multiple files per single HTML widget, sent using - * <code>multipart/mixed</code> encoding type, as specified by + * {@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.tomcat.util.http.fileupload.FileItem}s associated with a given HTML @@ -55,14 +56,14 @@ public abstract class FileUploadBase { * content.</p> * * <p><strong>NOTE:</strong>This method will be moved to the - * <code>ServletFileUpload</code> class after the FileUpload 1.1 release. + * {@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</code> if the request is multipart; - * <code>false</code> otherwise. + * @return {@code true} if the request is multipart; + * {@code false} otherwise. */ public static final boolean isMultipartContent(RequestContext ctx) { String contentType = ctx.getContentType(); @@ -209,8 +210,8 @@ public abstract class FileUploadBase { /** * Retrieves the character encoding used when reading the headers of an - * individual part. When not specified, or <code>null</code>, the request - * encoding is used. If that is also not specified, or <code>null</code>, + * 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. @@ -221,8 +222,8 @@ public abstract class FileUploadBase { /** * Specifies the character encoding to be used when reading the headers of - * individual part. When not specified, or <code>null</code>, the request - * encoding is used. If that is also not specified, or <code>null</code>, + * 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. @@ -235,11 +236,11 @@ public abstract class FileUploadBase { /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> - * compliant <code>multipart/form-data</code> stream. + * compliant {@code multipart/form-data} stream. * * @param ctx The context for the request to be parsed. * - * @return An iterator to instances of <code>FileItemStream</code> + * @return An iterator to instances of {@code FileItemStream} * parsed from the request, in the order that they were * transmitted. * @@ -261,11 +262,11 @@ public abstract class FileUploadBase { /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> - * compliant <code>multipart/form-data</code> stream. + * compliant {@code multipart/form-data} stream. * * @param ctx The context for the request to be parsed. * - * @return A list of <code>FileItem</code> instances parsed from the + * @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 @@ -277,16 +278,13 @@ public abstract class FileUploadBase { boolean successful = false; try { FileItemIterator iter = getItemIterator(ctx); - FileItemFactory fac = getFileItemFactory(); + FileItemFactory fileItemFactory = Objects.requireNonNull(getFileItemFactory(), "No FileItemFactory has been set."); final byte[] buffer = new byte[Streams.DEFAULT_BUFFER_SIZE]; - if (fac == null) { - throw new NullPointerException("No FileItemFactory has been set."); - } while (iter.hasNext()) { final FileItemStream item = iter.next(); // Don't use getName() here to prevent an InvalidFileNameException. final String fileName = ((FileItemStreamImpl) item).getName(); - FileItem fileItem = fac.createItem(item.getFieldName(), item.getContentType(), + FileItem fileItem = fileItemFactory.createItem(item.getFieldName(), item.getContentType(), item.isFormField(), fileName); items.add(fileItem); try { @@ -302,8 +300,8 @@ public abstract class FileUploadBase { } successful = true; return items; - } catch (FileUploadIOException e) { - throw (FileUploadException) e.getCause(); + } catch (FileUploadException e) { + throw e; } catch (IOException e) { throw new FileUploadException(e.getMessage(), e); } finally { @@ -321,11 +319,11 @@ public abstract class FileUploadBase { /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> - * compliant <code>multipart/form-data</code> stream. + * compliant {@code multipart/form-data} stream. * * @param ctx The context for the request to be parsed. * - * @return A map of <code>FileItem</code> instances parsed from the request. + * @return A map of {@code FileItem} instances parsed from the request. * * @throws FileUploadException if there are problems reading/parsing * the request or storing files. @@ -355,7 +353,7 @@ public abstract class FileUploadBase { // ------------------------------------------------------ Protected methods /** - * Retrieves the boundary from the <code>Content-type</code> header. + * Retrieves the boundary from the {@code Content-type} header. * * @param contentType The value of the content type header from which to * extract the boundary value. @@ -366,8 +364,7 @@ public abstract class FileUploadBase { ParameterParser parser = new ParameterParser(); parser.setLowerCaseNames(true); // Parameter parser can handle null input - Map<String,String> params = - parser.parse(contentType, new char[] {';', ','}); + Map<String, String> params = parser.parse(contentType, new char[] {';', ','}); String boundaryStr = params.get("boundary"); if (boundaryStr == null) { @@ -379,12 +376,12 @@ public abstract class FileUploadBase { } /** - * Retrieves the file name from the <code>Content-disposition</code> + * Retrieves the file name from the {@code Content-disposition} * header. * * @param headers The HTTP headers object. * - * @return The file name for the current <code>encapsulation</code>. + * @return The file name for the current {@code encapsulation}. */ public String getFileName(FileItemHeaders headers) { return getFileName(headers.getHeader(CONTENT_DISPOSITION)); @@ -421,12 +418,12 @@ public abstract class FileUploadBase { } /** - * Retrieves the field name from the <code>Content-disposition</code> + * Retrieves the field name from the {@code Content-disposition} * header. * - * @param headers A <code>Map</code> containing the HTTP request headers. + * @param headers A {@code Map} containing the HTTP request headers. * - * @return The field name for the current <code>encapsulation</code>. + * @return The field name for the current {@code encapsulation}. */ public String getFieldName(FileItemHeaders headers) { return getFieldName(headers.getHeader(CONTENT_DISPOSITION)); @@ -455,16 +452,16 @@ public abstract class FileUploadBase { } /** - * <p> Parses the <code>header-part</code> and returns as key/value + * <p> 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. * - * @param headerPart The <code>header-part</code> of the current - * <code>encapsulation</code>. + * @param headerPart The {@code header-part} of the current + * {@code encapsulation}. * - * @return A <code>Map</code> containing the parsed HTTP request headers. + * @return A {@code Map} containing the parsed HTTP request headers. */ public FileItemHeaders getParsedHeaders(String headerPart) { final int len = headerPart.length(); diff --git a/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java b/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java index 56334d1..211275c 100644 --- a/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java +++ b/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java @@ -16,25 +16,49 @@ */ package org.apache.tomcat.util.http.fileupload; +import java.io.IOException; + /** * Exception for errors encountered while processing the request. */ -public class FileUploadException extends Exception { +public class FileUploadException extends IOException { private static final long serialVersionUID = -4222909057964038517L; + /** + * Constructs a new {@code FileUploadException} without message. + */ public FileUploadException() { super(); } - public FileUploadException(String message, Throwable cause) { - super(message, cause); + /** + * Constructs a new {@code FileUploadException} with specified detail + * message. + * + * @param msg the error message. + */ + public FileUploadException(String msg) { + super(msg); } - public FileUploadException(String message) { - super(message); + /** + * Creates a new {@code FileUploadException} with the given + * detail message and cause. + * + * @param msg The exceptions detail message. + * @param cause The exceptions cause. + */ + public FileUploadException(String msg, Throwable cause) { + super(msg, cause); } + /** + * Creates a new {@code FileUploadException} with the given + * cause. + * + * @param cause The exceptions cause. + */ public FileUploadException(Throwable cause) { super(cause); } diff --git a/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java b/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java index c3616c3..07cdc70 100644 --- a/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java +++ b/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java @@ -170,7 +170,7 @@ public class MultipartStream { public static final byte DASH = 0x2D; /** - * The maximum length of <code>header-part</code> that will be + * The maximum length of {@code header-part} that will be * processed (10 kilobytes = 10240 bytes.). */ public static final int HEADER_PART_SIZE_MAX = 10240; @@ -181,25 +181,25 @@ public class MultipartStream { protected static final int DEFAULT_BUFSIZE = 4096; /** - * A byte sequence that marks the end of <code>header-part</code> - * (<code>CRLFCRLF</code>). + * A byte sequence that marks the end of {@code header-part} + * ({@code CRLFCRLF}). */ protected static final byte[] HEADER_SEPARATOR = {CR, LF, CR, LF}; /** * A byte sequence that that follows a delimiter that will be - * followed by an encapsulation (<code>CRLF</code>). + * followed by an encapsulation ({@code CRLF}). */ protected static final byte[] FIELD_SEPARATOR = {CR, LF}; /** * A byte sequence that that follows a delimiter of the last - * encapsulation in the stream (<code>--</code>). + * encapsulation in the stream ({@code --}). */ protected static final byte[] STREAM_TERMINATOR = {DASH, DASH}; /** - * A byte sequence that precedes a boundary (<code>CRLF--</code>). + * A byte sequence that precedes a boundary ({@code CRLF--}). */ protected static final byte[] BOUNDARY_PREFIX = {CR, LF, DASH, DASH}; @@ -211,7 +211,7 @@ public class MultipartStream { private final InputStream input; /** - * The length of the boundary token plus the leading <code>CRLF--</code>. + * The length of the boundary token plus the leading {@code CRLF--}. */ private int boundaryLength; @@ -268,16 +268,16 @@ public class MultipartStream { // ----------------------------------------------------------- Constructors /** - * <p> Constructs a <code>MultipartStream</code> with a custom size buffer. + * <p> 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. * - * @param input The <code>InputStream</code> to serve as a data source. + * @param input The {@code InputStream} to serve as a data source. * @param boundary The token used for dividing the stream into - * <code>encapsulations</code>. + * {@code encapsulations}. * @param bufSize The size of the buffer to be used, in bytes. * @param pNotifier The notifier, which is used for calling the * progress listener, if any. @@ -322,11 +322,11 @@ public class MultipartStream { } /** - * <p> Constructs a <code>MultipartStream</code> with a default size buffer. + * <p> Constructs a {@code MultipartStream} with a default size buffer. * - * @param input The <code>InputStream</code> to serve as a data source. + * @param input The {@code InputStream} to serve as a data source. * @param boundary The token used for dividing the stream into - * <code>encapsulations</code>. + * {@code encapsulations}. * @param pNotifier An object for calling the progress listener, if any. * * @@ -342,7 +342,7 @@ public class MultipartStream { /** * Retrieves the character encoding used when reading the headers of an - * individual part. When not specified, or <code>null</code>, the platform + * individual part. When not specified, or {@code null}, the platform * default encoding is used. * * @return The encoding used to read part headers. @@ -353,7 +353,7 @@ public class MultipartStream { /** * Specifies the character encoding to be used when reading the headers of - * individual parts. When not specified, or <code>null</code>, the platform + * individual parts. When not specified, or {@code null}, the platform * default encoding is used. * * @param encoding The encoding used to read part headers. @@ -363,7 +363,7 @@ public class MultipartStream { } /** - * Reads a byte from the <code>buffer</code>, and refills it as + * Reads a byte from the {@code buffer}, and refills it as * necessary. * * @return The next byte from the input stream. @@ -388,11 +388,11 @@ public class MultipartStream { } /** - * Skips a <code>boundary</code> token, and checks whether more - * <code>encapsulations</code> are contained in the stream. + * Skips a {@code boundary} token, and checks whether more + * {@code encapsulations} are contained in the stream. * - * @return <code>true</code> if there are more encapsulations in - * this stream; <code>false</code> otherwise. + * @return {@code true} if there are more encapsulations in + * this stream; {@code false} otherwise. * * @throws FileUploadIOException if the bytes read from the stream exceeded the size limits * @throws MalformedStreamException if the stream ends unexpectedly or @@ -440,7 +440,7 @@ public class MultipartStream { * <p>This method allows single pass processing of nested multipart * streams. * - * <p>The boundary token of the nested stream is <code>required</code> + * <p>The boundary token of the nested stream is {@code required} * to be of the same length as the boundary token in parent stream. * * <p>Restoring the parent stream boundary token after processing of a @@ -449,7 +449,7 @@ public class MultipartStream { * @param boundary The boundary to be used for parsing of the nested * stream. * - * @throws IllegalBoundaryException if the <code>boundary</code> + * @throws IllegalBoundaryException if the {@code boundary} * has a different length than the one * being currently parsed. */ @@ -489,17 +489,17 @@ public class MultipartStream { } /** - * <p>Reads the <code>header-part</code> of the current - * <code>encapsulation</code>. + * <p>Reads the {@code header-part} of the current + * {@code encapsulation}. * * <p>Headers are returned verbatim to the input stream, including the - * trailing <code>CRLF</code> marker. Parsing is left to the + * trailing {@code CRLF} marker. Parsing is left to the * application. * * <p><strong>TODO</strong> allow limiting maximum header size to * protect against abuse. * - * @return The <code>header-part</code> of the current encapsulation. + * @return The {@code header-part} of the current encapsulation. * * @throws FileUploadIOException if the bytes read from the stream exceeded the size limits. * @throws MalformedStreamException if the stream ends unexpectedly. @@ -549,16 +549,16 @@ public class MultipartStream { } /** - * <p>Reads <code>body-data</code> from the current - * <code>encapsulation</code> and writes its contents into the - * output <code>Stream</code>. + * <p>Reads {@code body-data} from the current + * {@code encapsulation} and writes its contents into the + * output {@code Stream}. * * <p>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}). * - * @param output The <code>Stream</code> to write data into. May + * @param output The {@code Stream} to write data into. May * be null, in which case this method is equivalent * to {@link #discardBodyData()}. * @@ -581,8 +581,8 @@ public class MultipartStream { } /** - * <p> Reads <code>body-data</code> from the current - * <code>encapsulation</code> and discards it. + * <p> Reads {@code body-data} from the current + * {@code encapsulation} and discards it. * * <p>Use this method to skip encapsulations you don't need or don't * understand. @@ -597,9 +597,9 @@ public class MultipartStream { } /** - * Finds the beginning of the first <code>encapsulation</code>. + * Finds the beginning of the first {@code encapsulation}. * - * @return <code>true</code> if an <code>encapsulation</code> was found in + * @return {@code true} if an {@code encapsulation} was found in * the stream. * * @throws IOException if an i/o error occurs. @@ -629,15 +629,15 @@ public class MultipartStream { } /** - * Compares <code>count</code> first bytes in the arrays - * <code>a</code> and <code>b</code>. + * Compares {@code count} first bytes in the arrays + * {@code a} and {@code b}. * * @param a The first array to compare. * @param b The second array to compare. * @param count How many bytes should be compared. * - * @return <code>true</code> if <code>count</code> first bytes in arrays - * <code>a</code> and <code>b</code> are equal. + * @return {@code true} if {@code count} first bytes in arrays + * {@code a} and {@code b} are equal. */ public static boolean arrayequals(byte[] a, byte[] b, @@ -651,14 +651,14 @@ public class MultipartStream { } /** - * Searches for a byte of specified value in the <code>buffer</code>, - * starting at the specified <code>position</code>. + * Searches for a byte of specified value in the {@code buffer}, + * starting at the specified {@code position}. * * @param value The value to find. * @param pos The starting position for searching. * * @return The position of byte found, counting from beginning of the - * <code>buffer</code>, or <code>-1</code> if not found. + * {@code buffer}, or {@code -1} if not found. */ protected int findByte(byte value, int pos) { @@ -672,11 +672,11 @@ public class MultipartStream { } /** - * Searches for the <code>boundary</code> in the <code>buffer</code> - * region delimited by <code>head</code> and <code>tail</code>. + * Searches for the {@code boundary} in the {@code buffer} + * region delimited by {@code head} and {@code tail}. * * @return The position of the boundary found, counting from the - * beginning of the <code>buffer</code>, or <code>-1</code> if + * beginning of the {@code buffer}, or {@code -1} if * not found. */ protected int findSeparator() { @@ -709,7 +709,7 @@ public class MultipartStream { private static final long serialVersionUID = 6466926458059796677L; /** - * Constructs a <code>MalformedStreamException</code> with no + * Constructs a {@code MalformedStreamException} with no * detail message. */ public MalformedStreamException() { @@ -717,7 +717,7 @@ public class MultipartStream { } /** - * Constructs an <code>MalformedStreamException</code> with + * Constructs an {@code MalformedStreamException} with * the specified detail message. * * @param message The detail message. @@ -739,7 +739,7 @@ public class MultipartStream { private static final long serialVersionUID = -161533165102632918L; /** - * Constructs an <code>IllegalBoundaryException</code> with no + * Constructs an {@code IllegalBoundaryException} with no * detail message. */ public IllegalBoundaryException() { @@ -747,7 +747,7 @@ public class MultipartStream { } /** - * Constructs an <code>IllegalBoundaryException</code> with + * Constructs an {@code IllegalBoundaryException} with * the specified detail message. * * @param message The detail message. diff --git a/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java b/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java index 061be67..943733c 100644 --- a/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java +++ b/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java @@ -22,6 +22,7 @@ import java.util.Locale; import java.util.Map; import org.apache.tomcat.util.http.fileupload.util.mime.MimeUtility; +import org.apache.tomcat.util.http.fileupload.util.mime.RFC2231Utility; /** * A simple parser intended to parse sequences of name/value pairs. @@ -31,7 +32,7 @@ import org.apache.tomcat.util.http.fileupload.util.mime.MimeUtility; * Parameter values are optional and can be omitted. * * <p> - * <code>param1 = value; param2 = "anything goes; really"; param3</code> + * {@code param1 = value; param2 = "anything goes; really"; param3} * </p> */ public class ParameterParser { @@ -316,7 +317,8 @@ public class ParameterParser { if (paramValue != null) { try { - paramValue = MimeUtility.decodeText(paramValue); + paramValue = RFC2231Utility.hasEncodedValue(paramName) ? RFC2231Utility.decodeText(paramValue) + : MimeUtility.decodeText(paramValue); } catch (UnsupportedEncodingException e) { // let's keep the original value in this case } @@ -326,10 +328,10 @@ public class ParameterParser { pos++; // skip separator } if ((paramName != null) && (paramName.length() > 0)) { + paramName = RFC2231Utility.stripDelimiter(paramName); if (this.lowerCaseNames) { paramName = paramName.toLowerCase(Locale.ENGLISH); } - params.put(paramName, paramValue); } } diff --git a/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java b/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java index 67f5e0c..4be597f 100644 --- a/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java +++ b/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java @@ -88,7 +88,7 @@ public class DiskFileItem private String fieldName; /** - * The content type passed by the browser, or <code>null</code> if + * The content type passed by the browser, or {@code null} if * not defined. */ private final String contentType; @@ -149,15 +149,15 @@ public class DiskFileItem // ----------------------------------------------------------- Constructors /** - * Constructs a new <code>DiskFileItem</code> instance. + * Constructs a new {@code DiskFileItem} instance. * * @param fieldName The name of the form field. * @param contentType The content type passed by the browser or - * <code>null</code> if not specified. + * {@code null} if not specified. * @param isFormField Whether or not this item is a plain form field, as * opposed to a file upload. * @param fileName The original file name in the user's file system, or - * <code>null</code> if not specified. + * {@code null} if not specified. * @param sizeThreshold The threshold, in bytes, below which items will be * retained in memory and above which they will be * stored as a file. @@ -201,10 +201,10 @@ public class DiskFileItem } /** - * Returns the content type passed by the agent or <code>null</code> if + * Returns the content type passed by the agent or {@code null} if * not defined. * - * @return The content type passed by the agent or <code>null</code> if + * @return The content type passed by the agent or {@code null} if * not defined. */ @Override @@ -213,10 +213,10 @@ public class DiskFileItem } /** - * Returns the content charset passed by the agent or <code>null</code> if + * Returns the content charset passed by the agent or {@code null} if * not defined. * - * @return The content charset passed by the agent or <code>null</code> if + * @return The content charset passed by the agent or {@code null} if * not defined. */ public String getCharSet() { @@ -248,8 +248,8 @@ public class DiskFileItem * Provides a hint as to whether or not the file contents will be read * from memory. * - * @return <code>true</code> if the file contents will be read - * from memory; <code>false</code> otherwise. + * @return {@code true} if the file contents will be read + * from memory; {@code false} otherwise. */ @Override public boolean isInMemory() { @@ -365,7 +365,7 @@ public class DiskFileItem * method renames a temporary file, that file will no longer be available * to copy or rename again at a later time. * - * @param file The <code>File</code> into which the uploaded item should + * @param file The {@code File} into which the uploaded item should * be stored. * * @throws Exception if an error occurs. @@ -426,7 +426,7 @@ public class DiskFileItem /** * Deletes the underlying storage for a file item, including deleting any * associated temporary disk file. Although this storage will be deleted - * automatically when the <code>FileItem</code> instance is garbage + * automatically when the {@code FileItem} instance is garbage * collected, this method can be used to ensure that this is done at an * earlier time, thus preserving system resources. */ @@ -467,11 +467,11 @@ public class DiskFileItem } /** - * Determines whether or not a <code>FileItem</code> instance represents + * Determines whether or not a {@code FileItem} instance represents * a simple form field. * - * @return <code>true</code> if the instance represents a simple form - * field; <code>false</code> 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. * * @see #setFormField(boolean) * @@ -482,11 +482,11 @@ public class DiskFileItem } /** - * Specifies whether or not a <code>FileItem</code> instance represents + * Specifies whether or not a {@code FileItem} instance represents * a simple form field. * - * @param state <code>true</code> if the instance represents a simple form - * field; <code>false</code> if it represents an uploaded file. + * @param state {@code true} if the instance represents a simple form + * field; {@code false} if it represents an uploaded file. * * @see #isFormField() * @@ -518,16 +518,16 @@ public class DiskFileItem // --------------------------------------------------------- Public methods /** - * Returns the {@link java.io.File} object for the <code>FileItem</code>'s + * Returns the {@link java.io.File} object for the {@code FileItem}'s * data's temporary location on the disk. Note that for - * <code>FileItem</code>s that have their data stored in memory, - * this method will return <code>null</code>. When handling large + * {@code FileItem}s that have their data stored in memory, + * this method will return {@code null}. When handling large * files, you can use {@link java.io.File#renameTo(java.io.File)} to * move the file to new location without copying the data, if the * source and destination locations reside within the same logical * volume. * - * @return The data file, or <code>null</code> if the data is stored in + * @return The data file, or {@code null} if the data is stored in * memory. */ public File getStoreLocation() { @@ -561,7 +561,7 @@ public class DiskFileItem /** * Creates and returns a {@link java.io.File File} representing a uniquely * named temporary file in the configured repository path. The lifetime of - * the file is tied to the lifetime of the <code>FileItem</code> instance; + * the file is tied to the lifetime of the {@code FileItem} instance; * the file will be deleted when the instance is garbage collected. * <p> * <b>Note: Subclasses that override this method must ensure that they return the diff --git a/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java b/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java index de54361..90e8ac8 100644 --- a/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java +++ b/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java @@ -36,7 +36,7 @@ import org.apache.tomcat.util.http.fileupload.FileItemFactory; * <ul> * <li>Size threshold is 10KB.</li> * <li>Repository is the system default temp directory, as returned by - * <code>System.getProperty("java.io.tmpdir")</code>.</li> + * {@code System.getProperty("java.io.tmpdir")}.</li> * </ul> * <p> * <b>NOTE</b>: Files are created in the system default temp directory with @@ -47,7 +47,7 @@ import org.apache.tomcat.util.http.fileupload.FileItemFactory; * 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>jakarta.servlet.context.tempdir</code> + * by the ServletContext attribute {@code jakarta.servlet.context.tempdir} * may be used. * </p> * @@ -169,8 +169,8 @@ public class DiskFileItemFactory implements FileItemFactory { * * @param fieldName The name of the form field. * @param contentType The content type of the form field. - * @param isFormField <code>true</code> if this is a plain form field; - * <code>false</code> otherwise. + * @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. * diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java index 098e089..7755f5d 100644 --- a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java +++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.NoSuchElementException; +import java.util.Objects; import org.apache.tomcat.util.http.fileupload.FileItem; import org.apache.tomcat.util.http.fileupload.FileItemHeaders; @@ -110,23 +111,18 @@ public class FileItemIteratorImpl implements FileItemIterator { /** * Creates a new instance. * - * @param pFileUploadBase Upload instance - * @param pRequestContext The request context. + * @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(FileUploadBase pFileUploadBase, RequestContext pRequestContext) - throws FileUploadException, IOException { - fileUploadBase = pFileUploadBase; + public FileItemIteratorImpl(FileUploadBase fileUploadBase, RequestContext requestContext) + throws FileUploadException, IOException { + this.fileUploadBase = fileUploadBase; sizeMax = fileUploadBase.getSizeMax(); fileSizeMax = fileUploadBase.getFileSizeMax(); - ctx = pRequestContext; - if (ctx == null) { - throw new NullPointerException("ctx parameter"); - } - - + ctx = Objects.requireNonNull(requestContext, "requestContext"); skipPreamble = true; findNextItem(); } diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java index 06bf33e..a65b896 100644 --- a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java +++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java @@ -67,14 +67,16 @@ public class FileItemStreamImpl implements FileItemStream { /** * Creates a new instance. - * @param pFileItemIterator Iterator for all files in this upload + * + * @param pFileItemIterator The {@link FileItemIteratorImpl iterator}, which returned this file + * item. * @param pName The items file name, or null. * @param pFieldName The items field name. * @param pContentType The items content type, or null. * @param pFormField Whether the item is a form field. * @param pContentLength The items content length, if known, or -1 - * @throws FileUploadException If an error is encountered processing the request * @throws IOException Creating the file item failed. + * @throws FileUploadException Parsing the incoming data stream failed. */ public FileItemStreamImpl(FileItemIteratorImpl pFileItemIterator, String pName, String pFieldName, String pContentType, boolean pFormField, @@ -210,4 +212,4 @@ public class FileItemStreamImpl implements FileItemStream { headers = pHeaders; } -} \ No newline at end of file +} diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java index 3eaa9d8..2ccac42 100644 --- a/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java +++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java @@ -38,7 +38,7 @@ public class FileSizeLimitExceededException private String fieldName; /** - * Constructs a <code>SizeExceededException</code> with + * Constructs a {@code SizeExceededException} with * the specified detail message, and actual and permitted sizes. * * @param message The detail message. diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java index 3e71b5c..a5b99d8 100644 --- a/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java +++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java @@ -39,7 +39,7 @@ public class FileUploadIOException extends IOException { private final FileUploadException cause; /** - * Creates a <code>FileUploadIOException</code> with the + * Creates a {@code FileUploadIOException} with the * given cause. * * @param pCause The exceptions cause, if any, or null. diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java b/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java index 295597b..f095ef0 100644 --- a/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java +++ b/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java @@ -30,7 +30,7 @@ public class InvalidContentTypeException private static final long serialVersionUID = -9073026332015646668L; /** - * Constructs a <code>InvalidContentTypeException</code> with no + * Constructs a {@code InvalidContentTypeException} with no * detail message. */ public InvalidContentTypeException() { @@ -38,7 +38,7 @@ public class InvalidContentTypeException } /** - * Constructs an <code>InvalidContentTypeException</code> with + * Constructs an {@code InvalidContentTypeException} with * the specified detail message. * * @param message The detail message. @@ -48,7 +48,7 @@ public class InvalidContentTypeException } /** - * Constructs an <code>InvalidContentTypeException</code> with + * Constructs an {@code InvalidContentTypeException} with * the specified detail message and cause. * * @param msg The detail message. diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java b/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java index 668e99b..6289dab 100644 --- a/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java +++ b/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java @@ -28,7 +28,7 @@ public class SizeLimitExceededException private static final long serialVersionUID = -2474893167098052828L; /** - * Constructs a <code>SizeExceededException</code> with + * Constructs a {@code SizeExceededException} with * the specified detail message, and actual and permitted sizes. * * @param message The detail message. diff --git a/java/org/apache/tomcat/util/http/fileupload/package-info.java b/java/org/apache/tomcat/util/http/fileupload/package-info.java index af24f38..aea8293 100644 --- a/java/org/apache/tomcat/util/http/fileupload/package-info.java +++ b/java/org/apache/tomcat/util/http/fileupload/package-info.java @@ -70,7 +70,7 @@ * </pre> * <p> * In the example above, the first file is loaded into memory as a - * <code>String</code>. Before calling the <code>getString</code> method, + * {@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 diff --git a/java/org/apache/tomcat/util/http/fileupload/servlet/ServletFileUpload.java b/java/org/apache/tomcat/util/http/fileupload/servlet/ServletFileUpload.java index 69ecb46..71ec1ca 100644 --- a/java/org/apache/tomcat/util/http/fileupload/servlet/ServletFileUpload.java +++ b/java/org/apache/tomcat/util/http/fileupload/servlet/ServletFileUpload.java @@ -34,7 +34,7 @@ import org.apache.tomcat.util.http.fileupload.FileUploadException; * <p>High level API for processing file uploads.</p> * * <p>This class handles multiple files per single HTML widget, sent using - * <code>multipart/mixed</code> encoding type, as specified by + * {@code multipart/mixed} encoding type, as specified by * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link * #parseRequest(org.apache.tomcat.util.http.fileupload.RequestContext)} to * acquire a list of {@link org.apache.tomcat.util.http.fileupload.FileItem}s @@ -59,8 +59,8 @@ public class ServletFileUpload extends FileUpload { * * @param request The servlet request to be evaluated. Must be non-null. * - * @return <code>true</code> if the request is multipart; - * <code>false</code> otherwise. + * @return {@code true} if the request is multipart; + * {@code false} otherwise. */ public static final boolean isMultipartContent( HttpServletRequest request) { @@ -74,7 +74,7 @@ public class ServletFileUpload extends FileUpload { /** * Constructs an uninitialised instance of this class. A factory must be - * configured, using <code>setFileItemFactory()</code>, before attempting + * configured, using {@code setFileItemFactory()}, before attempting * to parse requests. * * @see FileUpload#FileUpload(FileItemFactory) @@ -85,7 +85,7 @@ public class ServletFileUpload extends FileUpload { /** * Constructs an instance of this class which uses the supplied factory to - * create <code>FileItem</code> instances. + * create {@code FileItem} instances. * * @see FileUpload#FileUpload() * @param fileItemFactory The factory to use for creating file items. @@ -98,11 +98,11 @@ public class ServletFileUpload extends FileUpload { /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> - * compliant <code>multipart/form-data</code> stream. + * compliant {@code multipart/form-data} stream. * * @param request The servlet request to be parsed. * - * @return A map of <code>FileItem</code> instances parsed from the request. + * @return A map of {@code FileItem} instances parsed from the request. * * @throws FileUploadException if there are problems reading/parsing * the request or storing files. @@ -116,11 +116,11 @@ public class ServletFileUpload extends FileUpload { /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> - * compliant <code>multipart/form-data</code> stream. + * compliant {@code multipart/form-data} stream. * * @param request The servlet request to be parsed. * - * @return An iterator to instances of <code>FileItemStream</code> + * @return An iterator to instances of {@code FileItemStream} * parsed from the request, in the order that they were * transmitted. * diff --git a/java/org/apache/tomcat/util/http/fileupload/servlet/package-info.java b/java/org/apache/tomcat/util/http/fileupload/servlet/package-info.java index 1a83e55..8abc92e 100644 --- a/java/org/apache/tomcat/util/http/fileupload/servlet/package-info.java +++ b/java/org/apache/tomcat/util/http/fileupload/servlet/package-info.java @@ -20,7 +20,7 @@ * An implementation of * {@link org.apache.tomcat.util.http.fileupload.FileUpload FileUpload} * for use in servlets conforming to JSR 53. This implementation requires - * only access to the servlet's current <code>HttpServletRequest</code> + * only access to the servlet's current {@code HttpServletRequest} * instance, and a suitable * {@link org.apache.tomcat.util.http.fileupload.FileItemFactory FileItemFactory} * implementation, such as diff --git a/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java b/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java index f6037b6..079a7b3 100644 --- a/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java +++ b/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java @@ -27,7 +27,6 @@ import java.util.Map; import org.apache.tomcat.util.http.fileupload.FileItemHeaders; - /** * Default implementation of the {@link FileItemHeaders} interface. * @@ -41,11 +40,10 @@ public class FileItemHeadersImpl implements FileItemHeaders, Serializable { private static final long serialVersionUID = -4455695752627032559L; /** - * Map of <code>String</code> keys to a <code>List</code> of - * <code>String</code> instances. + * Map of {@code String} keys to a {@code List} of + * {@code String} instances. */ - private final Map<String,List<String>> headerNameToValueListMap = - new LinkedHashMap<>(); + private final Map<String, List<String>> headerNameToValueListMap = new LinkedHashMap<>(); /** * {@inheritDoc} diff --git a/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java b/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java index f454731..0679314 100644 --- a/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java +++ b/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java @@ -79,17 +79,17 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl /** * Reads the next byte of data from this input stream. The value - * byte is returned as an <code>int</code> in the range - * <code>0</code> to <code>255</code>. If no byte is available + * 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</code> is returned. This method blocks until input data + * {@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()</code> and returns the result. + * simply performs {@code in.read()} and returns the result. * - * @return the next byte of data, or <code>-1</code> if the end of the + * @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 @@ -105,25 +105,25 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl } /** - * Reads up to <code>len</code> bytes of data from this input stream - * into an array of bytes. If <code>len</code> is not zero, the method + * 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</code> is returned. + * bytes are read and {@code 0} is returned. * <p> - * This method simply performs <code>in.read(b, off, len)</code> + * This method simply performs {@code in.read(b, off, len)} * and returns the result. * * @param b the buffer into which the data is read. * @param off The start offset in the destination array - * <code>b</code>. + * {@code b}. * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or - * <code>-1</code> if there is no more data because the end of + * {@code -1} if there is no more data because the end of * the stream has been reached. - * @throws NullPointerException If <code>b</code> is <code>null</code>. - * @throws IndexOutOfBoundsException If <code>off</code> is negative, - * <code>len</code> is negative, or <code>len</code> is greater than - * <code>b.length - off</code> + * @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 */ @@ -152,7 +152,7 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl * Closes this input stream and releases any system resources * associated with the stream. * This - * method simply performs <code>in.close()</code>. + * method simply performs {@code in.close()}. * * @throws IOException if an I/O error occurs. * @see java.io.FilterInputStream#in diff --git a/java/org/apache/tomcat/util/http/fileupload/util/Streams.java b/java/org/apache/tomcat/util/http/fileupload/util/Streams.java index feeec94..e7afa72 100644 --- a/java/org/apache/tomcat/util/http/fileupload/util/Streams.java +++ b/java/org/apache/tomcat/util/http/fileupload/util/Streams.java @@ -56,10 +56,10 @@ public final class Streams { * @param outputStream The output stream, to which data should * be written. May be null, in which case the input streams * contents are simply discarded. - * @param closeOutputStream True guarantees, that {@link OutputStream#close()} - * is called on the stream. False indicates, that only + * @param closeOutputStream True guarantees, that + * {@link OutputStream#close()} is called on the stream. + * False indicates, that only * {@link OutputStream#flush()} should be called finally. - * * @return Number of bytes, which have been copied. * @throws IOException An I/O error occurred. */ @@ -153,7 +153,8 @@ public final class Streams { * @return The streams contents, as a string. * @throws IOException An I/O error occurred. */ - public static String asString(InputStream inputStream, String encoding) throws IOException { + public static String asString(final InputStream inputStream, final String encoding) + throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); copy(inputStream, baos, true); return baos.toString(encoding); diff --git a/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java b/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java new file mode 100644 index 0000000..386b228 --- /dev/null +++ b/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java @@ -0,0 +1,133 @@ +/* + * 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.tomcat.util.http.fileupload.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 + * + * 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> + */ +public final class RFC2231Utility { + + private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + + private static final byte[] HEX_DECODE = new byte[0x80]; + + // create a ASCII decoded array of Hexadecimal values + static { + for (int i = 0; i < HEX_DIGITS.length; i++) { + HEX_DECODE[HEX_DIGITS[i]] = (byte) i; + HEX_DECODE[Character.toLowerCase(HEX_DIGITS[i])] = (byte) i; + } + } + + /** + * Checks 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 + */ + public static boolean hasEncodedValue(String paramName) { + if (paramName != null) { + return paramName.lastIndexOf("*") == (paramName.length() - 1); + } + return false; + } + + /** + * 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 + */ + public static String stripDelimiter(String paramName) { + if (hasEncodedValue(paramName)) { + StringBuilder paramBuilder = new StringBuilder(paramName); + paramBuilder.deleteCharAt(paramName.lastIndexOf("*")); + return paramBuilder.toString(); + } + return paramName; + } + + /** + * Decode 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 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}. + * + * @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. + */ + public static String decodeText(String encodedText) throws UnsupportedEncodingException { + int langDelimitStart = encodedText.indexOf('\''); + if (langDelimitStart == -1) { + // missing charset + return encodedText; + } + String mimeCharset = encodedText.substring(0, langDelimitStart); + int langDelimitEnd = encodedText.indexOf('\'', langDelimitStart + 1); + if (langDelimitEnd == -1) { + // missing language + return encodedText; + } + byte[] bytes = fromHex(encodedText.substring(langDelimitEnd + 1)); + return new String(bytes, getJavaCharset(mimeCharset)); + } + + /** + * Convert {@code text} to their corresponding Hex value + * @param text - ASCII text input + * @return Byte array of characters decoded from ASCII table + */ + private static byte[] fromHex(String text) { + ByteArrayOutputStream out = new ByteArrayOutputStream(text.length()); + for (int i = 0; i < text.length();) { + char c = text.charAt(i++); + if (c == '%') { + if (i > text.length() - 2) { + break; // unterminated sequence + } + byte b1 = HEX_DECODE[text.charAt(i++) & 0x7f]; + byte b2 = HEX_DECODE[text.charAt(i++) & 0x7f]; + out.write((b1 << 4) | b2); + } else { + out.write((byte) c); + } + } + return out.toByteArray(); + } + + private static String getJavaCharset(String mimeCharset) { + // good enough for standard values + return mimeCharset; + } +} diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 79135a7..bac2c21 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -211,6 +211,10 @@ Update the internal fork of Apache Commons Codec to 53c93d0 (2020-08-18, 1.15-SNAPSHOT). Code clean-up. (markt) </add> + <add> + Update the internal fork of Apache Commons FileUpload to c25a4e3 + (2020-08-26, 2.0-SNAPSHOT). Code clean-up and RFC 2231 support. (markt) + </add> </changelog> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org