OLD | NEW |
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 Loading... |
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, |
| 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) == '\\') |
| 527 return false; |
| 528 |
| 529 // Unescape quoted-pair (defined in RFC 2616 section 2.2) |
| 530 bool prev_escape = false; |
| 531 out->clear(); |
| 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 } |
| 541 prev_escape = false; |
| 542 out->push_back(c); |
| 543 } |
| 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 Loading... |
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 OptionalValues optional_values, |
| 963 StrictQuotes 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 == STRICT_QUOTES) {} |
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, end, delimiter, VALUES_NOT_OPTIONAL) {} |
928 | 979 |
929 HttpUtil::NameValuePairsIterator::NameValuePairsIterator( | 980 HttpUtil::NameValuePairsIterator::NameValuePairsIterator( |
930 const NameValuePairsIterator& other) = default; | 981 const NameValuePairsIterator& other) = default; |
931 | 982 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 | 1032 |
982 if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) { | 1033 if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) { |
983 // Trim surrounding quotemarks off the value | 1034 // Trim surrounding quotemarks off the value |
984 if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) { | 1035 if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) { |
985 // NOTE: This is not as graceful as it sounds: | 1036 // NOTE: This is not as graceful as it sounds: |
986 // * quoted-pairs will no longer be unquoted | 1037 // * quoted-pairs will no longer be unquoted |
987 // (["\"hello] should give ["hello]). | 1038 // (["\"hello] should give ["hello]). |
988 // * Does not detect when the final quote is escaped | 1039 // * Does not detect when the final quote is escaped |
989 // (["value\"] should give [value"]) | 1040 // (["value\"] should give [value"]) |
990 ++value_begin_; // Gracefully recover from mismatching quotes. | 1041 ++value_begin_; // Gracefully recover from mismatching quotes. |
| 1042 |
| 1043 // If requiring string quotes, this is an error. |
| 1044 if (strict_quotes_) |
| 1045 return valid_ = false; |
991 } else { | 1046 } else { |
992 value_is_quoted_ = true; | 1047 value_is_quoted_ = true; |
993 // Do not store iterators into this. See declaration of unquoted_value_. | 1048 // Do not store iterators into this. See declaration of unquoted_value_. |
994 unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_); | 1049 if (strict_quotes_) { |
| 1050 if (!HttpUtil::StrictUnquote(value_begin_, value_end_, |
| 1051 &unquoted_value_)) |
| 1052 return valid_ = false; |
| 1053 } else { |
| 1054 unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_); |
| 1055 } |
995 } | 1056 } |
996 } | 1057 } |
997 | 1058 |
998 return true; | 1059 return true; |
999 } | 1060 } |
1000 | 1061 |
1001 } // namespace net | 1062 } // namespace net |
OLD | NEW |