| 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 header parsing were borrowed from Firefox: | 5 // The rules for header parsing were borrowed from Firefox: |
| 6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo
nseHead.cpp | 6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo
nseHead.cpp |
| 7 // The rules for parsing content-types were also borrowed from Firefox: | 7 // The rules for parsing content-types were also borrowed from Firefox: |
| 8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 | 8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 |
| 9 | 9 |
| 10 #include "net/http/http_response_headers.h" | 10 #include "net/http/http_response_headers.h" |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) { | 354 void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) { |
| 355 CheckDoesNotHaveEmbededNulls(new_status); | 355 CheckDoesNotHaveEmbededNulls(new_status); |
| 356 // Copy up to the null byte. This just copies the status line. | 356 // Copy up to the null byte. This just copies the status line. |
| 357 std::string new_raw_headers(new_status); | 357 std::string new_raw_headers(new_status); |
| 358 new_raw_headers.push_back('\0'); | 358 new_raw_headers.push_back('\0'); |
| 359 | 359 |
| 360 HeaderSet empty_to_remove; | 360 HeaderSet empty_to_remove; |
| 361 MergeWithHeaders(new_raw_headers, empty_to_remove); | 361 MergeWithHeaders(new_raw_headers, empty_to_remove); |
| 362 } | 362 } |
| 363 | 363 |
| 364 void HttpResponseHeaders::UpdateWithNewRange( | 364 void HttpResponseHeaders::UpdateWithNewRange(const HttpByteRange& byte_range, |
| 365 const HttpByteRange& byte_range, | 365 int64_t resource_size, |
| 366 int64 resource_size, | 366 bool replace_status_line) { |
| 367 bool replace_status_line) { | |
| 368 DCHECK(byte_range.IsValid()); | 367 DCHECK(byte_range.IsValid()); |
| 369 DCHECK(byte_range.HasFirstBytePosition()); | 368 DCHECK(byte_range.HasFirstBytePosition()); |
| 370 DCHECK(byte_range.HasLastBytePosition()); | 369 DCHECK(byte_range.HasLastBytePosition()); |
| 371 | 370 |
| 372 const char kLengthHeader[] = "Content-Length"; | 371 const char kLengthHeader[] = "Content-Length"; |
| 373 const char kRangeHeader[] = "Content-Range"; | 372 const char kRangeHeader[] = "Content-Range"; |
| 374 | 373 |
| 375 RemoveHeader(kLengthHeader); | 374 RemoveHeader(kLengthHeader); |
| 376 RemoveHeader(kRangeHeader); | 375 RemoveHeader(kRangeHeader); |
| 377 | 376 |
| 378 int64 start = byte_range.first_byte_position(); | 377 int64_t start = byte_range.first_byte_position(); |
| 379 int64 end = byte_range.last_byte_position(); | 378 int64_t end = byte_range.last_byte_position(); |
| 380 int64 range_len = end - start + 1; | 379 int64_t range_len = end - start + 1; |
| 381 | 380 |
| 382 if (replace_status_line) | 381 if (replace_status_line) |
| 383 ReplaceStatusLine("HTTP/1.1 206 Partial Content"); | 382 ReplaceStatusLine("HTTP/1.1 206 Partial Content"); |
| 384 | 383 |
| 385 AddHeader(base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64, | 384 AddHeader(base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64, |
| 386 kRangeHeader, start, end, resource_size)); | 385 kRangeHeader, start, end, resource_size)); |
| 387 AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, range_len)); | 386 AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, range_len)); |
| 388 } | 387 } |
| 389 | 388 |
| 390 void HttpResponseHeaders::Parse(const std::string& raw_input) { | 389 void HttpResponseHeaders::Parse(const std::string& raw_input) { |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 } | 651 } |
| 653 | 652 |
| 654 ++p; // from / to first digit. | 653 ++p; // from / to first digit. |
| 655 ++dot; // from . to second digit. | 654 ++dot; // from . to second digit. |
| 656 | 655 |
| 657 if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) { | 656 if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) { |
| 658 DVLOG(1) << "malformed version number"; | 657 DVLOG(1) << "malformed version number"; |
| 659 return HttpVersion(); | 658 return HttpVersion(); |
| 660 } | 659 } |
| 661 | 660 |
| 662 uint16 major = *p - '0'; | 661 uint16_t major = *p - '0'; |
| 663 uint16 minor = *dot - '0'; | 662 uint16_t minor = *dot - '0'; |
| 664 | 663 |
| 665 return HttpVersion(major, minor); | 664 return HttpVersion(major, minor); |
| 666 } | 665 } |
| 667 | 666 |
| 668 // Note: this implementation implicitly assumes that line_end points at a valid | 667 // Note: this implementation implicitly assumes that line_end points at a valid |
| 669 // sentinel character (such as '\0'). | 668 // sentinel character (such as '\0'). |
| 670 void HttpResponseHeaders::ParseStatusLine( | 669 void HttpResponseHeaders::ParseStatusLine( |
| 671 std::string::const_iterator line_begin, | 670 std::string::const_iterator line_begin, |
| 672 std::string::const_iterator line_end, | 671 std::string::const_iterator line_end, |
| 673 bool has_headers) { | 672 bool has_headers) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 std::string value; | 755 std::string value; |
| 757 | 756 |
| 758 size_t directive_size = directive.size(); | 757 size_t directive_size = directive.size(); |
| 759 | 758 |
| 760 void* iter = NULL; | 759 void* iter = NULL; |
| 761 while (EnumerateHeader(&iter, name, &value)) { | 760 while (EnumerateHeader(&iter, name, &value)) { |
| 762 if (value.size() > directive_size + 1 && | 761 if (value.size() > directive_size + 1 && |
| 763 base::StartsWith(value, directive, | 762 base::StartsWith(value, directive, |
| 764 base::CompareCase::INSENSITIVE_ASCII) && | 763 base::CompareCase::INSENSITIVE_ASCII) && |
| 765 value[directive_size] == '=') { | 764 value[directive_size] == '=') { |
| 766 int64 seconds; | 765 int64_t seconds; |
| 767 base::StringToInt64( | 766 base::StringToInt64( |
| 768 StringPiece(value.begin() + directive_size + 1, value.end()), | 767 StringPiece(value.begin() + directive_size + 1, value.end()), |
| 769 &seconds); | 768 &seconds); |
| 770 *result = TimeDelta::FromSeconds(seconds); | 769 *result = TimeDelta::FromSeconds(seconds); |
| 771 return true; | 770 return true; |
| 772 } | 771 } |
| 773 } | 772 } |
| 774 | 773 |
| 775 return false; | 774 return false; |
| 776 } | 775 } |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 | 1147 |
| 1149 bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const { | 1148 bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const { |
| 1150 return GetCacheControlDirective("max-age", result); | 1149 return GetCacheControlDirective("max-age", result); |
| 1151 } | 1150 } |
| 1152 | 1151 |
| 1153 bool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const { | 1152 bool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const { |
| 1154 std::string value; | 1153 std::string value; |
| 1155 if (!EnumerateHeader(NULL, "Age", &value)) | 1154 if (!EnumerateHeader(NULL, "Age", &value)) |
| 1156 return false; | 1155 return false; |
| 1157 | 1156 |
| 1158 int64 seconds; | 1157 int64_t seconds; |
| 1159 base::StringToInt64(value, &seconds); | 1158 base::StringToInt64(value, &seconds); |
| 1160 *result = TimeDelta::FromSeconds(seconds); | 1159 *result = TimeDelta::FromSeconds(seconds); |
| 1161 return true; | 1160 return true; |
| 1162 } | 1161 } |
| 1163 | 1162 |
| 1164 bool HttpResponseHeaders::GetDateValue(Time* result) const { | 1163 bool HttpResponseHeaders::GetDateValue(Time* result) const { |
| 1165 return GetTimeValuedHeader("Date", result); | 1164 return GetTimeValuedHeader("Date", result); |
| 1166 } | 1165 } |
| 1167 | 1166 |
| 1168 bool HttpResponseHeaders::GetLastModifiedValue(Time* result) const { | 1167 bool HttpResponseHeaders::GetLastModifiedValue(Time* result) const { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 std::string date_header; | 1242 std::string date_header; |
| 1244 EnumerateHeader(NULL, "Date", &date_header); | 1243 EnumerateHeader(NULL, "Date", &date_header); |
| 1245 return HttpUtil::HasStrongValidators(GetHttpVersion(), | 1244 return HttpUtil::HasStrongValidators(GetHttpVersion(), |
| 1246 etag_header, | 1245 etag_header, |
| 1247 last_modified_header, | 1246 last_modified_header, |
| 1248 date_header); | 1247 date_header); |
| 1249 } | 1248 } |
| 1250 | 1249 |
| 1251 // From RFC 2616: | 1250 // From RFC 2616: |
| 1252 // Content-Length = "Content-Length" ":" 1*DIGIT | 1251 // Content-Length = "Content-Length" ":" 1*DIGIT |
| 1253 int64 HttpResponseHeaders::GetContentLength() const { | 1252 int64_t HttpResponseHeaders::GetContentLength() const { |
| 1254 return GetInt64HeaderValue("content-length"); | 1253 return GetInt64HeaderValue("content-length"); |
| 1255 } | 1254 } |
| 1256 | 1255 |
| 1257 int64 HttpResponseHeaders::GetInt64HeaderValue( | 1256 int64_t HttpResponseHeaders::GetInt64HeaderValue( |
| 1258 const std::string& header) const { | 1257 const std::string& header) const { |
| 1259 void* iter = NULL; | 1258 void* iter = NULL; |
| 1260 std::string content_length_val; | 1259 std::string content_length_val; |
| 1261 if (!EnumerateHeader(&iter, header, &content_length_val)) | 1260 if (!EnumerateHeader(&iter, header, &content_length_val)) |
| 1262 return -1; | 1261 return -1; |
| 1263 | 1262 |
| 1264 if (content_length_val.empty()) | 1263 if (content_length_val.empty()) |
| 1265 return -1; | 1264 return -1; |
| 1266 | 1265 |
| 1267 if (content_length_val[0] == '+') | 1266 if (content_length_val[0] == '+') |
| 1268 return -1; | 1267 return -1; |
| 1269 | 1268 |
| 1270 int64 result; | 1269 int64_t result; |
| 1271 bool ok = base::StringToInt64(content_length_val, &result); | 1270 bool ok = base::StringToInt64(content_length_val, &result); |
| 1272 if (!ok || result < 0) | 1271 if (!ok || result < 0) |
| 1273 return -1; | 1272 return -1; |
| 1274 | 1273 |
| 1275 return result; | 1274 return result; |
| 1276 } | 1275 } |
| 1277 | 1276 |
| 1278 // From RFC 2616 14.16: | 1277 // From RFC 2616 14.16: |
| 1279 // content-range-spec = | 1278 // content-range-spec = |
| 1280 // bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" ) | 1279 // bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" ) |
| 1281 // byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*" | 1280 // byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*" |
| 1282 // instance-length = 1*DIGIT | 1281 // instance-length = 1*DIGIT |
| 1283 // bytes-unit = "bytes" | 1282 // bytes-unit = "bytes" |
| 1284 bool HttpResponseHeaders::GetContentRange(int64* first_byte_position, | 1283 bool HttpResponseHeaders::GetContentRange(int64_t* first_byte_position, |
| 1285 int64* last_byte_position, | 1284 int64_t* last_byte_position, |
| 1286 int64* instance_length) const { | 1285 int64_t* instance_length) const { |
| 1287 void* iter = NULL; | 1286 void* iter = NULL; |
| 1288 std::string content_range_spec; | 1287 std::string content_range_spec; |
| 1289 *first_byte_position = *last_byte_position = *instance_length = -1; | 1288 *first_byte_position = *last_byte_position = *instance_length = -1; |
| 1290 if (!EnumerateHeader(&iter, kContentRange, &content_range_spec)) | 1289 if (!EnumerateHeader(&iter, kContentRange, &content_range_spec)) |
| 1291 return false; | 1290 return false; |
| 1292 | 1291 |
| 1293 // If the header value is empty, we have an invalid header. | 1292 // If the header value is empty, we have an invalid header. |
| 1294 if (content_range_spec.empty()) | 1293 if (content_range_spec.empty()) |
| 1295 return false; | 1294 return false; |
| 1296 | 1295 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 return true; | 1441 return true; |
| 1443 } | 1442 } |
| 1444 | 1443 |
| 1445 bool HttpResponseHeaders::IsChunkEncoded() const { | 1444 bool HttpResponseHeaders::IsChunkEncoded() const { |
| 1446 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1445 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
| 1447 return GetHttpVersion() >= HttpVersion(1, 1) && | 1446 return GetHttpVersion() >= HttpVersion(1, 1) && |
| 1448 HasHeaderValue("Transfer-Encoding", "chunked"); | 1447 HasHeaderValue("Transfer-Encoding", "chunked"); |
| 1449 } | 1448 } |
| 1450 | 1449 |
| 1451 } // namespace net | 1450 } // namespace net |
| OLD | NEW |