File: parsed_cookie.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (218 lines) | stat: -rw-r--r-- 9,089 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_COOKIES_PARSED_COOKIE_H_
#define NET_COOKIES_PARSED_COOKIE_H_

#include <stddef.h>

#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "net/base/net_export.h"
#include "net/cookies/cookie_constants.h"

namespace net {

class CookieInclusionStatus;

class NET_EXPORT ParsedCookie {
 public:
  typedef std::pair<std::string, std::string> TokenValuePair;
  typedef std::vector<TokenValuePair> PairList;

  // The maximum length allowed for a cookie string's name/value pair.
  static const size_t kMaxCookieNamePlusValueSize = 4096;

  // The maximum length allowed for each attribute value in a cookie string.
  static const size_t kMaxCookieAttributeValueSize = 1024;

  // Construct from a cookie string like "BLAH=1; path=/; domain=.google.com"
  // Format is according to RFC6265bis. Cookies with both name and value empty
  // will be considered invalid.
  // `status_out` is a nullable output param which will be populated with
  // informative exclusion reasons if the resulting ParsedCookie is invalid.
  // The CookieInclusionStatus will not be altered if the resulting ParsedCookie
  // is valid.
  explicit ParsedCookie(std::string_view cookie_line,
                        CookieInclusionStatus* status_out = nullptr);

  ParsedCookie(const ParsedCookie&) = delete;
  ParsedCookie& operator=(const ParsedCookie&) = delete;

  ~ParsedCookie();

  // You should not call any other methods except for SetName/SetValue on the
  // class if !IsValid.
  bool IsValid() const;

  const std::string& Name() const { return pairs_[0].first; }
  const std::string& Token() const { return Name(); }
  const std::string& Value() const { return pairs_[0].second; }

  std::optional<std::string_view> Path() const {
    if (path_index_ == 0) {
      return std::nullopt;
    }
    return pairs_[path_index_].second;
  }
  // Note that Domain() may return the empty string; in the case of cookie_line
  // "domain=", Domain().has_value() will return true (as the empty string is an
  // acceptable domain value), and Domain().value() will be an empty string.
  std::optional<std::string_view> Domain() const {
    if (domain_index_ == 0) {
      return std::nullopt;
    }
    return pairs_[domain_index_].second;
  }
  std::optional<std::string_view> Expires() const {
    if (expires_index_ == 0) {
      return std::nullopt;
    }
    return pairs_[expires_index_].second;
  }
  std::optional<std::string_view> MaxAge() const {
    if (maxage_index_ == 0) {
      return std::nullopt;
    }
    return pairs_[maxage_index_].second;
  }
  bool IsSecure() const { return secure_index_ != 0; }
  bool IsHttpOnly() const { return httponly_index_ != 0; }
  // Also spits out an enum value representing the string given as the SameSite
  // attribute value, if |samesite_string| is non-null.
  CookieSameSite SameSite(
      CookieSameSiteString* samesite_string = nullptr) const;
  CookiePriority Priority() const;
  bool IsPartitioned() const { return partitioned_index_ != 0; }
  bool HasInternalHtab() const { return internal_htab_; }
  // Returns the number of attributes, for example, returning 2 for:
  //   "BLAH=hah; path=/; domain=.google.com"
  size_t NumberOfAttributes() const { return pairs_.size() - 1; }

  // These functions set the respective properties of the cookie. If the
  // parameters are empty, the respective properties are cleared.
  // The functions return false in case an error occurred.
  // The cookie needs to be assigned a name/value before setting the other
  // attributes.
  //
  // These functions should only be used if you need to modify a response's
  // Set-Cookie string. The resulting ParsedCookie and its Set-Cookie string
  // should still go through the regular cookie parsing process before entering
  // the cookie jar.
  bool SetName(const std::string& name);
  bool SetValue(const std::string& value);
  bool SetPath(const std::string& path);
  bool SetDomain(const std::string& domain);
  bool SetExpires(const std::string& expires);
  bool SetMaxAge(const std::string& maxage);
  bool SetIsSecure(bool is_secure);
  bool SetIsHttpOnly(bool is_http_only);
  bool SetSameSite(const std::string& same_site);
  bool SetPriority(const std::string& priority);
  bool SetIsPartitioned(bool is_partitioned);

