Decode quoted pairs in ContentDisposition

This commit makes sure that quoted pairs, as used in Content-Disposition
header file names (i.e. \" and \\), are properly decoded, whereas before
they were stored as is.

Closes gh-28837
This commit is contained in:
Arjen Poutsma
2022-09-06 15:47:25 +02:00
parent 9cfe79186d
commit 4cc91e46b2
2 changed files with 56 additions and 37 deletions

View File

@@ -259,7 +259,7 @@ public final class ContentDisposition {
if (this.filename != null) {
if (this.charset == null || StandardCharsets.US_ASCII.equals(this.charset)) {
sb.append("; filename=\"");
sb.append(escapeQuotationsInFilename(this.filename)).append('\"');
sb.append(encodeQuotedPairs(this.filename)).append('\"');
}
else {
sb.append("; filename*=");
@@ -404,6 +404,9 @@ public final class ContentDisposition {
}
}
}
else if (value.indexOf('\\') != -1) {
filename = decodeQuotedPairs(value);
}
else {
filename = value;
}
@@ -560,25 +563,33 @@ public final class ContentDisposition {
return StreamUtils.copyToString(baos, charset);
}
private static String escapeQuotationsInFilename(String filename) {
private static String encodeQuotedPairs(String filename) {
if (filename.indexOf('"') == -1 && filename.indexOf('\\') == -1) {
return filename;
}
boolean escaped = false;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filename.length() ; i++) {
char c = filename.charAt(i);
if (!escaped && c == '"') {
sb.append("\\\"");
if (c == '"' || c == '\\') {
sb.append('\\');
}
sb.append(c);
}
return sb.toString();
}
private static String decodeQuotedPairs(String filename) {
StringBuilder sb = new StringBuilder();
int length = filename.length();
for (int i = 0; i < length; i++) {
char c = filename.charAt(i);
if (filename.charAt(i) == '\\' && i + 1 < length) {
i++;
sb.append(filename.charAt(i));
}
else {
sb.append(c);
}
escaped = (!escaped && c == '\\');
}
// Remove backslash at the end.
if (escaped) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}