* roottypes.cs: Rename from tree.cs.
[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.Globalization;
35 using System.Runtime.Remoting.Messaging;
36 using System.Security.Permissions;
37 using System.Security.Principal;
38 using System.Threading;
39 using System.Web.Caching;
40 using System.Web.Configuration;
41 using System.Web.SessionState;
42 using System.Web.UI;
43 using System.Web.Util;
44 #if NET_2_0
45 using System.Web.Profile;
46 using CustomErrorMode = System.Web.Configuration.CustomErrorsMode;
47 #endif
48
49 namespace System.Web {
50         
51         // CAS - no InheritanceDemand here as the class is sealed
52         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
53         public sealed class HttpContext : IServiceProvider {
54                 internal HttpWorkerRequest WorkerRequest;
55                 HttpApplication app_instance;
56                 HttpRequest request;
57                 HttpResponse response;
58                 HttpSessionState session_state;
59                 HttpServerUtility server;
60                 TraceContext trace_context;
61                 IHttpHandler handler;
62                 string error_page;
63                 bool skip_authorization = false;
64                 IPrincipal user;
65                 object errors;
66                 Hashtable items;
67                 object config_timeout;
68                 int timeout_possible;
69                 DateTime time_stamp = DateTime.UtcNow;
70 #if TARGET_JVM // No remoting support (CallContext) yet in Grasshopper
71                 static LocalDataStoreSlot _ContextSlot = Thread.GetNamedDataSlot ("Context");
72 #endif
73                 
74                 public HttpContext (HttpWorkerRequest wr)
75                 {
76                         WorkerRequest = wr;
77                         request = new HttpRequest (WorkerRequest, this);
78                         response = new HttpResponse (WorkerRequest, this);
79                 }
80
81                 public HttpContext (HttpRequest request, HttpResponse response)
82                 {
83                         this.request = request;
84                         this.response = response;
85                         
86                 }
87
88                 public Exception [] AllErrors {
89                         get {
90                                 if (errors == null)
91                                         return null;
92
93                                 if (errors is Exception){
94                                         Exception [] all = new Exception [1];
95                                         all [0] = (Exception) errors;
96                                         return all;
97                                 } 
98                                 return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception)));
99                         }
100                 }
101
102                 public HttpApplicationState Application {
103                         get {
104                                 return HttpApplicationFactory.ApplicationState;
105                         }
106                 }
107
108                 public HttpApplication ApplicationInstance {
109                         get {
110                                 return app_instance;
111                         }
112
113                         set {
114                                 app_instance = value;
115                         }
116                               
117                 }
118
119                 public Cache Cache {
120                         get {
121                                 return HttpRuntime.Cache;
122                         }
123                 }
124
125                 //
126                 // The "Current" property is set just after we have constructed it with 
127                 // the 'HttpContext (HttpWorkerRequest)' constructor.
128                 //
129 #if TARGET_JVM // No remoting support (CallContext) yet in Grasshopper
130                 [MonoTODO("Context - Use System.Remoting.Messaging.CallContext instead of Thread storage")]
131                 public static HttpContext Current
132                 {
133                         get { return (HttpContext) Thread.GetData (_ContextSlot); }
134                         set { Thread.SetData (_ContextSlot, value); }
135                 }
136 #else
137                 public static HttpContext Current {
138                         get {
139                                 return (HttpContext) CallContext.GetData ("c");
140                         }
141
142                         set {
143                                 CallContext.SetData ("c", value);
144                         }
145                 }
146 #endif
147
148                 public Exception Error {
149                         get {
150                                 if (errors == null || (errors is Exception))
151                                         return (Exception) errors;
152                                 return (Exception) (((ArrayList) errors) [0]);
153                         }
154                 }
155
156                 public IHttpHandler Handler {
157                         get {
158                                 return handler;
159                         }
160
161                         set {
162                                 handler = value;
163                         }
164                 }
165
166                 public bool IsCustomErrorEnabled {
167                         get {
168 #if NET_2_0
169                                 CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors");
170 #else
171                                 CustomErrorsConfig cfg = null;
172                                 try {
173                                         cfg = (CustomErrorsConfig) GetConfig ("system.web/customErrors");
174                                 } catch {
175                                 }
176
177                                 if (cfg == null)
178                                         return false;
179 #endif
180
181                                 if (cfg.Mode == CustomErrorMode.On)
182                                         return true;
183
184                                 return (cfg.Mode == CustomErrorMode.RemoteOnly) && 
185                                         (Request.WorkerRequest.GetLocalAddress () != Request.UserHostAddress);
186                         }
187                 }
188 #if TARGET_JVM
189                 public bool IsDebuggingEnabled { get { return false; } }
190 #else
191                 public bool IsDebuggingEnabled {
192                         get {
193 #if NET_2_0
194                                 CompilationSection section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
195                                 return section.Debug;
196 #else
197                                 try {
198                                         return CompilationConfiguration.GetInstance (this).Debug;
199                                 } catch {
200                                         return false;
201                                 }
202 #endif
203                         }
204                 }
205 #endif
206                 public IDictionary Items {
207                         get {
208                                 if (items == null)
209                                         items = new Hashtable ();
210                                 return items;
211                         }
212                 }
213
214                 public HttpRequest Request {
215                         get {
216                                 return request;
217                         }
218                 }
219
220                 public HttpResponse Response {
221                         get {
222                                 return response;
223                         }
224                 }
225
226                 public HttpServerUtility Server {
227                         get {
228                                 if (server == null)
229                                         server = new HttpServerUtility (this);
230                                 return server;
231                         }
232                 }
233
234                 public HttpSessionState Session {
235                         get {
236                                 return session_state;
237                         }
238                 }
239
240                 public bool SkipAuthorization {
241                         get {
242                                 return skip_authorization;
243                         }
244
245                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
246                         set {
247                                 skip_authorization = value;
248                         }
249                 }
250
251                 public DateTime Timestamp {
252                         get {
253                                 return time_stamp.ToLocalTime ();
254                         }
255                 }
256                 
257                 public TraceContext Trace {
258                         get {
259                                 if (trace_context == null)
260                                         trace_context = new TraceContext (this);
261                                 return trace_context;
262                         }
263                 }
264
265                 public IPrincipal User {
266                         get {
267                                 return user;
268                         }
269
270                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
271                         set {
272                                 user = value;
273                         }
274                 }
275
276 #if NET_2_0
277                 [MonoTODO]
278                 public IHttpHandler CurrentHandler {
279                         get { throw new NotImplementedException (); }
280                 }
281
282                 [MonoTODO]
283                 public IHttpHandler PreviousHandler {
284                         get { throw new NotImplementedException (); }
285                 }
286
287                 [MonoTODO]
288                 public ProfileBase Profile {
289                         get { throw new NotImplementedException (); }
290                 }
291 #endif
292
293                 public void AddError (Exception errorInfo)
294                 {
295                         if (errors == null){
296                                 errors = errorInfo;
297                                 return;
298                         }
299                         ArrayList l;
300                         if (errors is Exception){
301                                 l = new ArrayList ();
302                                 l.Add (errors);
303                                 errors = l;
304                         } else 
305                                 l = (ArrayList) errors;
306                         l.Add (errorInfo);
307                 }
308
309                 internal void ClearError (Exception e)
310                 {
311                         if (errors == e)
312                                 errors = null;
313                 }
314
315                 public void ClearError ()
316                 {
317                         errors = null;
318                 }
319
320 #if NET_2_0
321                 [Obsolete ("use WebConfigurationManager.GetWebApplicationSection")]
322 #endif
323                 public static object GetAppConfig (string name)
324                 {
325                         object o = ConfigurationSettings.GetConfig (name);
326
327                         return o;
328                 }
329
330 #if NET_2_0
331                 [Obsolete ("see GetSection")]
332 #endif
333                 public object GetConfig (string name)
334                 {
335 #if NET_2_0
336                         return GetSection (name);
337 #else
338                         return WebConfigurationSettings.GetConfig (name, this);
339 #endif
340                 }
341
342 #if NET_2_0
343                 [MonoTODO]
344                 public static object GetGlobalResourceObject (string classKey, string resourceKey)
345                 {
346                         throw new NotImplementedException ();
347                 }
348
349                 [MonoTODO]
350                 public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture)
351                 {
352                         throw new NotImplementedException ();
353                 }
354
355                 [MonoTODO]
356                 public static object GetLocalResourceObject (string virtualPath, string resourceKey)
357                 {
358                         throw new NotImplementedException ();
359                 }
360
361                 [MonoTODO]
362                 public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture)
363                 {
364                         throw new NotImplementedException ();
365                 }
366
367                 [MonoTODO]
368                 public object GetSection (string name)
369                 {
370 #if NET_2_0
371                         return WebConfigurationManager.GetSection (name);
372 #else
373                         throw new NotImplementedException ();
374 #endif
375                 }
376 #endif
377                 object IServiceProvider.GetService (Type service)
378                 {
379                         if (service == typeof (HttpWorkerRequest))
380                                 return WorkerRequest;
381
382                         //
383                         // We return everything out of properties in case
384                         // they are dynamically computed in some form in the future.
385                         //
386                         if (service == typeof (HttpApplication))
387                                 return ApplicationInstance;
388
389                         if (service == typeof (HttpRequest))
390                                 return Request;
391
392                         if (service == typeof (HttpResponse))
393                                 return Response;
394
395                         if (service == typeof (HttpSessionState))
396                                 return Session;
397
398                         if (service == typeof (HttpApplicationState))
399                                 return Application;
400
401                         if (service == typeof (IPrincipal))
402                                 return User;
403
404                         if (service == typeof (Cache))
405                                 return Cache;
406
407                         if (service == typeof (HttpContext))
408                                 return Current;
409
410                         if (service == typeof (IHttpHandler))
411                                 return Handler;
412
413                         if (service == typeof (HttpServerUtility))
414                                 return Server;
415                         
416                         if (service == typeof (TraceContext))
417                                 return Trace;
418                         
419                         return null;
420                 }
421
422                 public void RewritePath (string path)
423                 {
424                         int qmark = path.IndexOf ('?');
425                         if (qmark != -1)
426                                 RewritePath (path.Substring (0, qmark), "", path.Substring (qmark + 1));
427                         else
428                                 RewritePath (path, null, null);
429                 }
430
431                 public void RewritePath (string filePath, string pathInfo, string queryString)
432                 {
433                         filePath = UrlUtils.Combine (Request.BaseVirtualDir, filePath);
434                         if (!filePath.StartsWith (HttpRuntime.AppDomainAppVirtualPath))
435                                 throw new HttpException (404, "The virtual path '" + filePath +
436                                         "' maps to another application.");
437
438                         Request.SetCurrentExePath (filePath);
439                         // A null pathInfo or queryString is ignored and previous values remain untouched
440                         if (pathInfo != null)
441                                 Request.SetPathInfo (pathInfo);
442
443                         if (queryString != null)
444                                 Request.QueryStringRaw = queryString;
445                 }
446
447 #if NET_2_0
448                 [MonoTODO]
449                 public void RewritePath (string path, bool rebaseClientPath)
450                 {
451                         throw new NotImplementedException ();
452                 }
453 #endif
454
455 #region internals
456                 
457                 internal void SetSession (HttpSessionState state)
458                 {
459                         session_state = state;
460                 }
461
462                 // URL of a page used for error redirection.
463                 internal string ErrorPage {
464                         get {
465                                 return error_page;
466                         }
467
468                         set {
469                                 error_page = value;
470                         }
471                 }
472
473                 internal TimeSpan ConfigTimeout {
474                         get {
475                                 if (config_timeout == null) {
476 #if NET_2_0
477                                         HttpRuntimeSection section = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
478                                         config_timeout = section.ExecutionTimeout;
479 #else
480                                         HttpRuntimeConfig config = (HttpRuntimeConfig)
481                                                                 GetConfig ("system.web/httpRuntime");
482                                         config_timeout = new TimeSpan (0, 0, config.ExecutionTimeout);
483 #endif
484                                 }
485
486                                 return (TimeSpan) config_timeout;
487                         }
488
489                         set {
490                                 config_timeout = value;
491                         }
492                 }
493
494                 internal bool CheckIfTimeout (DateTime t)
495                 {
496                         if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0)
497                                 return false;
498
499                         TimeSpan ts = t - time_stamp;
500                         return (ts > ConfigTimeout);
501                 }
502
503                 internal bool TimeoutPossible {
504                         get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); }
505                 }
506
507                 internal void BeginTimeoutPossible ()
508                 {
509                         timeout_possible = 1;
510                 }
511
512                 internal void EndTimeoutPossible ()
513                 {
514                         Interlocked.CompareExchange (ref timeout_possible, 0, 1);
515                 }
516 #endregion
517
518 #if NET_2_0
519                 Page last_page;
520                 
521                 internal Page LastPage {
522                         get {
523                                 return last_page;
524                         }
525
526                         set {
527                                 last_page = value;
528                         }
529                 }
530 #endif
531         }
532 }