1//
2// HTTPCookie.cpp
3//
4// Library: Net
5// Package: HTTP
6// Module: HTTPCookie
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/HTTPCookie.h"
16#include "Poco/Net/NameValueCollection.h"
17#include "Poco/Timestamp.h"
18#include "Poco/DateTime.h"
19#include "Poco/DateTimeFormatter.h"
20#include "Poco/DateTimeFormat.h"
21#include "Poco/DateTimeParser.h"
22#include "Poco/NumberFormatter.h"
23#include "Poco/NumberParser.h"
24#include "Poco/String.h"
25#include "Poco/URI.h"
26
27
28using Poco::Timestamp;
29using Poco::DateTime;
30using Poco::DateTimeFormatter;
31using Poco::DateTimeFormat;
32using Poco::DateTimeParser;
33using Poco::NumberFormatter;
34using Poco::NumberParser;
35using Poco::icompare;
36
37
38namespace Poco {
39namespace Net {
40
41
42HTTPCookie::HTTPCookie():
43 _version(0),
44 _secure(false),
45 _maxAge(-1),
46 _httpOnly(false)
47{
48}
49
50
51HTTPCookie::HTTPCookie(const std::string& name):
52 _version(0),
53 _name(name),
54 _secure(false),
55 _maxAge(-1),
56 _httpOnly(false)
57{
58}
59
60
61HTTPCookie::HTTPCookie(const NameValueCollection& nvc):
62 _version(0),
63 _secure(false),
64 _maxAge(-1),
65 _httpOnly(false)
66{
67 for (NameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it)
68 {
69 const std::string& name = it->first;
70 const std::string& value = it->second;
71 if (icompare(name, "comment") == 0)
72 {
73 setComment(value);
74 }
75 else if (icompare(name, "domain") == 0)
76 {
77 setDomain(value);
78 }
79 else if (icompare(name, "path") == 0)
80 {
81 setPath(value);
82 }
83 else if (icompare(name, "priority") == 0)
84 {
85 setPriority(value);
86 }
87 else if (icompare(name, "max-age") == 0)
88 {
89 setMaxAge(NumberParser::parse(value));
90 }
91 else if (icompare(name, "secure") == 0)
92 {
93 setSecure(true);
94 }
95 else if (icompare(name, "expires") == 0)
96 {
97 int tzd;
98 DateTime exp = DateTimeParser::parse(value, tzd);
99 Timestamp now;
100 setMaxAge((int) ((exp.timestamp() - now) / Timestamp::resolution()));
101 }
102 else if (icompare(name, "version") == 0)
103 {
104 setVersion(NumberParser::parse(value));
105 }
106 else if (icompare(name, "HttpOnly") == 0)
107 {
108 setHttpOnly(true);
109 }
110 else
111 {
112 setName(name);
113 setValue(value);
114 }
115 }
116}
117
118
119HTTPCookie::HTTPCookie(const std::string& name, const std::string& value):
120 _version(0),
121 _name(name),
122 _value(value),
123 _secure(false),
124 _maxAge(-1),
125 _httpOnly(false)
126{
127}
128
129
130HTTPCookie::HTTPCookie(const HTTPCookie& cookie):
131 _version(cookie._version),
132 _name(cookie._name),
133 _value(cookie._value),
134 _comment(cookie._comment),
135 _domain(cookie._domain),
136 _path(cookie._path),
137 _priority(cookie._priority),
138 _secure(cookie._secure),
139 _maxAge(cookie._maxAge),
140 _httpOnly(cookie._httpOnly)
141{
142}
143
144
145HTTPCookie::~HTTPCookie()
146{
147}
148
149
150HTTPCookie& HTTPCookie::operator = (const HTTPCookie& cookie)
151{
152 if (&cookie != this)
153 {
154 _version = cookie._version;
155 _name = cookie._name;
156 _value = cookie._value;
157 _comment = cookie._comment;
158 _domain = cookie._domain;
159 _path = cookie._path;
160 _priority = cookie._priority;
161 _secure = cookie._secure;
162 _maxAge = cookie._maxAge;
163 _httpOnly = cookie._httpOnly;
164 }
165 return *this;
166}
167
168
169void HTTPCookie::setVersion(int version)
170{
171 _version = version;
172}
173
174
175void HTTPCookie::setName(const std::string& name)
176{
177 _name = name;
178}
179
180
181void HTTPCookie::setValue(const std::string& value)
182{
183 _value = value;
184}
185
186
187void HTTPCookie::setComment(const std::string& comment)
188{
189 _comment = comment;
190}
191
192
193void HTTPCookie::setDomain(const std::string& domain)
194{
195 _domain = domain;
196}
197
198
199void HTTPCookie::setPath(const std::string& path)
200{
201 _path = path;
202}
203
204
205void HTTPCookie::setPriority(const std::string& priority)
206{
207 _priority = priority;
208}
209
210
211void HTTPCookie::setSecure(bool secure)
212{
213 _secure = secure;
214}
215
216
217void HTTPCookie::setMaxAge(int maxAge)
218{
219 _maxAge = maxAge;
220}
221
222
223void HTTPCookie::setHttpOnly(bool flag)
224{
225 _httpOnly = flag;
226}
227
228
229std::string HTTPCookie::toString() const
230{
231 std::string result;
232 result.reserve(256);
233 result.append(_name);
234 result.append("=");
235 if (_version == 0)
236 {
237 // Netscape cookie
238 result.append(_value);
239 if (!_domain.empty())
240 {
241 result.append("; domain=");
242 result.append(_domain);
243 }
244 if (!_path.empty())
245 {
246 result.append("; path=");
247 result.append(_path);
248 }
249 if (!_priority.empty())
250 {
251 result.append("; Priority=");
252 result.append(_priority);
253 }
254 if (_maxAge != -1)
255 {
256 Timestamp ts;
257 ts += _maxAge * Timestamp::resolution();
258 result.append("; expires=");
259 DateTimeFormatter::append(result, ts, DateTimeFormat::HTTP_FORMAT);
260 }
261 if (_secure)
262 {
263 result.append("; secure");
264 }
265 if (_httpOnly)
266 {
267 result.append("; HttpOnly");
268 }
269 }
270 else
271 {
272 // RFC 2109 cookie
273 result.append("\"");
274 result.append(_value);
275 result.append("\"");
276 if (!_comment.empty())
277 {
278 result.append("; Comment=\"");
279 result.append(_comment);
280 result.append("\"");
281 }
282 if (!_domain.empty())
283 {
284 result.append("; Domain=\"");
285 result.append(_domain);
286 result.append("\"");
287 }
288 if (!_path.empty())
289 {
290 result.append("; Path=\"");
291 result.append(_path);
292 result.append("\"");
293 }
294 if (!_priority.empty())
295 {
296 result.append("; Priority=\"");
297 result.append(_priority);
298 result.append("\"");
299 }
300
301 if (_maxAge != -1)
302 {
303 result.append("; Max-Age=\"");
304 NumberFormatter::append(result, _maxAge);
305 result.append("\"");
306 }
307 if (_secure)
308 {
309 result.append("; secure");
310 }
311 if (_httpOnly)
312 {
313 result.append("; HttpOnly");
314 }
315 result.append("; Version=\"1\"");
316 }
317 return result;
318}
319
320
321namespace
322{
323 static const std::string ILLEGAL_CHARS("()[]/|\\',;");
324}
325
326
327std::string HTTPCookie::escape(const std::string& str)
328{
329 std::string result;
330 Poco::URI::encode(str, ILLEGAL_CHARS, result);
331 return result;
332}
333
334
335std::string HTTPCookie::unescape(const std::string& str)
336{
337 std::string result;
338 Poco::URI::decode(str, result);
339 return result;
340}
341
342
343} } // namespace Poco::Net
344