// // System.Web.HttpContext.cs // // Author: // Miguel de Icaza (miguel@novell.com) // Gonzalo Paniagua Javier (gonzalo@novell.com) // // // Copyright (C) 2005 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Collections; using System.Configuration; using System.Globalization; using System.Runtime.Remoting.Messaging; using System.Security.Permissions; using System.Security.Principal; using System.Threading; using System.Web.Caching; using System.Web.Configuration; using System.Web.SessionState; using System.Web.UI; using System.Web.Util; #if NET_2_0 using System.Web.Profile; using CustomErrorMode = System.Web.Configuration.CustomErrorsMode; #endif namespace System.Web { // CAS - no InheritanceDemand here as the class is sealed [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] public sealed class HttpContext : IServiceProvider { internal HttpWorkerRequest WorkerRequest; HttpApplication app_instance; HttpRequest request; HttpResponse response; HttpSessionState session_state; HttpServerUtility server; TraceContext trace_context; IHttpHandler handler; string error_page; bool skip_authorization = false; IPrincipal user; object errors; Hashtable items; object config_timeout; int timeout_possible; DateTime time_stamp = DateTime.UtcNow; #if TARGET_JVM // No remoting support (CallContext) yet in Grasshopper static LocalDataStoreSlot _ContextSlot = Thread.GetNamedDataSlot ("Context"); #endif public HttpContext (HttpWorkerRequest wr) { WorkerRequest = wr; request = new HttpRequest (WorkerRequest, this); response = new HttpResponse (WorkerRequest, this); } public HttpContext (HttpRequest request, HttpResponse response) { this.request = request; this.response = response; } public Exception [] AllErrors { get { if (errors == null) return null; if (errors is Exception){ Exception [] all = new Exception [1]; all [0] = (Exception) errors; return all; } return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception))); } } public HttpApplicationState Application { get { return HttpApplicationFactory.ApplicationState; } } public HttpApplication ApplicationInstance { get { return app_instance; } set { app_instance = value; } } public Cache Cache { get { return HttpRuntime.Cache; } } // // The "Current" property is set just after we have constructed it with // the 'HttpContext (HttpWorkerRequest)' constructor. // #if TARGET_JVM // No remoting support (CallContext) yet in Grasshopper [MonoTODO("Context - Use System.Remoting.Messaging.CallContext instead of Thread storage")] public static HttpContext Current { get { return (HttpContext) Thread.GetData (_ContextSlot); } set { Thread.SetData (_ContextSlot, value); } } #else public static HttpContext Current { get { return (HttpContext) CallContext.GetData ("c"); } set { CallContext.SetData ("c", value); } } #endif public Exception Error { get { if (errors == null || (errors is Exception)) return (Exception) errors; return (Exception) (((ArrayList) errors) [0]); } } public IHttpHandler Handler { get { return handler; } set { handler = value; } } public bool IsCustomErrorEnabled { get { #if NET_2_0 CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors"); #else CustomErrorsConfig cfg = null; try { cfg = (CustomErrorsConfig) GetConfig ("system.web/customErrors"); } catch { } if (cfg == null) return false; #endif if (cfg.Mode == CustomErrorMode.On) return true; return (cfg.Mode == CustomErrorMode.RemoteOnly) && (Request.WorkerRequest.GetLocalAddress () != Request.UserHostAddress); } } #if TARGET_JVM public bool IsDebuggingEnabled { get { return false; } } #else public bool IsDebuggingEnabled { get { #if NET_2_0 CompilationSection section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation"); return section.Debug; #else try { return CompilationConfiguration.GetInstance (this).Debug; } catch { return false; } #endif } } #endif public IDictionary Items { get { if (items == null) items = new Hashtable (); return items; } } public HttpRequest Request { get { return request; } } public HttpResponse Response { get { return response; } } public HttpServerUtility Server { get { if (server == null) server = new HttpServerUtility (this); return server; } } public HttpSessionState Session { get { return session_state; } } public bool SkipAuthorization { get { return skip_authorization; } [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)] set { skip_authorization = value; } } public DateTime Timestamp { get { return time_stamp.ToLocalTime (); } } public TraceContext Trace { get { if (trace_context == null) trace_context = new TraceContext (this); return trace_context; } } public IPrincipal User { get { return user; } [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)] set { user = value; } } #if NET_2_0 [MonoTODO] public IHttpHandler CurrentHandler { get { throw new NotImplementedException (); } } [MonoTODO] public IHttpHandler PreviousHandler { get { throw new NotImplementedException (); } } [MonoTODO] public ProfileBase Profile { get { throw new NotImplementedException (); } } #endif public void AddError (Exception errorInfo) { if (errors == null){ errors = errorInfo; return; } ArrayList l; if (errors is Exception){ l = new ArrayList (); l.Add (errors); errors = l; } else l = (ArrayList) errors; l.Add (errorInfo); } internal void ClearError (Exception e) { if (errors == e) errors = null; } public void ClearError () { errors = null; } #if NET_2_0 [Obsolete ("use WebConfigurationManager.GetWebApplicationSection")] #endif public static object GetAppConfig (string name) { object o = ConfigurationSettings.GetConfig (name); return o; } #if NET_2_0 [Obsolete ("see GetSection")] #endif public object GetConfig (string name) { #if NET_2_0 return GetSection (name); #else return WebConfigurationSettings.GetConfig (name, this); #endif } #if NET_2_0 [MonoTODO] public static object GetGlobalResourceObject (string classKey, string resourceKey) { throw new NotImplementedException (); } [MonoTODO] public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture) { throw new NotImplementedException (); } [MonoTODO] public static object GetLocalResourceObject (string virtualPath, string resourceKey) { throw new NotImplementedException (); } [MonoTODO] public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture) { throw new NotImplementedException (); } [MonoTODO] public object GetSection (string name) { #if NET_2_0 return WebConfigurationManager.GetSection (name); #else throw new NotImplementedException (); #endif } #endif object IServiceProvider.GetService (Type service) { if (service == typeof (HttpWorkerRequest)) return WorkerRequest; // // We return everything out of properties in case // they are dynamically computed in some form in the future. // if (service == typeof (HttpApplication)) return ApplicationInstance; if (service == typeof (HttpRequest)) return Request; if (service == typeof (HttpResponse)) return Response; if (service == typeof (HttpSessionState)) return Session; if (service == typeof (HttpApplicationState)) return Application; if (service == typeof (IPrincipal)) return User; if (service == typeof (Cache)) return Cache; if (service == typeof (HttpContext)) return Current; if (service == typeof (IHttpHandler)) return Handler; if (service == typeof (HttpServerUtility)) return Server; if (service == typeof (TraceContext)) return Trace; return null; } public void RewritePath (string path) { int qmark = path.IndexOf ('?'); if (qmark != -1) RewritePath (path.Substring (0, qmark), "", path.Substring (qmark + 1)); else RewritePath (path, null, null); } public void RewritePath (string filePath, string pathInfo, string queryString) { filePath = UrlUtils.Combine (Request.BaseVirtualDir, filePath); if (!filePath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) throw new HttpException (404, "The virtual path '" + filePath + "' maps to another application."); Request.SetCurrentExePath (filePath); // A null pathInfo or queryString is ignored and previous values remain untouched if (pathInfo != null) Request.SetPathInfo (pathInfo); if (queryString != null) Request.QueryStringRaw = queryString; } #if NET_2_0 [MonoTODO] public void RewritePath (string path, bool rebaseClientPath) { throw new NotImplementedException (); } #endif #region internals internal void SetSession (HttpSessionState state) { session_state = state; } // URL of a page used for error redirection. internal string ErrorPage { get { return error_page; } set { error_page = value; } } internal TimeSpan ConfigTimeout { get { if (config_timeout == null) { #if NET_2_0 HttpRuntimeSection section = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime"); config_timeout = section.ExecutionTimeout; #else HttpRuntimeConfig config = (HttpRuntimeConfig) GetConfig ("system.web/httpRuntime"); config_timeout = new TimeSpan (0, 0, config.ExecutionTimeout); #endif } return (TimeSpan) config_timeout; } set { config_timeout = value; } } internal bool CheckIfTimeout (DateTime t) { if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) return false; TimeSpan ts = t - time_stamp; return (ts > ConfigTimeout); } internal bool TimeoutPossible { get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); } } internal void BeginTimeoutPossible () { timeout_possible = 1; } internal void EndTimeoutPossible () { Interlocked.CompareExchange (ref timeout_possible, 0, 1); } #endregion #if NET_2_0 Page last_page; internal Page LastPage { get { return last_page; } set { last_page = value; } } #endif } }