Panda3D
Loading...
Searching...
No Matches
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
22using 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 */
29bool HTTPCookie::
30operator < (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 */
55void HTTPCookie::
56update_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 */
69bool HTTPCookie::
70parse_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 */
111bool HTTPCookie::
112matches_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 */
144void HTTPCookie::
145output(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 */
164bool HTTPCookie::
165parse_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
A container for an HTTP-legal time/date indication.
Definition httpDate.h:27
A container for a URL, e.g.
Definition urlSpec.h:28
get_server
Returns the server name specified by the URL, if any.
Definition urlSpec.h:96
get_path
Returns the path specified by the URL, or "/" if no path is specified.
Definition urlSpec.h:99
is_ssl
Returns true if the URL's scheme specifies an SSL-secured protocol such as https, or false otherwise.
Definition urlSpec.h:101
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.