1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef NET_COOKIES_PARSED_COOKIE_H_ 6*6777b538SAndroid Build Coastguard Worker #define NET_COOKIES_PARSED_COOKIE_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include <string> 11*6777b538SAndroid Build Coastguard Worker #include <utility> 12*6777b538SAndroid Build Coastguard Worker #include <vector> 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h" 15*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_constants.h" 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker namespace net { 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker class CookieInclusionStatus; 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker class NET_EXPORT ParsedCookie { 22*6777b538SAndroid Build Coastguard Worker public: 23*6777b538SAndroid Build Coastguard Worker typedef std::pair<std::string, std::string> TokenValuePair; 24*6777b538SAndroid Build Coastguard Worker typedef std::vector<TokenValuePair> PairList; 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker // The maximum length allowed for a cookie string's name/value pair. 27*6777b538SAndroid Build Coastguard Worker static const size_t kMaxCookieNamePlusValueSize = 4096; 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker // The maximum length allowed for each attribute value in a cookie string. 30*6777b538SAndroid Build Coastguard Worker static const size_t kMaxCookieAttributeValueSize = 1024; 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker // Construct from a cookie string like "BLAH=1; path=/; domain=.google.com" 33*6777b538SAndroid Build Coastguard Worker // Format is according to RFC6265bis. Cookies with both name and value empty 34*6777b538SAndroid Build Coastguard Worker // will be considered invalid. 35*6777b538SAndroid Build Coastguard Worker // `status_out` is a nullable output param which will be populated with 36*6777b538SAndroid Build Coastguard Worker // informative exclusion reasons if the resulting ParsedCookie is invalid. 37*6777b538SAndroid Build Coastguard Worker // The CookieInclusionStatus will not be altered if the resulting ParsedCookie 38*6777b538SAndroid Build Coastguard Worker // is valid. 39*6777b538SAndroid Build Coastguard Worker // `block_truncated` indicates whether cookies containing '\00', '\r', or '\n' 40*6777b538SAndroid Build Coastguard Worker // characters should be treated as invalid. 41*6777b538SAndroid Build Coastguard Worker explicit ParsedCookie(const std::string& cookie_line, 42*6777b538SAndroid Build Coastguard Worker bool block_truncated = true, 43*6777b538SAndroid Build Coastguard Worker CookieInclusionStatus* status_out = nullptr); 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker ParsedCookie(const ParsedCookie&) = delete; 46*6777b538SAndroid Build Coastguard Worker ParsedCookie& operator=(const ParsedCookie&) = delete; 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker ~ParsedCookie(); 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker // You should not call any other methods except for SetName/SetValue on the 51*6777b538SAndroid Build Coastguard Worker // class if !IsValid. 52*6777b538SAndroid Build Coastguard Worker bool IsValid() const; 53*6777b538SAndroid Build Coastguard Worker Name()54*6777b538SAndroid Build Coastguard Worker const std::string& Name() const { return pairs_[0].first; } Token()55*6777b538SAndroid Build Coastguard Worker const std::string& Token() const { return Name(); } Value()56*6777b538SAndroid Build Coastguard Worker const std::string& Value() const { return pairs_[0].second; } 57*6777b538SAndroid Build Coastguard Worker HasPath()58*6777b538SAndroid Build Coastguard Worker bool HasPath() const { return path_index_ != 0; } Path()59*6777b538SAndroid Build Coastguard Worker const std::string& Path() const { 60*6777b538SAndroid Build Coastguard Worker DCHECK(HasPath()); 61*6777b538SAndroid Build Coastguard Worker return pairs_[path_index_].second; 62*6777b538SAndroid Build Coastguard Worker } 63*6777b538SAndroid Build Coastguard Worker // Note that Domain() may return the empty string; in the case of cookie_line 64*6777b538SAndroid Build Coastguard Worker // "domain=", HasDomain() will return true (as the empty string is an 65*6777b538SAndroid Build Coastguard Worker // acceptable domain value), so Domain() will return std::string(). HasDomain()66*6777b538SAndroid Build Coastguard Worker bool HasDomain() const { return domain_index_ != 0; } Domain()67*6777b538SAndroid Build Coastguard Worker const std::string& Domain() const { 68*6777b538SAndroid Build Coastguard Worker DCHECK(HasDomain()); 69*6777b538SAndroid Build Coastguard Worker return pairs_[domain_index_].second; 70*6777b538SAndroid Build Coastguard Worker } HasExpires()71*6777b538SAndroid Build Coastguard Worker bool HasExpires() const { return expires_index_ != 0; } Expires()72*6777b538SAndroid Build Coastguard Worker const std::string& Expires() const { 73*6777b538SAndroid Build Coastguard Worker DCHECK(HasExpires()); 74*6777b538SAndroid Build Coastguard Worker return pairs_[expires_index_].second; 75*6777b538SAndroid Build Coastguard Worker } HasMaxAge()76*6777b538SAndroid Build Coastguard Worker bool HasMaxAge() const { return maxage_index_ != 0; } MaxAge()77*6777b538SAndroid Build Coastguard Worker const std::string& MaxAge() const { 78*6777b538SAndroid Build Coastguard Worker DCHECK(HasMaxAge()); 79*6777b538SAndroid Build Coastguard Worker return pairs_[maxage_index_].second; 80*6777b538SAndroid Build Coastguard Worker } IsSecure()81*6777b538SAndroid Build Coastguard Worker bool IsSecure() const { return secure_index_ != 0; } IsHttpOnly()82*6777b538SAndroid Build Coastguard Worker bool IsHttpOnly() const { return httponly_index_ != 0; } 83*6777b538SAndroid Build Coastguard Worker // Also spits out an enum value representing the string given as the SameSite 84*6777b538SAndroid Build Coastguard Worker // attribute value, if |samesite_string| is non-null. 85*6777b538SAndroid Build Coastguard Worker CookieSameSite SameSite( 86*6777b538SAndroid Build Coastguard Worker CookieSameSiteString* samesite_string = nullptr) const; 87*6777b538SAndroid Build Coastguard Worker CookiePriority Priority() const; IsPartitioned()88*6777b538SAndroid Build Coastguard Worker bool IsPartitioned() const { return partitioned_index_ != 0; } HasInternalHtab()89*6777b538SAndroid Build Coastguard Worker bool HasInternalHtab() const { return internal_htab_; } 90*6777b538SAndroid Build Coastguard Worker TruncatingCharacterInCookieStringType GetTruncatingCharacterInCookieStringType()91*6777b538SAndroid Build Coastguard Worker GetTruncatingCharacterInCookieStringType() const { 92*6777b538SAndroid Build Coastguard Worker return truncating_char_in_cookie_string_type_; 93*6777b538SAndroid Build Coastguard Worker } 94*6777b538SAndroid Build Coastguard Worker // Returns the number of attributes, for example, returning 2 for: 95*6777b538SAndroid Build Coastguard Worker // "BLAH=hah; path=/; domain=.google.com" NumberOfAttributes()96*6777b538SAndroid Build Coastguard Worker size_t NumberOfAttributes() const { return pairs_.size() - 1; } 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker // These functions set the respective properties of the cookie. If the 99*6777b538SAndroid Build Coastguard Worker // parameters are empty, the respective properties are cleared. 100*6777b538SAndroid Build Coastguard Worker // The functions return false in case an error occurred. 101*6777b538SAndroid Build Coastguard Worker // The cookie needs to be assigned a name/value before setting the other 102*6777b538SAndroid Build Coastguard Worker // attributes. 103*6777b538SAndroid Build Coastguard Worker // 104*6777b538SAndroid Build Coastguard Worker // These functions should only be used if you need to modify a response's 105*6777b538SAndroid Build Coastguard Worker // Set-Cookie string. The resulting ParsedCookie and its Set-Cookie string 106*6777b538SAndroid Build Coastguard Worker // should still go through the regular cookie parsing process before entering 107*6777b538SAndroid Build Coastguard Worker // the cookie jar. 108*6777b538SAndroid Build Coastguard Worker bool SetName(const std::string& name); 109*6777b538SAndroid Build Coastguard Worker bool SetValue(const std::string& value); 110*6777b538SAndroid Build Coastguard Worker bool SetPath(const std::string& path); 111*6777b538SAndroid Build Coastguard Worker bool SetDomain(const std::string& domain); 112*6777b538SAndroid Build Coastguard Worker bool SetExpires(const std::string& expires); 113*6777b538SAndroid Build Coastguard Worker bool SetMaxAge(const std::string& maxage); 114*6777b538SAndroid Build Coastguard Worker bool SetIsSecure(bool is_secure); 115*6777b538SAndroid Build Coastguard Worker bool SetIsHttpOnly(bool is_http_only); 116*6777b538SAndroid Build Coastguard Worker bool SetSameSite(const std::string& same_site); 117*6777b538SAndroid Build Coastguard Worker bool SetPriority(const std::string& priority); 118*6777b538SAndroid Build Coastguard Worker bool SetIsPartitioned(bool is_partitioned); 119*6777b538SAndroid Build Coastguard Worker 120*6777b538SAndroid Build Coastguard Worker // Returns the cookie description as it appears in a HTML response header. 121*6777b538SAndroid Build Coastguard Worker std::string ToCookieLine() const; 122*6777b538SAndroid Build Coastguard Worker 123*6777b538SAndroid Build Coastguard Worker // Returns an iterator pointing to the first terminator character found in 124*6777b538SAndroid Build Coastguard Worker // the given string. 125*6777b538SAndroid Build Coastguard Worker static std::string::const_iterator FindFirstTerminator(const std::string& s); 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker // Given iterators pointing to the beginning and end of a string segment, 128*6777b538SAndroid Build Coastguard Worker // returns as output arguments token_start and token_end to the start and end 129*6777b538SAndroid Build Coastguard Worker // positions of a cookie attribute token name parsed from the segment, and 130*6777b538SAndroid Build Coastguard Worker // updates the segment iterator to point to the next segment to be parsed. 131*6777b538SAndroid Build Coastguard Worker // If no token is found, the function returns false and the segment iterator 132*6777b538SAndroid Build Coastguard Worker // is set to end. 133*6777b538SAndroid Build Coastguard Worker static bool ParseToken(std::string::const_iterator* it, 134*6777b538SAndroid Build Coastguard Worker const std::string::const_iterator& end, 135*6777b538SAndroid Build Coastguard Worker std::string::const_iterator* token_start, 136*6777b538SAndroid Build Coastguard Worker std::string::const_iterator* token_end); 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker // Given iterators pointing to the beginning and end of a string segment, 139*6777b538SAndroid Build Coastguard Worker // returns as output arguments value_start and value_end to the start and end 140*6777b538SAndroid Build Coastguard Worker // positions of a cookie attribute value parsed from the segment, and updates 141*6777b538SAndroid Build Coastguard Worker // the segment iterator to point to the next segment to be parsed. 142*6777b538SAndroid Build Coastguard Worker static void ParseValue(std::string::const_iterator* it, 143*6777b538SAndroid Build Coastguard Worker const std::string::const_iterator& end, 144*6777b538SAndroid Build Coastguard Worker std::string::const_iterator* value_start, 145*6777b538SAndroid Build Coastguard Worker std::string::const_iterator* value_end); 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker // Same as the above functions, except the input is assumed to contain the 148*6777b538SAndroid Build Coastguard Worker // desired token/value and nothing else. 149*6777b538SAndroid Build Coastguard Worker static std::string ParseTokenString(const std::string& token); 150*6777b538SAndroid Build Coastguard Worker static std::string ParseValueString(const std::string& value); 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker // Returns |true| if the parsed version of |value| matches |value|. 153*6777b538SAndroid Build Coastguard Worker static bool ValueMatchesParsedValue(const std::string& value); 154*6777b538SAndroid Build Coastguard Worker 155*6777b538SAndroid Build Coastguard Worker // Is the string valid as the name of the cookie or as an attribute name? 156*6777b538SAndroid Build Coastguard Worker static bool IsValidCookieName(const std::string& name); 157*6777b538SAndroid Build Coastguard Worker 158*6777b538SAndroid Build Coastguard Worker // Is the string valid as the value of the cookie? 159*6777b538SAndroid Build Coastguard Worker static bool IsValidCookieValue(const std::string& value); 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker // Is the string free of any characters not allowed in attribute values? 162*6777b538SAndroid Build Coastguard Worker static bool CookieAttributeValueHasValidCharSet(const std::string& value); 163*6777b538SAndroid Build Coastguard Worker 164*6777b538SAndroid Build Coastguard Worker // Is the string less than the size limits set for attribute values? 165*6777b538SAndroid Build Coastguard Worker static bool CookieAttributeValueHasValidSize(const std::string& value); 166*6777b538SAndroid Build Coastguard Worker 167*6777b538SAndroid Build Coastguard Worker // Returns `true` if the name and value combination are valid. Calls 168*6777b538SAndroid Build Coastguard Worker // IsValidCookieName() and IsValidCookieValue() on `name` and `value` 169*6777b538SAndroid Build Coastguard Worker // respectively, in addition to checking that the sum of the two doesn't 170*6777b538SAndroid Build Coastguard Worker // exceed size limits specified in RFC6265bis. 171*6777b538SAndroid Build Coastguard Worker static bool IsValidCookieNameValuePair( 172*6777b538SAndroid Build Coastguard Worker const std::string& name, 173*6777b538SAndroid Build Coastguard Worker const std::string& value, 174*6777b538SAndroid Build Coastguard Worker CookieInclusionStatus* status_out = nullptr); 175*6777b538SAndroid Build Coastguard Worker 176*6777b538SAndroid Build Coastguard Worker private: 177*6777b538SAndroid Build Coastguard Worker void ParseTokenValuePairs(const std::string& cookie_line, 178*6777b538SAndroid Build Coastguard Worker bool block_truncated, 179*6777b538SAndroid Build Coastguard Worker CookieInclusionStatus& status_out); 180*6777b538SAndroid Build Coastguard Worker void SetupAttributes(); 181*6777b538SAndroid Build Coastguard Worker 182*6777b538SAndroid Build Coastguard Worker // Sets a key/value pair for a cookie. |index| has to point to one of the 183*6777b538SAndroid Build Coastguard Worker // |*_index_| fields in ParsedCookie and is updated to the position where 184*6777b538SAndroid Build Coastguard Worker // the key/value pair is set in |pairs_|. Accordingly, |key| has to correspond 185*6777b538SAndroid Build Coastguard Worker // to the token matching |index|. If |value| contains invalid characters, the 186*6777b538SAndroid Build Coastguard Worker // cookie parameter is not changed and the function returns false. 187*6777b538SAndroid Build Coastguard Worker // If |value| is empty/false the key/value pair is removed. 188*6777b538SAndroid Build Coastguard Worker bool SetString(size_t* index, 189*6777b538SAndroid Build Coastguard Worker const std::string& key, 190*6777b538SAndroid Build Coastguard Worker const std::string& value); 191*6777b538SAndroid Build Coastguard Worker bool SetBool(size_t* index, const std::string& key, bool value); 192*6777b538SAndroid Build Coastguard Worker 193*6777b538SAndroid Build Coastguard Worker // Helper function for SetString and SetBool handling the case that the 194*6777b538SAndroid Build Coastguard Worker // key/value pair shall not be removed. 195*6777b538SAndroid Build Coastguard Worker bool SetAttributePair(size_t* index, 196*6777b538SAndroid Build Coastguard Worker const std::string& key, 197*6777b538SAndroid Build Coastguard Worker const std::string& value); 198*6777b538SAndroid Build Coastguard Worker 199*6777b538SAndroid Build Coastguard Worker // Removes the key/value pair from a cookie that is identified by |index|. 200*6777b538SAndroid Build Coastguard Worker // |index| refers to a position in |pairs_|. 201*6777b538SAndroid Build Coastguard Worker void ClearAttributePair(size_t index); 202*6777b538SAndroid Build Coastguard Worker 203*6777b538SAndroid Build Coastguard Worker PairList pairs_; 204*6777b538SAndroid Build Coastguard Worker // These will default to 0, but that should never be valid since the 205*6777b538SAndroid Build Coastguard Worker // 0th index is the user supplied cookie name/value, not an attribute. 206*6777b538SAndroid Build Coastguard Worker size_t path_index_ = 0; 207*6777b538SAndroid Build Coastguard Worker size_t domain_index_ = 0; 208*6777b538SAndroid Build Coastguard Worker size_t expires_index_ = 0; 209*6777b538SAndroid Build Coastguard Worker size_t maxage_index_ = 0; 210*6777b538SAndroid Build Coastguard Worker size_t secure_index_ = 0; 211*6777b538SAndroid Build Coastguard Worker size_t httponly_index_ = 0; 212*6777b538SAndroid Build Coastguard Worker size_t same_site_index_ = 0; 213*6777b538SAndroid Build Coastguard Worker size_t priority_index_ = 0; 214*6777b538SAndroid Build Coastguard Worker size_t partitioned_index_ = 0; 215*6777b538SAndroid Build Coastguard Worker TruncatingCharacterInCookieStringType truncating_char_in_cookie_string_type_ = 216*6777b538SAndroid Build Coastguard Worker TruncatingCharacterInCookieStringType::kTruncatingCharNone; 217*6777b538SAndroid Build Coastguard Worker // For metrics on cookie name/value internal HTABS 218*6777b538SAndroid Build Coastguard Worker bool internal_htab_ = false; 219*6777b538SAndroid Build Coastguard Worker }; 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker } // namespace net 222*6777b538SAndroid Build Coastguard Worker 223*6777b538SAndroid Build Coastguard Worker #endif // NET_COOKIES_PARSED_COOKIE_H_ 224