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 // Portions of this code based on Mozilla: | 5 // Portions of this code based on Mozilla: |
6 // (netwerk/cookie/src/nsCookieService.cpp) | 6 // (netwerk/cookie/src/nsCookieService.cpp) |
7 /* ***** BEGIN LICENSE BLOCK ***** | 7 /* ***** BEGIN LICENSE BLOCK ***** |
8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
9 * | 9 * |
10 * The contents of this file are subject to the Mozilla Public License Version | 10 * The contents of this file are subject to the Mozilla Public License Version |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // The cookie path was invalid or a single '/'. | 97 // The cookie path was invalid or a single '/'. |
98 if (idx == 0 || idx == std::string::npos) | 98 if (idx == 0 || idx == std::string::npos) |
99 return std::string("/"); | 99 return std::string("/"); |
100 | 100 |
101 // Return up to the rightmost '/'. | 101 // Return up to the rightmost '/'. |
102 return url_path.substr(0, idx); | 102 return url_path.substr(0, idx); |
103 } | 103 } |
104 | 104 |
105 } // namespace | 105 } // namespace |
106 | 106 |
107 CanonicalCookie::CanonicalCookie() | 107 CanonicalCookie::CanonicalCookie() : secure_(false), httponly_(false) { |
108 : secure_(false), | |
109 httponly_(false) { | |
110 } | 108 } |
111 | 109 |
112 CanonicalCookie::CanonicalCookie( | 110 CanonicalCookie::CanonicalCookie(const GURL& url, |
113 const GURL& url, const std::string& name, const std::string& value, | 111 const std::string& name, |
114 const std::string& domain, const std::string& path, | 112 const std::string& value, |
115 const base::Time& creation, const base::Time& expiration, | 113 const std::string& domain, |
116 const base::Time& last_access, bool secure, bool httponly, | 114 const std::string& path, |
117 CookiePriority priority) | 115 const base::Time& creation, |
| 116 const base::Time& expiration, |
| 117 const base::Time& last_access, |
| 118 bool secure, |
| 119 bool httponly, |
| 120 CookiePriority priority) |
118 : source_(GetCookieSourceFromURL(url)), | 121 : source_(GetCookieSourceFromURL(url)), |
119 name_(name), | 122 name_(name), |
120 value_(value), | 123 value_(value), |
121 domain_(domain), | 124 domain_(domain), |
122 path_(path), | 125 path_(path), |
123 creation_date_(creation), | 126 creation_date_(creation), |
124 expiry_date_(expiration), | 127 expiry_date_(expiration), |
125 last_access_date_(last_access), | 128 last_access_date_(last_access), |
126 secure_(secure), | 129 secure_(secure), |
127 httponly_(httponly), | 130 httponly_(httponly), |
(...skipping 12 matching lines...) Expand all Loading... |
140 priority_(pc.Priority()) { | 143 priority_(pc.Priority()) { |
141 if (pc.HasExpires()) | 144 if (pc.HasExpires()) |
142 expiry_date_ = CanonExpiration(pc, creation_date_, creation_date_); | 145 expiry_date_ = CanonExpiration(pc, creation_date_, creation_date_); |
143 | 146 |
144 // Do the best we can with the domain. | 147 // Do the best we can with the domain. |
145 std::string cookie_domain; | 148 std::string cookie_domain; |
146 std::string domain_string; | 149 std::string domain_string; |
147 if (pc.HasDomain()) { | 150 if (pc.HasDomain()) { |
148 domain_string = pc.Domain(); | 151 domain_string = pc.Domain(); |
149 } | 152 } |
150 bool result | 153 bool result = cookie_util::GetCookieDomainWithString( |
151 = cookie_util::GetCookieDomainWithString(url, domain_string, | 154 url, domain_string, &cookie_domain); |
152 &cookie_domain); | |
153 // Caller is responsible for passing in good arguments. | 155 // Caller is responsible for passing in good arguments. |
154 DCHECK(result); | 156 DCHECK(result); |
155 domain_ = cookie_domain; | 157 domain_ = cookie_domain; |
156 } | 158 } |
157 | 159 |
158 CanonicalCookie::~CanonicalCookie() { | 160 CanonicalCookie::~CanonicalCookie() { |
159 } | 161 } |
160 | 162 |
161 std::string CanonicalCookie::GetCookieSourceFromURL(const GURL& url) { | 163 std::string CanonicalCookie::GetCookieSourceFromURL(const GURL& url) { |
162 if (url.SchemeIsFile()) | 164 if (url.SchemeIsFile()) |
(...skipping 21 matching lines...) Expand all Loading... |
184 const Time& current, | 186 const Time& current, |
185 const Time& server_time) { | 187 const Time& server_time) { |
186 // First, try the Max-Age attribute. | 188 // First, try the Max-Age attribute. |
187 uint64 max_age = 0; | 189 uint64 max_age = 0; |
188 if (pc.HasMaxAge() && | 190 if (pc.HasMaxAge() && |
189 #ifdef COMPILER_MSVC | 191 #ifdef COMPILER_MSVC |
190 sscanf_s( | 192 sscanf_s( |
191 #else | 193 #else |
192 sscanf( | 194 sscanf( |
193 #endif | 195 #endif |
194 pc.MaxAge().c_str(), " %" PRIu64, &max_age) == 1) { | 196 pc.MaxAge().c_str(), " %" PRIu64, &max_age) == 1) { |
195 return current + TimeDelta::FromSeconds(max_age); | 197 return current + TimeDelta::FromSeconds(max_age); |
196 } | 198 } |
197 | 199 |
198 // Try the Expires attribute. | 200 // Try the Expires attribute. |
199 if (pc.HasExpires() && !pc.Expires().empty()) { | 201 if (pc.HasExpires() && !pc.Expires().empty()) { |
200 // Adjust for clock skew between server and host. | 202 // Adjust for clock skew between server and host. |
201 base::Time parsed_expiry = cookie_util::ParseCookieTime(pc.Expires()); | 203 base::Time parsed_expiry = cookie_util::ParseCookieTime(pc.Expires()); |
202 if (!parsed_expiry.is_null()) | 204 if (!parsed_expiry.is_null()) |
203 return parsed_expiry + (current - server_time); | 205 return parsed_expiry + (current - server_time); |
204 } | 206 } |
(...skipping 22 matching lines...) Expand all Loading... |
227 std::string cookie_domain; | 229 std::string cookie_domain; |
228 if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) { | 230 if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) { |
229 return NULL; | 231 return NULL; |
230 } | 232 } |
231 | 233 |
232 std::string cookie_path = CanonicalCookie::CanonPath(url, parsed_cookie); | 234 std::string cookie_path = CanonicalCookie::CanonPath(url, parsed_cookie); |
233 Time server_time(creation_time); | 235 Time server_time(creation_time); |
234 if (options.has_server_time()) | 236 if (options.has_server_time()) |
235 server_time = options.server_time(); | 237 server_time = options.server_time(); |
236 | 238 |
237 Time cookie_expires = CanonicalCookie::CanonExpiration(parsed_cookie, | 239 Time cookie_expires = CanonicalCookie::CanonExpiration( |
238 creation_time, | 240 parsed_cookie, creation_time, server_time); |
239 server_time); | |
240 | 241 |
241 return new CanonicalCookie(url, parsed_cookie.Name(), parsed_cookie.Value(), | 242 return new CanonicalCookie(url, |
242 cookie_domain, cookie_path, creation_time, | 243 parsed_cookie.Name(), |
243 cookie_expires, creation_time, | 244 parsed_cookie.Value(), |
| 245 cookie_domain, |
| 246 cookie_path, |
| 247 creation_time, |
| 248 cookie_expires, |
| 249 creation_time, |
244 parsed_cookie.IsSecure(), | 250 parsed_cookie.IsSecure(), |
245 parsed_cookie.IsHttpOnly(), | 251 parsed_cookie.IsHttpOnly(), |
246 parsed_cookie.Priority()); | 252 parsed_cookie.Priority()); |
247 } | 253 } |
248 | 254 |
249 CanonicalCookie* CanonicalCookie::Create(const GURL& url, | 255 CanonicalCookie* CanonicalCookie::Create(const GURL& url, |
250 const std::string& name, | 256 const std::string& name, |
251 const std::string& value, | 257 const std::string& value, |
252 const std::string& domain, | 258 const std::string& domain, |
253 const std::string& path, | 259 const std::string& path, |
254 const base::Time& creation, | 260 const base::Time& creation, |
255 const base::Time& expiration, | 261 const base::Time& expiration, |
256 bool secure, | 262 bool secure, |
257 bool http_only, | 263 bool http_only, |
258 CookiePriority priority) { | 264 CookiePriority priority) { |
259 // Expect valid attribute tokens and values, as defined by the ParsedCookie | 265 // Expect valid attribute tokens and values, as defined by the ParsedCookie |
260 // logic, otherwise don't create the cookie. | 266 // logic, otherwise don't create the cookie. |
261 std::string parsed_name = ParsedCookie::ParseTokenString(name); | 267 std::string parsed_name = ParsedCookie::ParseTokenString(name); |
262 if (parsed_name != name) | 268 if (parsed_name != name) |
263 return NULL; | 269 return NULL; |
264 std::string parsed_value = ParsedCookie::ParseValueString(value); | 270 std::string parsed_value = ParsedCookie::ParseValueString(value); |
265 if (parsed_value != value) | 271 if (parsed_value != value) |
266 return NULL; | 272 return NULL; |
267 | 273 |
268 std::string parsed_domain = ParsedCookie::ParseValueString(domain); | 274 std::string parsed_domain = ParsedCookie::ParseValueString(domain); |
269 if (parsed_domain != domain) | 275 if (parsed_domain != domain) |
270 return NULL; | 276 return NULL; |
271 std::string cookie_domain; | 277 std::string cookie_domain; |
272 if (!cookie_util::GetCookieDomainWithString(url, parsed_domain, | 278 if (!cookie_util::GetCookieDomainWithString( |
273 &cookie_domain)) { | 279 url, parsed_domain, &cookie_domain)) { |
274 return NULL; | 280 return NULL; |
275 } | 281 } |
276 | 282 |
277 std::string parsed_path = ParsedCookie::ParseValueString(path); | 283 std::string parsed_path = ParsedCookie::ParseValueString(path); |
278 if (parsed_path != path) | 284 if (parsed_path != path) |
279 return NULL; | 285 return NULL; |
280 | 286 |
281 std::string cookie_path = CanonPathWithString(url, parsed_path); | 287 std::string cookie_path = CanonPathWithString(url, parsed_path); |
282 // Expect that the path was either not specified (empty), or is valid. | 288 // Expect that the path was either not specified (empty), or is valid. |
283 if (!parsed_path.empty() && cookie_path != parsed_path) | 289 if (!parsed_path.empty() && cookie_path != parsed_path) |
284 return NULL; | 290 return NULL; |
285 // Canonicalize path again to make sure it escapes characters as needed. | 291 // Canonicalize path again to make sure it escapes characters as needed. |
286 url::Component path_component(0, cookie_path.length()); | 292 url::Component path_component(0, cookie_path.length()); |
287 url::RawCanonOutputT<char> canon_path; | 293 url::RawCanonOutputT<char> canon_path; |
288 url::Component canon_path_component; | 294 url::Component canon_path_component; |
289 url::CanonicalizePath(cookie_path.data(), path_component, &canon_path, | 295 url::CanonicalizePath( |
290 &canon_path_component); | 296 cookie_path.data(), path_component, &canon_path, &canon_path_component); |
291 cookie_path = std::string(canon_path.data() + canon_path_component.begin, | 297 cookie_path = std::string(canon_path.data() + canon_path_component.begin, |
292 canon_path_component.len); | 298 canon_path_component.len); |
293 | 299 |
294 return new CanonicalCookie(url, parsed_name, parsed_value, cookie_domain, | 300 return new CanonicalCookie(url, |
295 cookie_path, creation, expiration, creation, | 301 parsed_name, |
296 secure, http_only, priority); | 302 parsed_value, |
| 303 cookie_domain, |
| 304 cookie_path, |
| 305 creation, |
| 306 expiration, |
| 307 creation, |
| 308 secure, |
| 309 http_only, |
| 310 priority); |
297 } | 311 } |
298 | 312 |
299 bool CanonicalCookie::IsOnPath(const std::string& url_path) const { | 313 bool CanonicalCookie::IsOnPath(const std::string& url_path) const { |
300 | |
301 // A zero length would be unsafe for our trailing '/' checks, and | 314 // A zero length would be unsafe for our trailing '/' checks, and |
302 // would also make no sense for our prefix match. The code that | 315 // would also make no sense for our prefix match. The code that |
303 // creates a CanonicalCookie should make sure the path is never zero length, | 316 // creates a CanonicalCookie should make sure the path is never zero length, |
304 // but we double check anyway. | 317 // but we double check anyway. |
305 if (path_.empty()) | 318 if (path_.empty()) |
306 return false; | 319 return false; |
307 | 320 |
308 // The Mozilla code broke this into three cases, based on if the cookie path | 321 // The Mozilla code broke this into three cases, based on if the cookie path |
309 // was longer, the same length, or shorter than the length of the url path. | 322 // was longer, the same length, or shorter than the length of the url path. |
310 // I think the approach below is simpler. | 323 // I think the approach below is simpler. |
311 | 324 |
312 // Make sure the cookie path is a prefix of the url path. If the | 325 // Make sure the cookie path is a prefix of the url path. If the |
313 // url path is shorter than the cookie path, then the cookie path | 326 // url path is shorter than the cookie path, then the cookie path |
314 // can't be a prefix. | 327 // can't be a prefix. |
315 if (url_path.find(path_) != 0) | 328 if (url_path.find(path_) != 0) |
316 return false; | 329 return false; |
317 | 330 |
318 // Now we know that url_path is >= cookie_path, and that cookie_path | 331 // Now we know that url_path is >= cookie_path, and that cookie_path |
319 // is a prefix of url_path. If they are the are the same length then | 332 // is a prefix of url_path. If they are the are the same length then |
320 // they are identical, otherwise we need an additional check: | 333 // they are identical, otherwise we need an additional check: |
321 | 334 |
322 // In order to avoid in correctly matching a cookie path of /blah | 335 // In order to avoid in correctly matching a cookie path of /blah |
323 // with a request path of '/blahblah/', we need to make sure that either | 336 // with a request path of '/blahblah/', we need to make sure that either |
324 // the cookie path ends in a trailing '/', or that we prefix up to a '/' | 337 // the cookie path ends in a trailing '/', or that we prefix up to a '/' |
325 // in the url path. Since we know that the url path length is greater | 338 // in the url path. Since we know that the url path length is greater |
326 // than the cookie path length, it's safe to index one byte past. | 339 // than the cookie path length, it's safe to index one byte past. |
327 if (path_.length() != url_path.length() && | 340 if (path_.length() != url_path.length() && path_[path_.length() - 1] != '/' && |
328 path_[path_.length() - 1] != '/' && | |
329 url_path[path_.length()] != '/') | 341 url_path[path_.length()] != '/') |
330 return false; | 342 return false; |
331 | 343 |
332 return true; | 344 return true; |
333 } | 345 } |
334 | 346 |
335 bool CanonicalCookie::IsDomainMatch(const std::string& host) const { | 347 bool CanonicalCookie::IsDomainMatch(const std::string& host) const { |
336 // Can domain match in two ways; as a domain cookie (where the cookie | 348 // Can domain match in two ways; as a domain cookie (where the cookie |
337 // domain begins with ".") or as a host cookie (where it doesn't). | 349 // domain begins with ".") or as a host cookie (where it doesn't). |
338 | 350 |
(...skipping 16 matching lines...) Expand all Loading... |
355 return false; | 367 return false; |
356 | 368 |
357 // The host with a "." prefixed. | 369 // The host with a "." prefixed. |
358 if (domain_.compare(1, std::string::npos, host) == 0) | 370 if (domain_.compare(1, std::string::npos, host) == 0) |
359 return true; | 371 return true; |
360 | 372 |
361 // A pure suffix of the host (ok since we know the domain already | 373 // A pure suffix of the host (ok since we know the domain already |
362 // starts with a ".") | 374 // starts with a ".") |
363 return (host.length() > domain_.length() && | 375 return (host.length() > domain_.length() && |
364 host.compare(host.length() - domain_.length(), | 376 host.compare(host.length() - domain_.length(), |
365 domain_.length(), domain_) == 0); | 377 domain_.length(), |
| 378 domain_) == 0); |
366 } | 379 } |
367 | 380 |
368 bool CanonicalCookie::IncludeForRequestURL(const GURL& url, | 381 bool CanonicalCookie::IncludeForRequestURL(const GURL& url, |
369 const CookieOptions& options) const { | 382 const CookieOptions& options) const { |
370 // Filter out HttpOnly cookies, per options. | 383 // Filter out HttpOnly cookies, per options. |
371 if (options.exclude_httponly() && IsHttpOnly()) | 384 if (options.exclude_httponly() && IsHttpOnly()) |
372 return false; | 385 return false; |
373 // Secure cookies should not be included in requests for URLs with an | 386 // Secure cookies should not be included in requests for URLs with an |
374 // insecure scheme. | 387 // insecure scheme. |
375 if (IsSecure() && !url.SchemeIsSecure()) | 388 if (IsSecure() && !url.SchemeIsSecure()) |
376 return false; | 389 return false; |
377 // Don't include cookies for requests that don't apply to the cookie domain. | 390 // Don't include cookies for requests that don't apply to the cookie domain. |
378 if (!IsDomainMatch(url.host())) | 391 if (!IsDomainMatch(url.host())) |
379 return false; | 392 return false; |
380 // Don't include cookies for requests with a url path that does not path | 393 // Don't include cookies for requests with a url path that does not path |
381 // match the cookie-path. | 394 // match the cookie-path. |
382 if (!IsOnPath(url.path())) | 395 if (!IsOnPath(url.path())) |
383 return false; | 396 return false; |
384 | 397 |
385 return true; | 398 return true; |
386 } | 399 } |
387 | 400 |
388 std::string CanonicalCookie::DebugString() const { | 401 std::string CanonicalCookie::DebugString() const { |
389 return base::StringPrintf( | 402 return base::StringPrintf( |
390 "name: %s value: %s domain: %s path: %s creation: %" | 403 "name: %s value: %s domain: %s path: %s creation: %" PRId64, |
391 PRId64, | 404 name_.c_str(), |
392 name_.c_str(), value_.c_str(), | 405 value_.c_str(), |
393 domain_.c_str(), path_.c_str(), | 406 domain_.c_str(), |
| 407 path_.c_str(), |
394 static_cast<int64>(creation_date_.ToTimeT())); | 408 static_cast<int64>(creation_date_.ToTimeT())); |
395 } | 409 } |
396 | 410 |
397 } // namespace net | 411 } // namespace net |
OLD | NEW |