Panda3D
httpCookie.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file httpCookie.cxx
10  * @author drose
11  * @date 2004-08-26
12  */
13 
14 #include "httpCookie.h"
15 
16 #ifdef HAVE_OPENSSL
17 
18 #include "httpChannel.h"
19 
20 #include <ctype.h>
21 
22 using std::string;
23 
24 /**
25  * The sorting operator allows the cookies to be stored in a single
26  * dictionary; it returns nonequal only if the cookies are different in name,
27  * path, or domain.
28  */
29 bool HTTPCookie::
30 operator < (const HTTPCookie &other) const {
31  if (_domain != other._domain) {
32  return _domain < other._domain;
33  }
34 
35  if (_path != other._path) {
36  // We use reverse sorting on the path, so that cookies with longer paths
37  // will be sent to the server before cookies with shorter paths.
38  return _path > other._path;
39  }
40 
41  if (_name != other._name) {
42  return _name < other._name;
43  }
44 
45  return false;
46 }
47 
48 /**
49  * Assuming the operator < method, above, has already evaluated these two
50  * cookies as equal, then assign the remaining values (value, expiration date,
51  * secure flag) from the indicated cookie. This is guaranteed not to change
52  * the ordering of the cookie in a set, and so can be used to update an
53  * existing cookie within a set with new values.
54  */
55 void HTTPCookie::
56 update_from(const HTTPCookie &other) {
57  nassertv(!(other < *this) && !(*this < other));
58 
59  _value = other._value;
60  _expires = other._expires;
61  _secure = other._secure;
62 }
63 
64 /**
65  * Separates out the parameter/value pairs of the Set-Cookie header and
66  * assigns the values of the cookie appropriate. Returns true if the header
67  * is parsed correctly, false if something is not understood.
68  */
69 bool HTTPCookie::
70 parse_set_cookie(const string &format, const URLSpec &url) {
71  _name = string();
72  _value = string();
73  _domain = url.get_server();
74  _path = url.get_path();
75  _expires = HTTPDate();
76  _secure = false;
77 
78  bool okflag = true;
79  bool first_param = true;
80 
81  size_t start = 0;
82  while (start < format.length() && isspace(format[start])) {
83  start++;
84  }
85  size_t semicolon = format.find(';', start);
86 
87  while (semicolon != string::npos) {
88  if (!parse_cookie_param(format.substr(start, semicolon - start),
89  first_param)) {
90  okflag = false;
91  }
92  first_param = false;
93  start = semicolon + 1;
94  while (start < format.length() && isspace(format[start])) {
95  start++;
96  }
97  semicolon = format.find(';', start);
98  }
99 
100  if (!parse_cookie_param(format.substr(start), first_param)) {
101  okflag = false;
102  }
103 
104  return okflag;
105 }
106 
107 /**
108  * Returns true if the cookie is appropriate to send with the indicated URL
109  * request, false otherwise.
110  */
111 bool HTTPCookie::
112 matches_url(const URLSpec &url) const {
113  if (_domain.empty()) {
114  return false;
115  }
116  string server = url.get_server();
117  if (server == _domain ||
118  (string(".") + server) == _domain ||
119  (server.length() > _domain.length() &&
120  server.substr(server.length() - _domain.length()) == _domain &&
121  (_domain[0] == '.' || server[server.length() - _domain.length() - 1] == '.'))) {
122  // The domain matches.
123 
124  string path = url.get_path();
125  if (path.length() >= _path.length() &&
126  path.substr(0, _path.length()) == _path) {
127 
128  // The path matches too.
129  if (_secure && !url.is_ssl()) {
130  // Oops, can't send a secure cookie over a non-secure connection.
131  return false;
132  }
133 
134  return true;
135  }
136  }
137 
138  return false;
139 }
140 
141 /**
142  *
143  */
144 void HTTPCookie::
145 output(std::ostream &out) const {
146  out << _name << "=" << _value
147  << "; path=" << _path << "; domain=" << _domain;
148 
149  if (has_expires()) {
150  out << "; expires=" << _expires;
151  }
152 
153  if (_secure) {
154  out << "; secure";
155  }
156 }
157 
158 /**
159  * Called internally by parse_set_cookie() with each parameter=value pair
160  * split out from the header string. first_param will be true for the first
161  * parameter (which has special meaning). This should return true on success,
162  * false on failure.
163  */
164 bool HTTPCookie::
165 parse_cookie_param(const string &param, bool first_param) {
166  size_t equals = param.find('=');
167 
168  string key, value;
169  if (equals == string::npos) {
170  key = param;
171  } else {
172  key = param.substr(0, equals);
173  value = param.substr(equals + 1);
174  }
175 
176  if (first_param) {
177  _name = key;
178  _value = value;
179 
180  } else {
181  key = HTTPChannel::downcase(key);
182  if (key == "expires") {
183  _expires = HTTPDate(value);
184  if (!_expires.is_valid()) {
185  return false;
186  }
187 
188  } else if (key == "path") {
189  _path = value;
190 
191  } else if (key == "domain") {
192  _domain = HTTPChannel::downcase(value);
193 
194  // From RFC 2965: If an explicitly specified value does not start with a
195  // dot, the user agent supplies a leading dot.
196  if (!_domain.empty() && _domain[0] != '.') {
197  _domain = string(".") + _domain;
198  }
199 
200  } else if (key == "secure") {
201  _secure = true;
202 
203  } else {
204  return false;
205  }
206  }
207 
208  return true;
209 }
210 
211 #endif // HAVE_OPENSSL
is_ssl
Returns true if the URL's scheme specifies an SSL-secured protocol such as https, or false otherwise.
Definition: urlSpec.h:101
A container for a URL, e.g.
Definition: urlSpec.h:28
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_path
Returns the path specified by the URL, or "/" if no path is specified.
Definition: urlSpec.h:99
A container for an HTTP-legal time/date indication.
Definition: httpDate.h:27
get_server
Returns the server name specified by the URL, if any.
Definition: urlSpec.h:96
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.