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 |