2004-05-05 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.SessionState / SessionStateModule.cs
1 //
2 // System.Web.SessionState.SesionStateModule
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //      Stefan Görling (stefan@gorling.se)
7 //      Jackson Harper (jackson@ximian.com)
8 //
9 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
10 // (C) 2003 Stefan Görling (http://www.gorling.se)
11
12 using System.Web;
13 using System.Web.Util;
14 using System.Security.Cryptography;
15
16 namespace System.Web.SessionState
17 {
18         public sealed class SessionStateModule : IHttpModule
19         {
20                 internal static readonly string CookieName = "ASPSESSION";
21                 internal static readonly string HeaderName = "AspFilterSessionId";
22                 
23                 static SessionConfig config;
24                 static Type handlerType;
25                 ISessionHandler handler;
26                 
27                 private RandomNumberGenerator rng;
28                 
29                 public SessionStateModule ()
30                 {
31                         rng = new RNGCryptoServiceProvider ();
32                 }
33
34                 internal RandomNumberGenerator Rng {
35                         get { return rng; }
36                 }
37
38                 public void Dispose ()
39                 {
40                     if (handler!=null)
41                         handler.Dispose();
42                 }
43
44                 public void Init (HttpApplication app)
45                 {
46                         if (config == null) {
47                                 config = (SessionConfig) HttpContext.GetAppConfig ("system.web/sessionState");
48                                 if (config ==  null)
49                                         config = new SessionConfig (null);
50
51                                 if (config.Mode == SessionStateMode.StateServer)
52                                         handlerType = typeof (SessionStateServerHandler);
53
54                                 if (config.Mode == SessionStateMode.SQLServer)
55                                         handlerType = typeof (SessionSQLServerHandler);
56                                 
57                                 if (config.Mode == SessionStateMode.InProc)
58                                         handlerType = typeof (SessionInProcHandler);
59
60                                 if (config.Mode == SessionStateMode.Off)
61                                         return;
62                         }
63
64                         if (config.CookieLess)
65                                 app.BeginRequest += new EventHandler (OnBeginRequest);
66                         
67                         app.AddOnAcquireRequestStateAsync (
68                                 new BeginEventHandler (OnBeginAcquireState),
69                                 new EndEventHandler (OnEndAcquireState));
70
71                         app.ReleaseRequestState += new EventHandler (OnReleaseRequestState);
72                         app.EndRequest += new EventHandler (OnEndRequest);
73                         
74                         if (handlerType != null && handler == null) {
75                                 handler = (ISessionHandler) Activator.CreateInstance (handlerType);
76                                 handler.Init(app, config); //initialize
77                         }
78                 }
79
80                 void OnBeginRequest (object o, EventArgs args)
81                 {
82                         HttpApplication application = (HttpApplication) o;
83                         HttpContext context = application.Context;
84                         string base_path = context.Request.BaseVirtualDir;
85                         string id = UrlUtils.GetSessionId (base_path);
86
87                         if (id == null)
88                                 return;
89                         
90                         context.Request.SetFilePath (UrlUtils.RemoveSessionId (base_path,
91                                                                      context.Request.FilePath));
92                         context.Request.SetHeader (HeaderName, id);
93                 }
94                 
95                 void OnReleaseRequestState (object o, EventArgs args)
96                 {
97                         if (handler == null)
98                                 return;
99
100                         HttpApplication application = (HttpApplication) o;
101                         HttpContext context = application.Context;
102                         handler.UpdateHandler (context, this);
103                 }
104
105                 void OnEndRequest (object o, EventArgs args)
106                 {
107                 }
108
109                 IAsyncResult OnBeginAcquireState (object o, EventArgs args, AsyncCallback cb, object data)
110                 {
111                         HttpApplication application = (HttpApplication) o;
112                         HttpContext context = application.Context;
113
114                         bool required = (context.Handler is IRequiresSessionState);
115                         bool read_only = (context.Handler is IReadOnlySessionState);
116                         
117                         bool isNew = false;
118                         HttpSessionState session = null;
119                         if (handler != null)
120                                 session = handler.UpdateContext (context, this, required, read_only, ref isNew);
121
122                         if (session != null) {
123                                 if (isNew)
124                                         session.SetNewSession (true);
125
126                                 if (read_only)
127                                         session = session.Clone ();
128                                         
129                                 context.SetSession (session);
130
131                                 if (isNew && config.CookieLess) {
132                                         string id = context.Session.SessionID;
133                                         context.Request.SetHeader (HeaderName, id);
134                                         context.Response.Redirect (UrlUtils.InsertSessionId (id,
135                                                                    context.Request.FilePath));
136                                 } else if (isNew) {
137                                         string id = context.Session.SessionID;
138                                         HttpCookie cookie = new HttpCookie (CookieName, id);
139                                         cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
140                                         context.Response.AppendCookie (cookie);
141                                 }
142                         }
143                         
144                         // In the future, we might want to move the Async stuff down to
145                         // the interface level, if we're going to support other than
146                         // InProc, we might actually want to do things async, now we
147                         // simply fake it.
148                         HttpAsyncResult result=new HttpAsyncResult (cb,this);
149                         result.Complete (true, o, null);
150                         if (isNew && Start != null)
151                                 Start (this, args);
152
153                         return result;
154                 }
155
156                 void OnEndAcquireState (IAsyncResult result)
157                 {
158                 }
159
160                 internal void OnEnd ()
161                 {
162                         if (End != null)
163                                 End (this, EventArgs.Empty);
164                 }
165                 
166                 public event EventHandler Start;
167                 public event EventHandler End;
168         }
169 }
170