diff options
author | pauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-29 22:54:58 +0000 |
---|---|---|
committer | pauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-29 22:54:58 +0000 |
commit | 6e6acc10590856575a4c4c330197e828917dc995 (patch) | |
tree | 9ef1ac70dcf7723188a3d08222ce98d1933e1b1b | |
parent | e42285a3b4def2770cc3ad504a0d73d2d565a313 (diff) | |
download | chromium_src-6e6acc10590856575a4c4c330197e828917dc995.zip chromium_src-6e6acc10590856575a4c4c330197e828917dc995.tar.gz chromium_src-6e6acc10590856575a4c4c330197e828917dc995.tar.bz2 |
Default to GMT when parsing HTTP "Date", "Expires" and "Last-Modified" headers.
BUG=153759
TEST=net_unittests --gtest_filter=HttpResponseHeadersTest.DefaultDateToGMT
Review URL: https://chromiumcodereview.appspot.com/11269011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164762 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/time.cc | 7 | ||||
-rw-r--r-- | base/time.h | 22 | ||||
-rw-r--r-- | net/http/http_response_headers.cc | 13 | ||||
-rw-r--r-- | net/http/http_response_headers_unittest.cc | 30 |
4 files changed, 67 insertions, 5 deletions
diff --git a/base/time.cc b/base/time.cc index f2f3168..e5afa12 100644 --- a/base/time.cc +++ b/base/time.cc @@ -157,14 +157,17 @@ Time Time::LocalMidnight() const { } // static -bool Time::FromString(const char* time_string, Time* parsed_time) { +bool Time::FromStringInternal(const char* time_string, + bool is_local, + Time* parsed_time) { DCHECK((time_string != NULL) && (parsed_time != NULL)); if (time_string[0] == '\0') return false; PRTime result_time = 0; - PRStatus result = PR_ParseTimeString(time_string, PR_FALSE, + PRStatus result = PR_ParseTimeString(time_string, + is_local ? PR_FALSE : PR_TRUE, &result_time); if (PR_SUCCESS != result) return false; diff --git a/base/time.h b/base/time.h index e33cb75..78d7456 100644 --- a/base/time.h +++ b/base/time.h @@ -355,10 +355,17 @@ class BASE_EXPORT Time { // Converts a string representation of time to a Time object. // An example of a time string which is converted is as below:- // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified - // in the input string, we assume local time. + // in the input string, FromString assumes local time and FromUTCString + // assumes UTC. A timezone that cannot be parsed (e.g. "UTC" which is not + // specified in RFC822) is treated as if the timezone is not specified. // TODO(iyengar) Move the FromString/FromTimeT/ToTimeT/FromFileTime to // a new time converter class. - static bool FromString(const char* time_string, Time* parsed_time); + static bool FromString(const char* time_string, Time* parsed_time) { + return FromStringInternal(time_string, true, parsed_time); + } + static bool FromUTCString(const char* time_string, Time* parsed_time) { + return FromStringInternal(time_string, false, parsed_time); + } // For serializing, use FromInternalValue to reconstitute. Please don't use // this and do arithmetic on it, as it is more error prone than using the @@ -442,6 +449,17 @@ class BASE_EXPORT Time { // |is_local = true| or UTC |is_local = false|. static Time FromExploded(bool is_local, const Exploded& exploded); + // Converts a string representation of time to a Time object. + // An example of a time string which is converted is as below:- + // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified + // in the input string, local time |is_local = true| or + // UTC |is_local = false| is assumed. A timezone that cannot be parsed + // (e.g. "UTC" which is not specified in RFC822) is treated as if the + // timezone is not specified. + static bool FromStringInternal(const char* time_string, + bool is_local, + Time* parsed_time); + // The representation of Jan 1, 1970 UTC in microseconds since the // platform-dependent epoch. static const int64 kTimeTToMicrosecondsOffset; diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index bc1340b..4cbe03c 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc @@ -1097,7 +1097,18 @@ bool HttpResponseHeaders::GetTimeValuedHeader(const std::string& name, if (!EnumerateHeader(NULL, name, &value)) return false; - return Time::FromString(value.c_str(), result); + // When parsing HTTP dates it's beneficial to default to GMT because: + // 1. RFC2616 3.3.1 says times should always be specified in GMT + // 2. Only counter-example incorrectly appended "UTC" (crbug.com/153759) + // 3. When adjusting cookie expiration times for clock skew + // (crbug.com/135131) this better matches our cookie expiration + // time parser which ignores timezone specifiers and assumes GMT. + // 4. This is exactly what Firefox does. + // TODO(pauljensen): The ideal solution would be to return false if the + // timezone could not be understood so as to avoid makeing other calculations + // based on an incorrect time. This would require modifying the time + // library or duplicating the code. (http://crbug.com/158327) + return Time::FromUTCString(value.c_str(), result); } bool HttpResponseHeaders::IsKeepAlive() const { diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc index 981fa10..28d97dd 100644 --- a/net/http/http_response_headers_unittest.cc +++ b/net/http/http_response_headers_unittest.cc @@ -547,6 +547,36 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_DateValued) { EXPECT_EQ("Wed, 01 Aug 2007 23:23:45 GMT", value); } +TEST(HttpResponseHeadersTest, DefaultDateToGMT) { + // Verify we make the best interpretation when parsing dates that incorrectly + // do not end in "GMT" as RFC2616 requires. + std::string headers = + "HTTP/1.1 200 OK\n" + "Date: Tue, 07 Aug 2007 23:10:55\n" + "Last-Modified: Tue, 07 Aug 2007 19:10:55 EDT\n" + "Expires: Tue, 07 Aug 2007 23:10:55 UTC\n"; + HeadersToRaw(&headers); + scoped_refptr<net::HttpResponseHeaders> parsed( + new net::HttpResponseHeaders(headers)); + base::Time expected_value; + ASSERT_TRUE(base::Time::FromString("Tue, 07 Aug 2007 23:10:55 GMT", + &expected_value)); + + base::Time value; + // When the timezone is missing, GMT is a good guess as its what RFC2616 + // requires. + EXPECT_TRUE(parsed->GetDateValue(&value)); + EXPECT_EQ(expected_value, value); + // If GMT is missing but an RFC822-conforming one is present, use that. + EXPECT_TRUE(parsed->GetLastModifiedValue(&value)); + EXPECT_EQ(expected_value, value); + // If an unknown timezone is present, treat like a missing timezone and + // default to GMT. The only example of a web server not specifying "GMT" + // used "UTC" which is equivalent to GMT. + if (parsed->GetExpiresValue(&value)) + EXPECT_EQ(expected_value, value); +} + TEST(HttpResponseHeadersTest, GetMimeType) { const ContentTypeTestData tests[] = { { "HTTP/1.1 200 OK\n" |