| 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 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 return -1; | 1296 return -1; |
| 1297 | 1297 |
| 1298 int64_t result; | 1298 int64_t result; |
| 1299 bool ok = base::StringToInt64(content_length_val, &result); | 1299 bool ok = base::StringToInt64(content_length_val, &result); |
| 1300 if (!ok || result < 0) | 1300 if (!ok || result < 0) |
| 1301 return -1; | 1301 return -1; |
| 1302 | 1302 |
| 1303 return result; | 1303 return result; |
| 1304 } | 1304 } |
| 1305 | 1305 |
| 1306 // From RFC 2616 14.16: | |
| 1307 // content-range-spec = | |
| 1308 // bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" ) | |
| 1309 // byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*" | |
| 1310 // instance-length = 1*DIGIT | |
| 1311 // bytes-unit = "bytes" | |
| 1312 bool HttpResponseHeaders::GetContentRange(int64_t* first_byte_position, | 1306 bool HttpResponseHeaders::GetContentRange(int64_t* first_byte_position, |
| 1313 int64_t* last_byte_position, | 1307 int64_t* last_byte_position, |
| 1314 int64_t* instance_length) const { | 1308 int64_t* instance_length) const { |
| 1315 size_t iter = 0; | 1309 size_t iter = 0; |
| 1316 std::string content_range_spec; | 1310 std::string content_range_spec; |
| 1317 *first_byte_position = *last_byte_position = *instance_length = -1; | 1311 if (!EnumerateHeader(&iter, kContentRange, &content_range_spec)) { |
| 1318 if (!EnumerateHeader(&iter, kContentRange, &content_range_spec)) | 1312 *first_byte_position = *last_byte_position = *instance_length = -1; |
| 1319 return false; | |
| 1320 | |
| 1321 // If the header value is empty, we have an invalid header. | |
| 1322 if (content_range_spec.empty()) | |
| 1323 return false; | |
| 1324 | |
| 1325 size_t space_position = content_range_spec.find(' '); | |
| 1326 if (space_position == std::string::npos) | |
| 1327 return false; | |
| 1328 | |
| 1329 // Invalid header if it doesn't contain "bytes-unit". | |
| 1330 std::string::const_iterator content_range_spec_begin = | |
| 1331 content_range_spec.begin(); | |
| 1332 std::string::const_iterator content_range_spec_end = | |
| 1333 content_range_spec.begin() + space_position; | |
| 1334 HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end); | |
| 1335 if (!base::LowerCaseEqualsASCII( | |
| 1336 base::StringPiece(content_range_spec_begin, content_range_spec_end), | |
| 1337 "bytes")) { | |
| 1338 return false; | 1313 return false; |
| 1339 } | 1314 } |
| 1340 | 1315 |
| 1341 size_t slash_position = content_range_spec.find('/', space_position + 1); | 1316 return HttpUtil::ParseContentRangeHeader(content_range_spec, |
| 1342 if (slash_position == std::string::npos) | 1317 first_byte_position, |
| 1343 return false; | 1318 last_byte_position, instance_length); |
| 1344 | |
| 1345 // Obtain the part behind the space and before slash. | |
| 1346 std::string::const_iterator byte_range_resp_spec_begin = | |
| 1347 content_range_spec.begin() + space_position + 1; | |
| 1348 std::string::const_iterator byte_range_resp_spec_end = | |
| 1349 content_range_spec.begin() + slash_position; | |
| 1350 HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end); | |
| 1351 | |
| 1352 // Parse the byte-range-resp-spec part. | |
| 1353 std::string byte_range_resp_spec(byte_range_resp_spec_begin, | |
| 1354 byte_range_resp_spec_end); | |
| 1355 // If byte-range-resp-spec != "*". | |
| 1356 if (!base::LowerCaseEqualsASCII(byte_range_resp_spec, "*")) { | |
| 1357 size_t minus_position = byte_range_resp_spec.find('-'); | |
| 1358 if (minus_position != std::string::npos) { | |
| 1359 // Obtain first-byte-pos. | |
| 1360 std::string::const_iterator first_byte_pos_begin = | |
| 1361 byte_range_resp_spec.begin(); | |
| 1362 std::string::const_iterator first_byte_pos_end = | |
| 1363 byte_range_resp_spec.begin() + minus_position; | |
| 1364 HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); | |
| 1365 | |
| 1366 bool ok = base::StringToInt64(StringPiece(first_byte_pos_begin, | |
| 1367 first_byte_pos_end), | |
| 1368 first_byte_position); | |
| 1369 | |
| 1370 // Obtain last-byte-pos. | |
| 1371 std::string::const_iterator last_byte_pos_begin = | |
| 1372 byte_range_resp_spec.begin() + minus_position + 1; | |
| 1373 std::string::const_iterator last_byte_pos_end = | |
| 1374 byte_range_resp_spec.end(); | |
| 1375 HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end); | |
| 1376 | |
| 1377 ok &= base::StringToInt64(StringPiece(last_byte_pos_begin, | |
| 1378 last_byte_pos_end), | |
| 1379 last_byte_position); | |
| 1380 if (!ok) { | |
| 1381 *first_byte_position = *last_byte_position = -1; | |
| 1382 return false; | |
| 1383 } | |
| 1384 if (*first_byte_position < 0 || *last_byte_position < 0 || | |
| 1385 *first_byte_position > *last_byte_position) | |
| 1386 return false; | |
| 1387 } else { | |
| 1388 return false; | |
| 1389 } | |
| 1390 } | |
| 1391 | |
| 1392 // Parse the instance-length part. | |
| 1393 // If instance-length == "*". | |
| 1394 std::string::const_iterator instance_length_begin = | |
| 1395 content_range_spec.begin() + slash_position + 1; | |
| 1396 std::string::const_iterator instance_length_end = | |
| 1397 content_range_spec.end(); | |
| 1398 HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end); | |
| 1399 | |
| 1400 if (base::StartsWith( | |
| 1401 base::StringPiece(instance_length_begin, instance_length_end), "*", | |
| 1402 base::CompareCase::SENSITIVE)) { | |
| 1403 return false; | |
| 1404 } else if (!base::StringToInt64(StringPiece(instance_length_begin, | |
| 1405 instance_length_end), | |
| 1406 instance_length)) { | |
| 1407 *instance_length = -1; | |
| 1408 return false; | |
| 1409 } | |
| 1410 | |
| 1411 // We have all the values; let's verify that they make sense for a 206 | |
| 1412 // response. | |
| 1413 if (*first_byte_position < 0 || *last_byte_position < 0 || | |
| 1414 *instance_length < 0 || *instance_length - 1 < *last_byte_position) | |
| 1415 return false; | |
| 1416 | |
| 1417 return true; | |
| 1418 } | 1319 } |
| 1419 | 1320 |
| 1420 std::unique_ptr<base::Value> HttpResponseHeaders::NetLogCallback( | 1321 std::unique_ptr<base::Value> HttpResponseHeaders::NetLogCallback( |
| 1421 NetLogCaptureMode capture_mode) const { | 1322 NetLogCaptureMode capture_mode) const { |
| 1422 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 1323 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 1423 base::ListValue* headers = new base::ListValue(); | 1324 base::ListValue* headers = new base::ListValue(); |
| 1424 headers->AppendString(EscapeNonASCII(GetStatusLine())); | 1325 headers->AppendString(EscapeNonASCII(GetStatusLine())); |
| 1425 size_t iterator = 0; | 1326 size_t iterator = 0; |
| 1426 std::string name; | 1327 std::string name; |
| 1427 std::string value; | 1328 std::string value; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 return true; | 1369 return true; |
| 1469 } | 1370 } |
| 1470 | 1371 |
| 1471 bool HttpResponseHeaders::IsChunkEncoded() const { | 1372 bool HttpResponseHeaders::IsChunkEncoded() const { |
| 1472 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1373 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
| 1473 return GetHttpVersion() >= HttpVersion(1, 1) && | 1374 return GetHttpVersion() >= HttpVersion(1, 1) && |
| 1474 HasHeaderValue("Transfer-Encoding", "chunked"); | 1375 HasHeaderValue("Transfer-Encoding", "chunked"); |
| 1475 } | 1376 } |
| 1476 | 1377 |
| 1477 } // namespace net | 1378 } // namespace net |
| OLD | NEW |