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_); |
+ } |
} |
} |