using System; using System.IO; using System.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.IO; namespace Umbraco.Core { /// /// Provides extension methods to . /// public static class UriExtensions { /// /// Checks if the current uri is a back office request /// /// /// internal static bool IsBackOfficeRequest(this Uri url) { var authority = url.GetLeftPart(UriPartial.Authority); var afterAuthority = url.GetLeftPart(UriPartial.Query) .TrimStart(authority) .TrimStart("/"); //check if this is in the umbraco back office return afterAuthority.InvariantStartsWith(GlobalSettings.Path.TrimStart("/")); } /// /// Checks if the current uri is an install request /// /// /// internal static bool IsInstallerRequest(this Uri url) { var authority = url.GetLeftPart(UriPartial.Authority); var afterAuthority = url.GetLeftPart(UriPartial.Query) .TrimStart(authority) .TrimStart("/"); //check if this is in the umbraco back office return afterAuthority.InvariantStartsWith(IOHelper.ResolveUrl("~/install").TrimStart("/")); } /// /// This is a performance tweak to check if this is a .css, .js or .ico, .jpg, .jpeg, .png, .gif file request since /// .Net will pass these requests through to the module when in integrated mode. /// We want to ignore all of these requests immediately. /// /// /// internal static bool IsClientSideRequest(this Uri url) { // fixme - IsClientSideRequest should not use an hard-coded list of extensions // a client-side request is anything that has an extension that is not .aspx? var toIgnore = new[] { ".js", ".css", ".ico", ".png", ".jpg", ".jpeg", ".gif", ".html", ".svg" }; return toIgnore.Any(x => Path.GetExtension(url.LocalPath).InvariantEquals(x)); } /// /// Rewrites the path of uri. /// /// The uri. /// The new path, which must begin with a slash. /// The rewritten uri. /// Everything else remains unchanged, except for the fragment which is removed. public static Uri Rewrite(this Uri uri, string path) { if (path.StartsWith("/") == false) throw new ArgumentException("Path must start with a slash.", "path"); return uri.IsAbsoluteUri ? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + uri.Query) : new Uri(path + uri.GetSafeQuery(), UriKind.Relative); } /// /// Rewrites the path and query of a uri. /// /// The uri. /// The new path, which must begin with a slash. /// The new query, which must be empty or begin with a question mark. /// The rewritten uri. /// Everything else remains unchanged, except for the fragment which is removed. public static Uri Rewrite(this Uri uri, string path, string query) { if (path.StartsWith("/") == false) throw new ArgumentException("Path must start with a slash.", "path"); if (query.Length > 0 && query.StartsWith("?") == false) throw new ArgumentException("Query must start with a question mark.", "query"); if (query == "?") query = ""; return uri.IsAbsoluteUri ? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + query) : new Uri(path + query, UriKind.Relative); } /// /// Gets the absolute path of the uri, even if the uri is relative. /// /// The uri. /// The absolute path of the uri. /// Default uri.AbsolutePath does not support relative uris. public static string GetSafeAbsolutePath(this Uri uri) { if (uri.IsAbsoluteUri) return uri.AbsolutePath; // cannot get .AbsolutePath on relative uri (InvalidOperation) var s = uri.OriginalString; var posq = s.IndexOf("?", StringComparison.Ordinal); var posf = s.IndexOf("#", StringComparison.Ordinal); var pos = posq > 0 ? posq : (posf > 0 ? posf : 0); var path = pos > 0 ? s.Substring(0, pos) : s; return path; } /// /// Gets the decoded, absolute path of the uri. /// /// The uri. /// The absolute path of the uri. /// Only for absolute uris. public static string GetAbsolutePathDecoded(this Uri uri) { return System.Web.HttpUtility.UrlDecode(uri.AbsolutePath); } /// /// Gets the decoded, absolute path of the uri, even if the uri is relative. /// /// The uri. /// The absolute path of the uri. /// Default uri.AbsolutePath does not support relative uris. public static string GetSafeAbsolutePathDecoded(this Uri uri) { return System.Web.HttpUtility.UrlDecode(uri.GetSafeAbsolutePath()); } /// /// Rewrites the path of the uri so it ends with a slash. /// /// The uri. /// The rewritten uri. /// Everything else remains unchanged. public static Uri EndPathWithSlash(this Uri uri) { var path = uri.GetSafeAbsolutePath(); if (uri.IsAbsoluteUri) { if (path != "/" && path.EndsWith("/") == false) uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path + "/" + uri.Query); return uri; } if (path != "/" && path.EndsWith("/") == false) uri = new Uri(path + "/" + uri.Query, UriKind.Relative); return uri; } /// /// Rewrites the path of the uri so it does not end with a slash. /// /// The uri. /// The rewritten uri. /// Everything else remains unchanged. public static Uri TrimPathEndSlash(this Uri uri) { var path = uri.GetSafeAbsolutePath(); if (uri.IsAbsoluteUri) { if (path != "/") uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path.TrimEnd('/') + uri.Query); } else { if (path != "/") uri = new Uri(path.TrimEnd('/') + uri.Query, UriKind.Relative); } return uri; } /// /// Transforms a relative uri into an absolute uri. /// /// The relative uri. /// The base absolute uri. /// The absolute uri. public static Uri MakeAbsolute(this Uri uri, Uri baseUri) { if (uri.IsAbsoluteUri) throw new ArgumentException("Uri is already absolute.", "uri"); return new Uri(baseUri.GetLeftPart(UriPartial.Authority) + uri.GetSafeAbsolutePath() + uri.GetSafeQuery()); } static string GetSafeQuery(this Uri uri) { if (uri.IsAbsoluteUri) return uri.Query; // cannot get .Query on relative uri (InvalidOperation) var s = uri.OriginalString; var posq = s.IndexOf("?", StringComparison.Ordinal); var posf = s.IndexOf("#", StringComparison.Ordinal); var query = posq < 0 ? null : (posf < 0 ? s.Substring(posq) : s.Substring(posq, posf - posq)); return query; } } }