diff options
author | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-12 12:21:41 +0000 |
---|---|---|
committer | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-12 12:21:41 +0000 |
commit | ebfe3173617e62ccbda071f8ca367a50a5ba4ee0 (patch) | |
tree | dc4d1b827721341b8329859e1c2242370c31ea29 /net/cookies/cookie_monster.cc | |
parent | 5a76f9b471e5ef367280fb92662bdef9f83cfd57 (diff) | |
download | chromium_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.cc | 278 |
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) { |