10 using System.Configuration;
12 using System.Web.Security;
14 using System.Web.UI.WebControls;
15 using System.Web.UI.WebControls.WebParts;
16 using System.Web.UI.HtmlControls;
17 using System.Collections.Specialized;
20 using System.Text.RegularExpressions;
21 using System.Web.Hosting;
25 namespace ImageResizer.Util
55 public string BaseFile =
"";
59 public NameValueCollection QueryString =
new NameValueCollection();
75 public string this[
int index] {
get {
return QueryString[index]; } }
91 public string this[
string name] {
get {
return QueryString[name]; } set { QueryString[name] = value; } }
103 public yrl(
string path)
105 if (path == null)
throw new ArgumentNullException(
"path",
"Cannot create a yrl from a null string");
106 yrl temp = FromString(path);
107 if (temp == null)
throw new ArgumentException(
"The specified path (" + path +
") could not be parsed! It may be outside the bounds of the application, or it may contain an invalid character, such as a tilde in the middle of the path.",
"path");
108 this.BaseFile = temp.BaseFile;
109 this.QueryString = temp.QueryString;
114 #region yrl Constructor components
126 PathType pathtype = GetPathType(path);
127 if (pathtype ==
PathType.Root)
return yrl.Root;
131 yrl test = FromPhysicalString(path);
132 if (test != null)
return test;
136 return FromYrlString(path);
139 if (pathtype ==
PathType.ForwardslashPath)
141 return FromYrlString(TrimStartAppFolder(path).TrimStart(
new char[] {
'/' }));
143 if (pathtype ==
PathType.ServerForwardslashPath)
145 int tilde = path.IndexOf(
'~');
148 return FromYrlString(TrimStartAppFolder(TrimStartServer(path).TrimStart(
new char[] {
'~',
'/' })).TrimStart(
new char[] {
'/' }));
151 return FromYrlString(TrimStartAppFolder(TrimStartServer(path)).TrimStart(
new char[] {
'/' }));
153 if (pathtype ==
PathType.TildeForwardslashPath)
156 return FromYrlString(path.TrimStart(
new char[] {
'~',
'/' }));
158 if (pathtype == PathType.DriveletterColonBackslashPath)
160 return FromPhysicalString(path);
162 if (pathtype == PathType.BackslashPath || pathtype == PathType.PathBackslashPath)
164 return FromRelativePhysicalString(path);
175 if (path.Length == 0)
return yrl.Root;
177 int firstdelimiter = path.IndexOfAny(
new char[] {
'?',
'&' });
178 if (firstdelimiter < 0) firstdelimiter = path.Length;
179 if (path.IndexOfAny(
new char[] {
'/',
'\\',
'~',
':' }) == 0)
return null;
182 temp.BaseFile = path.Substring(0, firstdelimiter);
184 string querystring =
"";
185 if (firstdelimiter < path.Length) querystring = path.Substring(firstdelimiter, path.Length - firstdelimiter);
186 if (querystring.Length > 0)
188 string[] pairs = querystring.Split(
new char[] {
'?',
'&' }, StringSplitOptions.RemoveEmptyEntries);
189 foreach (
string s
in pairs)
191 string[] namevalue = s.Split(
new char[] {
'=' }, StringSplitOptions.RemoveEmptyEntries);
192 if (namevalue.Length == 2)
194 temp.QueryString[HttpUtility.UrlDecode(namevalue[0])] =
195 HttpUtility.UrlDecode(namevalue[1]);
202 temp.QueryString[HttpUtility.UrlDecode(namevalue[0])] =
"";
218 if (temp[0] !=
'\\') temp =
"\\" + temp;
219 temp = TrimStartAppFolder(temp);
220 string newpath = HostingEnvironment.MapPath(
"~") + temp;
221 return FromPhysicalString(newpath);
231 string localapproot = HostingEnvironment.MapPath(
"~").TrimEnd(
new char[] {
'/',
'\\',
'~' });
233 if (temp.StartsWith(localapproot, StringComparison.OrdinalIgnoreCase))
235 temp = temp.Remove(0, localapproot.Length);
242 temp = temp.TrimStart(
new char[] {
'/',
'\\',
'~' }).Replace(
'\\',
'/');
244 return FromYrlString(temp);
253 return HostingEnvironment.ApplicationVirtualPath;
265 string appfoldername = GetAppFolderName();
266 if (appfoldername.Length <= 1)
return path;
269 if (path.StartsWith(appfoldername, StringComparison.InvariantCultureIgnoreCase))
270 return path.Remove(0, appfoldername.Length);
273 string appfolderwithoutslash = appfoldername.TrimStart(
new char[] {
'/' });
274 if (path.StartsWith(appfolderwithoutslash, StringComparison.InvariantCultureIgnoreCase))
275 return path.Remove(0, appfolderwithoutslash.Length);
278 string appfolderwithbackslash = appfoldername.Replace(
'/',
'\\');
279 if (path.StartsWith(appfolderwithbackslash, StringComparison.InvariantCultureIgnoreCase))
280 return path.Remove(0, appfolderwithbackslash.Length);
283 string appfolderwithtilde =
'~' + appfoldername;
284 if (path.StartsWith(appfolderwithtilde, StringComparison.InvariantCultureIgnoreCase))
285 return path.Remove(0, appfolderwithtilde.Length);
290 public static string TrimStartServer(
string path)
292 int firstdoubleforwardslash = path.IndexOf(
"//");
293 if (firstdoubleforwardslash < 0)
return path;
294 if (path.Length < firstdoubleforwardslash + 3)
return path;
296 int nextforwardslash = path.IndexOf(
"/", firstdoubleforwardslash + 2);
297 if (nextforwardslash < 0)
302 return path.Remove(0, nextforwardslash);
306 #region Path Type Analysis
323 DriveletterColonBackslashPath,
331 TildeForwardslashPath,
339 PathForwardslashPath,
343 ServerForwardslashPath,
364 if (path == null)
return PathType.Invalid;
365 if (path.Trim(
new char[] {
'\\',
'/',
'~' }).Length == 0)
return PathType.Root;
366 int firstbackslash = path.IndexOf(
'\\');
367 int firstforwardslash = path.IndexOf(
'/');
368 int firsttilde = path.IndexOf(
'~');
369 int firstcolon = path.IndexOf(
':');
370 int firstdoubleforwardslash = path.IndexOf(
"//");
371 if (firstbackslash == 0 && path[1] ==
'\\')
373 return PathType.UNCPath;
375 if (firstbackslash == 0 && firstforwardslash < 0 && firstcolon < 0)
377 return PathType.BackslashPath;
379 if (firstcolon == 1 && firstbackslash == 2)
381 return PathType.DriveletterColonBackslashPath;
383 if (firstcolon < 0 && firstbackslash > 0 && firstforwardslash < 0)
385 return PathType.PathBackslashPath;
387 if (firsttilde == 0 && firstforwardslash == 1)
389 return PathType.TildeForwardslashPath;
391 if (firstforwardslash == 0 && firsttilde != 0 && firstdoubleforwardslash < 0)
393 return PathType.ForwardslashPath;
395 if (firstcolon > 0 && firstdoubleforwardslash > 0 && firsttilde != 0)
397 return PathType.ServerForwardslashPath;
399 if (firsttilde != 0 && firstforwardslash < 0 && firstbackslash < 0 && firstcolon < 0)
401 return PathType.File;
403 if (firstforwardslash > 0)
405 return PathType.PathForwardslashPath;
407 return PathType.Invalid;
411 #region Properties and methods
421 if (QueryString[
"id"] == null)
return -1;
423 if (!
int.TryParse(QueryString[
"id"], out temp))
431 QueryString[
"id"] = value.ToString();
441 if (QueryString[
"path"] == null)
return null;
442 return new yrl(QueryString[
"path"]);
446 QueryString[
"path"] = value.ToString();
456 if (QueryString[
"dir"] == null)
return null;
457 return new yrl(QueryString[
"dir"]);
461 if (value == null) QueryString.Remove(
"dir");
463 QueryString[
"dir"] = value.ToString();
469 public int QueryFindID
474 if (try1 > 0)
return try1;
476 yrl try2 = QueryPath;
479 if (try2.
ID > 0)
return try2.ID;
493 temp.BaseFile = string.Copy(this.BaseFile);
494 foreach (
string s
in QueryString.Keys)
496 string value = QueryString[s];
497 temp.QueryString.Add(string.Copy(s),
string.Copy(value));
508 StringBuilder path =
new StringBuilder();
509 path.Append(BaseFile);
510 if (QueryString.Count > 0)
513 foreach (
string key
in QueryString.Keys)
515 string value = QueryString[key];
517 path.Append(HttpUtility.UrlEncode(key));
519 path.Append(HttpUtility.UrlEncode(value));
522 if (path[path.Length - 1] ==
'&') path.Remove(path.Length - 1, 1);
524 return path.ToString();
535 if (BaseFile.Length == 0)
return HostingEnvironment.MapPath(
"~");
536 return HostingEnvironment.MapPath(
"~/" + HttpUtility.UrlDecode(BaseFile));
542 public string Virtual
546 if (BaseFile.Length == 0)
return "~";
547 return "~/" + this.BaseFile;
554 public string VirtualURL
558 if (this.URL.Length == 0)
return "~";
559 return "~/" + this.URL;
565 public string NavigateURL
569 StringBuilder path =
new StringBuilder();
570 path.Append(BaseFile);
571 if (QueryString.Count > 0)
574 foreach (
string key
in QueryString.Keys)
576 string value = QueryString[key];
578 path.Append(NavigateUrlEncode(key));
580 path.Append(NavigateUrlEncode(value));
583 if (path[path.Length - 1] ==
'&') path.Remove(path.Length - 1, 1);
585 return "~/" + path.ToString();
597 return text.Replace(
"/",
"%2f").Replace(
"?",
"%3f").Replace(
"&",
"&").Replace(
" ",
"%20");
607 return this.ToString();
615 public string URLEncoded
617 get {
return HttpUtility.UrlEncode(this.ToString()); }
624 public string URLHtmlEncoded
628 return HttpUtility.UrlPathEncode(this.ToString());
635 public string URLAnchorTarget
639 return yrl.GetAppFolderName().TrimEnd(
new char[] {
'/' }) +
"/" + HttpUtility.HtmlAttributeEncode(
this.URL);
646 public string RelativeURL
650 return this.ToString();
667 string filename = System.IO.Path.GetFileName(BaseFile);
669 if (filename.Length < 8)
return -1;
670 if (!
int.TryParse(filename.Substring(0, 8), out id))
688 string[] segments = BaseFile.Split(
new char[] {
'/' }, StringSplitOptions.None);
690 for (
int i = 0; i < segments.Length; i++)
692 if (segments[i].Length >= 8)
695 if (
int.TryParse(segments[i].Substring(0, 8), out tempid))
710 public bool FileExists
714 return System.IO.File.Exists(Local);
721 public bool DirExists
725 return System.IO.Directory.Exists(Local);
731 public DirectoryInfo DirInfo
736 return new DirectoryInfo(Local);
738 return new DirectoryInfo(System.IO.Path.GetDirectoryName(Local));
749 if (IsRoot)
return null;
750 if (IsAspx)
return new yrl(System.IO.Path.GetDirectoryName(Local) );
751 if (!DirExists)
return new yrl(System.IO.Path.GetDirectoryName(Local) );
754 DirectoryInfo d =
new DirectoryInfo(Local);
755 return new yrl(d.Parent.FullName);
766 if (IsRoot)
return this;
767 if (IsAspx)
return new yrl(System.IO.Path.GetDirectoryName(Local));
768 if (!DirExists)
return new yrl(System.IO.Path.GetDirectoryName(Local));
779 public static yrl Root
781 get {
return new yrl(); }
809 public static yrl Current
813 if (HttpContext.Current == null)
return null;
817 object o = HttpContext.Current.Items[
"UrlRewritingNet.UrlRewriter.CachedPathAfterRewrite"];
820 return yrl.FromString((string)o);
822 return CurrentBrowserURL;
828 public static yrl CurrentBrowserURL
832 if (HttpContext.Current == null)
return null;
833 if (HttpContext.Current.Request == null)
return null;
834 return FromUri(HttpContext.Current.Request.Url);
838 public static yrl FromUri(Uri url)
840 if (url == null)
return null;
841 return new yrl(url.AbsoluteUri);
847 public static yrl Referrer
851 if (HttpContext.Current == null)
return null;
852 if (HttpContext.Current.Request == null)
return null;
853 if (HttpContext.Current.Request.UrlReferrer == null)
return null;
854 if (HttpContext.Current.Request.UrlReferrer.OriginalString == null)
return null;
855 return new yrl(HttpContext.Current.Request.UrlReferrer.OriginalString);
867 if (obj == null)
return false;
868 return (obj.GetHashCode() == this.GetHashCode());
876 return URL.ToLower().GetHashCode();
898 return (BaseFile.Length == 0 && QueryString.Count == 0);
910 return (BaseFile.Length == 0);
920 if (Parent == null)
return true;
921 return (Parent.IsRoot);
932 if (IsAspx)
return System.IO.Path.GetFileName(Local);
933 if (DirExists)
return new DirectoryInfo(Local).Name;
934 else return System.IO.Path.GetFileName(Local);
937 #region File Extension stuff & associated .aspx/.cs file lookup. Also contains FilenameWithout.... properties
941 public string NameWithoutExtension
945 return System.IO.Path.GetFileNameWithoutExtension(Local);
952 public string PrettyTitle
956 return FilenameWithoutIdAndExtension.Replace(
'_',
' ').Trim();
962 public string FilenameWithoutIdAndExtension
967 string filename = this.NameWithoutExtension;
968 if (filename.Length >= 8)
970 if (
int.TryParse(filename.Substring(0, 8), out id))
974 return filename.Substring(8, filename.Length - 8);
985 public string Extension
989 return System.IO.Path.GetExtension(Local);
999 return BaseFile.EndsWith(
".aspx", StringComparison.InvariantCultureIgnoreCase);
1003 public bool HasExtension
1007 return (Extension.Length > 0);
1013 public bool IsCodeFile
1017 return BaseFile.EndsWith(
".cs", StringComparison.InvariantCultureIgnoreCase) |
1018 BaseFile.EndsWith(
".vb", StringComparison.InvariantCultureIgnoreCase);
1026 public yrl FindAssociatedMarkupFile
1032 yrl baseAspx =
new yrl(this.Local.ToLower().Replace(
".cs",
"").Replace(
".vb",
""));
1048 public yrl FindAssociatedCodeFile
1054 yrl codeCs =
new yrl(this.Local +
".cs");
1055 yrl codeVb =
new yrl(this.Local +
".vb");
1074 BaseFile = BaseFile.Remove(BaseFile.Length - this.Extension.Length, this.Extension.Length);
1075 BaseFile +=
"." + newextension.TrimStart(
new char[] {
'.' });
1085 yrl newfilename = this.Copy();
1097 string minusext = newfilename.Parent.Local +
1098 System.IO.Path.DirectorySeparatorChar +
1099 newfilename.NameWithoutExtension;
1101 for (
int i = 1; i < 100; i++)
1103 if (!System.IO.File.Exists(minusext +
" (" + i.ToString() +
")" + newfilename.Extension))
1105 newfilename =
new yrl(minusext +
" (" + i.ToString() +
")" + newfilename.Extension);
1112 public static explicit operator string(
yrl url)
1114 return url.ToString();
1116 public static explicit operator yrl(
string s)
1118 return yrl.FromString(s);
1129 return new yrl(folder.
Local + System.IO.Path.DirectorySeparatorChar + filenameOrSubdir.
BaseFile.Replace(
'/',
'\\'));
1138 return protocolHostnameFolder + this.URL;
1147 if (path == null)
return true;
1148 if (path.
IsEmpty)
return true;
override int GetHashCode()
Returns a unique hash code derived from the URL property of this instance
static string TrimStartAppFolder(string path)
Removes the application folder from the specified path. Leaves the leading forwardslash. Assuming the Application path is /yf, this function will transform /yf/home.aspx to /home.aspx and /yf/css/john.css to /css/john.css If the application is located in '/', nothing will be done to the path. Transforms yf/home.aspx to /home.aspx, yf\home.aspx to .aspx, .aspx to .aspx Won't work if the app folder has a child directory named the same!
static yrl FromRelativePhysicalString(string path)
static yrl Combine(yrl folder, yrl filenameOrSubdir)
Joins two yrls. Querystrings on either are discarded.
static bool IsNullOrEmpty(yrl path)
Returns true if the yrl is null or empty (site root)
static string NavigateUrlEncode(string text)
yrl()
Creates a default instance of yrl which points to the application root directory. ...
string BaseFile
The base file, usually a .aspx page. Ex. 'home.aspx' or 'admin/new.aspx'. Can also be a base director...
Enapsulates a mutable (changable) site-relative URL. Note that "" is equivalent to the application ...
static PathType GetPathType(string path)
Returns the type of path
static string GetAppFolderName()
either '/' or '/folder' like '/yf' or sometimes '/folder/folder'
static yrl FromPhysicalString(string path)
Creates a yrl Instance from the specified physical path. Throws an exception if the path is outside t...
int ID
Returns the ID if a leading 8-digit ID is found in the base file. Returns -1 otherwise ...
static yrl FromString(string path)
Returns a yrl object from a path. Returns null if the path cannot be parsed. (Out of application boun...
void ChangeExtension(string newextension)
Deletes the old extension and replaces it with the specified extension. A leading '...
yrl GetNextAvailableDerivitive()
Returns the next unused filename similar to the current one,by incrementing (i)
string Local
Returns the physical filesystem path for this yrl
static yrl FromYrlString(string path)
Creates an instance from a yrl-syntax string (virtual, but without ~/). Use FromString if you're not ...
bool IsEmpty
An empty yrl signifies the application root. This verifies both the path and the querystring are empt...
string CreateAbsoluteUrl(string protocolHostnameFolder)
Returns an absolute path to the current yrl using the specified base path
override bool Equals(object obj)
Compares the hash codes of the two instances.
bool FileExists
Returns true if BaseFile exists as a local file.
override string ToString()
Returns a site-root-relative path along with query paramaters
yrl Copy()
Creates a deep copy of the yrl
PathType
Path syntaxes, determined by patterns.