Parse correctly ContentDisposition header with semicolons

Issue: SPR-16091
This commit is contained in:
Sebastien Deleuze
2017-10-23 22:59:25 +02:00
parent a3e62284ea
commit 1c256a112b
2 changed files with 57 additions and 6 deletions

View File

@@ -21,11 +21,12 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import static java.nio.charset.StandardCharsets.*;
import static java.time.format.DateTimeFormatter.*;
@@ -253,9 +254,8 @@ public class ContentDisposition {
* @see #toString()
*/
public static ContentDisposition parse(String contentDisposition) {
String[] parts = StringUtils.tokenizeToStringArray(contentDisposition, ";");
Assert.isTrue(parts.length >= 1, "Content-Disposition header must not be empty");
String type = parts[0];
List<String> parts = tokenize(contentDisposition);
String type = parts.get(0);
String name = null;
String filename = null;
Charset charset = null;
@@ -263,8 +263,8 @@ public class ContentDisposition {
ZonedDateTime creationDate = null;
ZonedDateTime modificationDate = null;
ZonedDateTime readDate = null;
for (int i = 1; i < parts.length; i++) {
String part = parts[i];
for (int i = 1; i < parts.size(); i++) {
String part = parts.get(i);
int eqIndex = part.indexOf('=');
if (eqIndex != -1) {
String attribute = part.substring(0, eqIndex);
@@ -318,6 +318,41 @@ public class ContentDisposition {
return new ContentDisposition(type, name, filename, charset, size, creationDate, modificationDate, readDate);
}
private static List<String> tokenize(String headerValue) {
int index = headerValue.indexOf(';');
String type = (index >= 0 ? headerValue.substring(0, index) : headerValue).trim();
if (type.isEmpty()) {
throw new IllegalArgumentException("Content-Disposition header must not be empty");
}
List<String> parts = new ArrayList<>();
parts.add(type);
if (index >= 0) {
do {
int nextIndex = index + 1;
boolean quoted = false;
while (nextIndex < headerValue.length()) {
char ch = headerValue.charAt(nextIndex);
if (ch == ';') {
if (!quoted) {
break;
}
}
else if (ch == '"') {
quoted = !quoted;
}
nextIndex++;
}
String part = headerValue.substring(index + 1, nextIndex).trim();
if (!part.isEmpty()) {
parts.add(part);
}
index = nextIndex;
}
while (index < headerValue.length());
}
return parts;
}
/**
* Decode the given header field param as describe in RFC 5987.
* <p>Only the US-ASCII, UTF-8 and ISO-8859-1 charsets are supported.