//
using System.Web.SessionState;
+using System.Text;
namespace System.Web.Util {
internal class UrlUtils {
internal static string GetSessionId (string path)
{
+ if (path == null)
+ return null;
+
string appvpath = HttpRuntime.AppDomainAppVirtualPath;
- if (path.Length <= appvpath.Length)
+ int appvpathlen = appvpath.Length;
+
+ if (path.Length <= appvpathlen)
return null;
- path = path.Substring (appvpath.Length);
- if (path.Length == 0 || path [0] != '/')
+ path = path.Substring (appvpathlen);
+
+ int len = path.Length;
+ if (len == 0 || path [0] != '/') {
path = '/' + path;
+ len++;
+ }
- int len = path.Length;
if ((len < SessionId.IdLength + 3) || (path [1] != '(') ||
(path [SessionId.IdLength + 2] != ')'))
return null;
return path.Substring (2, SessionId.IdLength);
}
+ internal static bool HasSessionId (string path)
+ {
+ if (path == null || path.Length < 5)
+ return false;
+
+ return (StrUtils.StartsWith (path, "/(") && path.IndexOf (")/") > 2);
+ }
+
internal static string RemoveSessionId (string base_path, string file_path)
{
// Caller did a GetSessionId first
return Canonic (basePath + slash + relPath);
}
- if (basePath == null || basePath == "" || basePath [0] == '~')
+ if (basePath == null || basePath.Length == 0 || basePath [0] == '~')
basePath = HttpRuntime.AppDomainAppVirtualPath;
if (basePath.Length <= 1)
internal static string Canonic (string path)
{
+ bool isRooted = IsRooted(path);
+ bool endsWithSlash = path.EndsWith("/");
string [] parts = path.Split (path_sep);
int end = parts.Length;
for (int i = 0; i < end; i++) {
string current = parts [i];
+
+ if (current.Length == 0)
+ continue;
+
if (current == "." )
continue;
if (current == "..") {
- if (dest == 0) {
- if (i == 1) // see bug 52599
- continue;
-
- throw new HttpException ("Invalid path.");
- }
-
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 "/";
- return String.Join ("/", parts, 0, dest);
+ 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;
}
internal static string GetDirectory (string url)
int last = url.LastIndexOf ('/');
if (last > 0) {
+ if (last < url.Length)
+ last++;
#if NET_2_0
return RemoveDoubleSlashes (url.Substring (0, last));
#else
internal static string RemoveDoubleSlashes (string input)
{
// MS VirtualPathUtility removes duplicate '/'
- string str = input;
- string x;
- while ((x = str.Replace ("//", "/")) != str) {
- str = x;
+
+ 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 str;
+ return sb.ToString ();
}
#endif
return url.Substring (last+1);
}
- throw new Exception (String.Format ("GetFile: `{0}' does not contain a /", url));
+ throw new ArgumentException (String.Format ("GetFile: `{0}' does not contain a /", url));
}
internal static bool IsRooted (string path)
{
- if (path == null || path == "")
+ if (path == null || path.Length == 0)
return true;
char c = path [0];