1 module hunt.framework.http.session.HttpSession;
2 
3 // import hunt.util.DateTime;
4 // import hunt.Exceptions;
5 // import hunt.framework.util.Random;
6 
7 // import std.algorithm;
8 // import std.array;
9 // import std.conv;
10 // // import std.datetime;
11 // import std.digest.sha;
12 // import std.json;
13 // import std.string;
14 // import std.traits;
15 
16 // __gshared string DefaultSessionIdName = "hunt_session";
17 
18 // /**
19 //  * 
20 //  */
21 // class HttpSession {
22 
23 //     private string id;
24 //     private long creationTime;
25 //     private long lastAccessedTime;
26 //     private int maxInactiveInterval;
27 //     private JSONValue attributes;
28 //     private bool newSession;
29 
30 //     string getId() {
31 //         return id;
32 //     }
33 
34 //     void setId(string id) {
35 //         this.id = id;
36 //     }
37 
38 //     long getCreationTime() {
39 //         return creationTime;
40 //     }
41 
42 //     void setCreationTime(long creationTime) {
43 //         this.creationTime = creationTime;
44 //     }
45 
46 //     long getLastAccessedTime() {
47 //         return lastAccessedTime;
48 //     }
49 
50 //     void setLastAccessedTime(long lastAccessedTime) {
51 //         this.lastAccessedTime = lastAccessedTime;
52 //     }
53 
54 //     /**
55 //      * Get the max inactive interval. The time unit is second.
56 //      *
57 //      * @return The max inactive interval.
58 //      */
59 //     int getMaxInactiveInterval() {
60 //         return maxInactiveInterval;
61 //     }
62 
63 //     /**
64 //      * Set the max inactive interval. The time unit is second.
65 //      *
66 //      * @param maxInactiveInterval The max inactive interval.
67 //      */
68 //     void setMaxInactiveInterval(int maxInactiveInterval) {
69 //         this.maxInactiveInterval = maxInactiveInterval;
70 //     }
71 
72 //     ref JSONValue getAttributes() {
73 //         return attributes;
74 //     }
75 
76 //     void setAttributes(ref JSONValue attributes) {
77 //         this.attributes = attributes;
78 //     }
79 
80 //     bool isNewSession() {
81 //         return newSession;
82 //     }
83 
84 //     void setNewSession(bool newSession) {
85 //         this.newSession = newSession;
86 //     }
87 
88 //     bool isValid() {
89 //         long currentTime = DateTime.currentTimeMillis();
90 //         return (currentTime - lastAccessedTime) < (maxInactiveInterval * 1000);
91 //     }
92 
93 //     void set(T)(string name, T value) {
94 //         this.attributes[name] = JSONValue(value);
95 //     }
96 
97 //     T get(T = string)(string name, T defaultValue = T.init) {
98 //         if(attributes.isNull)
99 //             return defaultValue;
100 
101 //         const(JSONValue)* itemPtr = name in attributes;
102 //         if (itemPtr is null)
103 //             return defaultValue;
104 //         static if (!is(T == string) && isDynamicArray!T && is(T : U[], U)) {
105 //             U[] r;
106 //             foreach (JSONValue jv; itemPtr.array) {
107 //                 r ~= get!U(jv);
108 //             }
109 //             return r;
110 //         }
111 //         else {
112 //             return get!T(*itemPtr);
113 //         }
114 //     }
115 
116 //     private static T get(T = string)(JSONValue itemPtr) {
117 //         static if (is(T == string)) {
118 //             return itemPtr.str;
119 //         }
120 //         else static if (isIntegral!T) {
121 //             return cast(T) itemPtr.integer;
122 //         }
123 //         else static if (isFloatingPoint!T) {
124 //             return cast(T) itemPtr.floating;
125 //         }
126 //         else {
127 //             static assert(false, "Unsupported type: " ~ typeid(T).name);
128 //         }
129 //     }
130 
131 //     void remove(string key) {
132 //         if(attributes.isNull)
133 //             return;
134 
135 //         JSONValue json;
136 //         foreach (string _key, ref value; attributes) {
137 //             if (_key != key) {
138 //                 json[_key] = value;
139 //             }
140 //         }
141 
142 //         attributes = json;
143 //     }
144 
145 //     alias forget = remove;
146 
147 //     string[] keys() {
148 //         if(attributes.isNull)
149 //             return null;
150             
151 //         string[] ret;
152 
153 //         foreach (string key, ref value; attributes) {
154 //             ret ~= key;
155 //         }
156 
157 //         return ret;
158 //     }
159 
160 //     /**
161 //      * Get all of the session data.
162 //      *
163 //      * @return array
164 //      */
165 //     string[string] all() {
166 //         if (attributes.isNull)
167 //             return null;
168 
169 //         string[string] v;
170 //         foreach (string key, ref JSONValue value; attributes) {
171 //             if (value.type == JSONType.string)
172 //                 v[key] = value.str;
173 //             else
174 //                 v[key] = value.toString();
175 //         }
176 
177 //         return v;
178 //     }
179 
180 //     /**
181 //      * Checks if a key exists.
182 //      *
183 //      * @param  string|array  key
184 //      * @return bool
185 //      */
186 //     bool exists(string key) {
187 //         if (attributes.isNull)
188 //             return false;
189 //         const(JSONValue)* item = key in attributes;
190 //         return item !is null;
191 //     }
192 
193 //     /**
194 //      * Checks if a key is present and not null.
195 //      *
196 //      * @param  string|array  key
197 //      * @return bool
198 //      */
199 //     bool has(string key) {
200 //         if (attributes.isNull)
201 //             return false;
202 
203 //         auto item = key in attributes;
204 //         if ((item !is null) && (!item.str.empty))
205 //             return true;
206 //         else
207 //             return false;
208 //     }
209 
210 //     /**
211 //      * Get the value of a given key and then forget it.
212 //      *
213 //      * @param  string  key
214 //      * @param  string  default
215 //      * @return mixed
216 //      */
217 //     void pull(string key, string value) {
218 //         attributes[key] = value;
219 //     }
220 
221 //     /**
222 //      * Determine if the session contains old input.
223 //      *
224 //      * @param  string  key
225 //      * @return bool
226 //      */
227 //     bool hasOldInput(string key) {
228 //         string old = getOldInput(key);
229 //         return !old.empty;
230 //     }
231 
232 //     /**
233 //      * Get the requested item from the flashed input array.
234 //      *
235 //      * @param  string  key
236 //      * @param  mixed   default
237 //      * @return mixed
238 //      */
239 //     string[string] getOldInput(string[string] defaults = null) {
240 //         string v = get("_old_input");
241 //         if (v.empty)
242 //             return defaults;
243 //         else
244 //             return to!(string[string])(v);
245 //     }
246 
247 //     /// ditto
248 //     string getOldInput(string key, string defaults = null) {
249 //         string old = get("_old_input");
250 //         string[string] v = to!(string[string])(old);
251 //         return v.get(key, defaults);
252 //     }
253 
254 //     /**
255 //      * Replace the given session attributes entirely.
256 //      *
257 //      * @param  array  attributes
258 //      * @return void
259 //      */
260 //     void replace(string[string] attributes) {
261 //         this.attributes = JSONValue.init;
262 //         put(attributes);
263 //     }
264 
265 //     /**
266 //      * Put a key / value pair or array of key / value pairs in the session.
267 //      *
268 //      * @param  string|array  key
269 //      * @param  mixed       value
270 //      * @return void
271 //      */
272 //     void put(T = string)(string key, T value) {
273 //         attributes[key] = value;
274 //     }
275 
276 //     /// ditto
277 //     void put(string[string] pairs) {
278 //         foreach (string key, string value; pairs)
279 //             attributes[key] = value;
280 //     }
281 
282 //     /**
283 //      * Get an item from the session, or store the default value.
284 //      *
285 //      * @param  string  key
286 //      * @param  \Closure  callback
287 //      * @return mixed
288 //      */
289 //     string remember(string key, string value) {
290 //         string v = this.get(key);
291 //         if (!v.empty)
292 //             return v;
293 
294 //         this.put(key, value);
295 //         return value;
296 //     }
297 
298 //     /**
299 //      * Push a value onto a session array.
300 //      *
301 //      * @param  string  key
302 //      * @param  mixed   value
303 //      * @return void
304 //      */
305 //     void push(T = string)(string key, T value) {
306 //         T[] array = this.get!(T[])(key);
307 //         array ~= value;
308 
309 //         this.put(key, array);
310 //     }
311 
312 //     /**
313 //      * Flash a key / value pair to the session.
314 //      *
315 //      * @param  string  key
316 //      * @param  mixed   value
317 //      * @return void
318 //      */
319 //     void flash(T = string)(string key, T value) {
320 //         this.put(key, value);
321 //         this.push("_flash.new", key);
322 //         this.removeFromOldFlashData([key]);
323 //     }
324 
325 //     /**
326 //      * Flash a key / value pair to the session for immediate use.
327 //      *
328 //      * @param  string key
329 //      * @param  mixed value
330 //      * @return void
331 //      */
332 //     void now(T = string)(string key, T value) {
333 //         this.put(key, value);
334 //         this.push("_flash.old", key);
335 //     }
336 
337 //     /**
338 //      * Reflash all of the session flash data.
339 //      *
340 //      * @return void
341 //      */
342 //     public void reflash() {
343 //         this.mergeNewFlashes(this.get!(string[])("_flash.old"));
344 //         this.put!(string[])("_flash.old", []);
345 //     }
346 
347 //     /**
348 //      * Reflash a subset of the current flash data.
349 //      *
350 //      * @param  array|mixed  keys
351 //      * @return void
352 //      */
353 //     void keep(string[] keys...) {
354 //         string[] ks = keys.dup;
355 //         mergeNewFlashes(ks);
356 //         removeFromOldFlashData(ks);
357 //     }
358 
359 //     /**
360 //      * Merge new flash keys into the new flash array.
361 //      *
362 //      * @param  array  keys
363 //      * @return void
364 //      */
365 //     protected void mergeNewFlashes(string[] keys) {
366 //         string[] oldKeys = this.get!(string[])("_flash.new");
367 //         string[] values = oldKeys ~ keys;
368 //         values = values.sort().uniq().array;
369 
370 //         this.put("_flash.new", values);
371 //     }
372 
373 //     /**
374 //      * Remove the given keys from the old flash data.
375 //      *
376 //      * @param  array  keys
377 //      * @return void
378 //      */
379 //     protected void removeFromOldFlashData(string[] keys) {
380 //         string[] olds = this.get!(string[])("_flash.old");
381 //         string[] news = olds.remove!(x => keys.canFind(x));
382 //         this.put("_flash.old", news);
383 //     }
384 
385 //     /**
386 //      * Flash an input array to the session.
387 //      *
388 //      * @param  array  value
389 //      * @return void
390 //      */
391 //     void flashInput(string[string] value) {
392 //         flash("_old_input", to!string(value));
393 //     }
394 
395 //     /**
396 //      * Flush the session data and regenerate the ID.
397 //      *
398 //      * @return bool
399 //      */
400 //     // bool invalidate()
401 //     // {
402 //     // 	flush();
403 
404 //     // 	return migrate(true);
405 //     // }
406 
407 //     override bool opEquals(Object o) {
408 //         if (this is o)
409 //             return true;
410 //         HttpSession that = cast(HttpSession) o;
411 //         if (that is null)
412 //             return false;
413 //         return id == that.id;
414 //     }
415 
416 //     override size_t toHash() @trusted nothrow {
417 //         return hashOf(id);
418 //     }
419 
420 //     static HttpSession create(string id, int maxInactiveInterval) {
421 //         long currentTime = DateTime.currentTimeMillis();
422 //         HttpSession session = new HttpSession();
423 //         session.setId(id);
424 //         session.setMaxInactiveInterval(maxInactiveInterval);
425 //         session.setCreationTime(currentTime);
426 //         session.setLastAccessedTime(session.getCreationTime());
427 //         // session.setAttributes(new HashMap!(string, Object)());
428 //         session.setNewSession(true);
429 //         return session;
430 //     }
431 
432 //     static string toJson(HttpSession session) {
433 //         JSONValue j;
434 //         j["CreationTime"] = session.creationTime;
435 //         j["attr"] = session.attributes;
436 //         return j.toString();
437 //     }
438 
439 //     static HttpSession fromJson(string id, string json) {
440 //         JSONValue j = parseJSON(json);
441 //         long currentTime = DateTime.currentTimeMillis();
442 //         HttpSession session = new HttpSession();
443 //         session.setId(id);
444 //         session.setCreationTime(j["CreationTime"].integer);
445 //         session.setLastAccessedTime(currentTime);
446 //         session.setNewSession(false);
447 //         session.attributes = j["attr"];
448 
449 //         return session;
450 //     }
451 
452 //     static string generateSessionId(string sessionName = DefaultSessionIdName) {
453 //         SHA1 hash;
454 //         hash.start();
455 //         hash.put(getRandom);
456 //         ubyte[20] result = hash.finish();
457 //         string str = toLower(toHexString(result));
458 
459 //         return str;
460 //     }
461 // }
462 
463 // /**
464 //  * 
465 //  */
466 // class SessionInvalidException : RuntimeException {
467 //     this() {
468 //         super("");
469 //     }
470 
471 //     this(string msg) {
472 //         super(msg);
473 //     }
474 // }
475 
476 // /**
477 //  * 
478 //  */
479 // class SessionNotFound : RuntimeException {
480 //     this() {
481 //         super("");
482 //     }
483 
484 //     this(string msg) {
485 //         super(msg);
486 //     }
487 // }