Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Unified Diff: net/http/http_util.cc

Issue 1811163002: Share link header parsing code between blink and content. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@base-optional
Patch Set: rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_util.h ('k') | net/http/http_util_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_util.cc
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index 932f8386dadc401914a559f20805b951f66876cb..06fc15edd3668e367d0551cf4314de04beb73c65 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -445,54 +445,99 @@ bool HttpUtil::IsQuote(char c) {
return c == '"' || c == '\'';
}
+namespace {
+bool IsTokenChar(unsigned char c) {
+ return !(c >= 0x80 || c <= 0x1F || c == 0x7F || c == '(' || c == ')' ||
+ c == '<' || c == '>' || c == '@' || c == ',' || c == ';' ||
+ c == ':' || c == '\\' || c == '"' || c == '/' || c == '[' ||
+ c == ']' || c == '?' || c == '=' || c == '{' || c == '}' ||
+ c == ' ' || c == '\t');
+}
+} // anonymous namespace
+
// See RFC 2616 Sec 2.2 for the definition of |token|.
bool HttpUtil::IsToken(std::string::const_iterator begin,
std::string::const_iterator end) {
if (begin == end)
return false;
for (std::string::const_iterator iter = begin; iter != end; ++iter) {
+ if (!IsTokenChar(*iter))
+ return false;
+ }
+ return true;
+}
+
+// See RFC 5987 Sec 3.2.1 for the definition of |parmname|.
+bool HttpUtil::IsParmName(std::string::const_iterator begin,
+ std::string::const_iterator end) {
+ if (begin == end)
+ return false;
+ for (std::string::const_iterator iter = begin; iter != end; ++iter) {
unsigned char c = *iter;
- if (c >= 0x80 || c <= 0x1F || c == 0x7F ||
- c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
- c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' ||
- c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
- c == '{' || c == '}' || c == ' ' || c == '\t')
+ if (!IsTokenChar(c) || c == '*' || c == '\'' || c == '%')
return false;
}
return true;
}
-std::string HttpUtil::Unquote(std::string::const_iterator begin,
- std::string::const_iterator end) {
+namespace {
+bool UnquoteImpl(std::string::const_iterator begin,
+ std::string::const_iterator end,
+ bool strict_quotes,
+ std::string* out) {
// Empty string
if (begin == end)
- return std::string();
+ return false;
// Nothing to unquote.
- if (!IsQuote(*begin))
- return std::string(begin, end);
+ if (!HttpUtil::IsQuote(*begin))
+ return false;
+
+ // Anything other than double quotes in strict mode.
+ if (strict_quotes && *begin != '"')
+ return false;
// No terminal quote mark.
if (end - begin < 2 || *begin != *(end - 1))
- return std::string(begin, end);
+ return false;
+
+ char quote = *begin;
// Strip quotemarks
++begin;
--end;
// Unescape quoted-pair (defined in RFC 2616 section 2.2)
- std::string unescaped;
bool prev_escape = false;
+ std::string unescaped;
for (; begin != end; ++begin) {
char c = *begin;
if (c == '\\' && !prev_escape) {
prev_escape = true;
continue;
}
+ if (strict_quotes && !prev_escape && c == quote)
+ return false;
prev_escape = false;
unescaped.push_back(c);
}
- return unescaped;
+
+ // Terminal quote is escaped.
+ if (strict_quotes && prev_escape)
+ return false;
+
+ *out = std::move(unescaped);
+ return true;
+}
+} // anonymous namespace
+
+std::string HttpUtil::Unquote(std::string::const_iterator begin,
+ std::string::const_iterator end) {
+ std::string result;
+ if (!UnquoteImpl(begin, end, false, &result))
+ return std::string(begin, end);
+
+ return result;
}
// static
@@ -501,6 +546,18 @@ 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) {
+ return UnquoteImpl(begin, end, true, out);
+}
+
+// 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 +967,8 @@ HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
std::string::const_iterator begin,
std::string::const_iterator end,
char delimiter,
- OptionalValues optional_values)
+ Values optional_values,
+ Quotes strict_quotes)
: props_(begin, end, delimiter),
valid_(true),
name_begin_(end),
@@ -918,13 +976,21 @@ HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
value_begin_(end),
value_end_(end),
value_is_quoted_(false),
- values_optional_(optional_values == VALUES_OPTIONAL) {}
+ values_optional_(optional_values == Values::NOT_REQUIRED),
+ strict_quotes_(strict_quotes == Quotes::STRICT_QUOTES) {
+ if (strict_quotes_)
+ props_.set_quote_chars("\"");
+}
HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
std::string::const_iterator begin,
std::string::const_iterator end,
char delimiter)
- : NameValuePairsIterator(begin, end, delimiter, VALUES_NOT_OPTIONAL) {}
+ : NameValuePairsIterator(begin,
+ end,
+ delimiter,
+ Values::REQUIRED,
+ Quotes::NOT_STRICT) {}
HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
const NameValuePairsIterator& other) = default;
@@ -960,7 +1026,7 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
// If an equals sign was found, verify that it wasn't inside of quote marks.
if (equals != value_end_) {
for (std::string::const_iterator it = value_begin_; it != equals; ++it) {
- if (HttpUtil::IsQuote(*it))
+ if (IsQuote(*it))
return valid_ = false; // Malformed, quote appears before equals sign
}
}
@@ -979,7 +1045,15 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
return valid_ = false;
}
- if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) {
+ if (value_begin_ != value_end_ && IsQuote(*value_begin_)) {
+ value_is_quoted_ = true;
+
+ if (strict_quotes_) {
+ if (!HttpUtil::StrictUnquote(value_begin_, value_end_, &unquoted_value_))
+ return valid_ = false;
+ return true;
+ }
+
// Trim surrounding quotemarks off the value
if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) {
// NOTE: This is not as graceful as it sounds:
@@ -987,9 +1061,9 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
// (["\"hello] should give ["hello]).
// * Does not detect when the final quote is escaped
// (["value\"] should give [value"])
+ value_is_quoted_ = false;
++value_begin_; // Gracefully recover from mismatching quotes.
} else {
- value_is_quoted_ = true;
// Do not store iterators into this. See declaration of unquoted_value_.
unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_);
}
@@ -998,4 +1072,10 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
return true;
}
+bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const {
+ if (strict_quotes_)
+ return c == '"';
+ return HttpUtil::IsQuote(c);
+}
+
} // namespace net
« no previous file with comments | « net/http/http_util.h ('k') | net/http/http_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698