Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
|
erikwright (departed)
2013/05/24 14:15:56
Was this removed intentionally?
jww
2013/05/24 17:56:33
Nope, not at all. Fixed.
On 2013/05/24 14:15:56, e
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | 1 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 2 // found in the LICENSE file. |
| 4 | 3 |
| 5 // Portions of this code based on Mozilla: | 4 // Portions of this code based on Mozilla: |
| 6 // (netwerk/cookie/src/nsCookieService.cpp) | 5 // (netwerk/cookie/src/nsCookieService.cpp) |
| 7 /* ***** BEGIN LICENSE BLOCK ***** | 6 /* ***** BEGIN LICENSE BLOCK ***** |
| 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 7 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 9 * | 8 * |
| 10 * The contents of this file are subject to the Mozilla Public License Version | 9 * The contents of this file are subject to the Mozilla Public License Version |
| 11 * 1.1 (the "License"); you may not use this file except in compliance with | 10 * 1.1 (the "License"); you may not use this file except in compliance with |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 38 * decision by deleting the provisions above and replace them with the notice | 37 * decision by deleting the provisions above and replace them with the notice |
| 39 * and other provisions required by the GPL or the LGPL. If you do not delete | 38 * and other provisions required by the GPL or the LGPL. If you do not delete |
| 40 * the provisions above, a recipient may use your version of this file under | 39 * the provisions above, a recipient may use your version of this file under |
| 41 * the terms of any one of the MPL, the GPL or the LGPL. | 40 * the terms of any one of the MPL, the GPL or the LGPL. |
| 42 * | 41 * |
| 43 * ***** END LICENSE BLOCK ***** */ | 42 * ***** END LICENSE BLOCK ***** */ |
| 44 | 43 |
| 45 #include "net/cookies/parsed_cookie.h" | 44 #include "net/cookies/parsed_cookie.h" |
| 46 | 45 |
| 47 #include "base/logging.h" | 46 #include "base/logging.h" |
| 47 #include "base/metrics/histogram.h" | |
| 48 #include "base/string_util.h" | 48 #include "base/string_util.h" |
| 49 | 49 |
| 50 namespace { | 50 namespace { |
| 51 | 51 |
| 52 const char kPathTokenName[] = "path"; | 52 const char kPathTokenName[] = "path"; |
| 53 const char kDomainTokenName[] = "domain"; | 53 const char kDomainTokenName[] = "domain"; |
| 54 const char kExpiresTokenName[] = "expires"; | 54 const char kExpiresTokenName[] = "expires"; |
| 55 const char kMaxAgeTokenName[] = "max-age"; | 55 const char kMaxAgeTokenName[] = "max-age"; |
| 56 const char kSecureTokenName[] = "secure"; | 56 const char kSecureTokenName[] = "secure"; |
| 57 const char kHttpOnlyTokenName[] = "httponly"; | 57 const char kHttpOnlyTokenName[] = "httponly"; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 if (value.size() >= 2 && *value.begin() == '"' && *(value.end()-1) == '"') | 123 if (value.size() >= 2 && *value.begin() == '"' && *(value.end()-1) == '"') |
| 124 skip = 1; | 124 skip = 1; |
| 125 for (std::string::const_iterator i = value.begin() + skip; | 125 for (std::string::const_iterator i = value.begin() + skip; |
| 126 i != value.end() - skip; ++i) { | 126 i != value.end() - skip; ++i) { |
| 127 bool valid_octet = | 127 bool valid_octet = |
| 128 (*i == 0x21 || | 128 (*i == 0x21 || |
| 129 (*i >= 0x23 && *i <= 0x2B) || | 129 (*i >= 0x23 && *i <= 0x2B) || |
| 130 (*i >= 0x2D && *i <= 0x3A) || | 130 (*i >= 0x2D && *i <= 0x3A) || |
| 131 (*i >= 0x3C && *i <= 0x5B) || | 131 (*i >= 0x3C && *i <= 0x5B) || |
| 132 (*i >= 0x5D && *i <= 0x7E)); | 132 (*i >= 0x5D && *i <= 0x7E)); |
| 133 if (!valid_octet) | 133 if (!valid_octet) { |
| 134 UMA_HISTOGRAM_BOOLEAN("Cookies.IsValidCookieValue", false); | |
|
erikwright (departed)
2013/05/24 14:15:56
This will be called for changing the value but not
jww
2013/05/24 17:56:33
Done.
| |
| 134 return false; | 135 return false; |
| 136 } | |
| 135 } | 137 } |
| 138 UMA_HISTOGRAM_BOOLEAN("Cookies.IsValidCookieValue", true); | |
| 136 return true; | 139 return true; |
| 137 } | 140 } |
| 138 | 141 |
| 139 bool IsValidCookieAttributeValue(const std::string& value) { | 142 bool IsValidCookieAttributeValue(const std::string& value) { |
| 140 // The greatest common denominator of cookie attribute values is | 143 // The greatest common denominator of cookie attribute values is |
| 141 // <any CHAR except CTLs or ";"> according to RFC 6265. | 144 // <any CHAR except CTLs or ";"> according to RFC 6265. |
| 142 for (std::string::const_iterator i = value.begin(); i != value.end(); ++i) { | 145 for (std::string::const_iterator i = value.begin(); i != value.end(); ++i) { |
| 143 if ((*i >= 0 && *i <= 31) || *i == ';') | 146 if ((*i >= 0 && *i <= 31) || *i == ';') { |
| 147 UMA_HISTOGRAM_BOOLEAN("Cookies.IsValidCookieAttributeValue", false); | |
|
erikwright (departed)
2013/05/24 14:15:56
These metrics will be clouded because they cover b
jww
2013/05/24 17:56:33
The goal of this measurement is to get an overall
erikwright (departed)
2013/05/27 19:19:41
The key is checked with IsValidToken and the value
| |
| 144 return false; | 148 return false; |
| 149 } | |
| 145 } | 150 } |
| 151 UMA_HISTOGRAM_BOOLEAN("Cookies.IsValidCookieAttributeValue", true); | |
| 146 return true; | 152 return true; |
| 147 } | 153 } |
| 148 | 154 |
| 149 } // namespace | 155 } // namespace |
| 150 | 156 |
| 151 namespace net { | 157 namespace net { |
| 152 | 158 |
| 153 ParsedCookie::ParsedCookie(const std::string& cookie_line) | 159 ParsedCookie::ParsedCookie(const std::string& cookie_line) |
| 154 : path_index_(0), | 160 : path_index_(0), |
| 155 domain_index_(0), | 161 domain_index_(0), |
| 156 expires_index_(0), | 162 expires_index_(0), |
| 157 maxage_index_(0), | 163 maxage_index_(0), |
| 158 secure_index_(0), | 164 secure_index_(0), |
| 159 httponly_index_(0), | 165 httponly_index_(0), |
| 160 priority_index_(0) { | 166 priority_index_(0), |
| 167 parsed_invalid_control_char_(false) { | |
| 161 | 168 |
| 162 if (cookie_line.size() > kMaxCookieSize) { | 169 if (cookie_line.size() > kMaxCookieSize) { |
| 163 VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size(); | 170 VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size(); |
| 164 return; | 171 return; |
| 165 } | 172 } |
| 166 | 173 |
| 167 ParseTokenValuePairs(cookie_line); | 174 ParseTokenValuePairs(cookie_line); |
| 175 UMA_HISTOGRAM_BOOLEAN("Cookies.ParsedInvalidControlCharacter", | |
| 176 parsed_invalid_control_char_); | |
| 168 if (!pairs_.empty()) | 177 if (!pairs_.empty()) |
| 169 SetupAttributes(); | 178 SetupAttributes(); |
| 170 } | 179 } |
| 171 | 180 |
| 172 ParsedCookie::~ParsedCookie() { | 181 ParsedCookie::~ParsedCookie() { |
| 173 } | 182 } |
| 174 | 183 |
| 175 bool ParsedCookie::IsValid() const { | 184 bool ParsedCookie::IsValid() const { |
| 176 return !pairs_.empty(); | 185 return !pairs_.empty(); |
| 177 } | 186 } |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 } | 383 } |
| 375 } else { | 384 } else { |
| 376 // We have a TOKEN=VALUE. | 385 // We have a TOKEN=VALUE. |
| 377 pair.first = std::string(token_start, token_end); | 386 pair.first = std::string(token_start, token_end); |
| 378 ++it; // Skip past the '='. | 387 ++it; // Skip past the '='. |
| 379 } | 388 } |
| 380 | 389 |
| 381 // OK, now try to parse a value. | 390 // OK, now try to parse a value. |
| 382 std::string::const_iterator value_start, value_end; | 391 std::string::const_iterator value_start, value_end; |
| 383 ParseValue(&it, end, &value_start, &value_end); | 392 ParseValue(&it, end, &value_start, &value_end); |
| 393 | |
| 394 std::string value(value_start, value_end); | |
| 395 | |
| 396 if (!IsValidCookieAttributeValue(value)) | |
|
erikwright (departed)
2013/05/24 14:15:56
Why not just put this after the assignment to pair
erikwright (departed)
2013/05/24 14:15:56
Note that the call to IsValidCookieAttributeValue
jww
2013/05/24 17:56:33
Done.
jww
2013/05/24 17:56:33
See my other responses. We want to measure a coupl
| |
| 397 parsed_invalid_control_char_ = true; | |
|
erikwright (departed)
2013/05/24 14:15:56
I suggest converting this to a local boolean and d
palmer
2013/05/24 17:38:43
I'll second that.
jww
2013/05/24 17:56:33
Done.
jww
2013/05/24 17:56:33
Done.
| |
| 398 | |
| 384 // OK, we're finished with a Token/Value. | 399 // OK, we're finished with a Token/Value. |
| 385 pair.second = std::string(value_start, value_end); | 400 pair.second = value; |
| 386 | 401 |
| 387 // From RFC2109: "Attributes (names) (attr) are case-insensitive." | 402 // From RFC2109: "Attributes (names) (attr) are case-insensitive." |
| 388 if (pair_num != 0) | 403 if (pair_num != 0) |
| 389 StringToLowerASCII(&pair.first); | 404 StringToLowerASCII(&pair.first); |
| 390 pairs_.push_back(pair); | 405 pairs_.push_back(pair); |
| 391 | 406 |
| 392 // We've processed a token/value pair, we're either at the end of | 407 // We've processed a token/value pair, we're either at the end of |
| 393 // the string or a ValueSeparator like ';', which we want to skip. | 408 // the string or a ValueSeparator like ';', which we want to skip. |
| 394 if (it != end) | 409 if (it != end) |
| 395 ++it; | 410 ++it; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 for (size_t i = 0; i < arraysize(indexes); ++i) { | 485 for (size_t i = 0; i < arraysize(indexes); ++i) { |
| 471 if (*indexes[i] == index) | 486 if (*indexes[i] == index) |
| 472 *indexes[i] = 0; | 487 *indexes[i] = 0; |
| 473 else if (*indexes[i] > index) | 488 else if (*indexes[i] > index) |
| 474 --*indexes[i]; | 489 --*indexes[i]; |
| 475 } | 490 } |
| 476 pairs_.erase(pairs_.begin() + index); | 491 pairs_.erase(pairs_.begin() + index); |
| 477 } | 492 } |
| 478 | 493 |
| 479 } // namespace | 494 } // namespace |
| OLD | NEW |