* SessionStateModule.cs: If using cookieless sessions add an
[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         [MonoTODO]
19         public sealed class SessionStateModule : IHttpModule, IRequiresSessionState
20         {
21                 internal static readonly string CookieName = "ASPSESSION";
22                 internal static readonly string HeaderName = "AspFilterSessionId";
23                 
24                 static SessionConfig config;
25                 static Type handlerType;
26                 ISessionHandler handler;
27
28                 private RandomNumberGenerator rng;
29                 
30                 public SessionStateModule ()
31                 {
32                         rng = new RNGCryptoServiceProvider ();
33                 }
34
35                 internal RandomNumberGenerator Rng {
36                         get { return rng; }
37                 }
38                 
39                 public void Dispose ()
40                 {
41                     if (handler!=null)
42                         handler.Dispose();
43                 }
44
45                 [MonoTODO]
46                 public void Init (HttpApplication app)
47                 {
48                         if (config == null) {
49                                 config = (SessionConfig) HttpContext.GetAppConfig ("system.web/sessionState");
50                                 if (config ==  null)
51                                         config = new SessionConfig (null);
52
53                                 if (config.Mode == SessionStateMode.StateServer)
54                                         handlerType = typeof (SessionStateServerHandler);
55
56                                 if (config.Mode == SessionStateMode.SQLServer)
57                                         handlerType = typeof (SessionSQLServerHandler);
58                                 
59                                 if (config.Mode == SessionStateMode.InProc)
60                                         handlerType = typeof (SessionInProcHandler);
61                         }
62
63                         if (config.CookieLess)
64                                 app.BeginRequest += new EventHandler (OnBeginRequest);
65                         
66                         app.AddOnAcquireRequestStateAsync (
67                                 new BeginEventHandler (OnBeginAcquireState),
68                                 new EndEventHandler (OnEndAcquireState));
69
70                         app.ReleaseRequestState += new EventHandler (OnReleaseRequestState);
71                         app.EndRequest += new EventHandler (OnEndRequest);
72                         
73                         if (handlerType != null && handler == null) {
74                                 handler = (ISessionHandler) Activator.CreateInstance (handlerType);
75                                 handler.Init(app, config); //initialize
76                         }
77                 }
78
79                 public void OnBeginRequest (object o, EventArgs args)
80                 {
81                         HttpApplication application = (HttpApplication) o;
82                         HttpContext context = application.Context;
83                         string base_path = context.Request.BaseVirtualDir;
84                         string id = UrlUtils.GetSessionId (base_path);
85
86                         if (id == null)
87                                 return;
88                         
89                         context.Request.SetFilePath (UrlUtils.RemoveSessionId (base_path,
90                                                                      context.Request.FilePath));
91                         context.Request.SetHeader (HeaderName, id);
92                 }
93                 
94                 void OnReleaseRequestState (object o, EventArgs args)
95                 {
96                         if (handler == null)
97                                 return;
98
99                         HttpApplication application = (HttpApplication) o;
100                         HttpContext context = application.Context;
101                         handler.UpdateHandler (context, this);
102                 }
103
104                 void OnEndRequest (object o, EventArgs args)
105                 {
106                 }
107
108                 IAsyncResult OnBeginAcquireState (object o, EventArgs args, AsyncCallback cb, object data)
109                 {
110                         HttpApplication application = (HttpApplication) o;
111                         HttpContext context = application.Context;
112
113                         bool isNew = false;
114                         if (handler != null)
115                             isNew = handler.UpdateContext (context, this);
116
117                         if (isNew && config.CookieLess) {
118                                 string id = context.Session.SessionID;
119                                 context.Request.SetHeader (HeaderName, id);
120                                 context.Response.Redirect (UrlUtils.InsertSessionId (id,
121                                                 context.Request.FilePath));
122                         } else {
123                                 string id = context.Session.SessionID;
124                                 HttpCookie cookie = new HttpCookie (CookieName, id);
125                                 cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
126                                 context.Response.AppendCookie (cookie);
127                         }
128                         
129                         // In the future, we might want to move the Async stuff down to
130                         // the interface level, if we're going to support other than
131                         // InProc, we might actually want to do things async, now we
132                         // simply fake it.
133                         HttpAsyncResult result=new HttpAsyncResult (cb,this);
134                         result.Complete (true, o, null);
135                         if (isNew && Start != null)
136                                 Start (this, args);
137
138                         return result;
139                 }
140
141                 void OnEndAcquireState (IAsyncResult result)
142                 {
143                 }
144
145                 internal void OnEnd ()
146                 {
147                         if (End != null)
148                                 End (this, EventArgs.Empty);
149                 }
150                 
151                 public event EventHandler Start;
152                 public event EventHandler End;
153         }
154 }
155