246 lines
7.5 KiB
C#
246 lines
7.5 KiB
C#
using System;
|
|
using System.Text;
|
|
using System.Web;
|
|
using Umbraco.Core;
|
|
using umbraco;
|
|
|
|
namespace Umbraco.Web
|
|
{
|
|
public static class UriUtility
|
|
{
|
|
static string _appPath;
|
|
static string _appPathPrefix;
|
|
|
|
static UriUtility()
|
|
{
|
|
SetAppDomainAppVirtualPath(HttpRuntime.AppDomainAppVirtualPath);
|
|
}
|
|
|
|
// internal for unit testing only
|
|
internal static void SetAppDomainAppVirtualPath(string appPath)
|
|
{
|
|
_appPath = appPath ?? "/";
|
|
_appPathPrefix = _appPath;
|
|
if (_appPathPrefix == "/")
|
|
_appPathPrefix = String.Empty;
|
|
}
|
|
|
|
// will be "/" or "/foo"
|
|
public static string AppPath
|
|
{
|
|
get { return _appPath; }
|
|
}
|
|
|
|
// will be "" or "/foo"
|
|
public static string AppPathPrefix
|
|
{
|
|
get { return _appPathPrefix; }
|
|
}
|
|
|
|
// adds the virtual directory if any
|
|
// see also VirtualPathUtility.ToAbsolute
|
|
// FIXME
|
|
public static string ToAbsolute(string url)
|
|
{
|
|
//return ResolveUrl(url);
|
|
url = url.TrimStart('~');
|
|
return _appPathPrefix + url;
|
|
}
|
|
|
|
// strips the virtual directory if any
|
|
// see also VirtualPathUtility.ToAppRelative
|
|
public static string ToAppRelative(string virtualPath)
|
|
{
|
|
if (virtualPath.InvariantStartsWith(_appPathPrefix))
|
|
virtualPath = virtualPath.Substring(_appPathPrefix.Length);
|
|
if (virtualPath.Length == 0)
|
|
virtualPath = "/";
|
|
return virtualPath;
|
|
}
|
|
|
|
// maps an internal umbraco uri to a public uri
|
|
// ie with virtual directory, .aspx if required...
|
|
public static Uri UriFromUmbraco(Uri uri)
|
|
{
|
|
var path = uri.GetSafeAbsolutePath();
|
|
|
|
if (path != "/")
|
|
{
|
|
if (!GlobalSettings.UseDirectoryUrls)
|
|
path += ".aspx";
|
|
else if (UmbracoSettings.AddTrailingSlash)
|
|
path += "/";
|
|
}
|
|
|
|
path = ToAbsolute(path);
|
|
|
|
return uri.Rewrite(path);
|
|
}
|
|
|
|
// maps a public uri to an internal umbraco uri
|
|
// ie no virtual directory, no .aspx, lowercase...
|
|
public static Uri UriToUmbraco(Uri uri)
|
|
{
|
|
// note: no need to decode uri here because we're returning a uri
|
|
// so it will be re-encoded anyway
|
|
var path = uri.GetSafeAbsolutePath();
|
|
|
|
path = path.ToLower();
|
|
path = ToAppRelative(path); // strip vdir if any
|
|
|
|
//we need to check if the path is /default.aspx because this will occur when using a
|
|
//web server pre IIS 7 when requesting the root document
|
|
//if this is the case we need to change it to '/'
|
|
if (path.StartsWith("/default.aspx", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
string rempath = path.Substring("/default.aspx".Length, path.Length - "/default.aspx".Length);
|
|
path = rempath.StartsWith("/") ? rempath : "/" + rempath;
|
|
}
|
|
if (path != "/")
|
|
{
|
|
path = path.TrimEnd('/');
|
|
}
|
|
|
|
//if any part of the path contains .aspx, replace it with nothing.
|
|
//sometimes .aspx is not at the end since we might have /home/sub1.aspx/customtemplate
|
|
path = path.Replace(".aspx", "");
|
|
|
|
return uri.Rewrite(path);
|
|
}
|
|
|
|
#region ResolveUrl
|
|
|
|
// http://www.codeproject.com/Articles/53460/ResolveUrl-in-ASP-NET-The-Perfect-Solution
|
|
// note
|
|
// if browsing http://example.com/sub/page1.aspx then
|
|
// ResolveUrl("page2.aspx") returns "/page2.aspx"
|
|
// Page.ResolveUrl("page2.aspx") returns "/sub/page2.aspx" (relative...)
|
|
//
|
|
public static string ResolveUrl(string relativeUrl)
|
|
{
|
|
if (relativeUrl == null) throw new ArgumentNullException("relativeUrl");
|
|
|
|
if (relativeUrl.Length == 0 || relativeUrl[0] == '/' || relativeUrl[0] == '\\')
|
|
return relativeUrl;
|
|
|
|
int idxOfScheme = relativeUrl.IndexOf(@"://", StringComparison.Ordinal);
|
|
if (idxOfScheme != -1)
|
|
{
|
|
int idxOfQM = relativeUrl.IndexOf('?');
|
|
if (idxOfQM == -1 || idxOfQM > idxOfScheme) return relativeUrl;
|
|
}
|
|
|
|
StringBuilder sbUrl = new StringBuilder();
|
|
sbUrl.Append(_appPathPrefix);
|
|
if (sbUrl.Length == 0 || sbUrl[sbUrl.Length - 1] != '/') sbUrl.Append('/');
|
|
|
|
// found question mark already? query string, do not touch!
|
|
bool foundQM = false;
|
|
bool foundSlash; // the latest char was a slash?
|
|
if (relativeUrl.Length > 1
|
|
&& relativeUrl[0] == '~'
|
|
&& (relativeUrl[1] == '/' || relativeUrl[1] == '\\'))
|
|
{
|
|
relativeUrl = relativeUrl.Substring(2);
|
|
foundSlash = true;
|
|
}
|
|
else foundSlash = false;
|
|
foreach (char c in relativeUrl)
|
|
{
|
|
if (!foundQM)
|
|
{
|
|
if (c == '?') foundQM = true;
|
|
else
|
|
{
|
|
if (c == '/' || c == '\\')
|
|
{
|
|
if (foundSlash) continue;
|
|
else
|
|
{
|
|
sbUrl.Append('/');
|
|
foundSlash = true;
|
|
continue;
|
|
}
|
|
}
|
|
else if (foundSlash) foundSlash = false;
|
|
}
|
|
}
|
|
sbUrl.Append(c);
|
|
}
|
|
|
|
return sbUrl.ToString();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Uri string utilities
|
|
|
|
public static bool HasScheme(string uri)
|
|
{
|
|
return uri.IndexOf("://") > 0;
|
|
}
|
|
|
|
public static string StartWithScheme(string uri)
|
|
{
|
|
return StartWithScheme(uri, null);
|
|
}
|
|
|
|
public static string StartWithScheme(string uri, string scheme)
|
|
{
|
|
return HasScheme(uri) ? uri : String.Format("{0}://{1}", scheme ?? Uri.UriSchemeHttp, uri);
|
|
}
|
|
|
|
public static string EndPathWithSlash(string uri)
|
|
{
|
|
var pos1 = Math.Max(0, uri.IndexOf('?'));
|
|
var pos2 = Math.Max(0, uri.IndexOf('#'));
|
|
var pos = Math.Min(pos1, pos2);
|
|
|
|
var path = pos > 0 ? uri.Substring(0, pos) : uri;
|
|
path = path.EnsureEndsWith('/');
|
|
|
|
if (pos > 0)
|
|
path += uri.Substring(pos);
|
|
|
|
return path;
|
|
}
|
|
|
|
public static string TrimPathEndSlash(string uri)
|
|
{
|
|
var pos1 = Math.Max(0, uri.IndexOf('?'));
|
|
var pos2 = Math.Max(0, uri.IndexOf('#'));
|
|
var pos = Math.Min(pos1, pos2);
|
|
|
|
var path = pos > 0 ? uri.Substring(0, pos) : uri;
|
|
path = path.TrimEnd('/');
|
|
|
|
if (pos > 0)
|
|
path += uri.Substring(pos);
|
|
|
|
return path;
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Returns an faull url with the host, port, etc...
|
|
/// </summary>
|
|
/// <param name="absolutePath">An absolute path (i.e. starts with a '/' )</param>
|
|
/// <param name="httpContext"> </param>
|
|
/// <returns></returns>
|
|
/// <remarks>
|
|
/// Based on http://stackoverflow.com/questions/3681052/get-absolute-url-from-relative-path-refactored-method
|
|
/// </remarks>
|
|
internal static Uri ToFullUrl(string absolutePath, HttpContextBase httpContext)
|
|
{
|
|
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
|
if (String.IsNullOrEmpty(absolutePath))
|
|
throw new ArgumentNullException("absolutePath");
|
|
|
|
if (!absolutePath.StartsWith("/"))
|
|
throw new FormatException("The absolutePath specified does not start with a '/'");
|
|
|
|
return new Uri(absolutePath, UriKind.Relative).MakeAbsolute(httpContext.Request.Url);
|
|
}
|
|
}
|
|
} |