PageRenderTime 23ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/referencesource/System.Web.Extensions/Handlers/ScriptModule.cs

https://github.com/pruiz/mono
C# | 194 lines | 126 code | 31 blank | 37 comment | 33 complexity | 30b5c7637762c69e851d6a2ddb3f221c MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //------------------------------------------------------------------------------
  2. // <copyright file="ScriptModule.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. namespace System.Web.Handlers {
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Globalization;
  10. using System.Linq;
  11. using System.Net;
  12. using System.Threading;
  13. using System.Web;
  14. using System.Web.ApplicationServices;
  15. using System.Web.UI;
  16. using System.Web.Resources;
  17. using System.Web.Script.Services;
  18. using System.Web.Security;
  19. public class ScriptModule : IHttpModule {
  20. private static readonly object _contextKey = new Object();
  21. private static Type _authenticationServiceType = typeof(System.Web.Security.AuthenticationService); // disambiguation required
  22. private static int _isHandlerRegistered;
  23. private static bool ShouldSkipAuthorization(HttpContext context) {
  24. if (context == null || context.Request == null) {
  25. return false;
  26. }
  27. string path = context.Request.FilePath;
  28. if (ScriptResourceHandler.IsScriptResourceRequest(path)) {
  29. return true;
  30. }
  31. // if auth service is disabled, dont bother checking.
  32. // (NOTE: if a custom webservice is used, it will be up to them to enable anon access to it)
  33. // if it isn't a rest request dont bother checking.
  34. if(!ApplicationServiceHelper.AuthenticationServiceEnabled || !RestHandlerFactory.IsRestRequest(context)) {
  35. return false;
  36. }
  37. if(context.SkipAuthorization) {
  38. return true;
  39. }
  40. // it may be a rest request to a webservice. It must end in axd if it is an app service.
  41. if((path == null) || !path.EndsWith(".axd", StringComparison.OrdinalIgnoreCase)) {
  42. return false;
  43. }
  44. // WebServiceData caches the object in cache, so this should be a quick lookup.
  45. // If it hasnt been cached yet, this will cause it to be cached, so later in the request
  46. // it will be a cache-hit anyway.
  47. WebServiceData wsd = WebServiceData.GetWebServiceData(context, path, false, false);
  48. if((wsd != null) && (_authenticationServiceType == wsd.TypeData.Type)) {
  49. return true;
  50. }
  51. return false;
  52. }
  53. protected virtual void Dispose() {
  54. }
  55. private void AuthenticateRequestHandler(object sender, EventArgs e) {
  56. // flags the request with SkipAuthorization if it is a request for
  57. // the script Authentication webservice.
  58. HttpApplication app = (HttpApplication)sender;
  59. if (app != null && ShouldSkipAuthorization(app.Context)) {
  60. app.Context.SetSkipAuthorizationNoDemand(true, false);
  61. }
  62. }
  63. private void EndRequestHandler(object sender, EventArgs e){
  64. // DevDiv 100198: Send error response from EndRequest so Page and Application error handlers still fire on async posts
  65. // DevDiv 118737: Call Response.Clear as well as Response.ClearHeaders to force status code reset in integrated mode and
  66. // to ensure there are no errant headers such as a caching policy. Do not call Response.End or app.CompleteRequest as they
  67. // are pointless from the EndRequest event.
  68. HttpApplication app = (HttpApplication)sender;
  69. HttpContext context = app.Context;
  70. object o = context.Items[PageRequestManager.AsyncPostBackErrorKey];
  71. if ((o != null) && ((bool)o == true)) {
  72. context.ClearError();
  73. context.Response.ClearHeaders();
  74. context.Response.Clear();
  75. context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
  76. context.Response.ContentType = "text/plain";
  77. string errorMessage = (string)context.Items[PageRequestManager.AsyncPostBackErrorMessageKey];
  78. o = context.Items[PageRequestManager.AsyncPostBackErrorHttpCodeKey];
  79. // o should definitely be an int, but user code could overwrite it
  80. int httpCode = (o is int) ? (int)o : 500;
  81. PageRequestManager.EncodeString(context.Response.Output,
  82. PageRequestManager.ErrorToken,
  83. httpCode.ToString(CultureInfo.InvariantCulture),
  84. errorMessage);
  85. }
  86. }
  87. protected virtual void Init(HttpApplication app) {
  88. //////////////////////////////////////////////////////////////////
  89. // Check if this module has been already addded
  90. if (app.Context.Items[_contextKey] != null) {
  91. return; // already added to the pipeline
  92. }
  93. app.Context.Items[_contextKey] = _contextKey;
  94. // use the static HttpResponse.Redirecting event to hook all Response.Redirects.
  95. // Only hook the event once. Multiple pipelines may cause multiple instances of this
  96. // module to be created.
  97. if (Interlocked.Exchange(ref _isHandlerRegistered, 1) == 0) {
  98. HttpResponse.Redirecting += new EventHandler(HttpResponse_Redirecting);
  99. }
  100. app.PostAcquireRequestState += new EventHandler(OnPostAcquireRequestState);
  101. app.AuthenticateRequest += new EventHandler(AuthenticateRequestHandler);
  102. // DevDiv 100198: Send error response from EndRequest so Page and Application error handlers still fire on async posts
  103. app.EndRequest += new EventHandler(EndRequestHandler);
  104. }
  105. private static void HttpResponse_Redirecting(object sender, EventArgs e) {
  106. HttpResponse response = (HttpResponse)sender;
  107. HttpContext context = response.Context;
  108. // Is in async postback, get status code and check for 302
  109. if (PageRequestManager.IsAsyncPostBackRequest(new HttpRequestWrapper(context.Request))) {
  110. // Save the redirect location and other data before we clear it
  111. string redirectLocation = response.RedirectLocation;
  112. List<HttpCookie> cookies = new List<HttpCookie>(response.Cookies.Count);
  113. for (int i = 0; i < response.Cookies.Count; i++) {
  114. cookies.Add(response.Cookies[i]);
  115. }
  116. // Clear the entire response and send a custom response that the client script can process
  117. response.ClearContent();
  118. response.ClearHeaders();
  119. for (int i = 0; i < cookies.Count; i++) {
  120. response.AppendCookie(cookies[i]);
  121. }
  122. response.Cache.SetCacheability(HttpCacheability.NoCache);
  123. response.ContentType = "text/plain";
  124. // DevDiv#961281
  125. // Allow apps to access to the redirect location
  126. context.Items[PageRequestManager.AsyncPostBackRedirectLocationKey] = redirectLocation;
  127. // Preserve redirected state: TFS#882879
  128. response.IsRequestBeingRedirected = true;
  129. PageRequestManager.EncodeString(response.Output, PageRequestManager.UpdatePanelVersionToken, String.Empty, PageRequestManager.UpdatePanelVersionNumber);
  130. // url encode the location in a way that javascript unescape() will be able to reverse
  131. redirectLocation = String.Join(" ", redirectLocation.Split(' ').Select(part => HttpUtility.UrlEncode(part)));
  132. PageRequestManager.EncodeString(response.Output, PageRequestManager.PageRedirectToken, String.Empty, redirectLocation);
  133. }
  134. else if (RestHandlerFactory.IsRestRequest(context)) {
  135. // We need to special case webservice redirects, as we want them to fail (always are auth failures)
  136. RestHandler.WriteExceptionJsonString(context, new InvalidOperationException(AtlasWeb.WebService_RedirectError), (int)HttpStatusCode.Unauthorized);
  137. }
  138. }
  139. private void OnPostAcquireRequestState(object sender, EventArgs eventArgs) {
  140. HttpApplication app = (HttpApplication)sender;
  141. HttpRequest request = app.Context.Request;
  142. if (app.Context.Handler is Page && RestHandlerFactory.IsRestMethodCall(request)) {
  143. // Get the data about the web service being invoked
  144. WebServiceData webServiceData = WebServiceData.GetWebServiceData(HttpContext.Current, request.FilePath, false, true);
  145. // Get the method name
  146. string methodName = request.PathInfo.Substring(1);
  147. // Get the data about the specific method being called
  148. WebServiceMethodData methodData = webServiceData.GetMethodData(methodName);
  149. RestHandler.ExecuteWebServiceCall(HttpContext.Current, methodData);
  150. // Skip the rest of the page lifecycle
  151. app.CompleteRequest();
  152. }
  153. }
  154. #region IHttpModule Members
  155. void IHttpModule.Dispose() {
  156. Dispose();
  157. }
  158. void IHttpModule.Init(HttpApplication context) {
  159. Init(context);
  160. }
  161. #endregion
  162. }
  163. }