Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: net/cookies/cookie_util.cc

Issue 10785017: Move CanonicalCookie into separate files (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include "net/cookies/cookie_util.h" 5 #include "net/cookies/cookie_util.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/string_tokenizer.h"
9 #include "base/string_util.h"
8 #include "googleurl/src/gurl.h" 10 #include "googleurl/src/gurl.h"
9 #include "net/base/net_util.h" 11 #include "net/base/net_util.h"
10 #include "net/base/registry_controlled_domain.h" 12 #include "net/base/registry_controlled_domain.h"
11 13
12 namespace net { 14 namespace net {
13 namespace cookie_util { 15 namespace cookie_util {
14 16
15 bool DomainIsHostOnly(const std::string& domain_string) { 17 bool DomainIsHostOnly(const std::string& domain_string) {
16 return (domain_string.empty() || domain_string[0] != '.'); 18 return (domain_string.empty() || domain_string[0] != '.');
17 } 19 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 (cookie_domain != ("." + url_host)) : 69 (cookie_domain != ("." + url_host)) :
68 (url_host.compare(url_host.length() - cookie_domain.length(), 70 (url_host.compare(url_host.length() - cookie_domain.length(),
69 cookie_domain.length(), cookie_domain) != 0); 71 cookie_domain.length(), cookie_domain) != 0);
70 if (is_suffix) 72 if (is_suffix)
71 return false; 73 return false;
72 74
73 *result = cookie_domain; 75 *result = cookie_domain;
74 return true; 76 return true;
75 } 77 }
76 78
79 // Parse a cookie expiration time. We try to be lenient, but we need to
80 // assume some order to distinguish the fields. The basic rules:
81 // - The month name must be present and prefix the first 3 letters of the
82 // full month name (jan for January, jun for June).
83 // - If the year is <= 2 digits, it must occur after the day of month.
84 // - The time must be of the format hh:mm:ss.
85 // An average cookie expiration will look something like this:
86 // Sat, 15-Apr-17 21:01:22 GMT
87 base::Time ParseCookieTime(const std::string& time_string) {
88 static const char* kMonths[] = { "jan", "feb", "mar", "apr", "may", "jun",
89 "jul", "aug", "sep", "oct", "nov", "dec" };
90 static const int kMonthsLen = arraysize(kMonths);
91 // We want to be pretty liberal, and support most non-ascii and non-digit
92 // characters as a delimiter. We can't treat : as a delimiter, because it
93 // is the delimiter for hh:mm:ss, and we want to keep this field together.
94 // We make sure to include - and +, since they could prefix numbers.
95 // If the cookie attribute came in in quotes (ex expires="XXX"), the quotes
96 // will be preserved, and we will get them here. So we make sure to include
97 // quote characters, and also \ for anything that was internally escaped.
98 static const char* kDelimiters = "\t !\"#$%&'()*+,-./;<=>?@[\\]^_`{|}~";
99
100 base::Time::Exploded exploded = {0};
101
102 StringTokenizer tokenizer(time_string, kDelimiters);
103
104 bool found_day_of_month = false;
105 bool found_month = false;
106 bool found_time = false;
107 bool found_year = false;
108
109 while (tokenizer.GetNext()) {
110 const std::string token = tokenizer.token();
111 DCHECK(!token.empty());
112 bool numerical = IsAsciiDigit(token[0]);
113
114 // String field
115 if (!numerical) {
116 if (!found_month) {
117 for (int i = 0; i < kMonthsLen; ++i) {
118 // Match prefix, so we could match January, etc
119 if (base::strncasecmp(token.c_str(), kMonths[i], 3) == 0) {
120 exploded.month = i + 1;
121 found_month = true;
122 break;
123 }
124 }
125 } else {
126 // If we've gotten here, it means we've already found and parsed our
127 // month, and we have another string, which we would expect to be the
128 // the time zone name. According to the RFC and my experiments with
129 // how sites format their expirations, we don't have much of a reason
130 // to support timezones. We don't want to ever barf on user input,
131 // but this DCHECK should pass for well-formed data.
132 // DCHECK(token == "GMT");
133 }
134 // Numeric field w/ a colon
135 } else if (token.find(':') != std::string::npos) {
136 if (!found_time &&
137 #ifdef COMPILER_MSVC
erikwright (departed) 2012/07/17 15:59:20 #include "build/build_config.h"
battre 2012/07/18 08:48:43 Done.
138 sscanf_s(
139 #else
140 sscanf(
erikwright (departed) 2012/07/17 15:59:20 #include <cstdio>
battre 2012/07/18 08:48:43 Done.
141 #endif
142 token.c_str(), "%2u:%2u:%2u", &exploded.hour,
143 &exploded.minute, &exploded.second) == 3) {
144 found_time = true;
145 } else {
146 // We should only ever encounter one time-like thing. If we're here,
147 // it means we've found a second, which shouldn't happen. We keep
148 // the first. This check should be ok for well-formed input:
149 // NOTREACHED();
150 }
151 // Numeric field
152 } else {
153 // Overflow with atoi() is unspecified, so we enforce a max length.
154 if (!found_day_of_month && token.length() <= 2) {
155 exploded.day_of_month = atoi(token.c_str());
156 found_day_of_month = true;
157 } else if (!found_year && token.length() <= 5) {
158 exploded.year = atoi(token.c_str());
erikwright (departed) 2012/07/17 15:59:20 <cstdlib>
battre 2012/07/18 08:48:43 Done.
159 found_year = true;
160 } else {
161 // If we're here, it means we've either found an extra numeric field,
162 // or a numeric field which was too long. For well-formed input, the
163 // following check would be reasonable:
164 // NOTREACHED();
165 }
166 }
167 }
168
169 if (!found_day_of_month || !found_month || !found_time || !found_year) {
170 // We didn't find all of the fields we need. For well-formed input, the
171 // following check would be reasonable:
172 // NOTREACHED() << "Cookie parse expiration failed: " << time_string;
173 return base::Time();
174 }
175
176 // Normalize the year to expand abbreviated years to the full year.
177 if (exploded.year >= 69 && exploded.year <= 99)
178 exploded.year += 1900;
179 if (exploded.year >= 0 && exploded.year <= 68)
180 exploded.year += 2000;
181
182 // If our values are within their correct ranges, we got our time.
183 if (exploded.day_of_month >= 1 && exploded.day_of_month <= 31 &&
184 exploded.month >= 1 && exploded.month <= 12 &&
185 exploded.year >= 1601 && exploded.year <= 30827 &&
186 exploded.hour <= 23 && exploded.minute <= 59 && exploded.second <= 59) {
187 return base::Time::FromUTCExploded(exploded);
188 }
189
190 // One of our values was out of expected range. For well-formed input,
191 // the following check would be reasonable:
192 // NOTREACHED() << "Cookie exploded expiration failed: " << time_string;
193
194 return base::Time();
195 }
196
77 } // namespace cookie_utils 197 } // namespace cookie_utils
78 } // namespace net 198 } // namespace net
79 199
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698