summaryrefslogtreecommitdiffstats
path: root/net/cookies/cookie_monster.cc
diff options
context:
space:
mode:
authorbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-12 12:21:41 +0000
committerbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-12 12:21:41 +0000
commitebfe3173617e62ccbda071f8ca367a50a5ba4ee0 (patch)
treedc4d1b827721341b8329859e1c2242370c31ea29 /net/cookies/cookie_monster.cc
parent5a76f9b471e5ef367280fb92662bdef9f83cfd57 (diff)
downloadchromium_src-ebfe3173617e62ccbda071f8ca367a50a5ba4ee0.zip
chromium_src-ebfe3173617e62ccbda071f8ca367a50a5ba4ee0.tar.gz
chromium_src-ebfe3173617e62ccbda071f8ca367a50a5ba4ee0.tar.bz2
Extract ParsedCookie into a top level class
BUG=137014,112155 TEST=no TBR=sky@chromium.org, rdsmith@chromium.org, jochen@chromium.org Review URL: https://chromiumcodereview.appspot.com/10689158 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146324 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/cookies/cookie_monster.cc')
-rw-r--r--net/cookies/cookie_monster.cc278
1 files changed, 4 insertions, 274 deletions
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index bdac04c..e44ba18 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -62,6 +62,7 @@
#include "googleurl/src/gurl.h"
#include "googleurl/src/url_canon.h"
#include "net/cookies/cookie_util.h"
+#include "net/cookies/parsed_cookie.h"
#include "net/base/registry_controlled_domain.h"
using base::Time;
@@ -190,7 +191,7 @@ struct CookieSignature {
// Determine the cookie domain to use for setting the specified cookie.
bool GetCookieDomain(const GURL& url,
- const CookieMonster::ParsedCookie& pc,
+ const ParsedCookie& pc,
std::string* result) {
std::string domain_string;
if (pc.HasDomain())
@@ -228,16 +229,14 @@ std::string CanonPathWithString(const GURL& url,
return url_path.substr(0, idx);
}
-std::string CanonPath(const GURL& url,
- const CookieMonster::ParsedCookie& pc) {
+std::string CanonPath(const GURL& url, const ParsedCookie& pc) {
std::string path_string;
if (pc.HasPath())
path_string = pc.Path();
return CanonPathWithString(url, path_string);
}
-Time CanonExpiration(const CookieMonster::ParsedCookie& pc,
- const Time& current) {
+Time CanonExpiration(const ParsedCookie& pc, const Time& current) {
// First, try the Max-Age attribute.
uint64 max_age = 0;
if (pc.HasMaxAge() &&
@@ -2335,275 +2334,6 @@ Time CookieMonster::CurrentTime() {
Time::FromInternalValue(last_time_seen_.ToInternalValue() + 1));
}
-CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line)
- : is_valid_(false),
- path_index_(0),
- domain_index_(0),
- mac_key_index_(0),
- mac_algorithm_index_(0),
- expires_index_(0),
- maxage_index_(0),
- secure_index_(0),
- httponly_index_(0) {
-
- if (cookie_line.size() > kMaxCookieSize) {
- VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size();
- return;
- }
-
- ParseTokenValuePairs(cookie_line);
- if (!pairs_.empty()) {
- is_valid_ = true;
- SetupAttributes();
- }
-}
-
-CookieMonster::ParsedCookie::~ParsedCookie() {
-}
-
-// Returns true if |c| occurs in |chars|
-// TODO(erikwright): maybe make this take an iterator, could check for end also?
-static inline bool CharIsA(const char c, const char* chars) {
- return strchr(chars, c) != NULL;
-}
-// Seek the iterator to the first occurrence of a character in |chars|.
-// Returns true if it hit the end, false otherwise.
-static inline bool SeekTo(std::string::const_iterator* it,
- const std::string::const_iterator& end,
- const char* chars) {
- for (; *it != end && !CharIsA(**it, chars); ++(*it)) {}
- return *it == end;
-}
-// Seek the iterator to the first occurrence of a character not in |chars|.
-// Returns true if it hit the end, false otherwise.
-static inline bool SeekPast(std::string::const_iterator* it,
- const std::string::const_iterator& end,
- const char* chars) {
- for (; *it != end && CharIsA(**it, chars); ++(*it)) {}
- return *it == end;
-}
-static inline bool SeekBackPast(std::string::const_iterator* it,
- const std::string::const_iterator& end,
- const char* chars) {
- for (; *it != end && CharIsA(**it, chars); --(*it)) {}
- return *it == end;
-}
-
-const char CookieMonster::ParsedCookie::kTerminator[] = "\n\r\0";
-const int CookieMonster::ParsedCookie::kTerminatorLen =
- sizeof(kTerminator) - 1;
-const char CookieMonster::ParsedCookie::kWhitespace[] = " \t";
-const char CookieMonster::ParsedCookie::kValueSeparator[] = ";";
-const char CookieMonster::ParsedCookie::kTokenSeparator[] = ";=";
-
-// Create a cookie-line for the cookie. For debugging only!
-// If we want to use this for something more than debugging, we
-// should rewrite it better...
-std::string CookieMonster::ParsedCookie::DebugString() const {
- std::string out;
- for (PairList::const_iterator it = pairs_.begin();
- it != pairs_.end(); ++it) {
- out.append(it->first);
- out.append("=");
- out.append(it->second);
- out.append("; ");
- }
- return out;
-}
-
-std::string::const_iterator CookieMonster::ParsedCookie::FindFirstTerminator(
- const std::string& s) {
- std::string::const_iterator end = s.end();
- size_t term_pos =
- s.find_first_of(std::string(kTerminator, kTerminatorLen));
- if (term_pos != std::string::npos) {
- // We found a character we should treat as an end of string.
- end = s.begin() + term_pos;
- }
- return end;
-}
-
-bool CookieMonster::ParsedCookie::ParseToken(
- std::string::const_iterator* it,
- const std::string::const_iterator& end,
- std::string::const_iterator* token_start,
- std::string::const_iterator* token_end) {
- DCHECK(it && token_start && token_end);
- std::string::const_iterator token_real_end;
-
- // Seek past any whitespace before the "token" (the name).
- // token_start should point at the first character in the token
- if (SeekPast(it, end, kWhitespace))
- return false; // No token, whitespace or empty.
- *token_start = *it;
-
- // Seek over the token, to the token separator.
- // token_real_end should point at the token separator, i.e. '='.
- // If it == end after the seek, we probably have a token-value.
- SeekTo(it, end, kTokenSeparator);
- token_real_end = *it;
-
- // Ignore any whitespace between the token and the token separator.
- // token_end should point after the last interesting token character,
- // pointing at either whitespace, or at '=' (and equal to token_real_end).
- if (*it != *token_start) { // We could have an empty token name.
- --(*it); // Go back before the token separator.
- // Skip over any whitespace to the first non-whitespace character.
- SeekBackPast(it, *token_start, kWhitespace);
- // Point after it.
- ++(*it);
- }
- *token_end = *it;
-
- // Seek us back to the end of the token.
- *it = token_real_end;
- return true;
-}
-
-void CookieMonster::ParsedCookie::ParseValue(
- std::string::const_iterator* it,
- const std::string::const_iterator& end,
- std::string::const_iterator* value_start,
- std::string::const_iterator* value_end) {
- DCHECK(it && value_start && value_end);
-
- // Seek past any whitespace that might in-between the token and value.
- SeekPast(it, end, kWhitespace);
- // value_start should point at the first character of the value.
- *value_start = *it;
-
- // Just look for ';' to terminate ('=' allowed).
- // We can hit the end, maybe they didn't terminate.
- SeekTo(it, end, kValueSeparator);
-
- // Will be pointed at the ; seperator or the end.
- *value_end = *it;
-
- // Ignore any unwanted whitespace after the value.
- if (*value_end != *value_start) { // Could have an empty value
- --(*value_end);
- SeekBackPast(value_end, *value_start, kWhitespace);
- ++(*value_end);
- }
-}
-
-std::string CookieMonster::ParsedCookie::ParseTokenString(
- const std::string& token) {
- std::string::const_iterator it = token.begin();
- std::string::const_iterator end = FindFirstTerminator(token);
-
- std::string::const_iterator token_start, token_end;
- if (ParseToken(&it, end, &token_start, &token_end))
- return std::string(token_start, token_end);
- return std::string();
-}
-
-std::string CookieMonster::ParsedCookie::ParseValueString(
- const std::string& value) {
- std::string::const_iterator it = value.begin();
- std::string::const_iterator end = FindFirstTerminator(value);
-
- std::string::const_iterator value_start, value_end;
- ParseValue(&it, end, &value_start, &value_end);
- return std::string(value_start, value_end);
-}
-
-// Parse all token/value pairs and populate pairs_.
-void CookieMonster::ParsedCookie::ParseTokenValuePairs(
- const std::string& cookie_line) {
- pairs_.clear();
-
- // Ok, here we go. We should be expecting to be starting somewhere
- // before the cookie line, not including any header name...
- std::string::const_iterator start = cookie_line.begin();
- std::string::const_iterator it = start;
-
- // TODO(erikwright): Make sure we're stripping \r\n in the network code.
- // Then we can log any unexpected terminators.
- std::string::const_iterator end = FindFirstTerminator(cookie_line);
-
- for (int pair_num = 0; pair_num < kMaxPairs && it != end; ++pair_num) {
- TokenValuePair pair;
-
- std::string::const_iterator token_start, token_end;
- if (!ParseToken(&it, end, &token_start, &token_end))
- break;
-
- if (it == end || *it != '=') {
- // We have a token-value, we didn't have any token name.
- if (pair_num == 0) {
- // For the first time around, we want to treat single values
- // as a value with an empty name. (Mozilla bug 169091).
- // IE seems to also have this behavior, ex "AAA", and "AAA=10" will
- // set 2 different cookies, and setting "BBB" will then replace "AAA".
- pair.first = "";
- // Rewind to the beginning of what we thought was the token name,
- // and let it get parsed as a value.
- it = token_start;
- } else {
- // Any not-first attribute we want to treat a value as a
- // name with an empty value... This is so something like
- // "secure;" will get parsed as a Token name, and not a value.
- pair.first = std::string(token_start, token_end);
- }
- } else {
- // We have a TOKEN=VALUE.
- pair.first = std::string(token_start, token_end);
- ++it; // Skip past the '='.
- }
-
- // OK, now try to parse a value.
- std::string::const_iterator value_start, value_end;
- ParseValue(&it, end, &value_start, &value_end);
- // OK, we're finished with a Token/Value.
- pair.second = std::string(value_start, value_end);
-
- // From RFC2109: "Attributes (names) (attr) are case-insensitive."
- if (pair_num != 0)
- StringToLowerASCII(&pair.first);
- pairs_.push_back(pair);
-
- // We've processed a token/value pair, we're either at the end of
- // the string or a ValueSeparator like ';', which we want to skip.
- if (it != end)
- ++it;
- }
-}
-
-void CookieMonster::ParsedCookie::SetupAttributes() {
- static const char kPathTokenName[] = "path";
- static const char kDomainTokenName[] = "domain";
- static const char kMACKeyTokenName[] = "mac-key";
- static const char kMACAlgorithmTokenName[] = "mac-algorithm";
- static const char kExpiresTokenName[] = "expires";
- static const char kMaxAgeTokenName[] = "max-age";
- static const char kSecureTokenName[] = "secure";
- static const char kHttpOnlyTokenName[] = "httponly";
-
- // We skip over the first token/value, the user supplied one.
- for (size_t i = 1; i < pairs_.size(); ++i) {
- if (pairs_[i].first == kPathTokenName) {
- path_index_ = i;
- } else if (pairs_[i].first == kDomainTokenName) {
- domain_index_ = i;
- } else if (pairs_[i].first == kMACKeyTokenName) {
- mac_key_index_ = i;
- } else if (pairs_[i].first == kMACAlgorithmTokenName) {
- mac_algorithm_index_ = i;
- } else if (pairs_[i].first == kExpiresTokenName) {
- expires_index_ = i;
- } else if (pairs_[i].first == kMaxAgeTokenName) {
- maxage_index_ = i;
- } else if (pairs_[i].first == kSecureTokenName) {
- secure_index_ = i;
- } else if (pairs_[i].first == kHttpOnlyTokenName) {
- httponly_index_ = i;
- } else {
- /* some attribute we don't know or don't care about. */
- }
- }
-}
-
CookieMonster::CanonicalCookie::CanonicalCookie()
: secure_(false),
httponly_(false) {