Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: net/cookies/parsed_cookie.cc

Issue 10785017: Move CanonicalCookie into separate files (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Diff Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 27 matching lines...) Expand all
38 * decision by deleting the provisions above and replace them with the notice 38 * 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 39 * 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 40 * 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. 41 * the terms of any one of the MPL, the GPL or the LGPL.
42 * 42 *
43 * ***** END LICENSE BLOCK ***** */ 43 * ***** END LICENSE BLOCK ***** */
44 44
45 #include "net/cookies/parsed_cookie.h" 45 #include "net/cookies/parsed_cookie.h"
46 46
47 #include "base/logging.h" 47 #include "base/logging.h"
48 #include "base/string_tokenizer.h"
48 #include "base/string_util.h" 49 #include "base/string_util.h"
49 50
51 using base::Time;
52
50 namespace net { 53 namespace net {
51 54
52 ParsedCookie::ParsedCookie(const std::string& cookie_line) 55 ParsedCookie::ParsedCookie(const std::string& cookie_line)
53 : is_valid_(false), 56 : is_valid_(false),
54 path_index_(0), 57 path_index_(0),
55 domain_index_(0), 58 domain_index_(0),
56 mac_key_index_(0), 59 mac_key_index_(0),
57 mac_algorithm_index_(0), 60 mac_algorithm_index_(0),
58 expires_index_(0), 61 expires_index_(0),
59 maxage_index_(0), 62 maxage_index_(0),
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 StringToLowerASCII(&pair.first); 274 StringToLowerASCII(&pair.first);
272 pairs_.push_back(pair); 275 pairs_.push_back(pair);
273 276
274 // We've processed a token/value pair, we're either at the end of 277 // We've processed a token/value pair, we're either at the end of
275 // the string or a ValueSeparator like ';', which we want to skip. 278 // the string or a ValueSeparator like ';', which we want to skip.
276 if (it != end) 279 if (it != end)
277 ++it; 280 ++it;
278 } 281 }
279 } 282 }
280 283
284 // Parse a cookie expiration time. We try to be lenient, but we need to
erikwright (departed) 2012/07/16 21:13:20 I think cookie_util.{h,cc} would be a better place
battre 2012/07/17 15:01:54 Done.
285 // assume some order to distinguish the fields. The basic rules:
286 // - The month name must be present and prefix the first 3 letters of the
287 // full month name (jan for January, jun for June).
288 // - If the year is <= 2 digits, it must occur after the day of month.
289 // - The time must be of the format hh:mm:ss.
290 // An average cookie expiration will look something like this:
291 // Sat, 15-Apr-17 21:01:22 GMT
292 //
293 // static
294 Time ParsedCookie::ParseCookieTime(const std::string& time_string) {
295 static const char* kMonths[] = { "jan", "feb", "mar", "apr", "may", "jun",
296 "jul", "aug", "sep", "oct", "nov", "dec" };
297 static const int kMonthsLen = arraysize(kMonths);
298 // We want to be pretty liberal, and support most non-ascii and non-digit
299 // characters as a delimiter. We can't treat : as a delimiter, because it
300 // is the delimiter for hh:mm:ss, and we want to keep this field together.
301 // We make sure to include - and +, since they could prefix numbers.
302 // If the cookie attribute came in in quotes (ex expires="XXX"), the quotes
303 // will be preserved, and we will get them here. So we make sure to include
304 // quote characters, and also \ for anything that was internally escaped.
305 static const char* kDelimiters = "\t !\"#$%&'()*+,-./;<=>?@[\\]^_`{|}~";
306
307 Time::Exploded exploded = {0};
308
309 StringTokenizer tokenizer(time_string, kDelimiters);
310
311 bool found_day_of_month = false;
312 bool found_month = false;
313 bool found_time = false;
314 bool found_year = false;
315
316 while (tokenizer.GetNext()) {
317 const std::string token = tokenizer.token();
318 DCHECK(!token.empty());
319 bool numerical = IsAsciiDigit(token[0]);
320
321 // String field
322 if (!numerical) {
323 if (!found_month) {
324 for (int i = 0; i < kMonthsLen; ++i) {
325 // Match prefix, so we could match January, etc
326 if (base::strncasecmp(token.c_str(), kMonths[i], 3) == 0) {
327 exploded.month = i + 1;
328 found_month = true;
329 break;
330 }
331 }
332 } else {
333 // If we've gotten here, it means we've already found and parsed our
334 // month, and we have another string, which we would expect to be the
335 // the time zone name. According to the RFC and my experiments with
336 // how sites format their expirations, we don't have much of a reason
337 // to support timezones. We don't want to ever barf on user input,
338 // but this DCHECK should pass for well-formed data.
339 // DCHECK(token == "GMT");
340 }
341 // Numeric field w/ a colon
342 } else if (token.find(':') != std::string::npos) {
343 if (!found_time &&
344 #ifdef COMPILER_MSVC
345 sscanf_s(
346 #else
347 sscanf(
348 #endif
349 token.c_str(), "%2u:%2u:%2u", &exploded.hour,
350 &exploded.minute, &exploded.second) == 3) {
351 found_time = true;
352 } else {
353 // We should only ever encounter one time-like thing. If we're here,
354 // it means we've found a second, which shouldn't happen. We keep
355 // the first. This check should be ok for well-formed input:
356 // NOTREACHED();
357 }
358 // Numeric field
359 } else {
360 // Overflow with atoi() is unspecified, so we enforce a max length.
361 if (!found_day_of_month && token.length() <= 2) {
362 exploded.day_of_month = atoi(token.c_str());
363 found_day_of_month = true;
364 } else if (!found_year && token.length() <= 5) {
365 exploded.year = atoi(token.c_str());
366 found_year = true;
367 } else {
368 // If we're here, it means we've either found an extra numeric field,
369 // or a numeric field which was too long. For well-formed input, the
370 // following check would be reasonable:
371 // NOTREACHED();
372 }
373 }
374 }
375
376 if (!found_day_of_month || !found_month || !found_time || !found_year) {
377 // We didn't find all of the fields we need. For well-formed input, the
378 // following check would be reasonable:
379 // NOTREACHED() << "Cookie parse expiration failed: " << time_string;
380 return Time();
381 }
382
383 // Normalize the year to expand abbreviated years to the full year.
384 if (exploded.year >= 69 && exploded.year <= 99)
385 exploded.year += 1900;
386 if (exploded.year >= 0 && exploded.year <= 68)
387 exploded.year += 2000;
388
389 // If our values are within their correct ranges, we got our time.
390 if (exploded.day_of_month >= 1 && exploded.day_of_month <= 31 &&
391 exploded.month >= 1 && exploded.month <= 12 &&
392 exploded.year >= 1601 && exploded.year <= 30827 &&
393 exploded.hour <= 23 && exploded.minute <= 59 && exploded.second <= 59) {
394 return Time::FromUTCExploded(exploded);
395 }
396
397 // One of our values was out of expected range. For well-formed input,
398 // the following check would be reasonable:
399 // NOTREACHED() << "Cookie exploded expiration failed: " << time_string;
400
401 return Time();
402 }
403
281 void ParsedCookie::SetupAttributes() { 404 void ParsedCookie::SetupAttributes() {
282 static const char kPathTokenName[] = "path"; 405 static const char kPathTokenName[] = "path";
283 static const char kDomainTokenName[] = "domain"; 406 static const char kDomainTokenName[] = "domain";
284 static const char kMACKeyTokenName[] = "mac-key"; 407 static const char kMACKeyTokenName[] = "mac-key";
285 static const char kMACAlgorithmTokenName[] = "mac-algorithm"; 408 static const char kMACAlgorithmTokenName[] = "mac-algorithm";
286 static const char kExpiresTokenName[] = "expires"; 409 static const char kExpiresTokenName[] = "expires";
287 static const char kMaxAgeTokenName[] = "max-age"; 410 static const char kMaxAgeTokenName[] = "max-age";
288 static const char kSecureTokenName[] = "secure"; 411 static const char kSecureTokenName[] = "secure";
289 static const char kHttpOnlyTokenName[] = "httponly"; 412 static const char kHttpOnlyTokenName[] = "httponly";
290 413
(...skipping 15 matching lines...) Expand all
306 secure_index_ = i; 429 secure_index_ = i;
307 } else if (pairs_[i].first == kHttpOnlyTokenName) { 430 } else if (pairs_[i].first == kHttpOnlyTokenName) {
308 httponly_index_ = i; 431 httponly_index_ = i;
309 } else { 432 } else {
310 /* some attribute we don't know or don't care about. */ 433 /* some attribute we don't know or don't care about. */
311 } 434 }
312 } 435 }
313 } 436 }
314 437
315 } // namespace 438 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698