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 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 | 1042 |
1043 return true; | 1043 return true; |
1044 } | 1044 } |
1045 | 1045 |
1046 bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const { | 1046 bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const { |
1047 if (strict_quotes_) | 1047 if (strict_quotes_) |
1048 return c == '"'; | 1048 return c == '"'; |
1049 return HttpUtil::IsQuote(c); | 1049 return HttpUtil::IsQuote(c); |
1050 } | 1050 } |
1051 | 1051 |
| 1052 bool HttpUtil::ParseAcceptEncoding(const std::string& accept_encoding, |
| 1053 std::set<std::string>* allowed_encodings) { |
| 1054 DCHECK(allowed_encodings); |
| 1055 if (accept_encoding.find_first_of("\"") != std::string::npos) |
| 1056 return false; |
| 1057 allowed_encodings->clear(); |
| 1058 |
| 1059 base::StringTokenizer tokenizer(accept_encoding.begin(), |
| 1060 accept_encoding.end(), ","); |
| 1061 while (tokenizer.GetNext()) { |
| 1062 base::StringPiece entry = tokenizer.token_piece(); |
| 1063 entry = TrimLWS(entry); |
| 1064 size_t semicolon_pos = entry.find(';'); |
| 1065 if (semicolon_pos == base::StringPiece::npos) { |
| 1066 if (entry.find_first_of(HTTP_LWS) != base::StringPiece::npos) |
| 1067 return false; |
| 1068 allowed_encodings->insert(base::ToLowerASCII(entry)); |
| 1069 continue; |
| 1070 } |
| 1071 base::StringPiece encoding = entry.substr(0, semicolon_pos); |
| 1072 encoding = TrimLWS(encoding); |
| 1073 if (encoding.find_first_of(HTTP_LWS) != base::StringPiece::npos) |
| 1074 return false; |
| 1075 base::StringPiece params = entry.substr(semicolon_pos + 1); |
| 1076 params = TrimLWS(params); |
| 1077 size_t equals_pos = params.find('='); |
| 1078 if (equals_pos == base::StringPiece::npos) |
| 1079 return false; |
| 1080 base::StringPiece param_name = params.substr(0, equals_pos); |
| 1081 param_name = TrimLWS(param_name); |
| 1082 if (!base::LowerCaseEqualsASCII(param_name, "q")) |
| 1083 return false; |
| 1084 base::StringPiece qvalue = params.substr(equals_pos + 1); |
| 1085 qvalue = TrimLWS(qvalue); |
| 1086 if (qvalue.empty()) |
| 1087 return false; |
| 1088 if (qvalue[0] == '1') { |
| 1089 if (base::StringPiece("1.000").starts_with(qvalue)) { |
| 1090 allowed_encodings->insert(base::ToLowerASCII(encoding)); |
| 1091 continue; |
| 1092 } |
| 1093 return false; |
| 1094 } |
| 1095 if (qvalue[0] != '0') |
| 1096 return false; |
| 1097 if (qvalue.length() == 1) |
| 1098 continue; |
| 1099 if (qvalue.length() <= 2 || qvalue.length() > 5) |
| 1100 return false; |
| 1101 if (qvalue[1] != '.') |
| 1102 return false; |
| 1103 bool nonzero_number = false; |
| 1104 for (size_t i = 2; i < qvalue.length(); ++i) { |
| 1105 if (!base::IsAsciiDigit(qvalue[i])) |
| 1106 return false; |
| 1107 if (qvalue[i] != '0') |
| 1108 nonzero_number = true; |
| 1109 } |
| 1110 if (nonzero_number) |
| 1111 allowed_encodings->insert(base::ToLowerASCII(encoding)); |
| 1112 } |
| 1113 |
| 1114 // RFC 7231 5.3.4 "A request without an Accept-Encoding header field implies |
| 1115 // that the user agent has no preferences regarding content-codings." |
| 1116 if (allowed_encodings->empty()) { |
| 1117 allowed_encodings->insert("*"); |
| 1118 return true; |
| 1119 } |
| 1120 |
| 1121 // Any browser must support "identity". |
| 1122 allowed_encodings->insert("identity"); |
| 1123 |
| 1124 // RFC says gzip == x-gzip; mirror it here for easier matching. |
| 1125 if (allowed_encodings->find("gzip") != allowed_encodings->end()) |
| 1126 allowed_encodings->insert("x-gzip"); |
| 1127 if (allowed_encodings->find("x-gzip") != allowed_encodings->end()) |
| 1128 allowed_encodings->insert("gzip"); |
| 1129 |
| 1130 // RFC says compress == x-compress; mirror it here for easier matching. |
| 1131 if (allowed_encodings->find("compress") != allowed_encodings->end()) |
| 1132 allowed_encodings->insert("x-compress"); |
| 1133 if (allowed_encodings->find("x-compress") != allowed_encodings->end()) |
| 1134 allowed_encodings->insert("compress"); |
| 1135 return true; |
| 1136 } |
| 1137 |
| 1138 bool HttpUtil::ParseContentEncoding(const std::string& content_encoding, |
| 1139 std::set<std::string>* used_encodings) { |
| 1140 DCHECK(used_encodings); |
| 1141 if (content_encoding.find_first_of("\"=;*") != std::string::npos) |
| 1142 return false; |
| 1143 used_encodings->clear(); |
| 1144 |
| 1145 base::StringTokenizer encoding_tokenizer(content_encoding.begin(), |
| 1146 content_encoding.end(), ","); |
| 1147 while (encoding_tokenizer.GetNext()) { |
| 1148 base::StringPiece encoding = TrimLWS(encoding_tokenizer.token_piece()); |
| 1149 if (encoding.find_first_of(HTTP_LWS) != base::StringPiece::npos) |
| 1150 return false; |
| 1151 used_encodings->insert(base::ToLowerASCII(encoding)); |
| 1152 } |
| 1153 return true; |
| 1154 } |
| 1155 |
1052 } // namespace net | 1156 } // namespace net |
OLD | NEW |