diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs
index dd3ae8c10c..2d9d644514 100644
--- a/src/Umbraco.Core/UriExtensions.cs
+++ b/src/Umbraco.Core/UriExtensions.cs
@@ -1,323 +1,323 @@
-using System;
-using System.IO;
-using System.Linq;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.IO;
-using Umbraco.Core.Logging;
-
-namespace Umbraco.Core
-{
- ///
- /// Provides extension methods to .
- ///
- public static class UriExtensions
- {
- ///
- /// Checks if the current uri is a back office request
- ///
- ///
- ///
- /// The current application path or VirtualPath
- ///
- ///
- ///
- /// There are some special routes we need to check to properly determine this:
- ///
- /// If any route has an extension in the path like .aspx = back office
- ///
- /// These are def back office:
- /// /Umbraco/RestServices = back office
- /// /Umbraco/BackOffice = back office
- /// If it's not any of the above, and there's no extension then we cannot determine if it's back office or front-end
- /// so we can only assume that it is not back office. This will occur if people use an UmbracoApiController for the backoffice
- /// but do not inherit from UmbracoAuthorizedApiController and do not use [IsBackOffice] attribute.
- ///
- /// These are def front-end:
- /// /Umbraco/Surface = front-end
- /// /Umbraco/Api = front-end
- /// But if we've got this far we'll just have to assume it's front-end anyways.
- ///
- ///
- internal static bool IsBackOfficeRequest(this Uri url, string applicationPath)
- {
- applicationPath = applicationPath ?? string.Empty;
-
- var fullUrlPath = url.AbsolutePath.TrimStart(new[] {'/'});
- var appPath = applicationPath.TrimStart(new[] {'/'});
- var urlPath = fullUrlPath.TrimStart(appPath).EnsureStartsWith('/');
-
- //check if this is in the umbraco back office
- var isUmbracoPath = urlPath.InvariantStartsWith(GlobalSettings.Path.EnsureStartsWith('/').TrimStart(appPath.EnsureStartsWith('/')).EnsureStartsWith('/'));
- //if not, then def not back office
- if (isUmbracoPath == false) return false;
-
- //if its the normal /umbraco path
- if (urlPath.InvariantEquals("/" + GlobalSettings.UmbracoMvcArea)
- || urlPath.InvariantEquals("/" + GlobalSettings.UmbracoMvcArea + "/"))
- {
- return true;
- }
-
- //check for a file extension
- var extension = Path.GetExtension(url.LocalPath);
- //has an extension, def back office
- if (extension.IsNullOrWhiteSpace() == false) return true;
- //check for special case asp.net calls like:
- // /umbraco/webservices/legacyAjaxCalls.asmx/js which will return a null file extension but are still considered extension'd requests
- if (urlPath.InvariantContains(".asmx/")
- || urlPath.InvariantContains(".aspx/")
- || urlPath.InvariantContains(".ashx/")
- || urlPath.InvariantContains(".axd/")
- || urlPath.InvariantContains(".svc/"))
- {
- return true;
- }
-
- //check for special back office paths
- if (urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/BackOffice/")
- || urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/RestServices/"))
- {
- return true;
- }
-
- //check for special front-end paths
- if (urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/Surface/")
- || urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/Api/"))
- {
- return false;
- }
-
- //if its none of the above, we will have to try to detect if it's a PluginController route, we can detect this by
- // checking how many parts the route has, for example, all PluginController routes will be routed like
- // Umbraco/MYPLUGINAREA/MYCONTROLLERNAME/{action}/{id}
- // so if the path contains at a minimum 3 parts: Umbraco + MYPLUGINAREA + MYCONTROLLERNAME then we will have to assume it is a
- // plugin controller for the front-end.
- if (urlPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries).Length >= 3)
- {
- return false;
- }
-
- //if its anything else we can assume it's back office
- return true;
- }
-
- ///
- /// 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("/"));
- }
-
- ///
- /// Checks if the uri is a request for the default back office page
- ///
- ///
- ///
- internal static bool IsDefaultBackOfficeRequest(this Uri url)
- {
- if (url.AbsolutePath.InvariantEquals(GlobalSettings.Path.TrimEnd("/"))
- || url.AbsolutePath.InvariantEquals(GlobalSettings.Path.EnsureEndsWith('/'))
- || url.AbsolutePath.InvariantEquals(GlobalSettings.Path.EnsureEndsWith('/') + "Default")
- || url.AbsolutePath.InvariantEquals(GlobalSettings.Path.EnsureEndsWith('/') + "Default/"))
- {
- return true;
- }
- return false;
- }
-
- ///
- /// This is a performance tweak to check if this not an ASP.Net server file
- /// .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)
- {
- try
- {
- var ext = Path.GetExtension(url.LocalPath);
- if (ext.IsNullOrWhiteSpace()) return false;
- var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"};
- return toInclude.Any(ext.InvariantEquals) == false;
- }
- catch (ArgumentException ex)
- {
- LogHelper.Error(typeof(UriExtensions), "Failed to determine if request was client side", ex);
- return false;
- }
- }
-
- ///
- /// 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;
- }
-
- ///
- /// Removes the port from the uri.
- ///
- /// The uri.
- /// The same uri, without its port.
- public static Uri WithoutPort(this Uri uri)
- {
- return new Uri(uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped));
- }
- }
-}
+using System;
+using System.IO;
+using System.Linq;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Core
+{
+ ///
+ /// Provides extension methods to .
+ ///
+ public static class UriExtensions
+ {
+ ///
+ /// Checks if the current uri is a back office request
+ ///
+ ///
+ ///
+ /// The current application path or VirtualPath
+ ///
+ ///
+ ///
+ /// There are some special routes we need to check to properly determine this:
+ ///
+ /// If any route has an extension in the path like .aspx = back office
+ ///
+ /// These are def back office:
+ /// /Umbraco/RestServices = back office
+ /// /Umbraco/BackOffice = back office
+ /// If it's not any of the above, and there's no extension then we cannot determine if it's back office or front-end
+ /// so we can only assume that it is not back office. This will occur if people use an UmbracoApiController for the backoffice
+ /// but do not inherit from UmbracoAuthorizedApiController and do not use [IsBackOffice] attribute.
+ ///
+ /// These are def front-end:
+ /// /Umbraco/Surface = front-end
+ /// /Umbraco/Api = front-end
+ /// But if we've got this far we'll just have to assume it's front-end anyways.
+ ///
+ ///
+ internal static bool IsBackOfficeRequest(this Uri url, string applicationPath)
+ {
+ applicationPath = applicationPath ?? string.Empty;
+
+ var fullUrlPath = url.AbsolutePath.TrimStart(new[] {'/'});
+ var appPath = applicationPath.TrimStart(new[] {'/'});
+ var urlPath = fullUrlPath.TrimStart(appPath).EnsureStartsWith('/');
+
+ //check if this is in the umbraco back office
+ var isUmbracoPath = urlPath.InvariantStartsWith(GlobalSettings.Path.EnsureStartsWith('/').TrimStart(appPath.EnsureStartsWith('/')).EnsureStartsWith('/'));
+ //if not, then def not back office
+ if (isUmbracoPath == false) return false;
+
+ //if its the normal /umbraco path
+ if (urlPath.InvariantEquals("/" + GlobalSettings.UmbracoMvcArea)
+ || urlPath.InvariantEquals("/" + GlobalSettings.UmbracoMvcArea + "/"))
+ {
+ return true;
+ }
+
+ //check for a file extension
+ var extension = Path.GetExtension(url.LocalPath);
+ //has an extension, def back office
+ if (extension.IsNullOrWhiteSpace() == false) return true;
+ //check for special case asp.net calls like:
+ // /umbraco/webservices/legacyAjaxCalls.asmx/js which will return a null file extension but are still considered extension'd requests
+ if (urlPath.InvariantContains(".asmx/")
+ || urlPath.InvariantContains(".aspx/")
+ || urlPath.InvariantContains(".ashx/")
+ || urlPath.InvariantContains(".axd/")
+ || urlPath.InvariantContains(".svc/"))
+ {
+ return true;
+ }
+
+ //check for special back office paths
+ if (urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/BackOffice/")
+ || urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/RestServices/"))
+ {
+ return true;
+ }
+
+ //check for special front-end paths
+ if (urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/Surface/")
+ || urlPath.InvariantStartsWith("/" + GlobalSettings.UmbracoMvcArea + "/Api/"))
+ {
+ return false;
+ }
+
+ //if its none of the above, we will have to try to detect if it's a PluginController route, we can detect this by
+ // checking how many parts the route has, for example, all PluginController routes will be routed like
+ // Umbraco/MYPLUGINAREA/MYCONTROLLERNAME/{action}/{id}
+ // so if the path contains at a minimum 3 parts: Umbraco + MYPLUGINAREA + MYCONTROLLERNAME then we will have to assume it is a
+ // plugin controller for the front-end.
+ if (urlPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries).Length >= 3)
+ {
+ return false;
+ }
+
+ //if its anything else we can assume it's back office
+ return true;
+ }
+
+ ///
+ /// 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("/"));
+ }
+
+ ///
+ /// Checks if the uri is a request for the default back office page
+ ///
+ ///
+ ///
+ internal static bool IsDefaultBackOfficeRequest(this Uri url)
+ {
+ if (url.AbsolutePath.InvariantEquals(GlobalSettings.Path.TrimEnd("/"))
+ || url.AbsolutePath.InvariantEquals(GlobalSettings.Path.EnsureEndsWith('/'))
+ || url.AbsolutePath.InvariantEquals(GlobalSettings.Path.EnsureEndsWith('/') + "Default")
+ || url.AbsolutePath.InvariantEquals(GlobalSettings.Path.EnsureEndsWith('/') + "Default/"))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// This is a performance tweak to check if this not an ASP.Net server file
+ /// .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)
+ {
+ try
+ {
+ var ext = Path.GetExtension(url.LocalPath);
+ if (ext.IsNullOrWhiteSpace()) return false;
+ var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"};
+ return toInclude.Any(ext.InvariantEquals) == false;
+ }
+ catch (ArgumentException)
+ {
+ LogHelper.Debug(typeof(UriExtensions), "Failed to determine if request was client side. Due to invalid characters in path: {0}", () => url.LocalPath);
+ return false;
+ }
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Removes the port from the uri.
+ ///
+ /// The uri.
+ /// The same uri, without its port.
+ public static Uri WithoutPort(this Uri uri)
+ {
+ return new Uri(uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped));
+ }
+ }
+}