2 // System.Web.HttpContext.cs
5 // Miguel de Icaza (miguel@novell.com)
6 // Gonzalo Paniagua Javier (gonzalo@novell.com)
10 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
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;
43 using System.Web.Util;
45 using System.Collections.Generic;
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;
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;
61 HttpResponse response;
62 HttpSessionState session_state;
63 HttpServerUtility server;
64 TraceContext trace_context;
67 bool skip_authorization = false;
71 object config_timeout;
73 DateTime time_stamp = DateTime.UtcNow;
76 bool _isProcessingInclude;
81 const string app_global_res_key = "HttpContext.app_global_res_key";
82 internal static Assembly AppGlobalResourcesAssembly {
83 get { return (Assembly) AppDomain.CurrentDomain.GetData (app_global_res_key); }
84 set { AppDomain.CurrentDomain.SetData (app_global_res_key, value); }
87 static Hashtable resourceManagerCache = new Hashtable ();
88 RequestNotification _currentNotification;
89 internal static Assembly AppGlobalResourcesAssembly;
91 ProfileBase profile = null;
92 LinkedList<IHttpHandler> handlers;
95 public HttpContext (HttpWorkerRequest wr)
98 request = new HttpRequest (WorkerRequest, this);
99 response = new HttpResponse (WorkerRequest, this);
102 public HttpContext (HttpRequest request, HttpResponse response)
104 this.request = request;
105 this.response = response;
109 internal bool IsProcessingInclude {
110 get { return _isProcessingInclude; }
111 set { _isProcessingInclude = value; }
114 public Exception [] AllErrors {
119 if (errors is Exception){
120 Exception [] all = new Exception [1];
121 all [0] = (Exception) errors;
124 return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception)));
128 public HttpApplicationState Application {
130 return HttpApplicationFactory.ApplicationState;
134 public HttpApplication ApplicationInstance {
140 app_instance = value;
147 return HttpRuntime.Cache;
151 internal Cache InternalCache {
153 return HttpRuntime.InternalCache;
158 // The "Current" property is set just after we have constructed it with
159 // the 'HttpContext (HttpWorkerRequest)' constructor.
161 #if !TARGET_JVM // No remoting CallContext support in Grasshopper
162 public static HttpContext Current {
164 return (HttpContext) CallContext.GetData ("c");
168 CallContext.SetData ("c", value);
173 public Exception Error {
175 if (errors == null || (errors is Exception))
176 return (Exception) errors;
177 return (Exception) (((ArrayList) errors) [0]);
181 public IHttpHandler Handler {
191 public bool IsCustomErrorEnabled {
194 return IsCustomErrorEnabledUnsafe;
202 internal bool IsCustomErrorEnabledUnsafe {
205 CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors");
207 CustomErrorsConfig cfg = null;
209 cfg = (CustomErrorsConfig) GetConfig ("system.web/customErrors");
217 if (cfg.Mode == CustomErrorMode.On)
220 return (cfg.Mode == CustomErrorMode.RemoteOnly) && !Request.IsLocal;
224 public bool IsDebuggingEnabled {
227 CompilationSection section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
228 return section.Debug;
231 return CompilationConfiguration.GetInstance (this).Debug;
239 public IDictionary Items {
242 items = new Hashtable ();
247 public HttpRequest Request {
253 public HttpResponse Response {
259 public HttpServerUtility Server {
262 server = new HttpServerUtility (this);
267 public HttpSessionState Session {
269 return session_state;
273 public bool SkipAuthorization {
275 return skip_authorization;
278 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
280 skip_authorization = value;
284 public DateTime Timestamp {
286 return time_stamp.ToLocalTime ();
290 public TraceContext Trace {
292 if (trace_context == null)
293 trace_context = new TraceContext (this);
294 return trace_context;
298 public IPrincipal User {
303 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
310 // The two properties below are defined only when the IIS7 integrated mode is used.
311 // They are useless under Mono
312 public RequestNotification CurrentNotification {
313 get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); }
316 public bool IsPostNotification {
317 get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); }
320 internal void PushHandler (IHttpHandler handler)
324 if (handlers == null)
325 handlers = new LinkedList <IHttpHandler> ();
326 handlers.AddLast (handler);
329 internal void PopHandler ()
331 if (handlers == null || handlers.Count == 0)
333 handlers.RemoveLast ();
336 IHttpHandler GetCurrentHandler ()
338 if (handlers == null || handlers.Count == 0)
341 return handlers.Last.Value;
344 IHttpHandler GetPreviousHandler ()
346 if (handlers == null || handlers.Count <= 1)
348 LinkedListNode <IHttpHandler> previous = handlers.Last.Previous;
349 if (previous != null)
350 return previous.Value;
354 public IHttpHandler CurrentHandler {
355 get { return GetCurrentHandler (); }
358 public IHttpHandler PreviousHandler {
359 get { return GetPreviousHandler (); }
362 internal bool ProfileInitialized {
363 get { return profile != null; }
366 public ProfileBase Profile {
368 if (profile == null) {
369 if (Request.IsAuthenticated)
370 profile = ProfileBase.Create (User.Identity.Name);
372 profile = ProfileBase.Create (Request.AnonymousID, false);
383 public void AddError (Exception errorInfo)
390 if (errors is Exception){
391 l = new ArrayList ();
395 l = (ArrayList) errors;
399 internal void ClearError (Exception e)
405 internal bool HasError (Exception e)
410 return (errors is ArrayList) ?
411 ((ArrayList) errors).Contains (e) : false;
414 public void ClearError ()
420 [Obsolete ("use WebConfigurationManager.GetWebApplicationSection")]
422 public static object GetAppConfig (string name)
424 object o = ConfigurationSettings.GetConfig (name);
430 [Obsolete ("see GetSection")]
432 public object GetConfig (string name)
435 return GetSection (name);
437 return WebConfigurationSettings.GetConfig (name, this);
442 static object GetResourceObject (string classKey, string resourceKey, CultureInfo culture, Assembly assembly)
446 ResourceManagerCacheKey key = new ResourceManagerCacheKey (classKey, assembly);
447 rm = (ResourceManager) resourceManagerCache [key];
450 rm = new ResourceManager (classKey, assembly);
451 rm.IgnoreCase = true;
452 Hashtable tmp = (Hashtable) resourceManagerCache.Clone ();
454 resourceManagerCache = tmp;
457 return rm.GetObject (resourceKey, culture);
458 } catch (MissingManifestResourceException) {
460 } catch (Exception ex) {
461 throw new HttpException ("Failed to retrieve the specified global resource object.", ex);
465 public static object GetGlobalResourceObject (string classKey, string resourceKey)
467 return GetGlobalResourceObject (classKey, resourceKey, Thread.CurrentThread.CurrentUICulture);
470 static object GetGlobalObjectFromFactory (string classKey, string resourceKey, CultureInfo culture)
472 GlobalizationSection gs = WebConfigurationManager.GetSection ("system.web/globalization") as GlobalizationSection;
477 String rsfTypeName = gs.ResourceProviderFactoryType;
478 if (String.IsNullOrEmpty (rsfTypeName))
481 Type rsfType = Type.GetType (rsfTypeName, true);
482 ResourceProviderFactory rpf = Activator.CreateInstance (rsfType) as ResourceProviderFactory;
487 IResourceProvider rp = rpf.CreateGlobalResourceProvider (classKey);
491 return rp.GetObject (resourceKey, culture);
494 public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture)
496 object ret = GetGlobalObjectFromFactory (classKey, resourceKey, culture);
500 if (AppGlobalResourcesAssembly == null)
501 throw new MissingManifestResourceException ();
503 return GetResourceObject ("Resources." + classKey, resourceKey, culture, AppGlobalResourcesAssembly);
506 public static object GetLocalResourceObject (string virtualPath, string resourceKey)
508 return GetLocalResourceObject (virtualPath, resourceKey, Thread.CurrentThread.CurrentUICulture);
511 public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture)
513 if (!VirtualPathUtility.IsAbsolute (virtualPath))
514 throw new ArgumentException ("The specified virtualPath was not rooted.");
516 string path = Path.GetDirectoryName (virtualPath);
517 Assembly asm = AppResourcesCompiler.GetCachedLocalResourcesAssembly (path);
519 AppResourcesCompiler ac = new AppResourcesCompiler (path);
522 throw new MissingManifestResourceException ("A resource object was not found at the specified virtualPath.");
525 path = Path.GetFileName (virtualPath);
526 return GetResourceObject (path, resourceKey, culture, asm);
529 public object GetSection (string name)
531 return WebConfigurationManager.GetSection (name);
534 private sealed class ResourceManagerCacheKey
536 readonly string _name;
537 readonly Assembly _asm;
539 public ResourceManagerCacheKey (string name, Assembly asm)
545 public override bool Equals (object obj)
547 if (!(obj is ResourceManagerCacheKey))
549 ResourceManagerCacheKey key = (ResourceManagerCacheKey) obj;
550 return key._asm == _asm && _name.Equals (key._name, StringComparison.Ordinal);
553 public override int GetHashCode ()
555 return _name.GetHashCode () + _asm.GetHashCode ();
559 object IServiceProvider.GetService (Type service)
561 if (service == typeof (HttpWorkerRequest))
562 return WorkerRequest;
565 // We return everything out of properties in case
566 // they are dynamically computed in some form in the future.
568 if (service == typeof (HttpApplication))
569 return ApplicationInstance;
571 if (service == typeof (HttpRequest))
574 if (service == typeof (HttpResponse))
577 if (service == typeof (HttpSessionState))
580 if (service == typeof (HttpApplicationState))
583 if (service == typeof (IPrincipal))
586 if (service == typeof (Cache))
589 if (service == typeof (HttpContext))
592 if (service == typeof (IHttpHandler))
595 if (service == typeof (HttpServerUtility))
598 if (service == typeof (TraceContext))
604 public void RewritePath (string path)
607 RewritePath (path, true);
609 RewritePath (path, false);
613 public void RewritePath (string filePath, string pathInfo, string queryString)
616 RewritePath (filePath, pathInfo, queryString, true);
618 RewritePath (filePath, pathInfo, queryString, false);
627 void RewritePath (string path, bool rebaseClientPath)
629 int qmark = path.IndexOf ('?');
631 RewritePath (path.Substring (0, qmark), "", path.Substring (qmark + 1), rebaseClientPath);
633 RewritePath (path, null, null, rebaseClientPath);
641 void RewritePath (string filePath, string pathInfo, string queryString, bool setClientFilePath)
643 filePath = UrlUtils.Combine (Request.BaseVirtualDir, filePath);
644 if (!StrUtils.StartsWith (filePath, HttpRuntime.AppDomainAppVirtualPath))
645 throw new HttpException (404, "The virtual path '" + filePath + "' maps to another application.", filePath);
647 Request.SetCurrentExePath (filePath);
649 Request.SetFilePath (filePath);
652 // A null pathInfo or queryString is ignored and previous values remain untouched
653 if (pathInfo != null)
654 Request.SetPathInfo (pathInfo);
656 if (queryString != null)
657 Request.QueryStringRaw = queryString;
659 if (setClientFilePath)
660 Request.SetFilePath (filePath);
666 internal void SetSession (HttpSessionState state)
668 session_state = state;
671 // URL of a page used for error redirection.
672 internal string ErrorPage {
682 internal TimeSpan ConfigTimeout {
684 if (config_timeout == null) {
686 HttpRuntimeSection section = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
687 config_timeout = section.ExecutionTimeout;
689 HttpRuntimeConfig config = (HttpRuntimeConfig)
690 GetConfig ("system.web/httpRuntime");
691 config_timeout = new TimeSpan (0, 0, config.ExecutionTimeout);
695 return (TimeSpan) config_timeout;
699 config_timeout = value;
702 TimeSpan remaining = value - (DateTime.UtcNow - time_stamp);
703 long remaining_ms = Math.Max ((long)remaining.TotalMilliseconds, 0);
705 // See http://msdn2.microsoft.com/en-us/library/7hs7492w.aspx
706 if (remaining_ms > 4294967294)
707 remaining_ms = 4294967294;
709 timer.Change (remaining_ms, (long)Timeout.Infinite);
716 void TimeoutReached(object state) {
717 if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) {
718 timer.Change(2000, 0);
723 thread.Abort (new StepTimeout ());
726 internal void StartTimeoutTimer() {
727 thread = Thread.CurrentThread;
728 timer = new Timer (TimeoutReached, null, (int)ConfigTimeout.TotalMilliseconds, Timeout.Infinite);
731 internal void StopTimeoutTimer() {
738 internal bool TimeoutPossible {
739 get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); }
742 internal void BeginTimeoutPossible ()
744 timeout_possible = 1;
747 internal void EndTimeoutPossible ()
749 Interlocked.CompareExchange (ref timeout_possible, 0, 1);