| 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 |