summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-29 22:54:58 +0000
committerpauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-29 22:54:58 +0000
commit6e6acc10590856575a4c4c330197e828917dc995 (patch)
tree9ef1ac70dcf7723188a3d08222ce98d1933e1b1b
parente42285a3b4def2770cc3ad504a0d73d2d565a313 (diff)
downloadchromium_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.cc7
-rw-r--r--base/time.h22
-rw-r--r--net/http/http_response_headers.cc13
-rw-r--r--net/http/http_response_headers_unittest.cc30
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"