Chromium Code Reviews| 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 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 bool HttpResponseHeaders::HasHeader(const base::StringPiece& name) const { | 613 bool HttpResponseHeaders::HasHeader(const base::StringPiece& name) const { |
| 614 return FindHeader(0, name) != std::string::npos; | 614 return FindHeader(0, name) != std::string::npos; |
| 615 } | 615 } |
| 616 | 616 |
| 617 HttpResponseHeaders::HttpResponseHeaders() : response_code_(-1) { | 617 HttpResponseHeaders::HttpResponseHeaders() : response_code_(-1) { |
| 618 } | 618 } |
| 619 | 619 |
| 620 HttpResponseHeaders::~HttpResponseHeaders() { | 620 HttpResponseHeaders::~HttpResponseHeaders() { |
| 621 } | 621 } |
| 622 | 622 |
| 623 // Shared function for major and minor section of HTTP Version string | |
|
eroman
2014/09/23 21:12:28
This wording needs work.
arun87.kumar
2014/09/24 12:04:05
Done.
| |
| 624 // to handle leading zeros and multiple digit usecases | |
| 625 // if string is valid, converts it to number, | |
| 626 // fills it to int variable passed as input param and returns true | |
| 627 // else returns false | |
| 628 bool HttpResponseHeaders::ParseVersionInternal( | |
| 629 std::string::const_iterator begin, | |
| 630 std::string::const_iterator end, | |
| 631 uint32* value) { | |
| 632 std::string::const_iterator start, p; | |
| 633 start = p = begin; | |
| 634 bool is_leading_zero = true; // handle leading zeroes | |
|
eroman
2014/09/23 21:12:28
Is there really a need to check for leading zeros?
arun87.kumar
2014/09/24 12:04:05
Done.
| |
| 635 | |
| 636 while (p < end) { | |
| 637 if (!(*p >= '0' && *p <= '9')) { | |
| 638 DVLOG(1) << "invalid value"; | |
| 639 return false; | |
| 640 } | |
| 641 if (is_leading_zero) { | |
| 642 if (*p != '0') | |
| 643 is_leading_zero = false; | |
| 644 else | |
| 645 start++; // ignore leading zeroes | |
| 646 } | |
| 647 p++; | |
| 648 } | |
| 649 base::StringToUint(StringPiece(start, p), value); | |
|
eroman
2014/09/23 21:12:28
This is still not checking for overflow.
arun87.kumar
2014/09/24 12:04:05
Added overflow check
| |
| 650 return true; | |
| 651 } | |
| 652 | |
| 623 // Note: this implementation implicitly assumes that line_end points at a valid | 653 // Note: this implementation implicitly assumes that line_end points at a valid |
| 624 // sentinel character (such as '\0'). | 654 // sentinel character (such as '\0'). |
| 625 // static | 655 // static |
| 626 HttpVersion HttpResponseHeaders::ParseVersion( | 656 HttpVersion HttpResponseHeaders::ParseVersion( |
| 627 std::string::const_iterator line_begin, | 657 std::string::const_iterator line_begin, |
| 628 std::string::const_iterator line_end) { | 658 std::string::const_iterator line_end) { |
| 629 std::string::const_iterator p = line_begin; | 659 std::string::const_iterator p = line_begin; |
| 630 | 660 |
| 631 // RFC2616 sec 3.1: HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT | 661 // RFC2616 sec 3.1: HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT |
| 632 // TODO: (1*DIGIT apparently means one or more digits, but we only handle 1). | |
| 633 // TODO: handle leading zeros, which is allowed by the rfc1616 sec 3.1. | |
| 634 | 662 |
| 635 if ((line_end - p < 4) || !LowerCaseEqualsASCII(p, p + 4, "http")) { | 663 if ((line_end - p < 4) || !LowerCaseEqualsASCII(p, p + 4, "http")) { |
| 636 DVLOG(1) << "missing status line"; | 664 DVLOG(1) << "missing status line"; |
| 637 return HttpVersion(); | 665 return HttpVersion(); |
| 638 } | 666 } |
| 639 | 667 |
| 640 p += 4; | 668 p += 4; |
| 641 | 669 |
| 642 if (p >= line_end || *p != '/') { | 670 if (p >= line_end || *p != '/') { |
| 643 DVLOG(1) << "missing version"; | 671 DVLOG(1) << "missing version"; |
| 644 return HttpVersion(); | 672 return HttpVersion(); |
| 645 } | 673 } |
| 646 | 674 |
| 647 std::string::const_iterator dot = std::find(p, line_end, '.'); | 675 std::string::const_iterator dot = std::find(p, line_end, '.'); |
| 648 if (dot == line_end) { | 676 //second check is to verify if there is nothing after dot |
| 677 if (dot == line_end || dot+1 == line_end) { | |
| 678 DVLOG(1) << "malformed version"; | |
| 679 return HttpVersion(); | |
| 680 } | |
| 681 | |
| 682 // find end of minor. | |
| 683 std::string::const_iterator end_of_minor = dot+1; | |
| 684 | |
| 685 //skip numbers | |
| 686 while(*end_of_minor >= '0' && *end_of_minor <= '9') | |
| 687 end_of_minor++; | |
| 688 | |
| 689 //If there is no number after dot | |
| 690 if(dot+1 == end_of_minor) { | |
| 649 DVLOG(1) << "malformed version"; | 691 DVLOG(1) << "malformed version"; |
| 650 return HttpVersion(); | 692 return HttpVersion(); |
| 651 } | 693 } |
| 652 | 694 |
| 653 ++p; // from / to first digit. | 695 ++p; // from / to first digit. |
| 654 ++dot; // from . to second digit. | |
| 655 | 696 |
| 656 if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) { | 697 uint32 major = 0; |
| 657 DVLOG(1) << "malformed version number"; | 698 uint32 minor = 0; |
| 699 | |
| 700 if (ParseVersionInternal(p, dot, &major) && | |
| 701 ParseVersionInternal(dot + 1, end_of_minor, &minor)) { | |
| 702 DVLOG(1) << "ParseVersion success!!!"; | |
| 703 return HttpVersion(major, minor); | |
| 704 } else { | |
| 705 DVLOG(1) << "ParseVersion fail!!!"; | |
| 658 return HttpVersion(); | 706 return HttpVersion(); |
| 659 } | 707 } |
| 660 | |
| 661 uint16 major = *p - '0'; | |
| 662 uint16 minor = *dot - '0'; | |
| 663 | |
| 664 return HttpVersion(major, minor); | |
| 665 } | 708 } |
| 666 | 709 |
| 667 // Note: this implementation implicitly assumes that line_end points at a valid | 710 // Note: this implementation implicitly assumes that line_end points at a valid |
| 668 // sentinel character (such as '\0'). | 711 // sentinel character (such as '\0'). |
| 669 void HttpResponseHeaders::ParseStatusLine( | 712 void HttpResponseHeaders::ParseStatusLine( |
| 670 std::string::const_iterator line_begin, | 713 std::string::const_iterator line_begin, |
| 671 std::string::const_iterator line_end, | 714 std::string::const_iterator line_end, |
| 672 bool has_headers) { | 715 bool has_headers) { |
| 673 // Extract the version number | 716 // Extract the version number |
| 674 parsed_http_version_ = ParseVersion(line_begin, line_end); | 717 parsed_http_version_ = ParseVersion(line_begin, line_end); |
| 675 | 718 |
| 676 // Clamp the version number to one of: {0.9, 1.0, 1.1} | 719 //Allow mulitple digits in major and minor values of HTTP Version. |
| 677 if (parsed_http_version_ == HttpVersion(0, 9) && !has_headers) { | 720 //If parseVersion failed, keep version as 1.0 as per old logic |
| 678 http_version_ = HttpVersion(0, 9); | 721 //If version is 0.9 and has headers, keep version as 1.0 as per old logic |
| 679 raw_headers_ = "HTTP/0.9"; | 722 //If version is 0.9 and has no headers, keep version as 0.9 as per old logic |
| 680 } else if (parsed_http_version_ >= HttpVersion(1, 1)) { | 723 //Else in all other cases, http_version will be same as parsed_http_version |
| 681 http_version_ = HttpVersion(1, 1); | 724 if (parsed_http_version_ == HttpVersion()) { |
| 682 raw_headers_ = "HTTP/1.1"; | |
| 683 } else { | |
| 684 // Treat everything else like HTTP 1.0 | |
| 685 http_version_ = HttpVersion(1, 0); | 725 http_version_ = HttpVersion(1, 0); |
| 686 raw_headers_ = "HTTP/1.0"; | 726 raw_headers_ = "HTTP/1.0"; |
| 727 } else if (parsed_http_version_ == HttpVersion(0, 9) && has_headers) { | |
| 728 http_version_ = HttpVersion(1, 0); | |
| 729 raw_headers_ = "HTTP/1.0"; | |
| 730 } else { | |
| 731 http_version_ = parsed_http_version_; | |
| 732 raw_headers_ = "HTTP/"; | |
| 733 raw_headers_.append(base::UintToString(http_version_.major_value())); | |
| 734 raw_headers_.append("."); | |
| 735 raw_headers_.append(base::UintToString(http_version_.minor_value())); | |
| 687 } | 736 } |
| 737 | |
| 688 if (parsed_http_version_ != http_version_) { | 738 if (parsed_http_version_ != http_version_) { |
| 689 DVLOG(1) << "assuming HTTP/" << http_version_.major_value() << "." | 739 DVLOG(1) << "assuming HTTP/" << http_version_.major_value() << "." |
| 690 << http_version_.minor_value(); | 740 << http_version_.minor_value(); |
| 691 } | 741 } |
| 692 | 742 |
| 693 // TODO(eroman): this doesn't make sense if ParseVersion failed. | 743 // TODO(eroman): this doesn't make sense if ParseVersion failed. |
| 694 std::string::const_iterator p = std::find(line_begin, line_end, ' '); | 744 std::string::const_iterator p = std::find(line_begin, line_end, ' '); |
| 695 | 745 |
| 696 if (p == line_end) { | 746 if (p == line_end) { |
| 697 DVLOG(1) << "missing response status; assuming 200 OK"; | 747 DVLOG(1) << "missing response status; assuming 200 OK"; |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1397 return true; | 1447 return true; |
| 1398 } | 1448 } |
| 1399 | 1449 |
| 1400 bool HttpResponseHeaders::IsChunkEncoded() const { | 1450 bool HttpResponseHeaders::IsChunkEncoded() const { |
| 1401 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1451 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
| 1402 return GetHttpVersion() >= HttpVersion(1, 1) && | 1452 return GetHttpVersion() >= HttpVersion(1, 1) && |
| 1403 HasHeaderValue("Transfer-Encoding", "chunked"); | 1453 HasHeaderValue("Transfer-Encoding", "chunked"); |
| 1404 } | 1454 } |
| 1405 | 1455 |
| 1406 } // namespace net | 1456 } // namespace net |
| OLD | NEW |