Do not abuse the 'private' keyword
[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.Collections.Generic;
46 using System.IO;
47 using System.Reflection;
48 using System.Resources;
49 using System.Web.Compilation;
50 using System.Web.Profile;
51 using CustomErrorMode = System.Web.Configuration.CustomErrorsMode;
52 #endif
53
54 namespace System.Web {
55         // CAS - no InheritanceDemand here as the class is sealed
56         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
57         public sealed partial class HttpContext : IServiceProvider {
58                 internal HttpWorkerRequest WorkerRequest;
59                 HttpApplication app_instance;
60                 HttpRequest request;
61                 HttpResponse response;
62                 HttpSessionState session_state;
63                 HttpServerUtility server;
64                 TraceContext trace_context;
65                 IHttpHandler handler;
66                 string error_page;
67                 bool skip_authorization = false;
68                 IPrincipal user;
69                 object errors;
70                 Hashtable items;
71                 object config_timeout;
72                 int timeout_possible;
73                 DateTime time_stamp = DateTime.UtcNow;
74                 Timer timer;
75                 Thread thread;
76                 bool _isProcessingInclude;
77
78 #if NET_2_0
79                 [ThreadStatic]
80                 static ResourceProviderFactory provider_factory;
81                 [ThreadStatic]
82                 static Dictionary <string, IResourceProvider> resource_providers;
83                 
84 #if TARGET_JVM
85                 const string app_global_res_key = "HttpContext.app_global_res_key";
86                 internal static Assembly AppGlobalResourcesAssembly {
87                         get { return (Assembly) AppDomain.CurrentDomain.GetData (app_global_res_key); }
88                         set { AppDomain.CurrentDomain.SetData (app_global_res_key, value); }
89                 }
90 #else
91                 [ThreadStatic]
92                 static Dictionary <ResourceManagerCacheKey, ResourceManager> resourceManagerCache;
93                 internal static Assembly AppGlobalResourcesAssembly;
94 #endif
95                 ProfileBase profile = null;
96                 LinkedList<IHttpHandler> handlers;
97 #endif
98                 
99                 public HttpContext (HttpWorkerRequest wr)
100                 {
101                         WorkerRequest = wr;
102                         request = new HttpRequest (WorkerRequest, this);
103                         response = new HttpResponse (WorkerRequest, this);
104                 }
105
106                 public HttpContext (HttpRequest request, HttpResponse response)
107                 {
108                         this.request = request;
109                         this.response = response;
110                         
111                 }
112
113                 internal bool IsProcessingInclude {
114                         get { return _isProcessingInclude; }
115                         set { _isProcessingInclude = value; }
116                 }
117
118                 public Exception [] AllErrors {
119                         get {
120                                 if (errors == null)
121                                         return null;
122
123                                 if (errors is Exception){
124                                         Exception [] all = new Exception [1];
125                                         all [0] = (Exception) errors;
126                                         return all;
127                                 } 
128                                 return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception)));
129                         }
130                 }
131
132                 public HttpApplicationState Application {
133                         get {
134                                 return HttpApplicationFactory.ApplicationState;
135                         }
136                 }
137
138                 public HttpApplication ApplicationInstance {
139                         get {
140                                 return app_instance;
141                         }
142
143                         set {
144                                 app_instance = value;
145                         }
146                               
147                 }
148
149                 public Cache Cache {
150                         get {
151                                 return HttpRuntime.Cache;
152                         }
153                 }
154
155                 internal Cache InternalCache {
156                         get {
157                                 return HttpRuntime.InternalCache;
158                         }
159                 }
160                 
161                 //
162                 // The "Current" property is set just after we have constructed it with 
163                 // the 'HttpContext (HttpWorkerRequest)' constructor.
164                 //
165 #if !TARGET_JVM // No remoting CallContext support in Grasshopper
166                 public static HttpContext Current {
167                         get {
168                                 return (HttpContext) CallContext.GetData ("c");
169                         }
170
171                         set {
172                                 CallContext.SetData ("c", value);
173                         }
174                 }
175 #endif
176
177                 public Exception Error {
178                         get {
179                                 if (errors == null || (errors is Exception))
180                                         return (Exception) errors;
181                                 return (Exception) (((ArrayList) errors) [0]);
182                         }
183                 }
184
185                 public IHttpHandler Handler {
186                         get {
187                                 return handler;
188                         }
189
190                         set {
191                                 handler = value;
192                         }
193                 }
194
195                 public bool IsCustomErrorEnabled {
196                         get {
197                                 try {
198                                         return IsCustomErrorEnabledUnsafe;
199                                 }
200                                 catch {
201                                         return false;
202                                 }
203                         }
204                 }
205
206                 internal bool IsCustomErrorEnabledUnsafe {
207                         get {
208 #if NET_2_0
209                                 CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors");
210 #else
211                                 CustomErrorsConfig cfg = null;
212                                 try {
213                                         cfg = (CustomErrorsConfig) GetConfig ("system.web/customErrors");
214                                 } catch {
215                                 }
216
217                                 if (cfg == null)
218                                         return false;
219 #endif
220
221                                 if (cfg.Mode == CustomErrorMode.On)
222                                         return true;
223
224                                 return (cfg.Mode == CustomErrorMode.RemoteOnly) && !Request.IsLocal;
225                         }
226                 }
227 #if !TARGET_JVM
228                 public bool IsDebuggingEnabled {
229                         get {
230 #if NET_2_0
231                                 CompilationSection section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
232                                 return section.Debug;
233 #else
234                                 try {
235                                         return CompilationConfiguration.GetInstance (this).Debug;
236                                 } catch {
237                                         return false;
238                                 }
239 #endif
240                         }
241                 }
242 #endif
243                 public IDictionary Items {
244                         get {
245                                 if (items == null)
246                                         items = new Hashtable ();
247                                 return items;
248                         }
249                 }
250
251                 public HttpRequest Request {
252                         get {
253                                 return request;
254                         }
255                 }
256
257                 public HttpResponse Response {
258                         get {
259                                 return response;
260                         }
261                 }
262
263                 public HttpServerUtility Server {
264                         get {
265                                 if (server == null)
266                                         server = new HttpServerUtility (this);
267                                 return server;
268                         }
269                 }
270
271                 public HttpSessionState Session {
272                         get {
273                                 return session_state;
274                         }
275                 }
276
277                 public bool SkipAuthorization {
278                         get {
279                                 return skip_authorization;
280                         }
281
282                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
283                         set {
284                                 skip_authorization = value;
285                         }
286                 }
287
288                 public DateTime Timestamp {
289                         get {
290                                 return time_stamp.ToLocalTime ();
291                         }
292                 }
293                 
294                 public TraceContext Trace {
295                         get {
296                                 if (trace_context == null)
297                                         trace_context = new TraceContext (this);
298                                 return trace_context;
299                         }
300                 }
301
302                 public IPrincipal User {
303                         get {
304                                 return user;
305                         }
306
307                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
308                         set {
309                                 user = value;
310                         }
311                 }
312
313 #if NET_2_0
314                 // The two properties below are defined only when the IIS7 integrated mode is used.
315                 // They are useless under Mono
316                 public RequestNotification CurrentNotification {
317                         get { throw new PlatformNotSupportedException ("This property is not supported on Mono.");  }
318                 }
319
320                 public bool IsPostNotification {
321                         get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); }
322                 }
323                 
324                 internal void PushHandler (IHttpHandler handler)
325                 {
326                         if (handler == null)
327                                 return;
328                         if (handlers == null)
329                                 handlers = new LinkedList <IHttpHandler> ();
330                         handlers.AddLast (handler);
331                 }
332
333                 internal void PopHandler ()
334                 {
335                         if (handlers == null || handlers.Count == 0)
336                                 return;
337                         handlers.RemoveLast ();
338                 }
339                 
340                 IHttpHandler GetCurrentHandler ()
341                 {
342                         if (handlers == null || handlers.Count == 0)
343                                 return null;
344                         
345                         return handlers.Last.Value;
346                 }
347
348                 IHttpHandler GetPreviousHandler ()
349                 {
350                         if (handlers == null || handlers.Count <= 1)
351                                 return null;
352                         LinkedListNode <IHttpHandler> previous = handlers.Last.Previous;
353                         if (previous != null)
354                                 return previous.Value;
355                         return null;
356                 }
357                 
358                 public IHttpHandler CurrentHandler {
359                         get { return GetCurrentHandler (); }
360                 }
361
362                 public IHttpHandler PreviousHandler {
363                         get { return GetPreviousHandler (); }
364                 }
365
366                 internal bool ProfileInitialized {
367                         get { return profile != null; }
368                 }
369
370                 public ProfileBase Profile {
371                         get {
372                                 if (profile == null) {
373                                         if (Request.IsAuthenticated)
374                                                 profile = ProfileBase.Create (User.Identity.Name);
375                                         else
376                                                 profile = ProfileBase.Create (Request.AnonymousID, false);
377                                 }
378                                 return profile;
379                         }
380
381                         internal set {
382                                 profile = value;
383                         }
384                 }
385 #endif
386
387                 public void AddError (Exception errorInfo)
388                 {
389                         if (errors == null){
390                                 errors = errorInfo;
391                                 return;
392                         }
393                         ArrayList l;
394                         if (errors is Exception){
395                                 l = new ArrayList ();
396                                 l.Add (errors);
397                                 errors = l;
398                         } else 
399                                 l = (ArrayList) errors;
400                         l.Add (errorInfo);
401                 }
402
403                 internal void ClearError (Exception e)
404                 {
405                         if (errors == e)
406                                 errors = null;
407                 }
408
409                 internal bool HasError (Exception e)
410                 {
411                         if (errors == e)
412                                 return true;
413
414                         return (errors is ArrayList) ?
415                                 ((ArrayList) errors).Contains (e) : false;
416                 }
417
418                 public void ClearError ()
419                 {
420                         errors = null;
421                 }
422
423 #if NET_2_0
424                 [Obsolete ("use WebConfigurationManager.GetWebApplicationSection")]
425 #endif
426                 public static object GetAppConfig (string name)
427                 {
428                         object o = ConfigurationSettings.GetConfig (name);
429
430                         return o;
431                 }
432
433 #if NET_2_0
434                 [Obsolete ("see GetSection")]
435 #endif
436                 public object GetConfig (string name)
437                 {
438 #if NET_2_0
439                         return GetSection (name);
440 #else
441                         return WebConfigurationSettings.GetConfig (name, this);
442 #endif
443                 }
444
445 #if NET_2_0
446                 static object GetResourceObject (string classKey, string resourceKey, CultureInfo culture, Assembly assembly)
447                 {
448                         ResourceManager rm;
449                         try {
450                                 if (resourceManagerCache == null)
451                                         resourceManagerCache = new Dictionary <ResourceManagerCacheKey, ResourceManager> ();
452                                 
453                                 ResourceManagerCacheKey key = new ResourceManagerCacheKey (classKey, assembly);
454                                 if (!resourceManagerCache.TryGetValue (key, out rm)) {
455                                         rm = new ResourceManager (classKey, assembly);
456                                         rm.IgnoreCase = true;
457                                         resourceManagerCache.Add (key, rm);
458                                 }
459                                 
460                                 return rm.GetObject (resourceKey, culture);
461                         } catch (MissingManifestResourceException) {
462                                 throw;
463                         } catch (Exception ex) {
464                                 throw new HttpException ("Failed to retrieve the specified global resource object.", ex);
465                         }
466                 }
467                 
468                 public static object GetGlobalResourceObject (string classKey, string resourceKey)
469                 {
470                         return GetGlobalResourceObject (classKey, resourceKey, Thread.CurrentThread.CurrentUICulture);
471                 }
472
473                 static object GetGlobalObjectFromFactory (string classKey, string resourceKey, CultureInfo culture)
474                 {
475                         // FIXME: Retention of data
476
477                         if (provider_factory == null) {
478                                 GlobalizationSection gs = WebConfigurationManager.GetSection ("system.web/globalization") as GlobalizationSection;
479
480                                 if (gs == null)
481                                         return null;
482
483                                 String rsfTypeName = gs.ResourceProviderFactoryType;
484                                 if (String.IsNullOrEmpty (rsfTypeName))
485                                         return null;
486                         
487                                 Type rsfType = Type.GetType (rsfTypeName, true);
488                                 ResourceProviderFactory rpf = Activator.CreateInstance (rsfType) as ResourceProviderFactory;
489                         
490                                 if (rpf == null)
491                                         return null;
492
493                                 provider_factory = rpf;
494                         }
495
496                         if (resource_providers == null)
497                                 resource_providers = new Dictionary <string, IResourceProvider> ();
498
499                         IResourceProvider rp;
500                         if (!resource_providers.TryGetValue (classKey, out rp)) {
501                                 rp = provider_factory.CreateGlobalResourceProvider (classKey);
502                                 if (rp == null)
503                                         return null;
504                                 resource_providers.Add (classKey, rp);
505                         }
506
507                         return rp.GetObject (resourceKey, culture);
508                 }
509                 
510                 public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture)
511                 {
512                         object ret = GetGlobalObjectFromFactory (classKey, resourceKey, culture);
513                         if (ret != null)
514                                 return ret;
515                         
516                         if (AppGlobalResourcesAssembly == null)
517                                 throw new MissingManifestResourceException ();
518                         
519                         return GetResourceObject ("Resources." + classKey, resourceKey, culture, AppGlobalResourcesAssembly);
520                 }
521
522                 public static object GetLocalResourceObject (string virtualPath, string resourceKey)
523                 {
524                         return GetLocalResourceObject (virtualPath, resourceKey, Thread.CurrentThread.CurrentUICulture);
525                 }
526
527                 public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture)
528                 {
529                         if (!VirtualPathUtility.IsAbsolute (virtualPath))
530                                 throw new ArgumentException ("The specified virtualPath was not rooted.");
531                         
532                         string path = Path.GetDirectoryName (virtualPath);
533                         Assembly asm = AppResourcesCompiler.GetCachedLocalResourcesAssembly (path);
534                         if (asm == null) {
535                                 AppResourcesCompiler ac = new AppResourcesCompiler (path);
536                                 asm = ac.Compile ();
537                                 if (asm == null)
538                                         throw new MissingManifestResourceException ("A resource object was not found at the specified virtualPath.");
539                         }
540                         
541                         path = Path.GetFileName (virtualPath);
542                         return GetResourceObject (path, resourceKey, culture, asm);
543                 }
544
545                 public object GetSection (string name)
546                 {
547                         return WebConfigurationManager.GetSection (name);
548                 }
549
550                 sealed class ResourceManagerCacheKey
551                 {
552                         readonly string _name;
553                         readonly Assembly _asm;
554
555                         public ResourceManagerCacheKey (string name, Assembly asm)
556                         {
557                                 _name = name;
558                                 _asm = asm;
559                         }
560
561                         public override bool Equals (object obj)
562                         {
563                                 if (!(obj is ResourceManagerCacheKey))
564                                         return false;
565                                 ResourceManagerCacheKey key = (ResourceManagerCacheKey) obj;
566                                 return key._asm == _asm && _name.Equals (key._name, StringComparison.Ordinal);
567                         }
568
569                         public override int GetHashCode ()
570                         {
571                                 return _name.GetHashCode () + _asm.GetHashCode ();
572                         }
573                 }
574 #endif
575                 object IServiceProvider.GetService (Type service)
576                 {
577                         if (service == typeof (HttpWorkerRequest))
578                                 return WorkerRequest;
579
580                         //
581                         // We return everything out of properties in case
582                         // they are dynamically computed in some form in the future.
583                         //
584                         if (service == typeof (HttpApplication))
585                                 return ApplicationInstance;
586
587                         if (service == typeof (HttpRequest))
588                                 return Request;
589
590                         if (service == typeof (HttpResponse))
591                                 return Response;
592
593                         if (service == typeof (HttpSessionState))
594                                 return Session;
595
596                         if (service == typeof (HttpApplicationState))
597                                 return Application;
598
599                         if (service == typeof (IPrincipal))
600                                 return User;
601
602                         if (service == typeof (Cache))
603                                 return Cache;
604
605                         if (service == typeof (HttpContext))
606                                 return Current;
607
608                         if (service == typeof (IHttpHandler))
609                                 return Handler;
610
611                         if (service == typeof (HttpServerUtility))
612                                 return Server;
613                         
614                         if (service == typeof (TraceContext))
615                                 return Trace;
616                         
617                         return null;
618                 }
619
620                 public void RewritePath (string path)
621                 {
622 #if NET_2_0
623                         RewritePath (path, true);
624 #else
625                         RewritePath (path, false);
626 #endif
627                 }
628
629                 public void RewritePath (string filePath, string pathInfo, string queryString)
630                 {
631                         RewritePath (filePath, pathInfo, queryString, false);
632                 }
633
634 #if NET_2_0
635                 public
636 #else
637                 internal
638 #endif
639                 void RewritePath (string path, bool rebaseClientPath)
640                 {
641                         int qmark = path.IndexOf ('?');
642                         if (qmark != -1)
643                                 RewritePath (path.Substring (0, qmark), "", path.Substring (qmark + 1), rebaseClientPath);
644                         else
645                                 RewritePath (path, null, null, rebaseClientPath);
646                 }
647
648 #if NET_2_0
649                 public
650 #else
651                 internal
652 #endif
653                 void RewritePath (string filePath, string pathInfo, string queryString, bool setClientFilePath)
654                 {
655                         if (UrlUtils.IsRooted (filePath))
656                                 filePath = UrlUtils.Combine (Request.BaseVirtualDir, UrlUtils.Canonic (filePath).Substring (1));
657                         else
658                                 filePath = UrlUtils.Combine (UrlUtils.GetDirectory (Request.FilePath), filePath);
659                         if (!StrUtils.StartsWith (filePath, HttpRuntime.AppDomainAppVirtualPath))
660                                 throw new HttpException (404, "The virtual path '" + filePath + "' maps to another application.", filePath);
661
662                         Request.SetCurrentExePath (filePath);
663                         if (setClientFilePath)
664                                 Request.SetFilePath (filePath);
665                         
666                         // A null pathInfo or queryString is ignored and previous values remain untouched
667                         if (pathInfo != null)
668                                 Request.SetPathInfo (pathInfo);
669
670                         if (queryString != null)
671                                 Request.QueryStringRaw = queryString;
672                 }
673
674 #region internals
675                 
676                 internal void SetSession (HttpSessionState state)
677                 {
678                         session_state = state;
679                 }
680
681                 // URL of a page used for error redirection.
682                 internal string ErrorPage {
683                         get {
684                                 return error_page;
685                         }
686
687                         set {
688                                 error_page = value;
689                         }
690                 }
691
692                 internal TimeSpan ConfigTimeout {
693                         get {
694                                 if (config_timeout == null) {
695 #if NET_2_0
696                                         HttpRuntimeSection section = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
697                                         config_timeout = section.ExecutionTimeout;
698 #else
699                                         HttpRuntimeConfig config = (HttpRuntimeConfig)
700                                                                 GetConfig ("system.web/httpRuntime");
701                                         config_timeout = new TimeSpan (0, 0, config.ExecutionTimeout);
702 #endif
703                                 }
704
705                                 return (TimeSpan) config_timeout;
706                         }
707
708                         set {
709                                 config_timeout = value;
710 #if !TARGET_J2EE
711                                 if (timer != null) {
712                                         TimeSpan remaining = value - (DateTime.UtcNow - time_stamp);
713                                         long remaining_ms = Math.Max ((long)remaining.TotalMilliseconds, 0);
714
715                                         // See http://msdn2.microsoft.com/en-us/library/7hs7492w.aspx
716                                         if (remaining_ms > 4294967294)
717                                                 remaining_ms = 4294967294;
718                                         
719                                         timer.Change (remaining_ms, (long)Timeout.Infinite);
720                                 }
721 #endif
722                         }
723                 }
724
725 #if !TARGET_J2EE
726                 void TimeoutReached(object state) {
727                         if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) {
728                                 timer.Change(2000, 0);
729                                 return;                 
730                         }
731                         StopTimeoutTimer();
732                         
733                         thread.Abort (new StepTimeout ());
734                 }
735                 
736                 internal void StartTimeoutTimer() {
737                         thread = Thread.CurrentThread;
738                         timer = new Timer (TimeoutReached, null, (int)ConfigTimeout.TotalMilliseconds, Timeout.Infinite);
739                 }
740                 
741                 internal void StopTimeoutTimer() {
742                         if(timer != null) {
743                                 timer.Dispose ();
744                                 timer = null;
745                         }
746                 }
747
748                 internal bool TimeoutPossible {
749                         get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); }
750                 }
751
752                 internal void BeginTimeoutPossible ()
753                 {
754                         timeout_possible = 1;
755                 }
756
757                 internal void EndTimeoutPossible ()
758                 {
759                         Interlocked.CompareExchange (ref timeout_possible, 0, 1);
760                 }
761 #endif
762 #endregion
763         }
764         
765         class StepTimeout
766         {
767         }
768 }