OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 if ((!eq && *had_charset) || type_has_charset) { | 188 if ((!eq && *had_charset) || type_has_charset) { |
189 *had_charset = true; | 189 *had_charset = true; |
190 charset->assign(content_type_str.begin() + charset_val, | 190 charset->assign(content_type_str.begin() + charset_val, |
191 content_type_str.begin() + charset_end); | 191 content_type_str.begin() + charset_end); |
192 StringToLowerASCII(charset); | 192 StringToLowerASCII(charset); |
193 } | 193 } |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 // static | 197 // static |
| 198 // Parse the Range header according to RFC 2616 14.35.1 |
| 199 // ranges-specifier = byte-ranges-specifier |
| 200 // byte-ranges-specifier = bytes-unit "=" byte-range-set |
| 201 // byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) |
| 202 // byte-range-spec = first-byte-pos "-" [last-byte-pos] |
| 203 // first-byte-pos = 1*DIGIT |
| 204 // last-byte-pos = 1*DIGIT |
| 205 bool HttpUtil::ParseRanges(const std::string& headers, |
| 206 std::vector<HttpByteRange>* ranges) { |
| 207 std::string ranges_specifier; |
| 208 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); |
| 209 |
| 210 while (it.GetNext()) { |
| 211 // Look for "Range" header. |
| 212 if (!LowerCaseEqualsASCII(it.name(), "range")) |
| 213 continue; |
| 214 ranges_specifier = it.values(); |
| 215 // We just care about the first "Range" header, so break here. |
| 216 break; |
| 217 } |
| 218 |
| 219 if (ranges_specifier.empty()) |
| 220 return false; |
| 221 |
| 222 size_t equal_char_offset = ranges_specifier.find('='); |
| 223 if (equal_char_offset == std::string::npos) |
| 224 return false; |
| 225 |
| 226 // Try to extract bytes-unit part. |
| 227 std::string::const_iterator bytes_unit_begin = ranges_specifier.begin(); |
| 228 std::string::const_iterator bytes_unit_end = bytes_unit_begin + |
| 229 equal_char_offset; |
| 230 std::string::const_iterator byte_range_set_begin = bytes_unit_end + 1; |
| 231 std::string::const_iterator byte_range_set_end = ranges_specifier.end(); |
| 232 |
| 233 TrimLWS(&bytes_unit_begin, &bytes_unit_end); |
| 234 // "bytes" unit identifier is not found. |
| 235 if (!LowerCaseEqualsASCII(bytes_unit_begin, bytes_unit_end, "bytes")) |
| 236 return false; |
| 237 |
| 238 ValuesIterator byte_range_set_iterator(byte_range_set_begin, |
| 239 byte_range_set_end, ','); |
| 240 while (byte_range_set_iterator.GetNext()) { |
| 241 size_t minus_char_offset = byte_range_set_iterator.value().find('-'); |
| 242 // If '-' character is not found, reports failure. |
| 243 if (minus_char_offset == std::string::npos) |
| 244 return false; |
| 245 |
| 246 std::string::const_iterator first_byte_pos_begin = |
| 247 byte_range_set_iterator.value_begin(); |
| 248 std::string::const_iterator first_byte_pos_end = |
| 249 first_byte_pos_begin + minus_char_offset; |
| 250 TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); |
| 251 std::string first_byte_pos(first_byte_pos_begin, first_byte_pos_end); |
| 252 |
| 253 HttpByteRange range; |
| 254 // Try to obtain first-byte-pos. |
| 255 if (!first_byte_pos.empty()) { |
| 256 int64 first_byte_position = -1; |
| 257 if (!StringToInt64(first_byte_pos, &first_byte_position)) |
| 258 return false; |
| 259 range.set_first_byte_position(first_byte_position); |
| 260 } |
| 261 |
| 262 std::string::const_iterator last_byte_pos_begin = |
| 263 byte_range_set_iterator.value_begin() + minus_char_offset + 1; |
| 264 std::string::const_iterator last_byte_pos_end = |
| 265 byte_range_set_iterator.value_end(); |
| 266 TrimLWS(&last_byte_pos_begin, &last_byte_pos_end); |
| 267 std::string last_byte_pos(last_byte_pos_begin, last_byte_pos_end); |
| 268 |
| 269 // We have last-byte-pos or suffix-byte-range-spec in this case. |
| 270 if (!last_byte_pos.empty()) { |
| 271 int64 last_byte_position; |
| 272 if (!StringToInt64(last_byte_pos, &last_byte_position)) |
| 273 return false; |
| 274 if (range.HasFirstBytePosition()) |
| 275 range.set_last_byte_position(last_byte_position); |
| 276 else |
| 277 range.set_suffix_length(last_byte_position); |
| 278 } else if (!range.HasFirstBytePosition()) { |
| 279 return false; |
| 280 } |
| 281 |
| 282 // Do a final check on the HttpByteRange object. |
| 283 if (!range.IsValid()) |
| 284 return false; |
| 285 ranges->push_back(range); |
| 286 } |
| 287 return ranges->size() > 0; |
| 288 } |
| 289 |
| 290 // static |
198 bool HttpUtil::HasHeader(const std::string& headers, const char* name) { | 291 bool HttpUtil::HasHeader(const std::string& headers, const char* name) { |
199 size_t name_len = strlen(name); | 292 size_t name_len = strlen(name); |
200 string::const_iterator it = | 293 string::const_iterator it = |
201 std::search(headers.begin(), | 294 std::search(headers.begin(), |
202 headers.end(), | 295 headers.end(), |
203 name, | 296 name, |
204 name + name_len, | 297 name + name_len, |
205 CaseInsensitiveCompareASCII<char>()); | 298 CaseInsensitiveCompareASCII<char>()); |
206 if (it == headers.end()) | 299 if (it == headers.end()) |
207 return false; | 300 return false; |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 TrimLWS(&value_begin_, &value_end_); | 674 TrimLWS(&value_begin_, &value_end_); |
582 | 675 |
583 // bypass empty values. | 676 // bypass empty values. |
584 if (value_begin_ != value_end_) | 677 if (value_begin_ != value_end_) |
585 return true; | 678 return true; |
586 } | 679 } |
587 return false; | 680 return false; |
588 } | 681 } |
589 | 682 |
590 } // namespace net | 683 } // namespace net |
OLD | NEW |