From 5a4a46af7811c00c748e5522813200cc17bb1b2e Mon Sep 17 00:00:00 2001 From: luozhenyu Date: Fri, 31 Mar 2023 14:16:37 +0800 Subject: [PATCH] Quote question marks in content-disposition This commit ensures that question marks are encoded, in accordance with RFC 2047, section 4.2, rule (3). Closes gh-30252 --- .../springframework/http/ContentDisposition.java | 2 +- .../http/ContentDispositionTests.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java index 8516e898e95..aa7c03580df 100644 --- a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java +++ b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java @@ -599,7 +599,7 @@ public final class ContentDisposition { } private static boolean isPrintable(byte c) { - return (c >= '!' && c <= '<') || (c >= '>' && c <= '~'); + return (c >= '!' && c <= '<') || (c >= '@' && c <= '~') || c == '>'; } private static String encodeQuotedPairs(String filename) { diff --git a/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java b/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java index ac4a8315430..e46a361a262 100644 --- a/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java +++ b/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java @@ -325,4 +325,20 @@ class ContentDispositionTests { assertThat(parsed.toString()).isEqualTo(cd.toString()); } + @Test // gh-30252 + void parseFormattedWithQuestionMark() { + String filename = "filename with ?问号.txt"; + ContentDisposition cd = ContentDisposition.attachment() + .filename(filename, StandardCharsets.UTF_8) + .build(); + String[] parts = cd.toString().split("; "); + + String quotedPrintableFilename = parts[0] + "; " + parts[1]; + assertThat(ContentDisposition.parse(quotedPrintableFilename).getFilename()) + .isEqualTo(filename); + + String rfc5987Filename = parts[0] + "; " + parts[2]; + assertThat(ContentDisposition.parse(rfc5987Filename).getFilename()) + .isEqualTo(filename); + } }