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

Side by Side 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: address mmenke's comments Created 4 years, 8 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The rules for parsing content-types were borrowed from Firefox: 5 // The rules for parsing content-types were borrowed from Firefox:
6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834
7 7
8 #include "net/http/http_util.h" 8 #include "net/http/http_util.h"
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 } 494 }
495 return unescaped; 495 return unescaped;
496 } 496 }
497 497
498 // static 498 // static
499 std::string HttpUtil::Unquote(const std::string& str) { 499 std::string HttpUtil::Unquote(const std::string& str) {
500 return Unquote(str.begin(), str.end()); 500 return Unquote(str.begin(), str.end());
501 } 501 }
502 502
503 // static 503 // static
504 bool HttpUtil::StrictUnquote(std::string::const_iterator begin,
mmenke 2016/04/26 18:05:57 Hrm...Should this and Unquote share an implementat
Marijn Kruisselbrink 2016/04/27 01:49:49 Good idea. Done.
505 std::string::const_iterator end,
506 std::string* out) {
507 // Empty string
508 if (begin == end)
509 return false;
510
511 // Nothing to unquote.
512 if (!IsQuote(*begin))
513 return false;
514
515 // No terminal quote mark.
516 if (end - begin < 2 || *begin != *(end - 1))
517 return false;
518
519 char quote = *begin;
520
521 // Strip quotemarks
522 ++begin;
523 --end;
524
525 // Terminal quote is escaped.
526 if (begin != end && *(end - 1) == '\\')
mmenke 2016/04/26 18:05:57 BUG: "\\" is valid. Instead, should have a "prev
Marijn Kruisselbrink 2016/04/27 01:49:49 Yeah, just caught that myself too. Added a test an
527 return false;
528
529 // Unescape quoted-pair (defined in RFC 2616 section 2.2)
530 bool prev_escape = false;
531 std::string unescaped;
532 for (; begin != end; ++begin) {
533 char c = *begin;
534 if (c == '\\' && !prev_escape) {
535 prev_escape = true;
536 continue;
537 }
538 if (!prev_escape && c == quote)
539 return false;
540 prev_escape = false;
541 unescaped.push_back(c);
542 }
543 *out = std::move(unescaped);
544 return true;
545 }
546
547 // static
548 bool HttpUtil::StrictUnquote(const std::string& str, std::string* out) {
549 return StrictUnquote(str.begin(), str.end(), out);
550 }
551
552 // static
504 std::string HttpUtil::Quote(const std::string& str) { 553 std::string HttpUtil::Quote(const std::string& str) {
505 std::string escaped; 554 std::string escaped;
506 escaped.reserve(2 + str.size()); 555 escaped.reserve(2 + str.size());
507 556
508 std::string::const_iterator begin = str.begin(); 557 std::string::const_iterator begin = str.begin();
509 std::string::const_iterator end = str.end(); 558 std::string::const_iterator end = str.end();
510 559
511 // Esape any backslashes or quotemarks within the string, and 560 // Esape any backslashes or quotemarks within the string, and
512 // then surround with quotes. 561 // then surround with quotes.
513 escaped.push_back('"'); 562 escaped.push_back('"');
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 if (value_begin_ != value_end_) 952 if (value_begin_ != value_end_)
904 return true; 953 return true;
905 } 954 }
906 return false; 955 return false;
907 } 956 }
908 957
909 HttpUtil::NameValuePairsIterator::NameValuePairsIterator( 958 HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
910 std::string::const_iterator begin, 959 std::string::const_iterator begin,
911 std::string::const_iterator end, 960 std::string::const_iterator end,
912 char delimiter, 961 char delimiter,
913 OptionalValues optional_values) 962 Values optional_values,
963 Quotes strict_quotes)
914 : props_(begin, end, delimiter), 964 : props_(begin, end, delimiter),
915 valid_(true), 965 valid_(true),
916 name_begin_(end), 966 name_begin_(end),
917 name_end_(end), 967 name_end_(end),
918 value_begin_(end), 968 value_begin_(end),
919 value_end_(end), 969 value_end_(end),
920 value_is_quoted_(false), 970 value_is_quoted_(false),
921 values_optional_(optional_values == VALUES_OPTIONAL) {} 971 values_optional_(optional_values == Values::OPTIONAL),
972 strict_quotes_(strict_quotes == Quotes::STRICT) {}
922 973
923 HttpUtil::NameValuePairsIterator::NameValuePairsIterator( 974 HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
924 std::string::const_iterator begin, 975 std::string::const_iterator begin,
925 std::string::const_iterator end, 976 std::string::const_iterator end,
926 char delimiter) 977 char delimiter)
927 : NameValuePairsIterator(begin, end, delimiter, VALUES_NOT_OPTIONAL) {} 978 : NameValuePairsIterator(begin,
979 end,
980 delimiter,
981 Values::NOT_OPTIONAL,
982 Quotes::NOT_STRICT) {}
928 983
929 HttpUtil::NameValuePairsIterator::NameValuePairsIterator( 984 HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
930 const NameValuePairsIterator& other) = default; 985 const NameValuePairsIterator& other) = default;
931 986
932 HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() {} 987 HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() {}
933 988
934 // We expect properties to be formatted as one of: 989 // We expect properties to be formatted as one of:
935 // name="value" 990 // name="value"
936 // name='value' 991 // name='value'
937 // name='\'value\'' 992 // name='\'value\''
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 TrimLWS(&name_begin_, &name_end_); 1027 TrimLWS(&name_begin_, &name_end_);
973 TrimLWS(&value_begin_, &value_end_); 1028 TrimLWS(&value_begin_, &value_end_);
974 value_is_quoted_ = false; 1029 value_is_quoted_ = false;
975 unquoted_value_.clear(); 1030 unquoted_value_.clear();
976 1031
977 if (equals != value_end_ && value_begin_ == value_end_) { 1032 if (equals != value_end_ && value_begin_ == value_end_) {
978 // Malformed; value is empty 1033 // Malformed; value is empty
979 return valid_ = false; 1034 return valid_ = false;
980 } 1035 }
981 1036
982 if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) { 1037 if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) {
mmenke 2016/04/26 18:05:57 So strict mode fails on foo='bar but succeeds on f
Marijn Kruisselbrink 2016/04/27 01:49:49 Argh, excellent question... And not really somethi
1038 value_is_quoted_ = true;
1039
1040 if (strict_quotes_) {
1041 if (!HttpUtil::StrictUnquote(value_begin_, value_end_, &unquoted_value_))
1042 return valid_ = false;
1043 return true;
1044 }
1045
983 // Trim surrounding quotemarks off the value 1046 // Trim surrounding quotemarks off the value
984 if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) { 1047 if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) {
985 // NOTE: This is not as graceful as it sounds: 1048 // NOTE: This is not as graceful as it sounds:
986 // * quoted-pairs will no longer be unquoted 1049 // * quoted-pairs will no longer be unquoted
987 // (["\"hello] should give ["hello]). 1050 // (["\"hello] should give ["hello]).
988 // * Does not detect when the final quote is escaped 1051 // * Does not detect when the final quote is escaped
989 // (["value\"] should give [value"]) 1052 // (["value\"] should give [value"])
1053 value_is_quoted_ = false;
990 ++value_begin_; // Gracefully recover from mismatching quotes. 1054 ++value_begin_; // Gracefully recover from mismatching quotes.
991 } else { 1055 } else {
992 value_is_quoted_ = true;
993 // Do not store iterators into this. See declaration of unquoted_value_. 1056 // Do not store iterators into this. See declaration of unquoted_value_.
994 unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_); 1057 unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_);
995 } 1058 }
996 } 1059 }
997 1060
998 return true; 1061 return true;
999 } 1062 }
1000 1063
1001 } // namespace net 1064 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698