/Web/Components/UrlRewriter.cs
C# | 382 lines | 252 code | 81 blank | 49 comment | 58 complexity | 029b92a4d4f5e1b9ad382442c49ec533 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause, CPL-1.0, CC-BY-SA-3.0, GPL-2.0
- // Author: Joe Audette
- // Created: 2005-06-01
- // Last Modified: 2011-11-18
- //
- // The use and distribution terms for this software are covered by the
- // Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
- // which can be found in the file CPL.TXT at the root of this distribution.
- // By using this software in any fashion, you are agreeing to be bound by
- // the terms of this license.
- //
- // You must not remove this notice, or any other, from this software.
-
- using System;
- using System.Data;
- using System.Text;
- using System.Web;
- using log4net;
- using mojoPortal.Business;
- using mojoPortal.Business.WebHelpers;
- using mojoPortal.Web.Framework;
-
- namespace mojoPortal.Web
- {
-
- public class UrlRewriter : IHttpModule
- {
- private static readonly ILog log = LogManager.GetLogger(typeof(UrlRewriter));
- private static bool debugLog = log.IsDebugEnabled;
-
-
- public void Init(HttpApplication app)
- {
- app.BeginRequest += new EventHandler(this.UrlRewriter_BeginRequest);
-
- }
-
-
-
- public void Dispose() {}
-
- protected void UrlRewriter_BeginRequest(object sender, EventArgs e)
- {
- if (sender == null) return;
-
- HttpApplication app = (HttpApplication)sender;
-
-
- if (!WebConfigSettings.UseUrlReWritingForStaticFiles)
- {
-
- if (WebUtils.IsRequestForStaticFile(app.Request.Path)) { return; }
-
- if (
- (app.Request.Path.EndsWith("csshandler.ashx", StringComparison.InvariantCultureIgnoreCase))
- || (app.Request.Path.EndsWith("CaptchaImage.ashx", StringComparison.InvariantCultureIgnoreCase))
- || (app.Request.Path.EndsWith("/Data/", StringComparison.InvariantCultureIgnoreCase))
- || (app.Request.Path.StartsWith("/Data/", StringComparison.InvariantCultureIgnoreCase))
- )
- {
- return;
-
- }
- }
-
- if (WebConfigSettings.UseUrlReWriting)
- {
- try
- {
- RewriteUrl(app);
- }
- catch (InvalidOperationException ex)
- {
- log.Error(ex);
- }
- catch (System.Data.Common.DbException ex)
- {
- log.Error(ex);
- }
- catch (Exception ex)
- {
- // hate to trap System.Exception but SqlCeException doe snot inherit from DbException as it should
- if (DatabaseHelper.DBPlatform() != "SqlCe") { throw ex; }
- log.Error(ex);
- }
-
-
- }
- }
-
- private static void RewriteUrl(HttpApplication app)
- {
- if (app == null) return;
-
- string requestPath = app.Request.Path;
-
- bool useFolderForSiteDetection = WebConfigSettings.UseFoldersInsteadOfHostnamesForMultipleSites;
-
- string virtualFolderName;
- if (useFolderForSiteDetection)
- {
- virtualFolderName = VirtualFolderEvaluator.VirtualFolderName();
- }
- else
- {
- virtualFolderName = string.Empty;
- }
-
- bool setClientFilePath = true;
-
-
- if (
- (useFolderForSiteDetection)
- && (virtualFolderName.Length > 0)
- )
- {
- setClientFilePath = false;
-
- // requesting root of folderbased site like /folder1/
- // don't re-write it
- if (requestPath.EndsWith(virtualFolderName + "/"))
- {
- return;
- }
- }
-
-
-
- // Remove extended information after path, such as for Web services
- // or bogus /default.aspx/default.aspx
- string pathInfo = app.Request.PathInfo;
- if (pathInfo != string.Empty)
- {
- requestPath = requestPath.Substring(0, requestPath.Length - pathInfo.Length);
- }
-
- // 2006-01-25 : David Neal : Updated URL checking, Fixes for sites where mojoPortal
- // is running at the root and for bogus default document URLs
- // Get the relative target URL without the application root
- string appRoot = WebUtils.GetApplicationRoot();
-
- if (requestPath.Length == appRoot.Length) { return; }
-
- string targetUrl = requestPath.Substring(appRoot.Length + 1);
- //if (targetUrl.Length == 0) return;
- if(StringHelper.IsCaseInsensitiveMatch(targetUrl, "default.aspx"))return;
-
- if (useFolderForSiteDetection)
- {
- if (targetUrl.StartsWith(virtualFolderName + "/"))
- {
- // 2009-03-01 Kris reported a bug where folder site using /er for the folder
- // was making an incorrect targetUrl
- // this url from an edit link in feed manager http://localhost/er/FeedManager/FeedEdit.aspx?mid=54&pageid=34
- // was getting changed to http://localhost/er/FeedManagFeedEdit.aspx?mid=54&pageid=34 causig a 404
- // caused by this commented line
- //targetUrl = targetUrl.Replace(virtualFolderName + "/", string.Empty);
- //fixed by changing to this
- targetUrl = targetUrl.Remove(0, virtualFolderName.Length + 1);
-
- }
- }
-
-
- if (!WebConfigSettings.Disable301Redirector)
- {
- try
- {
- // check if the requested url is supposed to redirect
- string redirectUrl = GetRedirectUrl(targetUrl);
- if (redirectUrl.Length > 0)
- {
- Do301Redirect(app, redirectUrl);
- return;
- }
- }
- catch (NullReferenceException ex)
- {
- // this can happen on a new installation so we catch and log it
- log.Error(ex);
- }
- }
-
-
- FriendlyUrl friendlyUrl = null;
- SiteSettings siteSettings = CacheHelper.GetCurrentSiteSettings();
- //this will happen on a new installation
- if (siteSettings == null) { return; }
-
- if (
- (useFolderForSiteDetection)
- && (virtualFolderName.Length > 0)
- )
- {
-
- //int siteID = SiteSettings.GetSiteIDFromFolderName(virtualFolderName);
- friendlyUrl = new FriendlyUrl(siteSettings.SiteId, targetUrl);
- }
- else
- {
- if (siteSettings.DefaultFriendlyUrlPattern == SiteSettings.FriendlyUrlPattern.PageName)
- {
- //when using extensionless urls we consistently store them without a trailing slash
- if (targetUrl.EndsWith("/"))
- {
-
- targetUrl = targetUrl.Substring(0, targetUrl.Length - 1);
- setClientFilePath = false;
- }
- }
-
- if (WebConfigSettings.AlwaysUrlEncode)
- {
- friendlyUrl = new FriendlyUrl(WebUtils.GetHostName(), HttpUtility.UrlEncode(targetUrl));
-
- //in case existing pages are not url encoded since this setting was added 2009-11-15, try again without encoding
-
- if (!friendlyUrl.FoundFriendlyUrl)
- {
- if (WebConfigSettings.RetryUnencodedOnUrlNotFound)
- {
- friendlyUrl = new FriendlyUrl(WebUtils.GetHostName(), targetUrl);
- }
- }
-
- }
- else
- {
- friendlyUrl = new FriendlyUrl(WebUtils.GetHostName(), targetUrl);
- }
- }
-
- if (
- (friendlyUrl == null)
- ||(!friendlyUrl.FoundFriendlyUrl)
- )
- {
- if (
- (useFolderForSiteDetection)
- && (virtualFolderName.Length > 0)
- )
- {
- SiteUtils.TrackUrlRewrite();
-
- //2009-03-01 same bug as above
- //string pathToUse = requestPath.Replace(virtualFolderName + "/", string.Empty);
- string pathToUse = requestPath.Remove(0, virtualFolderName.Length + 1);
-
- // this is a flag that can be used to detect if the url was already rewritten if you need to run a custom url rewriter after this one
- // you should only rewrite urls that were not rewritten by mojoPortal url rewriter
- app.Context.Items["mojoPortaLDidRewriteUrl"] = true;
-
- app.Context.RewritePath(
- pathToUse,
- string.Empty,
- app.Request.QueryString.ToString(),
- setClientFilePath);
-
- }
- else
- {
- if ((targetUrl.Length > 1)&&(!targetUrl.Contains(".")))
- {
- // this is a flag that will be detected in our pagenotfoundhttpmodule
- // so we can handle 404 for extensionless urls
- app.Context.Items["UrlNotFound"] = true;
- }
- return;
- }
-
-
- }
-
- string queryStringToUse = string.Empty;
- string realPageName = string.Empty;
-
-
- if (friendlyUrl.RealUrl.IndexOf('?') > 0)
- {
- realPageName = friendlyUrl.RealUrl.Substring(0, friendlyUrl.RealUrl.IndexOf('?'));
- queryStringToUse = friendlyUrl.RealUrl.Substring(friendlyUrl.RealUrl.IndexOf('?') + 1);
- }
- else // Added by Christian Fredh 10/30/2006
- {
- realPageName = friendlyUrl.RealUrl;
- }
-
- if (debugLog) { log.Debug("Rewriting URL to " + friendlyUrl.RealUrl); }
-
-
- if ((realPageName != null) && (!String.IsNullOrEmpty(realPageName)))
- {
- if (queryStringToUse == null)
- {
- queryStringToUse = String.Empty;
- }
-
- StringBuilder originalQueryString = new StringBuilder();
-
- // get any additional params besides pageid
- string separator = string.Empty;
- foreach (string key in app.Request.QueryString.AllKeys)
- {
- if (key != "pageid")
- {
- originalQueryString.Append( separator + key + "="
- + app.Request.QueryString.Get(key));
-
- if(separator.Length == 0)separator = "&";
-
- }
- }
-
- if (originalQueryString.Length > 0)
- {
- if (queryStringToUse.Length == 0)
- {
- queryStringToUse = originalQueryString.ToString();
- }
- else
- {
- queryStringToUse += "&" + originalQueryString.ToString();
- }
- }
-
- SiteUtils.TrackUrlRewrite();
- //log.Info("re-writing to " + realPageName);
-
- // this is a flag that can be used to detect if the url was already rewritten if you need to run a custom url rewriter after this one
- // you should only rewrite urls that were not rewritten by mojoPortal url rewriter
- app.Context.Items["mojoPortaLDidRewriteUrl"] = true;
-
- app.Context.RewritePath(realPageName, string.Empty, queryStringToUse, setClientFilePath);
- }
-
-
- }
-
- /// <summary>
- /// note the expected targetUrl and returned url are not fully qualified, but relative without a /
- /// </summary>
- /// <param name="targetUrl"></param>
- /// <returns></returns>
- private static string GetRedirectUrl(string targetUrl)
- {
- //lookup if this url is to be redirected, if found return the new url
- string newUrl = string.Empty;
-
- SiteSettings siteSettings = CacheHelper.GetCurrentSiteSettings();
- using (IDataReader reader = RedirectInfo.GetBySiteAndUrl(siteSettings.SiteId, targetUrl))
- {
- if (reader.Read())
- {
- newUrl = reader["NewUrl"].ToString();
- }
- }
-
- return newUrl;
- }
-
- private static void Do301Redirect(HttpApplication app, string newUrl)
- {
-
- string siteRoot = SiteUtils.GetNavigationSiteRoot();
-
- app.Context.Response.Status = "301 Moved Permanently";
- if (WebConfigSettings.PassQueryStringFor301Redirects)
- {
- app.Context.Response.AddHeader("Location", siteRoot + "/" + newUrl + app.Request.Url.Query);
- }
- else
- {
- app.Context.Response.AddHeader("Location", siteRoot + "/" + newUrl);
- }
-
- }
-
-
-
-
-
- }
- }