1 /*******************************************************************************
2
3 HTTP Cookie Generator
4
5 Reference: RFC 2109
6
7 @see http://www.w3.org/Protocols/rfc2109/rfc2109.txt
8 @see http://www.servlets.com/rfcs/rfc2109.html
9
10 Copyright:
11 Copyright (c) 2009-2016 dunnhumby Germany GmbH.
12 All rights reserved.
13
14 License:
15 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
16 Alternatively, this file may be distributed under the terms of the Tango
17 3-Clause BSD License (see LICENSE_BSD.txt for details).
18
19 ******************************************************************************/
20
21 module ocean.net.http.cookie.HttpCookieGenerator;
22
23
24 import ocean.meta.types.Qualifiers;
25
26 import ocean.core.Verify;
27
28 import ocean.net.util.ParamSet;
29
30 import ocean.net.http.consts.CookieAttributeNames;
31
32 import ocean.net.http.time.HttpTimeFormatter;
33
34 import core.stdc.time: time_t;
35
36 /******************************************************************************/
37
38 class HttpCookieGenerator : ParamSet
39 {
40 /**************************************************************************
41
42 Cookie ID
43
44 **************************************************************************/
45
46 public istring id;
47
48 /**************************************************************************
49
50 Cookie domain and path
51
52 **************************************************************************/
53
54 public cstring domain, path;
55
56 /**************************************************************************
57
58 Expiration time manager
59
60 **************************************************************************/
61
62 private static class ExpirationTime
63 {
64 /**********************************************************************
65
66 Expiration time if set.
67
68 **********************************************************************/
69
70 private time_t t;
71
72 /**********************************************************************
73
74 true if the expiration time is currently defined or false otherwise.
75
76 **********************************************************************/
77
78 private bool is_set_ = false;
79
80 /**********************************************************************
81
82 Sets the expiration time.
83
84 Params:
85 t = expiration time
86
87 Returns:
88 t
89
90 In:
91 t must be at least 0.
92
93 **********************************************************************/
94
95 public time_t opAssign ( time_t t )
96 {
97 verify(t >= 0, "negative time value");
98 this.is_set_ = true;
99 return this.t = t;
100 }
101
102 /**********************************************************************
103
104 Marks the expiration time as "not set".
105
106 **********************************************************************/
107
108 public void clear ( )
109 {
110 this.is_set_ = false;
111 }
112
113 /**********************************************************************
114
115 Returns:
116 true if the expiration time is currently defined or false
117 otherwise.
118
119 **********************************************************************/
120
121 public bool is_set ( )
122 {
123 return this.is_set_;
124 }
125
126 /**********************************************************************
127
128 Obtains the expiration time.
129
130 Params:
131 t = destination variable, will be set to the expiration time if
132 and only if an expiration time is currently defined.
133
134 Returns:
135 true if an expiration time is currently defined and t has been
136 set to it or false otherwise.
137
138 **********************************************************************/
139
140 public bool get ( ref time_t t )
141 {
142 if (this.is_set_)
143 {
144 t = this.t;
145 }
146
147 return this.is_set_;
148 }
149 }
150
151 /**************************************************************************
152
153 Expiration time manager with string formatter
154
155 **************************************************************************/
156
157 private static class FormatExpirationTime : ExpirationTime
158 {
159 /**********************************************************************
160
161 String formatter
162
163 **********************************************************************/
164
165 private HttpTimeFormatter formatter;
166
167 /**********************************************************************
168
169 Returns:
170 current expiration time as HTTP time string or null if currently
171 no expiration time is defined.
172
173 **********************************************************************/
174
175 public mstring format ( )
176 {
177 return super.is_set_? this.formatter.format(super.t) : null;
178 }
179 }
180
181 /**************************************************************************
182
183 Expiration time manager instance
184
185 **************************************************************************/
186
187 public ExpirationTime expiration_time;
188
189 /**************************************************************************
190
191 Expiration time manager/formatter instance
192
193 **************************************************************************/
194
195 private FormatExpirationTime fmt_expiration_time;
196
197 /**************************************************************************
198
199 Constructor
200
201 Params:
202 id = cookie ID
203 attribute_names = cookie attribute names
204
205 Note:
206 This constructor takes a reference to id and use it internally,
207 hence 'id' must remain valid for the lifetime of this object.
208
209 **************************************************************************/
210
211 this ( istring id, istring[] attribute_names ... )
212 {
213 super.addKeys(this.id = id);
214
215 super.addKeys(attribute_names);
216
217 super.rehash();
218
219 this.expiration_time = this.fmt_expiration_time = new FormatExpirationTime;
220 }
221
222 /**************************************************************************
223
224 Sets the cookie value.
225
226 Params:
227 val = cookie value string
228
229 Returns:
230 cookie value
231
232 **************************************************************************/
233
234 cstring value ( cstring val )
235 {
236 return super[this.id] = val;
237 }
238
239 /**************************************************************************
240
241 Returns:
242 the current cookie value
243
244 **************************************************************************/
245
246 cstring value ( )
247 {
248 return super[this.id];
249 }
250
251 /**************************************************************************
252
253 Renders the HTTP response Cookie header line field value.
254
255 Params:
256 appendContent = callback delegate that will be invoked repeatedly
257 to concatenate the Cookie header line field value.
258
259 **************************************************************************/
260
261 void render ( scope void delegate ( cstring str ) appendContent )
262 {
263 uint i = 0;
264
265 void append ( cstring key, cstring val )
266 {
267 if (val)
268 {
269 if (i++)
270 {
271 appendContent("; ");
272 }
273
274 appendContent(key);
275 appendContent("=");
276 appendContent(val);
277 }
278 }
279
280 foreach (key, val; super)
281 {
282 append(key, val);
283 }
284
285 append(CookieAttributeNames.Names.Domain, this.domain);
286 append(CookieAttributeNames.Names.Path, this.path);
287 append(CookieAttributeNames.Names.Expires, this.fmt_expiration_time.format());
288 }
289
290 /**************************************************************************
291
292 Clears the expiration time.
293
294 **************************************************************************/
295
296 public override void reset ( )
297 {
298 super.reset();
299
300 this.expiration_time.clear();
301 }
302 }