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 3 // found in the LICENSE file. 4 5 #ifndef NET_COOKIES_PARSED_COOKIE_H_ 6 #define NET_COOKIES_PARSED_COOKIE_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "net/base/net_export.h" 13 #include "net/cookies/cookie_constants.h" 14 15 namespace net { 16 17 class NET_EXPORT ParsedCookie { 18 public: 19 typedef std::pair<std::string, std::string> TokenValuePair; 20 typedef std::vector<TokenValuePair> PairList; 21 22 // The maximum length of a cookie string we will try to parse 23 static const size_t kMaxCookieSize = 4096; 24 // The maximum number of Token/Value pairs. Shouldn't have more than 8. 25 static const int kMaxPairs = 16; 26 27 // Construct from a cookie string like "BLAH=1; path=/; domain=.google.com" 28 // Format is according to RFC 6265. Cookies with both name and value empty 29 // will be considered invalid. 30 ParsedCookie(const std::string& cookie_line); 31 ~ParsedCookie(); 32 33 // You should not call any other methods except for SetName/SetValue on the 34 // class if !IsValid. 35 bool IsValid() const; 36 Name()37 const std::string& Name() const { return pairs_[0].first; } Token()38 const std::string& Token() const { return Name(); } Value()39 const std::string& Value() const { return pairs_[0].second; } 40 HasPath()41 bool HasPath() const { return path_index_ != 0; } Path()42 const std::string& Path() const { return pairs_[path_index_].second; } HasDomain()43 bool HasDomain() const { return domain_index_ != 0; } Domain()44 const std::string& Domain() const { return pairs_[domain_index_].second; } HasExpires()45 bool HasExpires() const { return expires_index_ != 0; } Expires()46 const std::string& Expires() const { return pairs_[expires_index_].second; } HasMaxAge()47 bool HasMaxAge() const { return maxage_index_ != 0; } MaxAge()48 const std::string& MaxAge() const { return pairs_[maxage_index_].second; } IsSecure()49 bool IsSecure() const { return secure_index_ != 0; } IsHttpOnly()50 bool IsHttpOnly() const { return httponly_index_ != 0; } 51 CookiePriority Priority() const; 52 53 // Returns the number of attributes, for example, returning 2 for: 54 // "BLAH=hah; path=/; domain=.google.com" NumberOfAttributes()55 size_t NumberOfAttributes() const { return pairs_.size() - 1; } 56 57 // These functions set the respective properties of the cookie. If the 58 // parameters are empty, the respective properties are cleared. 59 // The functions return false in case an error occurred. 60 // The cookie needs to be assigned a name/value before setting the other 61 // attributes. 62 bool SetName(const std::string& name); 63 bool SetValue(const std::string& value); 64 bool SetPath(const std::string& path); 65 bool SetDomain(const std::string& domain); 66 bool SetExpires(const std::string& expires); 67 bool SetMaxAge(const std::string& maxage); 68 bool SetIsSecure(bool is_secure); 69 bool SetIsHttpOnly(bool is_http_only); 70 bool SetPriority(const std::string& priority); 71 72 // Returns the cookie description as it appears in a HTML response header. 73 std::string ToCookieLine() const; 74 75 // Returns an iterator pointing to the first terminator character found in 76 // the given string. 77 static std::string::const_iterator FindFirstTerminator(const std::string& s); 78 79 // Given iterators pointing to the beginning and end of a string segment, 80 // returns as output arguments token_start and token_end to the start and end 81 // positions of a cookie attribute token name parsed from the segment, and 82 // updates the segment iterator to point to the next segment to be parsed. 83 // If no token is found, the function returns false. 84 static bool ParseToken(std::string::const_iterator* it, 85 const std::string::const_iterator& end, 86 std::string::const_iterator* token_start, 87 std::string::const_iterator* token_end); 88 89 // Given iterators pointing to the beginning and end of a string segment, 90 // returns as output arguments value_start and value_end to the start and end 91 // positions of a cookie attribute value parsed from the segment, and updates 92 // the segment iterator to point to the next segment to be parsed. 93 static void ParseValue(std::string::const_iterator* it, 94 const std::string::const_iterator& end, 95 std::string::const_iterator* value_start, 96 std::string::const_iterator* value_end); 97 98 // Same as the above functions, except the input is assumed to contain the 99 // desired token/value and nothing else. 100 static std::string ParseTokenString(const std::string& token); 101 static std::string ParseValueString(const std::string& value); 102 103 private: 104 void ParseTokenValuePairs(const std::string& cookie_line); 105 void SetupAttributes(); 106 107 // Sets a key/value pair for a cookie. |index| has to point to one of the 108 // |*_index_| fields in ParsedCookie and is updated to the position where 109 // the key/value pair is set in |pairs_|. Accordingly, |key| has to correspond 110 // to the token matching |index|. If |value| contains invalid characters, the 111 // cookie parameter is not changed and the function returns false. 112 // If |value| is empty/false the key/value pair is removed. 113 bool SetString(size_t* index, 114 const std::string& key, 115 const std::string& value); 116 bool SetBool(size_t* index, 117 const std::string& key, 118 bool value); 119 120 // Helper function for SetString and SetBool handling the case that the 121 // key/value pair shall not be removed. 122 bool SetAttributePair(size_t* index, 123 const std::string& key, 124 const std::string& value); 125 126 // Removes the key/value pair from a cookie that is identified by |index|. 127 // |index| refers to a position in |pairs_|. 128 void ClearAttributePair(size_t index); 129 130 PairList pairs_; 131 bool is_valid_; 132 // These will default to 0, but that should never be valid since the 133 // 0th index is the user supplied token/value, not an attribute. 134 // We're really never going to have more than like 8 attributes, so we 135 // could fit these into 3 bits each if we're worried about size... 136 size_t path_index_; 137 size_t domain_index_; 138 size_t expires_index_; 139 size_t maxage_index_; 140 size_t secure_index_; 141 size_t httponly_index_; 142 size_t priority_index_; 143 144 DISALLOW_COPY_AND_ASSIGN(ParsedCookie); 145 }; 146 147 } // namespace net 148 149 #endif // NET_COOKIES_COOKIE_MONSTER_H_ 150