  // Returns the cookie description as it appears in a HTML response header.
  std::string ToCookieLine() const;

  // Returns an iterator pointing to the first terminator character found in
  // the given string.
  static std::string_view::iterator FindFirstTerminator(std::string_view s);

  // Given iterators pointing to the beginning and end of a string segment,
  // returns as output arguments token_start and token_end to the start and end
  // positions of a cookie attribute token name parsed from the segment, and
  // updates the segment iterator to point to the next segment to be parsed.
  // If no token is found, the function returns false and the segment iterator
  // is set to end.
  static bool ParseToken(std::string_view::iterator* it,
                         const std::string_view::iterator& end,
                         std::string_view::iterator* token_start,
                         std::string_view::iterator* token_end);

  // Given iterators pointing to the beginning and end of a string segment,
  // returns as output arguments value_start and value_end to the start and end
  // positions of a cookie attribute value parsed from the segment, and updates
  // the segment iterator to point to the next segment to be parsed.
  static void ParseValue(std::string_view::iterator* it,
                         const std::string_view::iterator& end,
                         std::string_view::iterator* value_start,
                         std::string_view::iterator* value_end);

  // Same as the above functions, except the input is assumed to contain the
  // desired token/value and nothing else.
  static std::string ParseTokenString(std::string_view token);
  static std::string ParseValueString(std::string_view value);

  // Returns |true| if the parsed version of |value| matches |value|.
  static bool ValueMatchesParsedValue(const std::string& value);

  // Is the string valid as the name of the cookie or as an attribute name?
  static bool IsValidCookieName(const std::string& name);

  // Is the string valid as the value of the cookie?
  static bool IsValidCookieValue(const std::string& value);

  // Is the string free of any characters not allowed in attribute values?
  static bool CookieAttributeValueHasValidCharSet(const std::string& value);

  // Is the string less than the size limits set for attribute values?
  static bool CookieAttributeValueHasValidSize(std::string_view value);

  // Returns `true` if the name and value combination are valid. Calls
  // IsValidCookieName() and IsValidCookieValue() on `name` and `value`
  // respectively, in addition to checking that the sum of the two doesn't
  // exceed size limits specified in RFC6265bis.
  static bool IsValidCookieNameValuePair(
      const std::string& name,
      const std::string& value,
      CookieInclusionStatus* status_out = nullptr);

 private:
  void ParseTokenValuePairs(std::string_view cookie_line,
                            CookieInclusionStatus& status_out);
  void SetupAttributes();

  // Sets a key/value pair for a cookie. |index| has to point to one of the
  // |*_index_| fields in ParsedCookie and is updated to the position where
  // the key/value pair is set in |pairs_|. Accordingly, |key| has to correspond
  // to the token matching |index|. If |value| contains invalid characters, the
  // cookie parameter is not changed and the function returns false.
  // If |value| is empty/false the key/value pair is removed.
  bool SetString(size_t* index,
                 const std::string& key,
                 const std::string& value);
  bool SetBool(size_t* index, const std::string& key, bool value);

  // Helper function for SetString and SetBool handling the case that the
  // key/value pair shall not be removed.
  bool SetAttributePair(size_t* index,
                        const std::string& key,
                        const std::string& value);

  // Removes the key/value pair from a cookie that is identified by |index|.
  // |index| refers to a position in |pairs_|.
  void ClearAttributePair(size_t index);

  PairList pairs_;
  // These will default to 0, but that should never be valid since the
  // 0th index is the user supplied cookie name/value, not an attribute.
  size_t path_index_ = 0;
  size_t domain_index_ = 0;
  size_t expires_index_ = 0;
  size_t maxage_index_ = 0;
  size_t secure_index_ = 0;
  size_t httponly_index_ = 0;
  size_t same_site_index_ = 0;
  size_t priority_index_ = 0;
  size_t partitioned_index_ = 0;
  // For metrics on cookie name/value internal HTABS
  bool internal_htab_ = false;
};

}  // namespace net

#endif  // NET_COOKIES_PARSED_COOKIE_H_