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