| Index: third_party/WebKit/Source/platform/network/ParsedContentType.cpp
|
| diff --git a/third_party/WebKit/Source/platform/network/ParsedContentType.cpp b/third_party/WebKit/Source/platform/network/ParsedContentType.cpp
|
| index 6755f4a8e7adf367380744d3112356209625615e..a80114072d062c8a768c380ee167f06a352e2a50 100644
|
| --- a/third_party/WebKit/Source/platform/network/ParsedContentType.cpp
|
| +++ b/third_party/WebKit/Source/platform/network/ParsedContentType.cpp
|
| @@ -31,148 +31,12 @@
|
|
|
| #include "platform/network/ParsedContentType.h"
|
|
|
| +#include "platform/network/ContentHeaderFieldInput.h"
|
| #include "platform/wtf/text/StringBuilder.h"
|
| #include "platform/wtf/text/StringView.h"
|
|
|
| namespace blink {
|
|
|
| -using Mode = ParsedContentType::Mode;
|
| -
|
| -namespace {
|
| -
|
| -bool IsTokenCharacter(Mode mode, UChar c) {
|
| - if (c >= 128)
|
| - return false;
|
| - if (c < 0x20)
|
| - return false;
|
| -
|
| - switch (c) {
|
| - case ' ':
|
| - case ';':
|
| - case '"':
|
| - return false;
|
| - case '(':
|
| - case ')':
|
| - case '<':
|
| - case '>':
|
| - case '@':
|
| - case ',':
|
| - case ':':
|
| - case '\\':
|
| - case '/':
|
| - case '[':
|
| - case ']':
|
| - case '?':
|
| - case '=':
|
| - return mode == Mode::kRelaxed;
|
| - default:
|
| - return true;
|
| - }
|
| -}
|
| -
|
| -bool Consume(char c, const String& input, unsigned& index) {
|
| - DCHECK_NE(c, ' ');
|
| - while (index < input.length() && input[index] == ' ')
|
| - ++index;
|
| -
|
| - if (index < input.length() && input[index] == c) {
|
| - ++index;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool ConsumeToken(Mode mode,
|
| - const String& input,
|
| - unsigned& index,
|
| - StringView& output) {
|
| - DCHECK(output.IsNull());
|
| -
|
| - while (index < input.length() && input[index] == ' ')
|
| - ++index;
|
| -
|
| - auto start = index;
|
| - while (index < input.length() && IsTokenCharacter(mode, input[index]))
|
| - ++index;
|
| -
|
| - if (start == index)
|
| - return false;
|
| -
|
| - output = StringView(input, start, index - start);
|
| - return true;
|
| -}
|
| -
|
| -bool ConsumeQuotedString(const String& input, unsigned& index, String& output) {
|
| - StringBuilder builder;
|
| - DCHECK_EQ('"', input[index]);
|
| - ++index;
|
| - while (index < input.length()) {
|
| - if (input[index] == '\\') {
|
| - ++index;
|
| - if (index == input.length())
|
| - return false;
|
| - builder.Append(input[index]);
|
| - ++index;
|
| - continue;
|
| - }
|
| - if (input[index] == '"') {
|
| - output = builder.ToString();
|
| - ++index;
|
| - return true;
|
| - }
|
| - builder.Append(input[index]);
|
| - ++index;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool ConsumeTokenOrQuotedString(Mode mode,
|
| - const String& input,
|
| - unsigned& index,
|
| - String& output) {
|
| - while (index < input.length() && input[index] == ' ')
|
| - ++index;
|
| - if (input.length() == index)
|
| - return false;
|
| - if (input[index] == '"') {
|
| - return ConsumeQuotedString(input, index, output);
|
| - }
|
| - StringView view;
|
| - auto result = ConsumeToken(mode, input, index, view);
|
| - output = view.ToString();
|
| - return result;
|
| -}
|
| -
|
| -bool IsEnd(const String& input, unsigned index) {
|
| - while (index < input.length()) {
|
| - if (input[index] != ' ')
|
| - return false;
|
| - ++index;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -ParsedContentType::ParsedContentType(const String& content_type, Mode mode)
|
| - : mode_(mode) {
|
| - is_valid_ = Parse(content_type);
|
| -}
|
| -
|
| -String ParsedContentType::Charset() const {
|
| - return ParameterValueForName("charset");
|
| -}
|
| -
|
| -String ParsedContentType::ParameterValueForName(const String& name) const {
|
| - if (!name.ContainsOnlyASCII())
|
| - return String();
|
| - return parameters_.at(name.DeprecatedLower());
|
| -}
|
| -
|
| -size_t ParsedContentType::ParameterCount() const {
|
| - return parameters_.size();
|
| -}
|
| -
|
| // From http://tools.ietf.org/html/rfc2045#section-5.1:
|
| //
|
| // content := "Content-Type" ":" type "/" subtype
|
| @@ -218,22 +82,21 @@ size_t ParsedContentType::ParameterCount() const {
|
| // "/" / "[" / "]" / "?" / "="
|
| // ; Must be in quoted-string,
|
| // ; to use within parameter values
|
| -
|
| -bool ParsedContentType::Parse(const String& content_type) {
|
| - unsigned index = 0;
|
| +ParsedContentType::ParsedContentType(const String& content_type, Mode mode) {
|
| + ContentHeaderFieldInput input(content_type);
|
|
|
| StringView type, subtype;
|
| - if (!ConsumeToken(Mode::kNormal, content_type, index, type)) {
|
| + if (!input.ConsumeToken(Mode::kNormal, type)) {
|
| DVLOG(1) << "Failed to find `type' in '" << content_type << "'";
|
| - return false;
|
| + return;
|
| }
|
| - if (!Consume('/', content_type, index)) {
|
| + if (!input.Consume('/')) {
|
| DVLOG(1) << "Failed to find '/' in '" << content_type << "'";
|
| - return false;
|
| + return;
|
| }
|
| - if (!ConsumeToken(Mode::kNormal, content_type, index, subtype)) {
|
| - DVLOG(1) << "Failed to find `type' in '" << content_type << "'";
|
| - return false;
|
| + if (!input.ConsumeToken(Mode::kNormal, subtype)) {
|
| + DVLOG(1) << "Failed to find `subtype' in '" << content_type << "'";
|
| + return;
|
| }
|
|
|
| StringBuilder builder;
|
| @@ -242,40 +105,11 @@ bool ParsedContentType::Parse(const String& content_type) {
|
| builder.Append(subtype);
|
| mime_type_ = builder.ToString();
|
|
|
| - KeyValuePairs map;
|
| - while (!IsEnd(content_type, index)) {
|
| - if (!Consume(';', content_type, index)) {
|
| - DVLOG(1) << "Failed to find ';'";
|
| - return false;
|
| - }
|
| + parameters_.ParseParameters(std::move(input), mode);
|
| +}
|
|
|
| - StringView key;
|
| - String value;
|
| - if (!ConsumeToken(Mode::kNormal, content_type, index, key)) {
|
| - DVLOG(1) << "Invalid Content-Type parameter name. (at " << index << ")";
|
| - return false;
|
| - }
|
| - if (!Consume('=', content_type, index)) {
|
| - DVLOG(1) << "Failed to find '='";
|
| - return false;
|
| - }
|
| - if (!ConsumeTokenOrQuotedString(mode_, content_type, index, value)) {
|
| - DVLOG(1) << "Invalid Content-Type, invalid parameter value (at " << index
|
| - << ", for '" << key.ToString() << "').";
|
| - return false;
|
| - }
|
| - // As |key| is parsed as a token, it consists of ascii characters
|
| - // and hence we don't need to care about non-ascii lowercasing.
|
| - DCHECK(key.ToString().ContainsOnlyASCII());
|
| - String key_string = key.ToString().DeprecatedLower();
|
| - if (mode_ == Mode::kStrict && map.find(key_string) != map.end()) {
|
| - DVLOG(1) << "Parameter " << key_string << " is defined multiple times.";
|
| - return false;
|
| - }
|
| - map.Set(key_string, value);
|
| - }
|
| - parameters_ = std::move(map);
|
| - return true;
|
| +String ParsedContentType::Charset() const {
|
| + return ParameterValueForName("charset");
|
| }
|
|
|
| } // namespace blink
|
|
|