35104d8f2f56b7b7ef19d4741bb05fdf876719ab
[mono.git] / mcs / class / System.Web / System.Web / HttpContext.cs
1 //
2 // System.Web.HttpContext.cs 
3 //
4 // Author:
5 //      Miguel de Icaza (miguel@novell.com)
6 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
7 //
8
9 //
10 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections;
33 using System.Configuration;
34 using System.Runtime.Remoting.Messaging;
35 using System.Security.Permissions;
36 using System.Security.Principal;
37 using System.Threading;
38 using System.Web.Caching;
39 using System.Web.Configuration;
40 using System.Web.SessionState;
41 using System.Web.UI;
42 using System.Web.Util;
43
44 namespace System.Web {
45         
46         public sealed class HttpContext : IServiceProvider {
47                 internal HttpWorkerRequest WorkerRequest;
48                 HttpApplication app_instance;
49                 HttpRequest request;
50                 HttpResponse response;
51                 HttpSessionState session_state;
52                 HttpServerUtility server;
53                 TraceContext trace_context;
54                 IHttpHandler handler;
55                 string error_page;
56                 bool skip_authorization = false;
57                 IPrincipal user;
58                 object errors;
59                 Hashtable items;
60                 object config_timeout;
61                 int timeout_possible;
62                 DateTime time_stamp = DateTime.UtcNow;
63                 
64                 public HttpContext (HttpWorkerRequest wr)
65                 {
66                         WorkerRequest = wr;
67                         request = new HttpRequest (WorkerRequest, this);
68                         response = new HttpResponse (WorkerRequest, this);
69                 }
70
71                 public HttpContext (HttpRequest request, HttpResponse response)
72                 {
73                         this.request = request;
74                         this.response = response;
75                         
76                 }
77
78                 public Exception [] AllErrors {
79                         get {
80                                 if (errors == null)
81                                         return null;
82
83                                 if (errors is Exception){
84                                         Exception [] all = new Exception [1];
85                                         all [0] = (Exception) errors;
86                                         return all;
87                                 } 
88                                 return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception)));
89                         }
90                 }
91
92                 public HttpApplicationState Application {
93                         get {
94                                 return HttpApplicationFactory.ApplicationState;
95                         }
96                 }
97
98                 public HttpApplication ApplicationInstance {
99                         get {
100                                 return app_instance;
101                         }
102
103                         set {
104                                 app_instance = value;
105                         }
106                               
107                 }
108
109                 public Cache Cache {
110                         get {
111                                 return HttpRuntime.Cache;
112                         }
113                 }
114
115                 //
116                 // The "Current" property is set just after we have constructed it with 
117                 // the 'HttpContext (HttpWorkerRequest)' constructor.
118                 //
119                 public static HttpContext Current {
120                         get {
121                                 return (HttpContext) CallContext.GetData ("c");
122                         }
123
124                         set {
125                                 CallContext.SetData ("c", value);
126                         }
127                 }
128
129                 public Exception Error {
130                         get {
131                                 if (errors == null || (errors is Exception))
132                                         return (Exception) errors;
133                                 return (Exception) (((ArrayList) errors) [0]);
134                         }
135                 }
136
137                 public IHttpHandler Handler {
138                         get {
139                                 return handler;
140                         }
141
142                         set {
143                                 handler = value;
144                         }
145                 }
146
147                 public bool IsCustomErrorEnabled {
148                         get {
149                                 CustomErrorsConfig cfg = null;
150                                 try {
151                                         cfg = (CustomErrorsConfig) GetConfig ("system.web/customErrors");
152                                 } catch {
153                                 }
154                                 if (cfg == null)
155                                         return false;
156
157                                 if (cfg.Mode == CustomErrorMode.On)
158                                         return true;
159
160                                 return (cfg.Mode == CustomErrorMode.RemoteOnly) &&
161                                         (Request.WorkerRequest.GetLocalAddress () != Request.UserHostAddress);
162                         }
163                 }
164
165                 public bool IsDebuggingEnabled {
166                         get {
167                                 return CompilationConfiguration.GetInstance (this).Debug;
168                         }
169                 }
170
171                 public IDictionary Items {
172                         get {
173                                 if (items == null)
174                                         items = new Hashtable ();
175                                 return items;
176                         }
177                 }
178
179                 public HttpRequest Request {
180                         get {
181                                 return request;
182                         }
183                 }
184
185                 public HttpResponse Response {
186                         get {
187                                 return response;
188                         }
189                 }
190
191                 public HttpServerUtility Server {
192                         get {
193                                 if (server == null)
194                                         server = new HttpServerUtility (this);
195                                 return server;
196                         }
197                 }
198
199                 public HttpSessionState Session {
200                         get {
201                                 return session_state;
202                         }
203                 }
204
205                 public bool SkipAuthorization {
206                         get {
207                                 return skip_authorization;
208                         }
209
210                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
211                         set {
212                                 skip_authorization = value;
213                         }
214                 }
215
216                 public DateTime Timestamp {
217                         get {
218                                 return time_stamp.ToLocalTime ();
219                         }
220                 }
221                 
222                 public TraceContext Trace {
223                         get {
224                                 if (trace_context == null)
225                                         trace_context = new TraceContext (this);
226                                 return trace_context;
227                         }
228                 }
229
230                 public IPrincipal User {
231                         get {
232                                 return user;
233                         }
234
235                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
236                         set {
237                                 user = value;
238                         }
239                 }
240
241                 public void AddError (Exception errorInfo)
242                 {
243                         if (errors == null){
244                                 errors = errorInfo;
245                                 return;
246                         }
247                         ArrayList l;
248                         if (errors is Exception){
249                                 l = new ArrayList ();
250                                 l.Add (errors);
251                                 errors = l;
252                         } else 
253                                 l = (ArrayList) errors;
254                         l.Add (errorInfo);
255                 }
256
257                 public void ClearError ()
258                 {
259                         errors = null;
260                 }
261
262                 public static object GetAppConfig (string name)
263                 {
264                         object o = ConfigurationSettings.GetConfig (name);
265
266                         return o;
267                 }
268
269                 public object GetConfig (string name)
270                 {
271                         return WebConfigurationSettings.GetConfig (name, this);
272                 }
273
274                 object IServiceProvider.GetService (Type service)
275                 {
276                         if (service == typeof (HttpWorkerRequest))
277                                 return WorkerRequest;
278
279                         //
280                         // We return everything out of properties in case
281                         // they are dynamically computed in some form in the future.
282                         //
283                         if (service == typeof (HttpApplication))
284                                 return ApplicationInstance;
285
286                         if (service == typeof (HttpRequest))
287                                 return Request;
288
289                         if (service == typeof (HttpResponse))
290                                 return Response;
291
292                         if (service == typeof (HttpSessionState))
293                                 return Session;
294
295                         if (service == typeof (HttpApplicationState))
296                                 return Application;
297
298                         if (service == typeof (IPrincipal))
299                                 return User;
300
301                         if (service == typeof (Cache))
302                                 return Cache;
303
304                         if (service == typeof (HttpContext))
305                                 return Current;
306
307                         if (service == typeof (IHttpHandler))
308                                 return Handler;
309
310                         if (service == typeof (HttpServerUtility))
311                                 return Server;
312                         
313                         if (service == typeof (TraceContext))
314                                 return Trace;
315                         
316                         return null;
317                 }
318
319                 public void RewritePath (string path)
320                 {
321                         int qmark = path.IndexOf ('?');
322                         if (qmark != -1)
323                                 RewritePath (path.Substring (0, qmark), "", path.Substring (qmark + 1));
324                         else
325                                 RewritePath (path, null, null);
326                 }
327
328                 public void RewritePath (string filePath, string pathInfo, string queryString)
329                 {
330                         filePath = UrlUtils.Combine (Request.BaseVirtualDir, filePath);
331                         if (!filePath.StartsWith (HttpRuntime.AppDomainAppVirtualPath))
332                                 throw new HttpException (404, "The virtual path '" + filePath +
333                                         "' maps to another application.");
334
335                         Request.SetCurrentExePath (filePath);
336                         // A null pathInfo or queryString is ignored and previous values remain untouched
337                         if (pathInfo != null)
338                                 Request.SetPathInfo (pathInfo);
339
340                         if (queryString != null)
341                                 Request.QueryStringRaw = queryString;
342                 }
343
344 #region internals
345                 
346                 internal void SetSession (HttpSessionState state)
347                 {
348                         session_state = state;
349                 }
350
351                 // URL of a page used for error redirection.
352                 internal string ErrorPage {
353                         get {
354                                 return error_page;
355                         }
356
357                         set {
358                                 error_page = value;
359                         }
360                 }
361
362                 internal TimeSpan ConfigTimeout {
363                         get {
364                                 if (config_timeout == null) {
365                                         HttpRuntimeConfig config = (HttpRuntimeConfig)
366                                                                 GetConfig ("system.web/httpRuntime");
367                                         config_timeout = new TimeSpan (0, 0, config.ExecutionTimeout);
368                                 }
369
370                                 return (TimeSpan) config_timeout;
371                         }
372
373                         set {
374                                 config_timeout = value;
375                         }
376                 }
377
378                 internal bool CheckIfTimeout (DateTime t)
379                 {
380                         if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0)
381                                 return false;
382
383                         TimeSpan ts = t - time_stamp;
384                         return (ts > ConfigTimeout);
385                 }
386
387                 internal bool TimeoutPossible {
388                         get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); }
389                 }
390
391                 internal void BeginTimeoutPossible ()
392                 {
393                         timeout_possible = 1;
394                 }
395
396                 internal void EndTimeoutPossible ()
397                 {
398                         Interlocked.CompareExchange (ref timeout_possible, 0, 1);
399                 }
400 #endregion
401
402 #if NET_2_0
403                 Page last_page;
404                 
405                 internal Page LastPage {
406                         get {
407                                 return last_page;
408                         }
409
410                         set {
411                                 last_page = value;
412                         }
413                 }
414 #endif
415         }
416 }