X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Web%2FSystem.Web%2FHttpContext.cs;h=d183afa0f4d31b816f5d2605417568a5e7fa9617;hb=9b87d46bdf11e08d30fe313737bd3822dbc21cbd;hp=78738f725f7583a5a9c6089e5ebc45dd55b5e81f;hpb=29224b63c36d918be252a920136c21b641ebe1ea;p=mono.git diff --git a/mcs/class/System.Web/System.Web/HttpContext.cs b/mcs/class/System.Web/System.Web/HttpContext.cs index 78738f725f7..d183afa0f4d 100644 --- a/mcs/class/System.Web/System.Web/HttpContext.cs +++ b/mcs/class/System.Web/System.Web/HttpContext.cs @@ -4,10 +4,11 @@ // Author: // Miguel de Icaza (miguel@novell.com) // Gonzalo Paniagua Javier (gonzalo@novell.com) +// Marek Habersack // // -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) +// Copyright (C) 2005-2009 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 @@ -41,21 +42,20 @@ using System.Web.Configuration; using System.Web.SessionState; using System.Web.UI; using System.Web.Util; -#if NET_2_0 +using System.Reflection; using System.Collections.Generic; using System.IO; -using System.Reflection; using System.Resources; using System.Web.Compilation; using System.Web.Profile; using CustomErrorMode = System.Web.Configuration.CustomErrorsMode; -#endif -namespace System.Web { - +namespace System.Web +{ // CAS - no InheritanceDemand here as the class is sealed [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] - public sealed partial class HttpContext : IServiceProvider { + public sealed partial class HttpContext : IServiceProvider + { internal HttpWorkerRequest WorkerRequest; HttpApplication app_instance; HttpRequest request; @@ -72,7 +72,19 @@ namespace System.Web { object config_timeout; int timeout_possible; DateTime time_stamp = DateTime.UtcNow; -#if NET_2_0 + Timer timer; + Thread thread; + bool _isProcessingInclude; + + [ThreadStatic] + static ResourceProviderFactory provider_factory; + + [ThreadStatic] + static DefaultResourceProviderFactory default_provider_factory; + + [ThreadStatic] + static Dictionary resource_providers; + #if TARGET_JVM const string app_global_res_key = "HttpContext.app_global_res_key"; internal static Assembly AppGlobalResourcesAssembly { @@ -84,20 +96,37 @@ namespace System.Web { #endif ProfileBase profile = null; LinkedList handlers; -#endif + static DefaultResourceProviderFactory DefaultProviderFactory { + get { + if (default_provider_factory == null) + default_provider_factory = new DefaultResourceProviderFactory (); + return default_provider_factory; + } + } + public HttpContext (HttpWorkerRequest wr) { WorkerRequest = wr; request = new HttpRequest (WorkerRequest, this); response = new HttpResponse (WorkerRequest, this); +#if NET_4_0 + SessionStateBehavior = SessionStateBehavior.Default; +#endif } public HttpContext (HttpRequest request, HttpResponse response) { this.request = request; this.response = response; - +#if NET_4_0 + SessionStateBehavior = SessionStateBehavior.Default; +#endif + } + + internal bool IsProcessingInclude { + get { return _isProcessingInclude; } + set { _isProcessingInclude = value; } } public Exception [] AllErrors { @@ -137,6 +166,12 @@ namespace System.Web { } } + internal Cache InternalCache { + get { + return HttpRuntime.InternalCache; + } + } + // // The "Current" property is set just after we have constructed it with // the 'HttpContext (HttpWorkerRequest)' constructor. @@ -173,40 +208,27 @@ namespace System.Web { 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 { + return IsCustomErrorEnabledUnsafe; } - - if (cfg == null) + catch { return false; -#endif + } + } + } + internal bool IsCustomErrorEnabledUnsafe { + get { + CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors"); if (cfg.Mode == CustomErrorMode.On) return true; - return (cfg.Mode == CustomErrorMode.RemoteOnly) && - (Request.WorkerRequest.GetLocalAddress () != Request.UserHostAddress); + return (cfg.Mode == CustomErrorMode.RemoteOnly) && !Request.IsLocal; } } #if !TARGET_JVM 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 - } + get { return RuntimeHelpers.DebuggingEnabled; } } #endif public IDictionary Items { @@ -279,7 +301,21 @@ namespace System.Web { } } -#if NET_2_0 + internal bool MapRequestHandlerDone { + get; + set; + } + + // The two properties below are defined only when the IIS7 integrated mode is used. + // They are useless under Mono + public RequestNotification CurrentNotification { + get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); } + } + + public bool IsPostNotification { + get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); } + } + internal void PushHandler (IHttpHandler handler) { if (handler == null) @@ -322,6 +358,10 @@ namespace System.Web { get { return GetPreviousHandler (); } } + internal bool ProfileInitialized { + get { return profile != null; } + } + public ProfileBase Profile { get { if (profile == null) { @@ -337,7 +377,6 @@ namespace System.Web { profile = value; } } -#endif public void AddError (Exception errorInfo) { @@ -361,14 +400,21 @@ namespace System.Web { errors = null; } + internal bool HasError (Exception e) + { + if (errors == e) + return true; + + return (errors is ArrayList) ? + ((ArrayList) errors).Contains (e) : false; + } + 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); @@ -376,42 +422,93 @@ namespace System.Web { 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 - static object GetResourceObject (string classKey, string resourceKey, CultureInfo culture, Assembly assembly) + public static object GetGlobalResourceObject (string classKey, string resourceKey) + { + return GetGlobalResourceObject (classKey, resourceKey, Thread.CurrentThread.CurrentUICulture); + } + + static bool EnsureProviderFactory () { - ResourceManager rm; - try { - rm = new ResourceManager (classKey, assembly); - return rm.GetObject (resourceKey, culture); - } catch (MissingManifestResourceException) { - throw; - } catch (Exception ex) { - throw new HttpException ("Failed to retrieve the specified global resource object.", ex); + if (resource_providers == null) + resource_providers = new Dictionary (); + + if (provider_factory != null) + return true; + + GlobalizationSection gs = WebConfigurationManager.GetSection ("system.web/globalization") as GlobalizationSection; + + if (gs == null) + return false; + + String rsfTypeName = gs.ResourceProviderFactoryType; + bool usingDefault = false; + if (String.IsNullOrEmpty (rsfTypeName)) { + usingDefault = true; + rsfTypeName = typeof (DefaultResourceProviderFactory).AssemblyQualifiedName; } + + Type rsfType = HttpApplication.LoadType (rsfTypeName, true); + ResourceProviderFactory rpf = Activator.CreateInstance (rsfType) as ResourceProviderFactory; + + if (rpf == null && usingDefault) + return false; + + provider_factory = rpf; + if (usingDefault) + default_provider_factory = rpf as DefaultResourceProviderFactory; + + return true; } - public static object GetGlobalResourceObject (string classKey, string resourceKey) + internal static IResourceProvider GetResourceProvider (string virtualPath, bool isLocal) { - return GetGlobalResourceObject (classKey, resourceKey, Thread.CurrentThread.CurrentUICulture); + if (!EnsureProviderFactory ()) + return null; + + // TODO: check if it makes sense to cache the providers and, if yes, maybe + // we should expire the entries (or just store them in InternalCache?) + IResourceProvider rp = null; + if (!resource_providers.TryGetValue (virtualPath, out rp)) { + if (isLocal) + rp = provider_factory.CreateLocalResourceProvider (virtualPath); + else + rp = provider_factory.CreateGlobalResourceProvider (virtualPath); + + if (rp == null) { + if (isLocal) + rp = DefaultProviderFactory.CreateLocalResourceProvider (virtualPath); + else + rp = DefaultProviderFactory.CreateGlobalResourceProvider (virtualPath); + + if (rp == null) + return null; + } + + resource_providers.Add (virtualPath, rp); + } + + return rp; } + static object GetGlobalObjectFromFactory (string classKey, string resourceKey, CultureInfo culture) + { + // FIXME: Retention of data + IResourceProvider rp = GetResourceProvider (classKey, false); + if (rp == null) + return null; + + return rp.GetObject (resourceKey, culture); + } + public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture) { - if (AppGlobalResourcesAssembly == null) - throw new MissingManifestResourceException (); - return GetResourceObject ("Resources." + classKey, resourceKey, culture, AppGlobalResourcesAssembly); + return GetGlobalObjectFromFactory ("Resources." + classKey, resourceKey, culture); } public static object GetLocalResourceObject (string virtualPath, string resourceKey) @@ -419,29 +516,28 @@ namespace System.Web { return GetLocalResourceObject (virtualPath, resourceKey, Thread.CurrentThread.CurrentUICulture); } + static object GetLocalObjectFromFactory (string virtualPath, string resourceKey, CultureInfo culture) + { + IResourceProvider rp = GetResourceProvider (virtualPath, true); + if (rp == null) + return null; + + return rp.GetObject (resourceKey, culture); + } + public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture) { if (!VirtualPathUtility.IsAbsolute (virtualPath)) throw new ArgumentException ("The specified virtualPath was not rooted."); - - string path = Path.GetDirectoryName (virtualPath); - Assembly asm = AppResourcesCompiler.GetCachedLocalResourcesAssembly (path); - if (asm == null) { - AppResourcesCompiler ac = new AppResourcesCompiler (path); - asm = ac.Compile (); - if (asm == null) - throw new MissingManifestResourceException ("A resource object was not found at the specified virtualPath."); - } - - path = Path.GetFileName (virtualPath); - return GetResourceObject (path, resourceKey, culture, asm); + + return GetLocalObjectFromFactory (virtualPath, resourceKey, culture); } public object GetSection (string name) { return WebConfigurationManager.GetSection (name); } -#endif + object IServiceProvider.GetService (Type service) { if (service == typeof (HttpWorkerRequest)) @@ -487,13 +583,16 @@ namespace System.Web { return null; } + public void RemapHandler (IHttpHandler handler) + { + if (MapRequestHandlerDone) + throw new InvalidOperationException ("The RemapHandler method was called after the MapRequestHandler event occurred."); + Handler = handler; + } + public void RewritePath (string path) { -#if NET_2_0 RewritePath (path, true); -#else - RewritePath (path, false); -#endif } public void RewritePath (string filePath, string pathInfo, string queryString) @@ -501,47 +600,59 @@ namespace System.Web { RewritePath (filePath, pathInfo, queryString, false); } -#if NET_2_0 - public -#else - internal -#endif - void RewritePath (string path, bool rebaseClientPath) + public void RewritePath (string path, bool rebaseClientPath) { int qmark = path.IndexOf ('?'); if (qmark != -1) - RewritePath (path.Substring (0, qmark), "", path.Substring (qmark + 1), rebaseClientPath); + RewritePath (path.Substring (0, qmark), String.Empty, path.Substring (qmark + 1), rebaseClientPath); else RewritePath (path, null, null, rebaseClientPath); } -#if NET_2_0 - public -#else - internal -#endif - void RewritePath (string filePath, string pathInfo, string queryString, bool setClientFilePath) + public void RewritePath (string filePath, string pathInfo, string queryString, bool setClientFilePath) { - filePath = UrlUtils.Combine (Request.BaseVirtualDir, filePath); - if (!filePath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) - throw new HttpException (404, "The virtual path '" + filePath + - "' maps to another application."); + if (filePath == null) + throw new ArgumentNullException ("filePath"); + if (!VirtualPathUtility.IsValidVirtualPath (filePath)) + throw new HttpException ("'" + HttpUtility.HtmlEncode (filePath) + "' is not a valid virtual path."); + + bool pathRelative = VirtualPathUtility.IsAppRelative (filePath); + bool pathAbsolute = pathRelative ? false : VirtualPathUtility.IsAbsolute (filePath); + HttpRequest req = Request; + if (req == null) + return; + + if (pathRelative || pathAbsolute) { + if (pathRelative) + filePath = VirtualPathUtility.ToAbsolute (filePath); + } else + filePath = VirtualPathUtility.AppendTrailingSlash (req.BaseVirtualDir) + filePath; + + if (!StrUtils.StartsWith (filePath, HttpRuntime.AppDomainAppVirtualPath)) + throw new HttpException (404, "The virtual path '" + HttpUtility.HtmlEncode (filePath) + "' maps to another application.", filePath); + + req.SetCurrentExePath (filePath); + req.SetFilePath (filePath); - Request.SetCurrentExePath (filePath); + if (setClientFilePath) + req.ClientFilePath = filePath; + // A null pathInfo or queryString is ignored and previous values remain untouched if (pathInfo != null) - Request.SetPathInfo (pathInfo); + req.SetPathInfo (pathInfo); if (queryString != null) - Request.QueryStringRaw = queryString; -#if NET_2_0 - if (setClientFilePath) - Request.SetFilePath (filePath); -#endif + req.QueryStringRaw = queryString; } -#region internals +#if NET_4_0 + public void SetSessionStateBehavior (SessionStateBehavior sessionStateBehavior) + { + SessionStateBehavior = sessionStateBehavior; + } +#endif +#region internals internal void SetSession (HttpSessionState state) { session_state = state; @@ -561,14 +672,8 @@ namespace System.Web { 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; @@ -576,17 +681,50 @@ namespace System.Web { set { config_timeout = value; +#if !TARGET_J2EE + if (timer != null) { + TimeSpan remaining = value - (DateTime.UtcNow - time_stamp); + long remaining_ms = Math.Max ((long)remaining.TotalMilliseconds, 0); + + // See http://msdn2.microsoft.com/en-us/library/7hs7492w.aspx + if (remaining_ms > 4294967294) + remaining_ms = 4294967294; + + timer.Change (remaining_ms, (long)Timeout.Infinite); + } +#endif } } +#if NET_4_0 + internal SessionStateBehavior SessionStateBehavior { + get; + private set; + } +#endif + #if !TARGET_J2EE - internal bool CheckIfTimeout (DateTime t) - { - if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) - return false; - - TimeSpan ts = t - time_stamp; - return (ts > ConfigTimeout); + void TimeoutReached(object state) { + HttpRuntime.QueuePendingRequest (false); + if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) { + timer.Change(2000, 0); + return; + } + StopTimeoutTimer(); + + thread.Abort (new StepTimeout ()); + } + + internal void StartTimeoutTimer() { + thread = Thread.CurrentThread; + timer = new Timer (TimeoutReached, null, (int)ConfigTimeout.TotalMilliseconds, Timeout.Infinite); + } + + internal void StopTimeoutTimer() { + if(timer != null) { + timer.Dispose (); + timer = null; + } } internal bool TimeoutPossible { @@ -604,19 +742,9 @@ namespace System.Web { } #endif #endregion - -#if NET_2_0 - Page last_page; - - internal Page LastPage { - get { - return last_page; - } - - set { - last_page = value; - } - } -#endif + } + + class StepTimeout + { } }