Skip to content

Commit a264013

Browse files
yusukerstoyanchev
authored andcommitted
Content-Disposition can parse BASE64 encoded filename
See gh-26463
1 parent cd80b6b commit a264013

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

spring-web/src/main/java/org/springframework/http/ContentDisposition.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
import java.time.ZonedDateTime;
2323
import java.time.format.DateTimeParseException;
2424
import java.util.ArrayList;
25+
import java.util.Base64;
2526
import java.util.List;
27+
import java.util.regex.Matcher;
28+
import java.util.regex.Pattern;
2629

2730
import org.springframework.lang.Nullable;
2831
import org.springframework.util.Assert;
@@ -320,6 +323,7 @@ public static ContentDisposition empty() {
320323
return new ContentDisposition("", null, null, null, null, null, null, null);
321324
}
322325

326+
private final static Pattern BASE64_ENCODED_PATTERN = Pattern.compile("=\\?([0-9a-zA-Z-_]+)\\?B\\?([+/0-9a-zA-Z]+=*)\\?=");
323327
/**
324328
* Parse a {@literal Content-Disposition} header value as defined in RFC 2183.
325329
* @param contentDisposition the {@literal Content-Disposition} header value
@@ -362,7 +366,14 @@ else if (attribute.equals("filename*") ) {
362366
}
363367
}
364368
else if (attribute.equals("filename") && (filename == null)) {
365-
filename = value;
369+
final Matcher matcher = BASE64_ENCODED_PATTERN.matcher(value);
370+
if (matcher.find()) {
371+
String charsetName = matcher.group(1);
372+
String encoded = matcher.group(2);
373+
filename = new String(Base64.getDecoder().decode(encoded), Charset.forName(charsetName));
374+
} else {
375+
filename = value;
376+
}
366377
}
367378
else if (attribute.equals("size") ) {
368379
size = Long.parseLong(value);

spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ void parseEncodedFilenameWithPaddedCharset() {
8080
.build());
8181
}
8282

83+
@Test
84+
void parseBase64EncodedUTF8Filename() {
85+
assertThat(parse("attachment; filename=\"=?UTF-8?B?5pel5pys6KqeLmNzdg==?=\"").getFilename())
86+
.isEqualTo("日本語.csv");
87+
}
88+
89+
@Test
90+
void parseBase64EncodedShiftJISFilename() {
91+
assertThat(parse("attachment; filename=\"=?SHIFT_JIS?B?k/qWe4zqLmNzdg==?=\"").getFilename())
92+
.isEqualTo("日本語.csv");
93+
}
94+
8395
@Test
8496
void parseEncodedFilenameWithoutCharset() {
8597
assertThat(parse("form-data; name=\"name\"; filename*=test.txt"))

0 commit comments

Comments
 (0)