//
// System.Web.UrlUtils.cs
//
// Authors:
// Gonzalo Paniagua (gonzalo@ximian.com)
// Jackson Harper (jackson@ximian.com)
//
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Web.SessionState;
using System.Text;
namespace System.Web.Util{
#if VISUAL_STUDIO
public
#else
internal
#endif
class UrlUtils {
// appRoot + SessionID + vpath
public static string InsertSessionId (string id, string path)
{
string dir = GetDirectory (path);
if (!dir.EndsWith ("/"))
dir += "/";
string appvpath = HttpRuntime.AppDomainAppVirtualPath;
if (!appvpath.EndsWith ("/"))
appvpath += "/";
if (path.StartsWith (appvpath))
path = path.Substring (appvpath.Length);
if (path [0] == '/')
path = path.Length > 1 ? path.Substring (1) : "";
return Canonic (appvpath + "(" + id + ")/" + path);
}
public static string GetSessionId (string path)
{
#if TARGET_DOTNET
return null;
#else
if (path == null)
return null;
string appvpath = HttpRuntime.AppDomainAppVirtualPath;
int appvpathlen = appvpath.Length;
if (path.Length <= appvpathlen)
return null;
path = path.Substring (appvpathlen);
int len = path.Length;
if (len == 0 || path [0] != '/') {
path = '/' + path;
len++;
}
if ((len < SessionId.IdLength + 3) || (path [1] != '(') ||
(path [SessionId.IdLength + 2] != ')'))
return null;
return path.Substring (2, SessionId.IdLength);
#endif
}
public static bool HasSessionId (string path)
{
if (path == null || path.Length < 5)
return false;
return (StrUtils.StartsWith (path, "/(") && path.IndexOf (")/") > 2);
}
public static string RemoveSessionId (string base_path, string file_path)
{
// Caller did a GetSessionId first
int idx = base_path.IndexOf ("/(");
string dir = base_path.Substring (0, idx + 1);
if (!dir.EndsWith ("/"))
dir += "/";
idx = base_path.IndexOf (")/");
if (idx != -1 && base_path.Length > idx + 2) {
string dir2 = base_path.Substring (idx + 2);
if (!dir2.EndsWith ("/"))
dir2 += "/";
dir += dir2;
}
return Canonic (dir + GetFile (file_path));
}
public static string Combine (string basePath, string relPath)
{
if (relPath == null)
throw new ArgumentNullException ("relPath");
int rlength = relPath.Length;
if (rlength == 0)
return "";
relPath = relPath.Replace ('\\', '/');
if (IsRooted (relPath))
return Canonic (relPath);
char first = relPath [0];
if (rlength < 3 || first == '~' || first == '/' || first == '\\') {
if (basePath == null || (basePath.Length == 1 && basePath [0] == '/'))
basePath = String.Empty;
string slash = (first == '/') ? "" : "/";
if (first == '~') {
if (rlength == 1) {
relPath = "";
} else if (rlength > 1 && relPath [1] == '/') {
relPath = relPath.Substring (2);
slash = "/";
}
string appvpath = HttpRuntime.AppDomainAppVirtualPath;
if (appvpath.EndsWith ("/"))
slash = "";
return Canonic (appvpath + slash + relPath);
}
return Canonic (basePath + slash + relPath);
}
if (basePath == null || basePath.Length == 0 || basePath [0] == '~')
basePath = HttpRuntime.AppDomainAppVirtualPath;
if (basePath.Length <= 1)
basePath = String.Empty;
return Canonic (basePath + "/" + relPath);
}
static char [] path_sep = {'\\', '/'};
public static string Canonic (string path)
{
bool isRooted = IsRooted(path);
bool endsWithSlash = path.EndsWith("/");
string [] parts = path.Split (path_sep);
int end = parts.Length;
int dest = 0;
for (int i = 0; i < end; i++) {
string current = parts [i];
if (current.Length == 0)
continue;
if (current == "." )
continue;
if (current == "..") {
dest --;
continue;
}
if (dest < 0)
if (!isRooted)
throw new HttpException ("Invalid path.");
else
dest = 0;
parts [dest++] = current;
}
if (dest < 0)
throw new HttpException ("Invalid path.");
if (dest == 0)
return "/";
string str = String.Join ("/", parts, 0, dest);
#if NET_2_0
str = RemoveDoubleSlashes (str);
#endif
if (isRooted)
str = "/" + str;
if (endsWithSlash)
str = str + "/";
return str;
}
public static string GetDirectory (string url)
{
url = url.Replace('\\','/');
int last = url.LastIndexOf ('/');
if (last > 0) {
if (last < url.Length)
last++;
#if NET_2_0
return RemoveDoubleSlashes (url.Substring (0, last));
#else
return url.Substring (0, last);
#endif
}
return "/";
}
#if NET_2_0
public static string RemoveDoubleSlashes (string input)
{
// MS VirtualPathUtility removes duplicate '/'
int index = -1;
for (int i = 1; i < input.Length; i++)
if (input [i] == '/' && input [i - 1] == '/') {
index = i - 1;
break;
}
if (index == -1) // common case optimization
return input;
StringBuilder sb = new StringBuilder (input.Length);
sb.Append (input, 0, index);
for (int i = index; i < input.Length; i++) {
if (input [i] == '/') {
int next = i + 1;
if (next < input.Length && input [next] == '/')
continue;
sb.Append ('/');
}
else {
sb.Append (input [i]);
}
}
return sb.ToString ();
}
#endif
public static string GetFile (string url)
{
url = url.Replace('\\','/');
int last = url.LastIndexOf ('/');
if (last >= 0) {
if (url.Length == 1) // Empty file name instead of ArgumentOutOfRange
return "";
return url.Substring (last+1);
}
throw new ArgumentException (String.Format ("GetFile: `{0}' does not contain a /", url));
}
public static bool IsRooted (string path)
{
if (path == null || path.Length == 0)
return true;
char c = path [0];
if (c == '/' || c == '\\')
return true;
return false;
}
public static bool IsRelativeUrl (string path)
{
return (path [0] != '/' && path.IndexOf (':') == -1);
}
public static string ResolveVirtualPathFromAppAbsolute (string path)
{
if (path [0] != '~') return path;
if (path.Length == 1)
return HttpRuntime.AppDomainAppVirtualPath;
if (path [1] == '/' || path [1] == '\\') {
string appPath = HttpRuntime.AppDomainAppVirtualPath;
if (appPath.Length > 1)
return appPath + "/" + path.Substring (2);
return "/" + path.Substring (2);
}
return path;
}
public static string ResolvePhysicalPathFromAppAbsolute (string path)
{
if (path [0] != '~') return path;
if (path.Length == 1)
return HttpRuntime.AppDomainAppPath;
if (path [1] == '/' || path [1] == '\\') {
string appPath = HttpRuntime.AppDomainAppPath;
if (appPath.Length > 1)
return appPath + "/" + path.Substring (2);
return "/" + path.Substring (2);
}
return path;
}
}
}
|