* SessionStateModule.cs: If using cookieless sessions add an
[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.IO;
20 using System.Collections;
21
22 namespace System.Web.SessionState
23 {
24         // Container object, containing the current session state and when it was last accessed.
25         internal class SessionContainer
26         {
27                 private HttpSessionState _state;
28                 private DateTime last_access;
29
30                 public SessionContainer (HttpSessionState state)
31                 {
32                         _state = state;
33                         this.Touch ();
34                 }
35
36                 public void Touch ()
37                 {
38                         last_access = DateTime.Now;
39                 }
40
41                 public HttpSessionState SessionState {
42                         get {
43                                 //Check if we should abandon it.
44                                 if (_state != null && last_access.AddMinutes (_state.Timeout) < DateTime.Now)
45                                         _state.Abandon ();
46
47                                 return _state;
48                         }
49                         set {
50                                 _state=value;
51                                 this.Touch ();
52                         }
53                 }
54         }
55
56
57         internal class SessionInProcHandler : ISessionHandler
58         {
59                 protected Hashtable _sessionTable;
60                 // The length of a session, in minutes. After this length, it's abandoned due to idle.
61                 const int SESSION_LIFETIME = 45;
62
63                 private SessionConfig config;
64                 
65                 public void Dispose ()
66                 {
67                         _sessionTable = null;
68                 }
69
70                 public void Init (HttpApplication context, SessionConfig config)
71                 {
72                         this.config = config;
73                         _sessionTable = (Hashtable) AppDomain.CurrentDomain.GetData (".MonoSessionInProc");
74                         if (_sessionTable == null)
75                                 _sessionTable = new Hashtable();
76                 }
77
78                 public void UpdateHandler (HttpContext context, SessionStateModule module)
79                 {
80                 }
81
82                 //this is the code that actually do stuff.
83                 public bool UpdateContext (HttpContext context, SessionStateModule module)
84                 {
85                         SessionContainer container = null;
86                         string id = SessionId.Lookup (context.Request, config.CookieLess);
87                         
88                         //first we try to get the cookie.
89                         // if we have a cookie, we look it up in the table.
90                         if (id != null) {
91                                 container = (SessionContainer) _sessionTable [id];
92
93                                 // if we have a session, and it is not expired, set isNew to false and return it.
94                                 if (container!=null && container.SessionState!=null && !container.SessionState.IsAbandoned) {
95                                         // Can we do this? It feels safe, but what do I know.
96                                         container.SessionState.IsNewSession = false;
97                                         // update the timestamp.
98                                         container.Touch ();
99                                          // Can we do this? It feels safe, but what do I know.
100                                         context.SetSession (container.SessionState);
101                                         return false; // and we're done
102                                 } else if(container!=null) {
103                                         _sessionTable.Remove (id);
104                                 }
105                         }
106
107                         // else we create a new session.
108                         string sessionID = SessionId.Create (module.Rng);
109                         container = new SessionContainer (new HttpSessionState (sessionID, // unique identifier
110                                                                                 new SessionDictionary(), // dictionary
111                                                                                 new HttpStaticObjectsCollection(),
112                                                                                 SESSION_LIFETIME, //lifetime befor death.
113                                                                                 true, //new session
114                                                                                 false, // is cookieless
115                                                                                 SessionStateMode.InProc,
116                                                                                 false)); //readonly
117                         // puts it in the table.
118                         _sessionTable [sessionID]=container;
119                         AppDomain.CurrentDomain.SetData (".MonoSessionInProc", _sessionTable);
120
121                         // and returns it.
122                         context.SetSession (container.SessionState);
123                         context.Session.IsNewSession = true;
124
125                         // And we're done!
126                         return true;
127                 }
128         }
129 }
130