| Index: net/http/http_util.cc
|
| diff --git a/net/http/http_util.cc b/net/http/http_util.cc
|
| index 932f8386dadc401914a559f20805b951f66876cb..60d47813495c52b4ddeb1e16b232f3079c45636a 100644
|
| --- a/net/http/http_util.cc
|
| +++ b/net/http/http_util.cc
|
| @@ -501,6 +501,55 @@ std::string HttpUtil::Unquote(const std::string& str) {
|
| }
|
|
|
| // static
|
| +bool HttpUtil::StrictUnquote(std::string::const_iterator begin,
|
| + std::string::const_iterator end,
|
| + std::string* out) {
|
| + // Empty string
|
| + if (begin == end)
|
| + return false;
|
| +
|
| + // Nothing to unquote.
|
| + if (!IsQuote(*begin))
|
| + return false;
|
| +
|
| + // No terminal quote mark.
|
| + if (end - begin < 2 || *begin != *(end - 1))
|
| + return false;
|
| +
|
| + char quote = *begin;
|
| +
|
| + // Strip quotemarks
|
| + ++begin;
|
| + --end;
|
| +
|
| + // Terminal quote is escaped.
|
| + if (begin != end && *(end - 1) == '\\')
|
| + return false;
|
| +
|
| + // Unescape quoted-pair (defined in RFC 2616 section 2.2)
|
| + bool prev_escape = false;
|
| + out->clear();
|
| + for (; begin != end; ++begin) {
|
| + char c = *begin;
|
| + if (c == '\\' && !prev_escape) {
|
| + prev_escape = true;
|
| + continue;
|
| + }
|
| + if (!prev_escape && c == quote) {
|
| + return false;
|
| + }
|
| + prev_escape = false;
|
| + out->push_back(c);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// static
|
| +bool HttpUtil::StrictUnquote(const std::string& str, std::string* out) {
|
| + return StrictUnquote(str.begin(), str.end(), out);
|
| +}
|
| +
|
| +// static
|
| std::string HttpUtil::Quote(const std::string& str) {
|
| std::string escaped;
|
| escaped.reserve(2 + str.size());
|
| @@ -910,7 +959,8 @@ HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
|
| std::string::const_iterator begin,
|
| std::string::const_iterator end,
|
| char delimiter,
|
| - OptionalValues optional_values)
|
| + OptionalValues optional_values,
|
| + StrictQuotes strict_quotes)
|
| : props_(begin, end, delimiter),
|
| valid_(true),
|
| name_begin_(end),
|
| @@ -918,7 +968,8 @@ HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
|
| value_begin_(end),
|
| value_end_(end),
|
| value_is_quoted_(false),
|
| - values_optional_(optional_values == VALUES_OPTIONAL) {}
|
| + values_optional_(optional_values == VALUES_OPTIONAL),
|
| + strict_quotes_(strict_quotes == STRICT_QUOTES) {}
|
|
|
| HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
|
| std::string::const_iterator begin,
|
| @@ -988,10 +1039,20 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
|
| // * Does not detect when the final quote is escaped
|
| // (["value\"] should give [value"])
|
| ++value_begin_; // Gracefully recover from mismatching quotes.
|
| +
|
| + // If requiring string quotes, this is an error.
|
| + if (strict_quotes_)
|
| + return valid_ = false;
|
| } else {
|
| value_is_quoted_ = true;
|
| // Do not store iterators into this. See declaration of unquoted_value_.
|
| - unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_);
|
| + if (strict_quotes_) {
|
| + if (!HttpUtil::StrictUnquote(value_begin_, value_end_,
|
| + &unquoted_value_))
|
| + return valid_ = false;
|
| + } else {
|
| + unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_);
|
| + }
|
| }
|
| }
|
|
|
|
|