ASCII encode ContentDisposition file name (#5514)
Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
diff --git a/connectors/jdk-connector/pom.xml b/connectors/jdk-connector/pom.xml
index bc24148..2d4b269 100644
--- a/connectors/jdk-connector/pom.xml
+++ b/connectors/jdk-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -98,6 +98,7 @@
<reuseForks>false</reuseForks>
<excludes>
<exclude>**/SslFilterTLS13Test.java</exclude>
+ <exclude>**/SslFilterTLS13UrlStoresTest.java</exclude>
</excludes>
</configuration>
</plugin>
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
index 34188e7..6d77453 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -28,8 +28,6 @@
import org.glassfish.jersey.message.internal.HttpHeaderReader;
import org.glassfish.jersey.uri.UriComponent;
-import javax.ws.rs.core.HttpHeaders;
-
/**
* A content disposition header.
*
@@ -60,10 +58,13 @@
private static final Pattern FILENAME_VALUE_CHARS_PATTERN =
Pattern.compile("(%[a-f0-9]{2}|[a-z0-9!#$&+.^_`|~-])+", Pattern.CASE_INSENSITIVE);
+ private static final char QUOTE = '"';
+ private static final char BACK_SLASH = '\\';
+
protected ContentDisposition(final String type, final String fileName, final Date creationDate,
final Date modificationDate, final Date readDate, final long size) {
this.type = type;
- this.fileName = fileName;
+ this.fileName = encodeAsciiFileName(fileName);
this.creationDate = creationDate;
this.modificationDate = modificationDate;
this.readDate = readDate;
@@ -211,6 +212,23 @@
}
}
+ protected String encodeAsciiFileName(String fileName) {
+ if (fileName == null
+ || (fileName.indexOf(QUOTE) == -1
+ && fileName.indexOf(BACK_SLASH) == -1)) {
+ return fileName;
+ }
+ final char[] chars = fileName.toCharArray();
+ final StringBuilder encodedBuffer = new StringBuilder();
+ for (char c : chars) {
+ if (c == QUOTE || c == BACK_SLASH) {
+ encodedBuffer.append(BACK_SLASH);
+ }
+ encodedBuffer.append(c);
+ }
+ return encodedBuffer.toString();
+ }
+
private void createParameters() throws ParseException {
defineFileName();
@@ -229,7 +247,7 @@
final String fileNameExt = parameters.get("filename*");
if (fileNameExt == null) {
- this.fileName = fileName;
+ this.fileName = encodeAsciiFileName(fileName);
return;
}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
index c4bcd53..8cecb6b 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -89,6 +89,14 @@
}
@Test
+ void testContentDispositionEncoded() {
+ final Date date = new Date();
+ final ContentDisposition contentDisposition = ContentDisposition.type(contentDispositionType).fileName("\"rm\\ -rf\".sh")
+ .creationDate(date).modificationDate(date).readDate(date).size(312).build();
+ assertEquals("\\\"rm\\\\ -rf\\\".sh", contentDisposition.getFileName());
+ }
+
+ @Test
public void testToString() {
final Date date = new Date();
final ContentDisposition contentDisposition = ContentDisposition.type(contentDispositionType).fileName("test.file")