2003-03-31 Stefan G�rling <stefan@gorling.se>
[mono.git] / mcs / class / System.Web / System.Web.SessionState / SessionInProcHandler.cs
1 //
2 // System.Web.SessionState.SessionInProcHandler
3 //
4 // Authors:
5 //      Stefan Görling (stefan@gorling.se)
6 //
7 // (C) 2003 Stefan Görling
8 //
9
10 /*
11         This is a rather lazy implementation, but it does the trick for me.
12
13         TODO:
14             * Remove abandoned sessions., preferably by a worker thread sleeping most of the time.
15             * Increase session security, for example by using UserAgent i hashcode.
16             * Generate SessionID:s in a good (more random) way.
17 */
18 using System;
19 using System.Collections;
20
21 namespace System.Web.SessionState
22 {
23         // Container object, containing the current session state and when it was last accessed.
24         public class SessionContainer
25         {
26                 private HttpSessionState _state;
27                 private long _last_access;
28
29                 public SessionContainer (HttpSessionState state)
30                 {
31                         _state = state;
32                         this.Touch ();
33                 }
34
35                 public void Touch ()
36                 {
37                         _last_access = DateTime.Now.Millisecond;            
38                 }
39
40                 public HttpSessionState SessionState {
41                         get {
42                                 //Check if we should abandon it.
43                                 if (_state != null &&
44                                     (DateTime.Now.Millisecond - _last_access) > (_state.Timeout * 60 * 1000))
45                                         _state.Abandon ();
46
47                                 return _state;
48                         }
49                         set {
50                                 _state=value;
51                                 this.Touch ();
52                         }
53                 }
54         }
55
56
57         public class SessionInProcHandler : ISessionHandler
58         {
59                 protected Hashtable _sessionTable;
60                 const string COOKIE_NAME = "ASPSESSION"; // The name of the cookie.
61                 // The length of a session, in minutes. After this length, it's abandoned due to idle.
62                 const int SESSION_LIFETIME = 45;
63
64                 public void Dispose ()
65                 {
66                         _sessionTable = null;
67                 }
68
69                 public void Init (HttpApplication context)
70                 {
71                         _sessionTable = new Hashtable();
72                 }
73
74
75                 //this is the code that actually do stuff.
76                 public void UpdateContext (HttpContext context)
77                 {
78                         SessionContainer container = null;
79
80                         //first we try to get the cookie.
81                         // if we have a cookie, we look it up in the table.
82                         if (context.Request.Cookies [COOKIE_NAME] != null) {
83                                 container = (SessionContainer) _sessionTable [context.Request.Cookies [COOKIE_NAME].Value];
84
85                                 // if we have a session, and it is not expired, set isNew to false and return it.
86                                 if (container!=null && container.SessionState!=null && !container.SessionState.IsAbandoned) {
87                                         // Can we do this? It feels safe, but what do I know.
88                                         container.SessionState.IsNewSession = false;
89                                         // update the timestamp.
90                                         container.Touch ();
91                                          // Can we do this? It feels safe, but what do I know.
92                                         context.Session = container.SessionState;
93                                         return; // and we're done
94                                 } else if(container!=null) {
95                                         //A empty or expired session, lets kill it.
96                                         _sessionTable[context.Request.Cookies[COOKIE_NAME]]=null;
97                                 }
98                         }
99
100                         // else we create a new session.
101                         string sessionID = System.Guid.NewGuid ().ToString ();
102                         container = new SessionContainer (new HttpSessionState (sessionID, // unique identifier
103                                                                                 new SessionDictionary(), // dictionary
104                                                                                 new HttpStaticObjectsCollection(),
105                                                                                 SESSION_LIFETIME, //lifetime befor death.
106                                                                                 true, //new session
107                                                                                 false, // is cookieless
108                                                                                 SessionStateMode.InProc,
109                                                                                 false)); //readonly
110                         // puts it in the table.
111                         _sessionTable [sessionID]=container;
112
113                         // and returns it.
114                         context.Session = container.SessionState;
115
116
117                         // sets the session cookie. We're assuming that session scope is the default mode.
118                         context.Response.AppendCookie (new HttpCookie (COOKIE_NAME,sessionID));
119
120                         // And we're done!
121                 }
122         }
123 }
124