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 }