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