/Framework/Web/UrlRewriting/UrlRewriterModule.cs

# · C# · 160 lines · 106 code · 31 blank · 23 comment · 22 complexity · 7a771827d95572d24eabe155b927f856 MD5 · raw file

  1. using System;
  2. using System.Configuration;
  3. using System.IO;
  4. using System.Text.RegularExpressions;
  5. using System.Web;
  6. using InfoControl.Security;
  7. namespace InfoControl.Web.UrlRewriting
  8. {
  9. public class UrlRewriterModule : HttpDataModule
  10. {
  11. private const string OriginalPath = "OriginalRequestPathInfo";
  12. private static bool _enabled;
  13. private readonly UrlRulesSectionCollection _rules = (ConfigurationManager.GetSection("InfoControl/UrlRewriting") as UrlRewriterSectionGroup).Rules;
  14. private string _newUrl;
  15. #region Properties
  16. public static bool Enabled
  17. {
  18. get { return _enabled; }
  19. }
  20. #endregion
  21. public override void Init(HttpApplication context)
  22. {
  23. base.Init(context);
  24. /*
  25. * FormsAuthenticationModule > AuthenticateRequest
  26. * Determines if the user is authenticated using forms authentication. If not,
  27. * the user is automatically redirected to the specified logon page.
  28. *
  29. * FileAuthorizationMoudle > AuthorizeRequest
  30. * When using Windows authentication, this HTTP module checks to ensure that the
  31. *
  32. * UrlAuthorizationModule > AuthorizeRequest
  33. * Checks to make sure the requestor can access the specified URL. URL authorization
  34. * is specified through the <authorization> and <location> elements in the Web.config file.
  35. *
  36. */
  37. context.ResolveRequestCache += ContextResolveRequestCache;
  38. context.PreRequestHandlerExecute += ContextPreRequestHandlerExecute;
  39. _enabled = true;
  40. }
  41. protected virtual void LookForNewUrl(HttpContext context, string requestedUrl)
  42. {
  43. string query = context.Request.Url.Query.Replace("?", "");
  44. if (!File.Exists(Context.Server.MapPath(requestedUrl)))
  45. foreach (UrlRulesSection rule in _rules)
  46. {
  47. string lookFor = ResolveUrl(Context.Request.ApplicationPath, rule.From);
  48. var reg = new Regex(lookFor, RegexOptions.IgnoreCase);
  49. if (reg.IsMatch(requestedUrl))
  50. {
  51. _newUrl = reg.Replace(requestedUrl, ResolveUrl(Context.Request.ApplicationPath, rule.To.Replace("^", "&")));
  52. if (_newUrl.IndexOf("?") > 0)
  53. {
  54. query = _newUrl.Substring(_newUrl.IndexOf("?") + 1) + query;
  55. _newUrl = _newUrl.Substring(0, _newUrl.IndexOf("?"));
  56. }
  57. // rewrite the path..
  58. if (File.Exists(Context.Server.MapPath(_newUrl)))
  59. {
  60. // query.Trim('&') because DataPager WebControl bug when trailing & in queryString
  61. RewritePath(_newUrl, String.Empty, query.Trim('&'));
  62. break;
  63. }
  64. }
  65. }
  66. }
  67. protected void RewritePath(string filePath, string pathInfo, string queryString)
  68. {
  69. Context.Items[OriginalPath] = Context.Request.Path;
  70. Context.RewritePath(filePath, pathInfo, queryString);
  71. }
  72. #region Events
  73. private void ContextResolveRequestCache(object sender, EventArgs e)
  74. {
  75. Context.Trace.Warn("UrlRewriter", "Begin OnBeginRequest");
  76. if (IsRequestValid())
  77. {
  78. string requestedUrl = ResolveUrl(Context.Request.ApplicationPath, Context.Request.Url.AbsolutePath);
  79. LookForNewUrl(Context, requestedUrl);
  80. }
  81. Context.Trace.Warn("UrlRewriter", "End OnBeginRequest");
  82. }
  83. private static void ContextPreRequestHandlerExecute(object sender, EventArgs e)
  84. {
  85. var app = sender as HttpApplication;
  86. if (app == null) return;
  87. var originalPath = app.Context.Items[OriginalPath] as String;
  88. if (!string.IsNullOrEmpty(originalPath))
  89. app.Context.RewritePath(originalPath);
  90. }
  91. #endregion
  92. #region Utility Functions
  93. private static string ResolveUrl(String appPath, String url)
  94. {
  95. // String is Empty, just return Url
  96. if (url.Length == 0)
  97. return url;
  98. // String does not contain a ~, so just return Url
  99. if (url.StartsWith("~") == false)
  100. return url;
  101. // There is just the ~ in the Url, return the appPath
  102. if (url.Length == 1)
  103. return appPath;
  104. if (url.ToCharArray()[1] == '/' || url.ToCharArray()[1] == '\\')
  105. {
  106. // Url looks like ~/ or ~\
  107. if (appPath.Length > 1)
  108. return appPath + "/" + url.Substring(2);
  109. return "/" + url.Substring(2);
  110. }
  111. // Url look like ~something
  112. if (appPath.Length > 1)
  113. return appPath + "/" + url.Substring(1);
  114. return appPath + url.Substring(1);
  115. }
  116. private bool IsRequestValid()
  117. {
  118. // URL validation
  119. // check for ".." escape characters commonly used by hackers to traverse the folder tree on the server
  120. // the application should always use the exact relative location of the resource it is requesting
  121. String strUrl = Context.Request.Url.AbsolutePath;
  122. String strDoubleDecodeUrl = Context.Server.UrlDecode(Context.Server.UrlDecode(Context.Request.RawUrl));
  123. if (Regex.Match(strUrl, @"[\\/]\.\.[\\/]").Success || Regex.Match(strDoubleDecodeUrl, @"[\\/]\.\.[\\/]").Success)
  124. throw new HttpException(404, "Not Found");
  125. return true;
  126. }
  127. #endregion
  128. }
  129. }