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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 : StringToCookieSameSite(pairs_[same_site_index_].second); | 188 : StringToCookieSameSite(pairs_[same_site_index_].second); |
189 } | 189 } |
190 | 190 |
191 CookiePriority ParsedCookie::Priority() const { | 191 CookiePriority ParsedCookie::Priority() const { |
192 return (priority_index_ == 0) | 192 return (priority_index_ == 0) |
193 ? COOKIE_PRIORITY_DEFAULT | 193 ? COOKIE_PRIORITY_DEFAULT |
194 : StringToCookiePriority(pairs_[priority_index_].second); | 194 : StringToCookiePriority(pairs_[priority_index_].second); |
195 } | 195 } |
196 | 196 |
197 bool ParsedCookie::SetName(const std::string& name) { | 197 bool ParsedCookie::SetName(const std::string& name) { |
198 if (!IsValidToken(name)) | 198 if (!name.empty() && !IsValidToken(name)) |
199 return false; | 199 return false; |
200 if (pairs_.empty()) | 200 if (pairs_.empty()) |
201 pairs_.push_back(std::make_pair("", "")); | 201 pairs_.push_back(std::make_pair("", "")); |
202 pairs_[0].first = name; | 202 pairs_[0].first = name; |
203 return true; | 203 return true; |
204 } | 204 } |
205 | 205 |
206 bool ParsedCookie::SetValue(const std::string& value) { | 206 bool ParsedCookie::SetValue(const std::string& value) { |
207 if (!IsValidCookieValue(value)) | 207 if (!IsValidCookieValue(value)) |
208 return false; | 208 return false; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 | 356 |
357 // Ok, here we go. We should be expecting to be starting somewhere | 357 // Ok, here we go. We should be expecting to be starting somewhere |
358 // before the cookie line, not including any header name... | 358 // before the cookie line, not including any header name... |
359 std::string::const_iterator start = cookie_line.begin(); | 359 std::string::const_iterator start = cookie_line.begin(); |
360 std::string::const_iterator it = start; | 360 std::string::const_iterator it = start; |
361 | 361 |
362 // TODO(erikwright): Make sure we're stripping \r\n in the network code. | 362 // TODO(erikwright): Make sure we're stripping \r\n in the network code. |
363 // Then we can log any unexpected terminators. | 363 // Then we can log any unexpected terminators. |
364 std::string::const_iterator end = FindFirstTerminator(cookie_line); | 364 std::string::const_iterator end = FindFirstTerminator(cookie_line); |
365 | 365 |
366 // For an empty |cookie_line|, add an empty-key with an empty value, which | |
367 // has the effect of clearing any prior setting of the empty-key. This is done | |
368 // to match the behavior of other browsers. See https://crbug.com/601786. | |
369 if (it == end) { | |
370 pairs_.push_back(TokenValuePair("", "")); | |
371 return; | |
372 } | |
373 | |
366 for (int pair_num = 0; pair_num < kMaxPairs && it != end; ++pair_num) { | 374 for (int pair_num = 0; pair_num < kMaxPairs && it != end; ++pair_num) { |
367 TokenValuePair pair; | 375 TokenValuePair pair; |
368 | 376 |
369 std::string::const_iterator token_start, token_end; | 377 std::string::const_iterator token_start, token_end; |
370 if (!ParseToken(&it, end, &token_start, &token_end)) | 378 bool did_parse_token = ParseToken(&it, end, &token_start, &token_end); |
379 // Allow first token to be treated as empty-key if unparsable | |
380 if (!did_parse_token && pair_num != 0) | |
371 break; | 381 break; |
372 | 382 |
373 if (it == end || *it != '=') { | 383 if (!did_parse_token || it == end || *it != '=') { |
374 // We have a token-value, we didn't have any token name. | 384 // We have a token-value, we didn't have any token name. |
375 if (pair_num == 0) { | 385 if (pair_num == 0) { |
376 // For the first time around, we want to treat single values | 386 // For the first time around, we want to treat single values |
377 // as a value with an empty name. (Mozilla bug 169091). | 387 // as a value with an empty name. (Mozilla bug 169091). |
378 // IE seems to also have this behavior, ex "AAA", and "AAA=10" will | 388 // IE seems to also have this behavior, ex "AAA", and "AAA=10" will |
379 // set 2 different cookies, and setting "BBB" will then replace "AAA". | 389 // set 2 different cookies, and setting "BBB" will then replace "AAA". |
380 pair.first = ""; | 390 pair.first = ""; |
381 // Rewind to the beginning of what we thought was the token name, | 391 // Rewind to the beginning of what we thought was the token name, |
382 // and let it get parsed as a value. | 392 // and let it get parsed as a value. If parsing failed, start the value |
383 it = token_start; | 393 // parsing at the very beginning. |
394 if (did_parse_token) | |
395 it = token_start; | |
396 else | |
397 it = start; | |
mmenke
2016/08/16 15:06:47
nit: Use braces in else/if.
Also, another option
jww
2016/08/16 18:18:17
Did both.
| |
384 } else { | 398 } else { |
385 // Any not-first attribute we want to treat a value as a | 399 // Any not-first attribute we want to treat a value as a |
386 // name with an empty value... This is so something like | 400 // name with an empty value... This is so something like |
387 // "secure;" will get parsed as a Token name, and not a value. | 401 // "secure;" will get parsed as a Token name, and not a value. |
388 pair.first = std::string(token_start, token_end); | 402 pair.first = std::string(token_start, token_end); |
389 } | 403 } |
390 } else { | 404 } else { |
391 // We have a TOKEN=VALUE. | 405 // We have a TOKEN=VALUE. |
392 pair.first = std::string(token_start, token_end); | 406 pair.first = std::string(token_start, token_end); |
393 ++it; // Skip past the '='. | 407 ++it; // Skip past the '='. |
(...skipping 20 matching lines...) Expand all Loading... | |
414 pairs_.push_back(pair); | 428 pairs_.push_back(pair); |
415 | 429 |
416 // We've processed a token/value pair, we're either at the end of | 430 // We've processed a token/value pair, we're either at the end of |
417 // the string or a ValueSeparator like ';', which we want to skip. | 431 // the string or a ValueSeparator like ';', which we want to skip. |
418 if (it != end) | 432 if (it != end) |
419 ++it; | 433 ++it; |
420 } | 434 } |
421 } | 435 } |
422 | 436 |
423 void ParsedCookie::SetupAttributes() { | 437 void ParsedCookie::SetupAttributes() { |
424 // Ignore Set-Cookie directive where name and value are both empty. | |
425 if (pairs_[0].first.empty() && pairs_[0].second.empty()) { | |
426 pairs_.clear(); | |
427 return; | |
428 } | |
429 | |
430 // We skip over the first token/value, the user supplied one. | 438 // We skip over the first token/value, the user supplied one. |
431 for (size_t i = 1; i < pairs_.size(); ++i) { | 439 for (size_t i = 1; i < pairs_.size(); ++i) { |
432 if (pairs_[i].first == kPathTokenName) { | 440 if (pairs_[i].first == kPathTokenName) { |
433 path_index_ = i; | 441 path_index_ = i; |
434 } else if (pairs_[i].first == kDomainTokenName) { | 442 } else if (pairs_[i].first == kDomainTokenName && pairs_[i].second != "") { |
435 domain_index_ = i; | 443 domain_index_ = i; |
436 } else if (pairs_[i].first == kExpiresTokenName) { | 444 } else if (pairs_[i].first == kExpiresTokenName) { |
437 expires_index_ = i; | 445 expires_index_ = i; |
438 } else if (pairs_[i].first == kMaxAgeTokenName) { | 446 } else if (pairs_[i].first == kMaxAgeTokenName) { |
439 maxage_index_ = i; | 447 maxage_index_ = i; |
440 } else if (pairs_[i].first == kSecureTokenName) { | 448 } else if (pairs_[i].first == kSecureTokenName) { |
441 secure_index_ = i; | 449 secure_index_ = i; |
442 } else if (pairs_[i].first == kHttpOnlyTokenName) { | 450 } else if (pairs_[i].first == kHttpOnlyTokenName) { |
443 httponly_index_ = i; | 451 httponly_index_ = i; |
444 } else if (pairs_[i].first == kSameSiteTokenName) { | 452 } else if (pairs_[i].first == kSameSiteTokenName) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 --*indexes[i]; | 512 --*indexes[i]; |
505 } | 513 } |
506 pairs_.erase(pairs_.begin() + index); | 514 pairs_.erase(pairs_.begin() + index); |
507 } | 515 } |
508 | 516 |
509 bool ParsedCookie::IsSameSiteAttributeValid() const { | 517 bool ParsedCookie::IsSameSiteAttributeValid() const { |
510 return same_site_index_ == 0 || SameSite() != CookieSameSite::DEFAULT_MODE; | 518 return same_site_index_ == 0 || SameSite() != CookieSameSite::DEFAULT_MODE; |
511 } | 519 } |
512 | 520 |
513 } // namespace | 521 } // namespace |
OLD | NEW |