Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
garydgregory committed Jul 7, 2024
2 parents 4ea6268 + 9f02e47 commit e1ae2a1
Show file tree
Hide file tree
Showing 23 changed files with 414 additions and 114 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
Expand All @@ -57,7 +57,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # 3.25.5
uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c # 3.25.11
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -68,7 +68,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # 3.25.5
uses: github/codeql-action/autobuild@b611370bb5703a7efb587f9d136a52ea24c5c38c # 3.25.11

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -82,4 +82,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # 3.25.5
uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c # 3.25.11
52 changes: 0 additions & 52 deletions .github/workflows/coverage.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
# experimental: true

steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/scorecards-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
steps:

- name: "Checkout code"
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false

Expand All @@ -57,13 +57,13 @@ jobs:
publish_results: true

- name: "Upload artifact"
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # 4.3.3
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # 4.3.4
with:
name: SARIF file
path: results.sarif
retention-days: 5

- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # 3.25.5
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # 3.25.11
with:
sarif_file: results.sarif
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ Apache Commons FileUpload
===================

[![Java CI](https://github.com/apache/commons-fileupload/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-fileupload/actions/workflows/maven.yml)
[![Coverage Status](https://codecov.io/gh/apache/commons-fileupload/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/commons-fileupload)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-fileupload2/badge.svg?gav=true)](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-fileupload2/?gav=true)
[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-fileupload2/2.0.0-M2.svg)](https://javadoc.io/doc/org.apache.commons/commons-fileupload2/2.0.0-M2)
[![CodeQL](https://github.com/apache/commons-fileupload/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-fileupload/actions/workflows/codeql-analysis.yml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@
import java.util.Objects;
import java.util.function.Function;
import java.util.function.LongSupplier;
import java.util.regex.Pattern;

public abstract class AbstractRequestContext<T> implements RequestContext {
/**
* The Content-Type Pattern for multipart/related Requests.
*/
private static final Pattern MULTIPART_RELATED =
Pattern.compile("^\\s*multipart/related.*", Pattern.CASE_INSENSITIVE);

/**
* Supplies the content length default.
Expand Down Expand Up @@ -79,4 +85,14 @@ public String toString() {
return String.format("%s [ContentLength=%s, ContentType=%s]", getClass().getSimpleName(), getContentLength(), getContentType());
}

/**
* Is the Request of type <code>multipart/related</code>?
*
* @return the Request is of type <code>multipart/related</code>
* @since 2.0.0
*/
@Override
public boolean isMultipartRelated() {
return MULTIPART_RELATED.matcher(getContentType()).matches();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ public InputStream getInputStream() throws IOException {
*/
@Override
public String getName() {
return DiskFileItem.checkFileName(fileName);
return checkFileName(fileName);
}

/**
Expand Down Expand Up @@ -500,7 +500,7 @@ public boolean isInMemory() {
* Sets the default charset for use when no explicit charset parameter is provided by the sender.
*
* @param charset the default charset
* @return this
* @return {@code this} instance.
*/
public DiskFileItem setCharsetDefault(final Charset charset) {
charsetDefault = charset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public DiskFileItemFactory get() {
* Sets the tracker, which is responsible for deleting temporary files.
*
* @param fileCleaningTracker Callback to track files created, or null (default) to disable tracking.
* @return this
* @return {@code this} instance.
*/
public Builder setFileCleaningTracker(final FileCleaningTracker fileCleaningTracker) {
this.fileCleaningTracker = fileCleaningTracker;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public interface FileItem<F extends FileItem<F>> extends FileItemHeadersProvider
* Deletes the underlying storage for a file item, including deleting any associated temporary disk file. Use this method to ensure that this is done at an
* earlier time, to preserve resources.
*
* @return this
* @return {@code this} instance.
* @throws IOException if an error occurs.
*/
F delete() throws IOException;
Expand Down Expand Up @@ -148,15 +148,15 @@ public interface FileItem<F extends FileItem<F>> extends FileItemHeadersProvider
* Sets the field name used to reference this file item.
*
* @param name The name of the form field.
* @return this
* @return {@code this} instance.
*/
F setFieldName(String name);

/**
* Sets whether or not a {@code FileItem} instance represents a simple form field.
*
* @param state {@code true} if the instance represents a simple form field; {@code false} if it represents an uploaded file.
* @return this
* @return {@code this} instance.
*/
F setFormField(boolean state);

Expand All @@ -173,7 +173,7 @@ public interface FileItem<F extends FileItem<F>> extends FileItemHeadersProvider
*
* @param file The {@code File} into which the uploaded item should be stored.
* @throws IOException if an error occurs.
* @return this
* @return {@code this} instance.
*/
F write(Path file) throws IOException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public interface FileItemHeadersProvider<T extends FileItemHeadersProvider<T>> {
* the raw headers found within the item header block.
*
* @param headers the instance that holds onto the headers for this instance.
* @return this
* @return {@code this} instance.
*/
T setHeaders(FileItemHeaders headers);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
* The iterator returned by {@link AbstractFileUpload#getItemIterator(RequestContext)}.
*/
class FileItemInputIteratorImpl implements FileItemInputIterator {

/**
* The file uploads processing utility.
*
Expand Down Expand Up @@ -96,6 +95,11 @@ class FileItemInputIteratorImpl implements FileItemInputIterator {
*/
private boolean eof;

/**
* Is the Request of type <code>multipart/related</code>.
*/
private final boolean multipartRelated;

/**
* Constructs a new instance.
*
Expand All @@ -109,6 +113,7 @@ class FileItemInputIteratorImpl implements FileItemInputIterator {
this.sizeMax = fileUploadBase.getSizeMax();
this.fileSizeMax = fileUploadBase.getFileSizeMax();
this.requestContext = Objects.requireNonNull(requestContext, "requestContext");
this.multipartRelated = this.requestContext.isMultipartRelated();
this.skipPreamble = true;
findNextItem();
}
Expand Down Expand Up @@ -147,7 +152,16 @@ private boolean findNextItem() throws FileUploadException, IOException {
continue;
}
final var headers = fileUpload.getParsedHeaders(multi.readHeaders());
if (currentFieldName == null) {
if (multipartRelated) {
currentFieldName = "";
currentItem = new FileItemInputImpl(
this, null, null, headers.getHeader(AbstractFileUpload.CONTENT_TYPE),
false, getContentLength(headers));
currentItem.setHeaders(headers);
progressNotifier.noteItem();
itemValid = true;
return true;
} else if (currentFieldName == null) {
// We're parsing the outer multipart
final var fieldName = fileUpload.getFieldName(headers);
if (fieldName != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public MultipartInput get() throws IOException {
* Sets the boundary.
*
* @param boundary the boundary.
* @return this
* @return {@code this} instance.
*/
public Builder setBoundary(final byte[] boundary) {
this.boundary = boundary;
Expand All @@ -146,7 +146,7 @@ public Builder setBoundary(final byte[] boundary) {
* Sets the progress notifier.
*
* @param progressNotifier progress notifier..
* @return this
* @return {@code this} instance.
*/
public Builder setProgressNotifier(final ProgressNotifier progressNotifier) {
this.progressNotifier = progressNotifier;
Expand Down Expand Up @@ -258,14 +258,16 @@ public void close(final boolean closeUnderlying) throws IOException {
input.close();
} else {
for (;;) {
var av = available();
if (av == 0) {
av = makeAvailable();
if (av == 0) {
var avail = available();
if (avail == 0) {
avail = makeAvailable();
if (avail == 0) {
break;
}
}
skip(av);
if (skip(avail) != avail) {
// TODO What to do?
}
}
}
closed = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,11 @@ default Charset getCharset() throws UnsupportedCharsetException {
*/
InputStream getInputStream() throws IOException;

/**
* Is the Request of type <code>multipart/related</code>?
*
* @return the Request is of type <code>multipart/related</code>
* @since 2.0.0
*/
boolean isMultipartRelated();
}
Original file line number Diff line number Diff line change
Expand Up @@ -393,4 +393,53 @@ public void testIE5MacBug() throws FileUploadException {
assertTrue(field2.isFormField());
assertEquals("fieldValue2", field2.getString());
}

/**
* Test for multipart/related without any content-disposition Header.
* This kind of Content-Type is commonly used by SOAP-Requests with Attachments (MTOM)
*/
@Test
public void testMultipleRelated() throws Exception {
final String soapEnvelope =
"<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">\r\n" +
" <soap:Header></soap:Header>\r\n" +
" <soap:Body>\r\n" +
" <ns1:Test xmlns:ns1=\"http://www.test.org/some-test-namespace\">\r\n" +
" <ns1:Attachment>\r\n" +
" <xop:Include xmlns:xop=\"http://www.w3.org/2004/08/xop/include\"" +
" href=\"ref-to-attachment%40some.domain.org\"/>\r\n" +
" </ns1:Attachment>\r\n" +
" </ns1:Test>\r\n" +
" </soap:Body>\r\n" +
"</soap:Envelope>";

final String text =
"-----1234\r\n" +
"content-type: application/xop+xml; type=\"application/soap+xml\"\r\n" +
"\r\n" +
soapEnvelope + "\r\n" +
"-----1234\r\n" +
"Content-type: text/plain\r\n" +
"content-id: <[email protected]>\r\n" +
"\r\n" +
"some text/plain content\r\n" +
"-----1234--\r\n";

final var bytes = text.getBytes(StandardCharsets.US_ASCII);
final var fileItems = parseUpload(upload, bytes, "multipart/related; boundary=---1234;" +
" type=\"application/xop+xml\"; start-info=\"application/soap+xml\"");
assertEquals(2, fileItems.size());

final var part1 = fileItems.get(0);
assertNull(part1.getFieldName());
assertFalse(part1.isFormField());
assertEquals(soapEnvelope, part1.getString());

final var part2 = fileItems.get(1);
assertNull(part2.getFieldName());
assertFalse(part2.isFormField());
assertEquals("some text/plain content", part2.getString());
assertEquals("text/plain", part2.getContentType());
assertNull(part2.getName());
}
}
Loading

0 comments on commit e1ae2a1

Please sign in to comment.