Skip to content

Commit

Permalink
All charsets for the filename* parameter are permitted
Browse files Browse the repository at this point in the history
Signed-off-by: aserkes <[email protected]>
  • Loading branch information
aserkes committed Jan 7, 2021
1 parent b8fac12 commit 7d4d5d5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,16 @@ public class ContentDisposition {
private long size;

private static final String CHARSET_GROUP_NAME = "charset";
private static final String CHARSET_REGEX = "(?<" + CHARSET_GROUP_NAME + ">UTF-8|ISO-8859-1)";
private static final String CHARSET_REGEX = "(?<" + CHARSET_GROUP_NAME + ">[^']+)";
private static final String LANG_GROUP_NAME = "lang";
private static final String LANG_REGEX = "(?<" + LANG_GROUP_NAME + ">[a-z]{2,8}(-[a-z0-9-]+)?)?";
private static final String FILENAME_GROUP_NAME = "filename";
private static final String FILENAME_REGEX = "(?<" + FILENAME_GROUP_NAME + ">.+)";
private static final Pattern FILENAME_EXT_VALUE_PATTERN =
Pattern.compile(CHARSET_REGEX + "'" + LANG_REGEX + "'" + FILENAME_REGEX,
Pattern.CASE_INSENSITIVE);
private static final Pattern FILENAME_VALUE_CHARS_PATTERN =
Pattern.compile("(%[a-f0-9]{2}|[a-z0-9!#$&+.^_`|~-])+", Pattern.CASE_INSENSITIVE);

protected ContentDisposition(final String type, final String fileName, final Date creationDate,
final Date modificationDate, final Date readDate, final long size) {
Expand Down Expand Up @@ -206,26 +208,31 @@ private void createParameters() throws ParseException {
}

private String defineFileName() throws ParseException {
final String fileName = parameters.get("filename");

final String fileName = parameters.get("filename");
final String fileNameExt = parameters.get("filename*");

if (fileNameExt == null) {
return fileName;
}

final Matcher matcher = FILENAME_EXT_VALUE_PATTERN.matcher(fileNameExt);

if (matcher.matches()) {
if (isEncodedInUriFormat(fileNameExt)) {

final String fileNameValueChars = matcher.group(FILENAME_GROUP_NAME);
if (isFilenameValueCharsEncoded(fileNameValueChars)) {
return fileNameExt;
}

if (matcher.group(CHARSET_GROUP_NAME).equalsIgnoreCase("UTF-8")) {
return new StringBuilder(matcher.group(CHARSET_GROUP_NAME))
.append("'")
.append(matcher.group(LANG_GROUP_NAME) == null ? "" : matcher.group(LANG_GROUP_NAME))
.append("'")
.append(encodeToUriFormat(fileNameValueChars))
.toString();
} else {
if (matcher.group(CHARSET_GROUP_NAME).equalsIgnoreCase("UTF-8")) {
return new StringBuilder(matcher.group(CHARSET_GROUP_NAME))
.append("'")
.append(matcher.group(LANG_GROUP_NAME) == null ? "" : matcher.group(LANG_GROUP_NAME))
.append("'")
.append(encodeToUriFormat(matcher.group(FILENAME_GROUP_NAME)))
.toString();
}
throw new ParseException(matcher.group(CHARSET_GROUP_NAME) + " charset is not supported", 0);
}
}
Expand All @@ -237,8 +244,8 @@ private String encodeToUriFormat(final String parameter) {
return UriComponent.contextualEncode(parameter, UriComponent.Type.UNRESERVED);
}

private boolean isEncodedInUriFormat(final String parameter) {
return UriComponent.valid(parameter, UriComponent.Type.UNRESERVED);
private boolean isFilenameValueCharsEncoded(final String parameter) {
return FILENAME_VALUE_CHARS_PATTERN.matcher(parameter).matches();
}

private Date createDate(final String name) throws ParseException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,13 @@ public void testFileNameExt() {
//expected
}

//correct fileNameExt, but unsupported charset (support only UTF-8)
try {
fileNameExt = "ISO-8859-1'language-us'abc%a1abc%a2%b1!#$&+.^_`|~-";
assertFileNameExt(fileNameExt, fileName, fileNameExt);
fail("ParseException was expected to be thrown.");
} catch (ParseException e) {
//expected
}
//correct fileNameExt
fileNameExt = "ISO-8859-1'language-us'abc%a1abc%a2%b1!#$&+.^_`|~-";
assertFileNameExt(fileNameExt, fileName, fileNameExt);

//correct fileNameExt with encoding
//correct fileNameExt
fileNameExt = "UTF-8'language-us'abc%a1abc%a2%b1!#$&+.^_`|~-";
encodedFilename = "UTF-8'language-us'abc%a1abc%a2%b1%21%23%24%26%2B.%5E_%60%7C~-";
assertFileNameExt(encodedFilename, fileName, fileNameExt);
assertFileNameExt(fileNameExt, fileName, fileNameExt);

//correct fileNameExt
fileNameExt = "UTF-8'us'fileName.txt";
Expand Down Expand Up @@ -159,19 +153,28 @@ public void testFileNameExt() {
encodedFilename = "utf-8'language-us'a%25z1";
assertFileNameExt(encodedFilename, fileName, fileNameExt);

//correct fileNameExt
fileNameExt = "UTF-8'language-us'abc%a1abc%a2%b1";
assertFileNameExt(fileNameExt, fileName, fileNameExt);

//incorrect fileNameExt - unsupported charset
//Incorrect fileNameExt - ext-value contains an inappropriate symbol sequence (%z1).
//Jersey won't encodes it because of the unsupported charset.
try {
fileNameExt = "Windows-1251'sr-Latn-RS'a";
fileNameExt = "windows-1251'ru-ru'a%z1";
assertFileNameExt(fileName, fileName, fileNameExt);
fail("ParseException was expected to be thrown.");
} catch (ParseException e) {
//expected
}

//correct fileNameExt
fileNameExt = "UTF-8'language-us'abc%a1abc%a2%b1";
assertFileNameExt(fileNameExt, fileName, fileNameExt);

//correct fileNameExt - encoded with other charset
fileNameExt = "UTF-16'language-us'abc%a1abc%a2%b1";
assertFileNameExt(fileNameExt, fileName, fileNameExt);

//correct fileNameExt - unsupported charset, but fileName contains only valid characters
fileNameExt = "Windows-1251'sr-Latn-RS'abc";
assertFileNameExt(fileNameExt, fileName, fileNameExt);

//correct fileNameExt
fileNameExt = "utf-8'sr-Latn-RS'a";
assertFileNameExt(fileNameExt, fileName, fileNameExt);
Expand Down

0 comments on commit 7d4d5d5

Please sign in to comment.