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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 } | 158 } |
159 if ((!eq && *had_charset) || type_has_charset) { | 159 if ((!eq && *had_charset) || type_has_charset) { |
160 *had_charset = true; | 160 *had_charset = true; |
161 *charset = base::ToLowerASCII( | 161 *charset = base::ToLowerASCII( |
162 base::StringPiece(begin + charset_val, begin + charset_end)); | 162 base::StringPiece(begin + charset_val, begin + charset_end)); |
163 } | 163 } |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 // static | 167 // static |
168 // Parse the Range header according to RFC 2616 14.35.1 | |
169 // ranges-specifier = byte-ranges-specifier | |
170 // byte-ranges-specifier = bytes-unit "=" byte-range-set | |
171 // byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) | |
172 // byte-range-spec = first-byte-pos "-" [last-byte-pos] | |
173 // first-byte-pos = 1*DIGIT | |
174 // last-byte-pos = 1*DIGIT | |
175 bool HttpUtil::ParseRanges(const std::string& headers, | |
176 std::vector<HttpByteRange>* ranges) { | |
177 std::string ranges_specifier; | |
178 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); | |
179 | |
180 while (it.GetNext()) { | |
181 // Look for "Range" header. | |
182 if (!base::LowerCaseEqualsASCII(it.name(), "range")) | |
183 continue; | |
184 ranges_specifier = it.values(); | |
185 // We just care about the first "Range" header, so break here. | |
186 break; | |
187 } | |
188 | |
189 if (ranges_specifier.empty()) | |
190 return false; | |
191 | |
192 return ParseRangeHeader(ranges_specifier, ranges); | |
193 } | |
194 | |
195 // static | |
196 bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier, | 168 bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier, |
197 std::vector<HttpByteRange>* ranges) { | 169 std::vector<HttpByteRange>* ranges) { |
198 size_t equal_char_offset = ranges_specifier.find('='); | 170 size_t equal_char_offset = ranges_specifier.find('='); |
199 if (equal_char_offset == std::string::npos) | 171 if (equal_char_offset == std::string::npos) |
200 return false; | 172 return false; |
201 | 173 |
202 // Try to extract bytes-unit part. | 174 // Try to extract bytes-unit part. |
203 std::string::const_iterator bytes_unit_begin = ranges_specifier.begin(); | 175 std::string::const_iterator bytes_unit_begin = ranges_specifier.begin(); |
204 std::string::const_iterator bytes_unit_end = bytes_unit_begin + | 176 std::string::const_iterator bytes_unit_end = bytes_unit_begin + |
205 equal_char_offset; | 177 equal_char_offset; |
206 std::string::const_iterator byte_range_set_begin = bytes_unit_end + 1; | 178 std::string::const_iterator byte_range_set_begin = bytes_unit_end + 1; |
207 std::string::const_iterator byte_range_set_end = ranges_specifier.end(); | 179 std::string::const_iterator byte_range_set_end = ranges_specifier.end(); |
208 | 180 |
209 TrimLWS(&bytes_unit_begin, &bytes_unit_end); | 181 TrimLWS(&bytes_unit_begin, &bytes_unit_end); |
210 // "bytes" unit identifier is not found. | 182 // "bytes" unit identifier is not found. |
211 if (!base::LowerCaseEqualsASCII( | 183 if (!base::LowerCaseEqualsASCII( |
212 base::StringPiece(bytes_unit_begin, bytes_unit_end), "bytes")) | 184 base::StringPiece(bytes_unit_begin, bytes_unit_end), "bytes")) { |
213 return false; | 185 return false; |
| 186 } |
214 | 187 |
215 ValuesIterator byte_range_set_iterator(byte_range_set_begin, | 188 ValuesIterator byte_range_set_iterator(byte_range_set_begin, |
216 byte_range_set_end, ','); | 189 byte_range_set_end, ','); |
217 while (byte_range_set_iterator.GetNext()) { | 190 while (byte_range_set_iterator.GetNext()) { |
218 size_t minus_char_offset = byte_range_set_iterator.value().find('-'); | 191 size_t minus_char_offset = byte_range_set_iterator.value().find('-'); |
219 // If '-' character is not found, reports failure. | 192 // If '-' character is not found, reports failure. |
220 if (minus_char_offset == std::string::npos) | 193 if (minus_char_offset == std::string::npos) |
221 return false; | 194 return false; |
222 | 195 |
223 std::string::const_iterator first_byte_pos_begin = | 196 std::string::const_iterator first_byte_pos_begin = |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 bool HttpUtil::IsValidHeaderValue(const base::StringPiece& value) { | 409 bool HttpUtil::IsValidHeaderValue(const base::StringPiece& value) { |
437 // Just a sanity check: disallow NUL, CR and LF. | 410 // Just a sanity check: disallow NUL, CR and LF. |
438 for (char c : value) { | 411 for (char c : value) { |
439 if (c == '\0' || c == '\r' || c == '\n') | 412 if (c == '\0' || c == '\r' || c == '\n') |
440 return false; | 413 return false; |
441 } | 414 } |
442 return true; | 415 return true; |
443 } | 416 } |
444 | 417 |
445 // static | 418 // static |
446 std::string HttpUtil::StripHeaders(const std::string& headers, | |
447 const char* const headers_to_remove[], | |
448 size_t headers_to_remove_len) { | |
449 std::string stripped_headers; | |
450 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); | |
451 | |
452 while (it.GetNext()) { | |
453 bool should_remove = false; | |
454 for (size_t i = 0; i < headers_to_remove_len; ++i) { | |
455 if (base::LowerCaseEqualsASCII( | |
456 base::StringPiece(it.name_begin(), it.name_end()), | |
457 headers_to_remove[i])) { | |
458 should_remove = true; | |
459 break; | |
460 } | |
461 } | |
462 if (!should_remove) { | |
463 // Assume that name and values are on the same line. | |
464 stripped_headers.append(it.name_begin(), it.values_end()); | |
465 stripped_headers.append("\r\n"); | |
466 } | |
467 } | |
468 return stripped_headers; | |
469 } | |
470 | |
471 // static | |
472 bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin, | 419 bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin, |
473 std::string::const_iterator name_end) { | 420 std::string::const_iterator name_end) { |
474 // NOTE: "set-cookie2" headers do not support expires attributes, so we don't | 421 // NOTE: "set-cookie2" headers do not support expires attributes, so we don't |
475 // have to list them here. | 422 // have to list them here. |
476 const char* const kNonCoalescingHeaders[] = { | 423 const char* const kNonCoalescingHeaders[] = { |
477 "date", | 424 "date", |
478 "expires", | 425 "expires", |
479 "last-modified", | 426 "last-modified", |
480 "location", // See bug 1050541 for details | 427 "location", // See bug 1050541 for details |
481 "retry-after", | 428 "retry-after", |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 return true; | 1094 return true; |
1148 } | 1095 } |
1149 | 1096 |
1150 bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const { | 1097 bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const { |
1151 if (strict_quotes_) | 1098 if (strict_quotes_) |
1152 return c == '"'; | 1099 return c == '"'; |
1153 return HttpUtil::IsQuote(c); | 1100 return HttpUtil::IsQuote(c); |
1154 } | 1101 } |
1155 | 1102 |
1156 } // namespace net | 1103 } // namespace net |
OLD | NEW |