Diff
Modified: trunk/LayoutTests/ChangeLog (240330 => 240331)
--- trunk/LayoutTests/ChangeLog 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/LayoutTests/ChangeLog 2019-01-23 11:32:55 UTC (rev 240331)
@@ -1,3 +1,16 @@
+2019-01-23 Rob Buis <[email protected]>
+
+ Update MIME type parser
+ https://bugs.webkit.org/show_bug.cgi?id=180526
+
+ Reviewed by Frédéric Wang.
+
+ Adjust test expectation.
+
+ * http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt:
+ * http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt:
+ * http/tests/xmlhttprequest/post-blob-content-type-tests.js:
+
2019-01-22 Simon Fraser <[email protected]>
Adding a child to a ScrollingStateNode needs to trigger a tree state commit
Modified: trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt (240330 => 240331)
--- trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt 2019-01-23 11:32:55 UTC (rev 240331)
@@ -12,7 +12,7 @@
PASS expectedMimeType is ""
PASS expectedMimeType is ""
PASS expectedMimeType is ""
-PASS expectedMimeType is ""
+PASS expectedMimeType is "multipart/mixed;boundary=\"--blob-boundary"
PASS expectedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
PASS expectedMimeType is ""
PASS expectedMimeType is ""
Modified: trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt (240330 => 240331)
--- trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt 2019-01-23 11:32:55 UTC (rev 240331)
@@ -12,7 +12,7 @@
PASS expectedMimeType is ""
PASS expectedMimeType is ""
PASS expectedMimeType is ""
-PASS expectedMimeType is ""
+PASS expectedMimeType is "multipart/mixed;boundary=\"--blob-boundary"
PASS expectedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
PASS expectedMimeType is ""
PASS expectedMimeType is ""
Modified: trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js (240330 => 240331)
--- trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js 2019-01-23 11:32:55 UTC (rev 240331)
@@ -23,7 +23,7 @@
expectedMime: ''
}, {
mime: 'multipart/mixed;boundary="--blob-boundary',
- expectedMime: ''
+ expectedMime: 'multipart/mixed;boundary="--blob-boundary'
}, {
mime: 'multipart/mixed;boundary="--blob-boundary"',
expectedMime: 'multipart/mixed;boundary="--blob-boundary"'
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (240330 => 240331)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2019-01-23 11:32:55 UTC (rev 240331)
@@ -1,3 +1,14 @@
+2019-01-23 Rob Buis <[email protected]>
+
+ Update MIME type parser
+ https://bugs.webkit.org/show_bug.cgi?id=180526
+
+ Reviewed by Frédéric Wang.
+
+ Update improved test expectations.
+
+ * web-platform-tests/xhr/overridemimetype-blob-expected.txt:
+
2019-01-22 Youenn Fablet <[email protected]>
Resync libwebrtc with latest M72 branch
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/overridemimetype-blob-expected.txt (240330 => 240331)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/overridemimetype-blob-expected.txt 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/overridemimetype-blob-expected.txt 2019-01-23 11:32:55 UTC (rev 240331)
@@ -4,59 +4,59 @@
PASS Loading data…
FAIL 1) MIME types need to be parsed and serialized: text/html;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
FAIL 2) MIME types need to be parsed and serialized: TEXT/HTML;CHARSET=GBK assert_equals: expected "text/html;charset=GBK" but got "text/html"
-FAIL 3) MIME types need to be parsed and serialized: text/html;charset=gbk( assert_equals: expected "text/html;charset=\"gbk(\"" but got "application/octet-stream"
-FAIL 4) MIME types need to be parsed and serialized: text/html;x=(;charset=gbk assert_equals: expected "text/html;x=\"(\";charset=gbk" but got "application/octet-stream"
+FAIL 3) MIME types need to be parsed and serialized: text/html;charset=gbk( assert_equals: expected "text/html;charset=\"gbk(\"" but got "text/html"
+FAIL 4) MIME types need to be parsed and serialized: text/html;x=(;charset=gbk assert_equals: expected "text/html;x=\"(\";charset=gbk" but got "text/html"
FAIL 5) MIME types need to be parsed and serialized: text/html;charset=gbk;charset=windows-1255 assert_equals: expected "text/html;charset=gbk" but got "text/html"
-FAIL 6) MIME types need to be parsed and serialized: text/html;charset=();charset=GBK assert_equals: expected "text/html;charset=\"()\"" but got "application/octet-stream"
-FAIL 7) MIME types need to be parsed and serialized: text/html;charset =gbk assert_equals: expected "text/html" but got "application/octet-stream"
+FAIL 6) MIME types need to be parsed and serialized: text/html;charset=();charset=GBK assert_equals: expected "text/html;charset=\"()\"" but got "text/html"
+PASS 7) MIME types need to be parsed and serialized: text/html;charset =gbk
FAIL 8) MIME types need to be parsed and serialized: text/html ;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
FAIL 9) MIME types need to be parsed and serialized: text/html; charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
-FAIL 10) MIME types need to be parsed and serialized: text/html;charset= gbk assert_equals: expected "text/html;charset=\" gbk\"" but got "application/octet-stream"
-FAIL 11) MIME types need to be parsed and serialized: text/html;charset= "gbk" assert_equals: expected "text/html;charset=\" \\\"gbk\\"\"" but got "application/octet-stream"
+FAIL 10) MIME types need to be parsed and serialized: text/html;charset= gbk assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html"
+FAIL 11) MIME types need to be parsed and serialized: text/html;charset= "gbk" assert_equals: expected "text/html;charset=\" \\\"gbk\\"\"" but got "text/html"
FAIL 12) MIME types need to be parsed and serialized: text/html;charset='gbk' assert_equals: expected "text/html;charset='gbk'" but got "text/html"
FAIL 13) MIME types need to be parsed and serialized: text/html;charset='gbk assert_equals: expected "text/html;charset='gbk" but got "text/html"
FAIL 14) MIME types need to be parsed and serialized: text/html;charset=gbk' assert_equals: expected "text/html;charset=gbk'" but got "text/html"
FAIL 15) MIME types need to be parsed and serialized: text/html;charset=';charset=GBK assert_equals: expected "text/html;charset='" but got "text/html"
-FAIL 16) MIME types need to be parsed and serialized: text/html;test;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
+FAIL 16) MIME types need to be parsed and serialized: text/html;test;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
FAIL 17) MIME types need to be parsed and serialized: text/html;test=;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
-FAIL 18) MIME types need to be parsed and serialized: text/html;';charset=gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
-FAIL 19) MIME types need to be parsed and serialized: text/html;";charset=gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
-FAIL 20) MIME types need to be parsed and serialized: text/html ; ; charset=gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
-FAIL 21) MIME types need to be parsed and serialized: text/html;;;;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
-FAIL 22) MIME types need to be parsed and serialized: text/html;charset= ";charset=GBK assert_equals: expected "text/html;charset=GBK" but got "application/octet-stream"
+FAIL 18) MIME types need to be parsed and serialized: text/html;';charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
+FAIL 19) MIME types need to be parsed and serialized: text/html;";charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
+FAIL 20) MIME types need to be parsed and serialized: text/html ; ; charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
+FAIL 21) MIME types need to be parsed and serialized: text/html;;;;charset=gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
+FAIL 22) MIME types need to be parsed and serialized: text/html;charset= ";charset=GBK assert_equals: expected "text/html;charset=GBK" but got "text/html"
FAIL 23) MIME types need to be parsed and serialized: text/html;charset=";charset=foo";charset=GBK assert_equals: expected "text/html;charset=GBK" but got "text/html"
FAIL 24) MIME types need to be parsed and serialized: text/html;charset="gbk" assert_equals: expected "text/html;charset=gbk" but got "text/html"
-FAIL 25) MIME types need to be parsed and serialized: text/html;charset="gbk assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
-FAIL 26) MIME types need to be parsed and serialized: text/html;charset=gbk" assert_equals: expected "text/html;charset=\"gbk\\\"\"" but got "application/octet-stream"
+FAIL 25) MIME types need to be parsed and serialized: text/html;charset="gbk assert_equals: expected "text/html;charset=gbk" but got "text/html"
+FAIL 26) MIME types need to be parsed and serialized: text/html;charset=gbk" assert_equals: expected "text/html;charset=\"gbk\\\"\"" but got "text/html"
FAIL 27) MIME types need to be parsed and serialized: text/html;charset=" gbk" assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html"
FAIL 28) MIME types need to be parsed and serialized: text/html;charset="gbk " assert_equals: expected "text/html;charset=\"gbk \"" but got "text/html"
FAIL 29) MIME types need to be parsed and serialized: text/html;charset="\ gbk" assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html"
FAIL 30) MIME types need to be parsed and serialized: text/html;charset="\g\b\k" assert_equals: expected "text/html;charset=gbk" but got "text/html"
-FAIL 31) MIME types need to be parsed and serialized: text/html;charset="gbk"x assert_equals: expected "text/html;charset=gbk" but got "application/octet-stream"
+FAIL 31) MIME types need to be parsed and serialized: text/html;charset="gbk"x assert_equals: expected "text/html;charset=gbk" but got "text/html"
FAIL 32) MIME types need to be parsed and serialized: text/html;charset="";charset=GBK assert_equals: expected "text/html;charset=\"\"" but got "text/html"
-FAIL 33) MIME types need to be parsed and serialized: text/html;charset=";charset=GBK assert_equals: expected "text/html;charset=\";charset=GBK\"" but got "application/octet-stream"
+FAIL 33) MIME types need to be parsed and serialized: text/html;charset=";charset=GBK assert_equals: expected "text/html;charset=\";charset=GBK\"" but got "text/html"
FAIL 34) MIME types need to be parsed and serialized: text/html;charset={gbk} assert_equals: expected "text/html;charset=\"{gbk}\"" but got "text/html"
FAIL 35) MIME types need to be parsed and serialized: text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk assert_equals: expected "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk" but got "text/html"
PASS 36) MIME types need to be parsed and serialized: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
FAIL 37) MIME types need to be parsed and serialized: !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz assert_equals: expected "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" but got "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
FAIL 38) MIME types need to be parsed and serialized: x/x;x=" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" assert_equals: expected "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\"" but got "x/x"
-FAIL 39) MIME types need to be parsed and serialized: x/x;test assert_equals: expected "x/x" but got "application/octet-stream"
-FAIL 40) MIME types need to be parsed and serialized: x/x;test="\ assert_equals: expected "x/x;test=\"\\\\"" but got "application/octet-stream"
-FAIL 41) MIME types need to be parsed and serialized: x/x;x= assert_equals: expected "x/x" but got "application/octet-stream"
-FAIL 42) MIME types need to be parsed and serialized: x/x;x= assert_equals: expected "x/x" but got "application/octet-stream"
-FAIL 43) MIME types need to be parsed and serialized: text/html;test=ÿ;charset=gbk assert_equals: expected "text/html;test=\"ÿ\";charset=gbk" but got "application/octet-stream"
-FAIL 44) MIME types need to be parsed and serialized: x/x;test=�;x=x assert_equals: expected "x/x;x=x" but got "application/octet-stream"
+PASS 39) MIME types need to be parsed and serialized: x/x;test
+FAIL 40) MIME types need to be parsed and serialized: x/x;test="\ assert_equals: expected "x/x;test=\"\\\\"" but got "x/x"
+PASS 41) MIME types need to be parsed and serialized: x/x;x=
+PASS 42) MIME types need to be parsed and serialized: x/x;x=
+FAIL 43) MIME types need to be parsed and serialized: text/html;test=ÿ;charset=gbk assert_equals: expected "text/html;test=\"ÿ\";charset=gbk" but got "text/html"
+FAIL 44) MIME types need to be parsed and serialized: x/x;test=�;x=x assert_equals: expected "x/x;x=x" but got "x/x"
PASS 45) MIME types need to be parsed and serialized:
PASS 46) MIME types need to be parsed and serialized:
PASS 47) MIME types need to be parsed and serialized: /
PASS 48) MIME types need to be parsed and serialized: bogus
PASS 49) MIME types need to be parsed and serialized: bogus/
-PASS 50) MIME types need to be parsed and serialized: bogus/
+FAIL 50) MIME types need to be parsed and serialized: bogus/ assert_equals: expected "application/octet-stream" but got "bogus/"
PASS 51) MIME types need to be parsed and serialized: bogus/bogus/;
PASS 52) MIME types need to be parsed and serialized: </>
PASS 53) MIME types need to be parsed and serialized: (/)
PASS 54) MIME types need to be parsed and serialized: ÿ/ÿ
-FAIL 55) MIME types need to be parsed and serialized: text/html(;doesnot=matter assert_equals: expected "application/octet-stream" but got "text/html("
+PASS 55) MIME types need to be parsed and serialized: text/html(;doesnot=matter
FAIL 56) MIME types need to be parsed and serialized: {/} assert_equals: expected "application/octet-stream" but got "{/}"
PASS 57) MIME types need to be parsed and serialized: Ā/Ā
Modified: trunk/Source/WebCore/ChangeLog (240330 => 240331)
--- trunk/Source/WebCore/ChangeLog 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Source/WebCore/ChangeLog 2019-01-23 11:32:55 UTC (rev 240331)
@@ -1,3 +1,50 @@
+2019-01-23 Rob Buis <[email protected]>
+
+ Update MIME type parser
+ https://bugs.webkit.org/show_bug.cgi?id=180526
+
+ Reviewed by Frédéric Wang.
+
+ Add an enum to allow two modes of MIME type parsing, one mode
+ to keep supporting RFC2045 as before, and one mode to support
+ the updated MIME parser from mimesniff [1]. Mimesniff support
+ brings the following changes:
+ - allows parameter names without matching =value.
+ - skips whitespace after subtype, parameter value and before
+ parameter name.
+ - lower cases MIME type and parameter name.
+ - parameter names parsed before are discarded.
+
+ The old mode is still used by CDM.cpp and MIMEHeader.cpp.
+
+ [1] https://mimesniff.spec.whatwg.org/
+
+ * Modules/encryptedmedia/CDM.cpp:
+ (WebCore::CDM::getSupportedCapabilitiesForAudioVideoType):
+ * platform/network/MIMEHeader.cpp:
+ (WebCore::MIMEHeader::parseHeader):
+ * platform/network/ParsedContentType.cpp:
+ (WebCore::DummyParsedContentType::setContentType const):
+ (WebCore::DummyParsedContentType::setContentTypeParameter const):
+ (WebCore::isQuotedStringTokenCharacter):
+ (WebCore::isTokenCharacter):
+ (WebCore::parseToken):
+ (WebCore::containsNonTokenCharacters):
+ (WebCore::parseQuotedString):
+ (WebCore::isNotForwardSlash):
+ (WebCore::isNotSemicolon):
+ (WebCore::isNotSemicolonOrEqualSign):
+ (WebCore::parseContentType):
+ (WebCore::isValidContentType):
+ (WebCore::ParsedContentType::ParsedContentType):
+ (WebCore::ParsedContentType::setContentType):
+ (WebCore::isNonTokenCharacter):
+ (WebCore::isNonQuotedStringTokenCharacter):
+ (WebCore::ParsedContentType::setContentTypeParameter):
+ * platform/network/ParsedContentType.h:
+
+ Test: web-platform-tests/xhr/overridemimetype-blob.html
+
2019-01-22 Wenson Hsieh <[email protected]>
Introduce CustomUndoStep.h and CustomUndoStep.cpp
Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp (240330 => 240331)
--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp 2019-01-23 11:32:55 UTC (rev 240331)
@@ -433,7 +433,7 @@
return WTF::nullopt;
// 3.4. If content type is an invalid or unrecognized MIME type, continue to the next iteration.
- if (!isValidContentType(requestedCapability.contentType))
+ if (!isValidContentType(requestedCapability.contentType, Mode::Rfc2045))
continue;
// 3.5. Let container be the container type specified by content type.
Modified: trunk/Source/WebCore/platform/network/MIMEHeader.cpp (240330 => 240331)
--- trunk/Source/WebCore/platform/network/MIMEHeader.cpp 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Source/WebCore/platform/network/MIMEHeader.cpp 2019-01-23 11:32:55 UTC (rev 240331)
@@ -87,7 +87,7 @@
KeyValueMap keyValuePairs = retrieveKeyValuePairs(buffer);
KeyValueMap::iterator mimeParametersIterator = keyValuePairs.find("content-type");
if (mimeParametersIterator != keyValuePairs.end()) {
- ParsedContentType parsedContentType(mimeParametersIterator->value);
+ ParsedContentType parsedContentType(mimeParametersIterator->value, Mode::Rfc2045);
mimeHeader->m_contentType = parsedContentType.mimeType();
if (!mimeHeader->isMultipart())
mimeHeader->m_charset = parsedContentType.charset().stripWhiteSpace();
Modified: trunk/Source/WebCore/platform/network/ParsedContentType.cpp (240330 => 240331)
--- trunk/Source/WebCore/platform/network/ParsedContentType.cpp 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Source/WebCore/platform/network/ParsedContentType.cpp 2019-01-23 11:32:55 UTC (rev 240331)
@@ -38,8 +38,8 @@
class DummyParsedContentType {
public:
- void setContentType(const SubstringRange&) const { }
- void setContentTypeParameter(const SubstringRange&, const SubstringRange&) const { }
+ void setContentType(const SubstringRange&, Mode) const { }
+ void setContentTypeParameter(const String&, const String&, Mode) const { }
};
static void skipSpaces(const String& input, unsigned& startIndex)
@@ -48,12 +48,19 @@
++startIndex;
}
-static bool isTokenCharacter(char c)
+static bool isQuotedStringTokenCharacter(UChar c)
{
+ return (c >= ' ' && c <= '~') || (c >= 0x80 && c <= 0xFF) || c == '\t';
+}
+
+static bool isTokenCharacter(UChar c)
+{
return isASCII(c) && c > ' ' && c != '"' && c != '(' && c != ')' && c != ',' && c != '/' && (c < ':' || c > '@') && (c < '[' || c > ']');
}
-static Optional<SubstringRange> parseToken(const String& input, unsigned& startIndex)
+using CharacterMeetsCondition = bool (*)(UChar);
+
+static Optional<SubstringRange> parseToken(const String& input, unsigned& startIndex, CharacterMeetsCondition characterMeetsCondition, Mode mode, bool skipTrailingWhitespace = false)
{
unsigned inputLength = input.length();
unsigned tokenStart = startIndex;
@@ -62,8 +69,8 @@
if (tokenEnd >= inputLength)
return WTF::nullopt;
- while (tokenEnd < inputLength) {
- if (!isTokenCharacter(input[tokenEnd]))
+ while (tokenEnd < inputLength && characterMeetsCondition(input[tokenEnd])) {
+ if (mode == Mode::Rfc2045 && !isTokenCharacter(input[tokenEnd]))
break;
++tokenEnd;
}
@@ -70,11 +77,24 @@
if (tokenEnd == tokenStart)
return WTF::nullopt;
+ if (skipTrailingWhitespace) {
+ while (input[tokenEnd - 1] == ' ')
+ --tokenEnd;
+ }
return SubstringRange(tokenStart, tokenEnd - tokenStart);
}
-static Optional<SubstringRange> parseQuotedString(const String& input, unsigned& startIndex)
+static bool containsNonTokenCharacters(const String& input, SubstringRange range)
{
+ for (unsigned index = 0; index < range.second; ++index) {
+ if (!isTokenCharacter(input[range.first + index]))
+ return true;
+ }
+ return false;
+}
+
+static Optional<SubstringRange> parseQuotedString(const String& input, unsigned& startIndex, Mode mode)
+{
unsigned inputLength = input.length();
unsigned quotedStringStart = startIndex + 1;
unsigned& quotedStringEnd = startIndex;
@@ -88,8 +108,11 @@
bool lastCharacterWasBackslash = false;
char currentCharacter;
while ((currentCharacter = input[quotedStringEnd++]) != '"' || lastCharacterWasBackslash) {
- if (quotedStringEnd >= inputLength)
- return WTF::nullopt;
+ if (quotedStringEnd >= inputLength) {
+ if (mode == Mode::Rfc2045)
+ return WTF::nullopt;
+ break;
+ }
if (currentCharacter == '\\' && !lastCharacterWasBackslash) {
lastCharacterWasBackslash = true;
continue;
@@ -151,8 +174,23 @@
// ; Must be in quoted-string,
// ; to use within parameter values
+static bool isNotForwardSlash(UChar ch)
+{
+ return ch != '/';
+}
+
+static bool isNotSemicolon(UChar ch)
+{
+ return ch != ';';
+}
+
+static bool isNotSemicolonOrEqualSign(UChar ch)
+{
+ return ch != ';' && ch != '=';
+}
+
template <class ReceiverType>
-bool parseContentType(const String& contentType, ReceiverType& receiver)
+bool parseContentType(const String& contentType, ReceiverType& receiver, Mode mode)
{
unsigned index = 0;
unsigned contentTypeLength = contentType.length();
@@ -163,8 +201,8 @@
}
unsigned contentTypeStart = index;
- auto typeRange = parseToken(contentType, index);
- if (!typeRange) {
+ auto typeRange = parseToken(contentType, index, isNotForwardSlash, mode);
+ if (!typeRange || containsNonTokenCharacters(contentType, *typeRange)) {
LOG_ERROR("Invalid Content-Type, invalid type value.");
return false;
}
@@ -174,8 +212,8 @@
return false;
}
- auto subTypeRange = parseToken(contentType, index);
- if (!subTypeRange) {
+ auto subTypeRange = parseToken(contentType, index, isNotSemicolon, mode, mode == Mode::MimeSniff);
+ if (!subTypeRange || containsNonTokenCharacters(contentType, *subTypeRange)) {
LOG_ERROR("Invalid Content-Type, invalid subtype value.");
return false;
}
@@ -183,33 +221,47 @@
// There should not be any quoted strings until we reach the parameters.
size_t semiColonIndex = contentType.find(';', contentTypeStart);
if (semiColonIndex == notFound) {
- receiver.setContentType(SubstringRange(contentTypeStart, contentTypeLength - contentTypeStart));
+ receiver.setContentType(SubstringRange(contentTypeStart, contentTypeLength - contentTypeStart), mode);
return true;
}
- receiver.setContentType(SubstringRange(contentTypeStart, semiColonIndex - contentTypeStart));
+ receiver.setContentType(SubstringRange(contentTypeStart, semiColonIndex - contentTypeStart), mode);
index = semiColonIndex + 1;
while (true) {
skipSpaces(contentType, index);
- auto keyRange = parseToken(contentType, index);
- if (!keyRange || index >= contentTypeLength) {
+ auto keyRange = parseToken(contentType, index, isNotSemicolonOrEqualSign, mode);
+ if (mode == Mode::Rfc2045 && (!keyRange || index >= contentTypeLength)) {
LOG_ERROR("Invalid Content-Type parameter name.");
return false;
}
// Should we tolerate spaces here?
- if (contentType[index++] != '=' || index >= contentTypeLength) {
- LOG_ERROR("Invalid Content-Type malformed parameter.");
- return false;
+ if (mode == Mode::Rfc2045) {
+ if (contentType[index++] != '=' || index >= contentTypeLength) {
+ LOG_ERROR("Invalid Content-Type malformed parameter.");
+ return false;
+ }
+ } else {
+ if (index >= contentTypeLength)
+ break;
+ if (contentType[index] != '=' && contentType[index] != ';') {
+ LOG_ERROR("Invalid Content-Type malformed parameter.");
+ return false;
+ }
+ if (contentType[index++] == ';')
+ continue;
}
+ String parameterName = substringForRange(contentType, *keyRange);
+
// Should we tolerate spaces here?
- String value;
Optional<SubstringRange> valueRange;
- if (contentType[index] == '"')
- valueRange = parseQuotedString(contentType, index);
- else
- valueRange = parseToken(contentType, index);
+ if (contentType[index] == '"') {
+ valueRange = parseQuotedString(contentType, index, mode);
+ if (mode == Mode::MimeSniff)
+ parseToken(contentType, index, isNotSemicolon, mode);
+ } else
+ valueRange = parseToken(contentType, index, isNotSemicolon, mode, mode == Mode::MimeSniff);
if (!valueRange) {
LOG_ERROR("Invalid Content-Type, invalid parameter value.");
@@ -216,13 +268,14 @@
return false;
}
+ String parameterValue = substringForRange(contentType, *valueRange);
// Should we tolerate spaces here?
- if (index < contentTypeLength && contentType[index++] != ';') {
+ if (mode == Mode::Rfc2045 && index < contentTypeLength && contentType[index++] != ';') {
LOG_ERROR("Invalid Content-Type, invalid character at the end of key/value parameter.");
return false;
}
- receiver.setContentTypeParameter(*keyRange, *valueRange);
+ receiver.setContentTypeParameter(parameterName, parameterValue, mode);
if (index >= contentTypeLength)
return true;
@@ -231,19 +284,19 @@
return true;
}
-bool isValidContentType(const String& contentType)
+bool isValidContentType(const String& contentType, Mode mode)
{
if (contentType.contains('\r') || contentType.contains('\n'))
return false;
DummyParsedContentType parsedContentType = DummyParsedContentType();
- return parseContentType<DummyParsedContentType>(contentType, parsedContentType);
+ return parseContentType<DummyParsedContentType>(contentType, parsedContentType, mode);
}
-ParsedContentType::ParsedContentType(const String& contentType)
+ParsedContentType::ParsedContentType(const String& contentType, Mode mode)
: m_contentType(contentType.stripWhiteSpace())
{
- parseContentType<ParsedContentType>(m_contentType, *this);
+ parseContentType<ParsedContentType>(m_contentType, *this, mode);
}
String ParsedContentType::charset() const
@@ -261,14 +314,31 @@
return m_parameters.size();
}
-void ParsedContentType::setContentType(const SubstringRange& contentRange)
+void ParsedContentType::setContentType(const SubstringRange& contentRange, Mode mode)
{
m_mimeType = substringForRange(m_contentType, contentRange).stripWhiteSpace();
+ if (mode == Mode::MimeSniff)
+ m_mimeType.convertToASCIILowercase();
}
-void ParsedContentType::setContentTypeParameter(const SubstringRange& key, const SubstringRange& value)
+static bool isNonTokenCharacter(UChar ch)
{
- m_parameters.set(substringForRange(m_contentType, key), substringForRange(m_contentType, value));
+ return !isTokenCharacter(ch);
}
+static bool isNonQuotedStringTokenCharacter(UChar ch)
+{
+ return !isQuotedStringTokenCharacter(ch);
}
+
+void ParsedContentType::setContentTypeParameter(const String& keyName, const String& keyValue, Mode mode)
+{
+ if (mode == Mode::MimeSniff) {
+ if (m_parameters.contains(keyName) || keyName.find(isNonTokenCharacter) != notFound || keyValue.find(isNonQuotedStringTokenCharacter) != notFound)
+ return;
+ keyName.convertToASCIILowercase();
+ }
+ m_parameters.set(keyName, keyValue);
+}
+
+}
Modified: trunk/Source/WebCore/platform/network/ParsedContentType.h (240330 => 240331)
--- trunk/Source/WebCore/platform/network/ParsedContentType.h 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Source/WebCore/platform/network/ParsedContentType.h 2019-01-23 11:32:55 UTC (rev 240331)
@@ -36,14 +36,18 @@
namespace WebCore {
+enum class Mode {
+ Rfc2045,
+ MimeSniff
+};
// <index, length>
typedef std::pair<unsigned, unsigned> SubstringRange;
-bool isValidContentType(const String&);
+WEBCORE_EXPORT bool isValidContentType(const String&, Mode = Mode::MimeSniff);
// FIXME: add support for comments.
class ParsedContentType {
public:
- explicit ParsedContentType(const String&);
+ explicit ParsedContentType(const String&, Mode = Mode::MimeSniff);
String mimeType() const { return m_mimeType; }
String charset() const;
@@ -54,9 +58,9 @@
private:
template<class ReceiverType>
- friend bool parseContentType(const String&, ReceiverType&);
- void setContentType(const SubstringRange&);
- void setContentTypeParameter(const SubstringRange&, const SubstringRange&);
+ friend bool parseContentType(const String&, ReceiverType&, Mode);
+ void setContentType(const SubstringRange&, Mode);
+ void setContentTypeParameter(const String&, const String&, Mode);
typedef HashMap<String, String> KeyValuePairs;
String m_contentType;
Modified: trunk/Tools/ChangeLog (240330 => 240331)
--- trunk/Tools/ChangeLog 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Tools/ChangeLog 2019-01-23 11:32:55 UTC (rev 240331)
@@ -1,3 +1,16 @@
+2019-01-23 Rob Buis <[email protected]>
+
+ Update MIME type parser
+ https://bugs.webkit.org/show_bug.cgi?id=180526
+
+ Reviewed by Frédéric Wang.
+
+ Add unit tests for both parse modes of ParsedContentType.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebCore/ParsedContentType.cpp: Added.
+ (TestWebKitAPI::TEST):
+
2019-01-22 Aakash Jain <[email protected]>
[ews-app] fetch loop should not stop on network issues
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (240330 => 240331)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-01-23 10:12:56 UTC (rev 240330)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-01-23 11:32:55 UTC (rev 240331)
@@ -696,6 +696,7 @@
A5A729F11F622AA700DE5A28 /* WKNavigationResponse.mm in Sources */ = {isa = PBXBuildFile; fileRef = A5A729F01F622A9A00DE5A28 /* WKNavigationResponse.mm */; };
A5B149DE1F5A19EA00C6DAFF /* MIMETypeRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5B149DD1F5A19DC00C6DAFF /* MIMETypeRegistry.cpp */; };
A5E2027515B21F6E00C13E14 /* WindowlessWebViewWithMedia.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = A5E2027015B2180600C13E14 /* WindowlessWebViewWithMedia.html */; };
+ AA96CAB621C7DB5000FD2F97 /* ParsedContentType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA96CAB421C7DB4200FD2F97 /* ParsedContentType.cpp */; };
AD57AC201DA7465000FF1BDE /* DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD57AC1E1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp */; };
AD57AC211DA7465B00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD57AC1F1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp */; };
AD57AC221DA7466E00FF1BDE /* many-iframes.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = AD57AC1D1DA7463800FF1BDE /* many-iframes.html */; };
@@ -1929,6 +1930,7 @@
A5E2027015B2180600C13E14 /* WindowlessWebViewWithMedia.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = WindowlessWebViewWithMedia.html; sourceTree = "<group>"; };
A5E2027215B2181900C13E14 /* WindowlessWebViewWithMedia.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowlessWebViewWithMedia.mm; sourceTree = "<group>"; };
A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CheckedArithmeticOperations.cpp; sourceTree = "<group>"; };
+ AA96CAB421C7DB4200FD2F97 /* ParsedContentType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedContentType.cpp; sourceTree = "<group>"; };
ABF510632A19B8AC7EC40E17 /* AbortableTaskQueue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AbortableTaskQueue.cpp; sourceTree = "<group>"; };
AD57AC1D1DA7463800FF1BDE /* many-iframes.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "many-iframes.html"; sourceTree = "<group>"; };
AD57AC1E1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp; sourceTree = "<group>"; };
@@ -2695,6 +2697,7 @@
CE1866471F72E8F100A0CAB6 /* MarkedText.cpp */,
A5B149DD1F5A19DC00C6DAFF /* MIMETypeRegistry.cpp */,
CD225C071C45A69200140761 /* ParsedContentRange.cpp */,
+ AA96CAB421C7DB4200FD2F97 /* ParsedContentType.cpp */,
041A1E33216FFDBC00789E0A /* PublicSuffix.cpp */,
F418BE141F71B7DC001970E6 /* RoundedRectTests.cpp */,
CDCFA7A91E45122F00C2433D /* SampleMap.cpp */,
@@ -4132,6 +4135,7 @@
7CCE7EC71A411A7E00447C4C /* PageVisibilityStateWithWindowChanges.mm in Sources */,
7CCE7F091A411AE600447C4C /* ParentFrame.cpp in Sources */,
7C83E0511D0A641800FEBCF3 /* ParsedContentRange.cpp in Sources */,
+ AA96CAB621C7DB5000FD2F97 /* ParsedContentType.cpp in Sources */,
F44C79FF20F9E8710014478C /* ParserYieldTokenTests.mm in Sources */,
7CCE7F0A1A411AE600447C4C /* PasteboardNotifications.mm in Sources */,
9BCB7C2820130600003E7C0C /* PasteHTML.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentType.cpp (0 => 240331)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentType.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentType.cpp 2019-01-23 11:32:55 UTC (rev 240331)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 Igalia, S.L. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <WebCore/ParsedContentType.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(ParsedContentType, MimeSniff)
+{
+ EXPECT_TRUE(isValidContentType("text/plain", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType(" text/plain", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType(" text/plain ", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("text /plain", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("text/ plain", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("text / plain", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("te xt/plain", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("text/pla in", Mode::MimeSniff));
+
+ EXPECT_FALSE(isValidContentType("text", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("text/", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("/plain", Mode::MimeSniff));
+
+ EXPECT_TRUE(isValidContentType("text/plain;", Mode::MimeSniff));
+
+ EXPECT_TRUE(isValidContentType("text/plain;test", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain; test", Mode::MimeSniff));
+ EXPECT_FALSE(isValidContentType("text/plain;test=", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test=value", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain; test=value", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test =value", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test= value", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test=value ", Mode::MimeSniff));
+
+ EXPECT_TRUE(isValidContentType("text/plain;test=\"value\"", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test=\"value", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test=\"value\"foo", Mode::MimeSniff));
+ EXPECT_TRUE(isValidContentType("text/plain;test=\"value\"foo;foo=bar", Mode::MimeSniff));
+}
+
+TEST(ParsedContentType, Rfc2045)
+{
+ EXPECT_TRUE(isValidContentType("text/plain", Mode::Rfc2045));
+ EXPECT_TRUE(isValidContentType(" text/plain", Mode::Rfc2045));
+ EXPECT_TRUE(isValidContentType(" text/plain ", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text /plain", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/ plain", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text / plain", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("te xt/plain", Mode::Rfc2045));
+ EXPECT_TRUE(isValidContentType("text/pla in", Mode::Rfc2045));
+
+ EXPECT_FALSE(isValidContentType("text", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("/plain", Mode::Rfc2045));
+
+ EXPECT_FALSE(isValidContentType("text/plain;", Mode::Rfc2045));
+
+ EXPECT_FALSE(isValidContentType("text/plain;test", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain; test", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test=", Mode::Rfc2045));
+ EXPECT_TRUE(isValidContentType("text/plain;test=value", Mode::Rfc2045));
+ EXPECT_TRUE(isValidContentType("text/plain; test=value", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test =value", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test= value", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test=value ", Mode::Rfc2045));
+
+ EXPECT_TRUE(isValidContentType("text/plain;test=\"value\"", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test=\"value", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test=\"value\"foo", Mode::Rfc2045));
+ EXPECT_FALSE(isValidContentType("text/plain;test=\"value\"foo;foo=bar", Mode::Rfc2045));
+}
+
+} // namespace TestWebKitAPI