Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / xsp / System / Web / VirtualPath.cs / 4 / VirtualPath.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web { using System.Globalization; using System.Collections; using System.IO; using System.Web.Util; using System.Web.Hosting; using System.Web.Caching; using System.Security.Permissions; using Microsoft.Win32; [Serializable] internal sealed class VirtualPath : IComparable { private static char[] s_illegalVirtualPathChars = new char[] { ':', '?', '*', '\0' }; private static char[] s_illegalVirtualPathChars_VerCompat = new char[] { '\0' }; private static bool s_VerCompatRegLookedUp = false; private static object s_VerCompatLock = new object(); private string _appRelativeVirtualPath; private string _virtualPath; // const masks into the BitVector32 private const int isWithinAppRootComputed = 0x00000001; private const int isWithinAppRoot = 0x00000002; private const int appRelativeAttempted = 0x00000004; #pragma warning disable 0649 private SimpleBitVector32 flags; #pragma warning restore 0649 internal static VirtualPath RootVirtualPath = VirtualPath.Create("/"); private VirtualPath() { } // This is called to set the appropriate virtual path field when we already know // that the path is generally well formed. private VirtualPath(string virtualPath) { if (UrlPath.IsAppRelativePath(virtualPath)) { _appRelativeVirtualPath = virtualPath; } else { _virtualPath = virtualPath; } } int IComparable.CompareTo(object obj) { VirtualPath virtualPath = obj as VirtualPath; // Make sure we're compared to another VirtualPath if (virtualPath == null) throw new ArgumentException(); // Check if it's the same object if (virtualPath == this) return 0; return StringComparer.InvariantCultureIgnoreCase.Compare( this.VirtualPathString, virtualPath.VirtualPathString); } public string VirtualPathString { get { if (_virtualPath == null) { Debug.Assert(_appRelativeVirtualPath != null); // This is not valid if we don't know the app path if (HttpRuntime.AppDomainAppVirtualPathObject == null) { throw new HttpException(SR.GetString(SR.VirtualPath_CantMakeAppAbsolute, _appRelativeVirtualPath)); } if (_appRelativeVirtualPath.Length == 1) { _virtualPath = HttpRuntime.AppDomainAppVirtualPath; } else { _virtualPath = HttpRuntime.AppDomainAppVirtualPathString + _appRelativeVirtualPath.Substring(2); } } return _virtualPath; } } internal string VirtualPathStringNoTrailingSlash { get { return UrlPath.RemoveSlashFromPathIfNeeded(VirtualPathString); } } // Return the virtual path string if we have it, otherwise null internal string VirtualPathStringIfAvailable { get { return _virtualPath; } } internal string AppRelativeVirtualPathStringOrNull { get { if (_appRelativeVirtualPath == null) { Debug.Assert(_virtualPath != null); // If we already tried to get it and couldn't, return null if (flags[appRelativeAttempted]) return null; // This is not valid if we don't know the app path if (HttpRuntime.AppDomainAppVirtualPathObject == null) { throw new HttpException(SR.GetString(SR.VirtualPath_CantMakeAppRelative, _virtualPath)); } _appRelativeVirtualPath = UrlPath.MakeVirtualPathAppRelativeOrNull(_virtualPath); // Remember that we've attempted it flags[appRelativeAttempted] = true; // It could be null if it's not under the app root if (_appRelativeVirtualPath == null) return null; ValidateState(); } return _appRelativeVirtualPath; } } // Return the app relative path if possible. Otherwise, settle for the absolute. public string AppRelativeVirtualPathString { get { string appRelativeVirtualPath = AppRelativeVirtualPathStringOrNull; return (appRelativeVirtualPath != null) ? appRelativeVirtualPath : _virtualPath; } } // Return the app relative virtual path string if we have it, otherwise null internal string AppRelativeVirtualPathStringIfAvailable { get { return _appRelativeVirtualPath; } } // Return the virtual string that's either app relative or not, depending on which // one we already have internally. If we have both, we return absolute internal string VirtualPathStringWhicheverAvailable { get { return _virtualPath != null ? _virtualPath : _appRelativeVirtualPath; } } public string Extension { get { return UrlPath.GetExtension(VirtualPathString); } } public string FileName { get { return UrlPath.GetFileName(VirtualPathStringNoTrailingSlash); } } // If it's relative, combine it with the app root public VirtualPath CombineWithAppRoot() { return HttpRuntime.AppDomainAppVirtualPathObject.Combine(this); } public VirtualPath Combine(VirtualPath relativePath) { if (relativePath == null) throw new ArgumentNullException("relativePath"); // If it's not relative, return it unchanged if (!relativePath.IsRelative) return relativePath; // The base of the combine should never be relative FailIfRelativePath(); // Get either _appRelativeVirtualPath or _virtualPath string virtualPath = VirtualPathStringWhicheverAvailable; // Combine it with the relative virtualPath = UrlPath.Combine(virtualPath, relativePath.VirtualPathString); // Set the appropriate virtual path in the new object return new VirtualPath(virtualPath); } // This simple version of combine should only be used when the relative // path is known to be relative. It's more efficient, but doesn't do any // sanity checks. internal VirtualPath SimpleCombine(string relativePath) { return SimpleCombine(relativePath, false /*addTrailingSlash*/); } internal VirtualPath SimpleCombineWithDir(string directoryName) { return SimpleCombine(directoryName, true /*addTrailingSlash*/); } private VirtualPath SimpleCombine(string filename, bool addTrailingSlash) { // The left part should always be a directory Debug.Assert(HasTrailingSlash); // The right part should not start or end with a slash Debug.Assert(filename[0] != '/' && !UrlPath.HasTrailingSlash(filename)); // Use either _appRelativeVirtualPath or _virtualPath string virtualPath = VirtualPathStringWhicheverAvailable + filename; if (addTrailingSlash) virtualPath += "/"; // Set the appropriate virtual path in the new object VirtualPath combinedVirtualPath = new VirtualPath(virtualPath); // Copy some flags over to avoid having to recalculate them combinedVirtualPath.CopyFlagsFrom(this, isWithinAppRootComputed | isWithinAppRoot | appRelativeAttempted); combinedVirtualPath.ValidateState(); return combinedVirtualPath; } public VirtualPath MakeRelative(VirtualPath toVirtualPath) { VirtualPath resultVirtualPath = new VirtualPath(); // Neither path can be relative FailIfRelativePath(); toVirtualPath.FailIfRelativePath(); // Set it directly since we know the slashes are already ok resultVirtualPath._virtualPath = UrlPath.MakeRelative(this.VirtualPathString, toVirtualPath.VirtualPathString); resultVirtualPath.ValidateState(); return resultVirtualPath; } public string MapPath() { return HostingEnvironment.MapPath(this); } internal string MapPathInternal() { return HostingEnvironment.MapPathInternal(this); } internal string MapPathInternal(bool permitNull) { return HostingEnvironment.MapPathInternal(this, permitNull); } internal string MapPathInternal(VirtualPath baseVirtualDir, bool allowCrossAppMapping) { return HostingEnvironment.MapPathInternal(this, baseVirtualDir, allowCrossAppMapping); } ///////////// VirtualPathProvider wrapper methods ///////////// public string GetFileHash(IEnumerable virtualPathDependencies) { return HostingEnvironment.VirtualPathProvider.GetFileHash(this, virtualPathDependencies); } public CacheDependency GetCacheDependency(IEnumerable virtualPathDependencies, DateTime utcStart) { return HostingEnvironment.VirtualPathProvider.GetCacheDependency( this, virtualPathDependencies, utcStart); } public bool FileExists() { return HostingEnvironment.VirtualPathProvider.FileExists(this); } public bool DirectoryExists() { return HostingEnvironment.VirtualPathProvider.DirectoryExists(this); } public VirtualFile GetFile() { return HostingEnvironment.VirtualPathProvider.GetFile(this); } public VirtualDirectory GetDirectory() { Debug.Assert(this.HasTrailingSlash); return HostingEnvironment.VirtualPathProvider.GetDirectory(this); } public string GetCacheKey() { return HostingEnvironment.VirtualPathProvider.GetCacheKey(this); } public Stream OpenFile() { return VirtualPathProvider.OpenFile(this); } ///////////// end of VirtualPathProvider methods ///////////// internal bool HasTrailingSlash { get { if (_virtualPath != null) { return UrlPath.HasTrailingSlash(_virtualPath); } else { return UrlPath.HasTrailingSlash(_appRelativeVirtualPath); } } } public bool IsWithinAppRoot { get { // If we don't already know it, compute it and cache it if (!flags[isWithinAppRootComputed]) { if (HttpRuntime.AppDomainIdInternal == null) { Debug.Assert(false); return true; // app domain not initialized } if (flags[appRelativeAttempted]) { // If we already tried to get the app relative path, we can tell whether // it's in the app root by checking whether it's not null flags[isWithinAppRoot] = (_appRelativeVirtualPath != null); } else { flags[isWithinAppRoot] = UrlPath.IsEqualOrSubpath(HttpRuntime.AppDomainAppVirtualPathString, VirtualPathString); } flags[isWithinAppRootComputed] = true; } return flags[isWithinAppRoot]; } } internal void FailIfNotWithinAppRoot() { if (!this.IsWithinAppRoot) { throw new ArgumentException(SR.GetString(SR.Cross_app_not_allowed, this.VirtualPathString)); } } internal void FailIfRelativePath() { if (this.IsRelative) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowRelativePath, _virtualPath)); } } public bool IsRelative { get { // Note that we don't need to check for "~/", since _virtualPath never contains // app relative paths (_appRelativeVirtualPath does) return _virtualPath != null && _virtualPath[0] != '/'; } } public bool IsRoot { get { return _virtualPath == "/"; } } public VirtualPath Parent { get { // Getting the parent doesn't make much sense on relative paths FailIfRelativePath(); // "/" doesn't have a parent, so return null if (IsRoot) return null; // Get either _appRelativeVirtualPath or _virtualPath string virtualPath = VirtualPathStringWhicheverAvailable; // Get rid of the ending slash, otherwise we end up with Parent("/app/sub/") == "/app/sub/" virtualPath = UrlPath.RemoveSlashFromPathIfNeeded(virtualPath); // But if it's just "~", use the absolute path instead to get the parent if (virtualPath == "~") virtualPath = VirtualPathStringNoTrailingSlash; int index = virtualPath.LastIndexOf('/'); Debug.Assert(index >= 0); // e.g. the parent of "/blah" is "/" if (index == 0) return RootVirtualPath; // // Get the parent virtualPath = virtualPath.Substring(0, index + 1); // Set the appropriate virtual path in the new object return new VirtualPath(virtualPath); } } internal static VirtualPath Combine(VirtualPath v1, VirtualPath v2) { // If the first is null, use the app root instead if (v1 == null) { v1 = HttpRuntime.AppDomainAppVirtualPathObject; } // If the first is still null, return the second, unless it's relative if (v1 == null) { v2.FailIfRelativePath(); return v2; } return v1.Combine(v2); } public static bool operator == (VirtualPath v1, VirtualPath v2) { return VirtualPath.Equals(v1, v2); } public static bool operator != (VirtualPath v1, VirtualPath v2) { return !VirtualPath.Equals(v1, v2); } public static bool Equals(VirtualPath v1, VirtualPath v2) { // Check if it's the same object if ((Object)v1 == (Object)v2) { return true; } if ((Object)v1 == null || (Object)v2 == null) { return false; } return EqualsHelper(v1, v2); } public override bool Equals(object value) { if (value == null) return false; VirtualPath virtualPath = value as VirtualPath; if ((object)virtualPath == null) { Debug.Assert(false); return false; } return EqualsHelper(virtualPath, this); } private static bool EqualsHelper(VirtualPath v1, VirtualPath v2) { return StringComparer.InvariantCultureIgnoreCase.Compare( v1.VirtualPathString, v2.VirtualPathString) == 0; } public override int GetHashCode() { return StringComparer.InvariantCultureIgnoreCase.GetHashCode(VirtualPathString); } public override String ToString() { // If we only have the app relative path, and we don't know the app root, return // the app relative path instead of accessing VirtualPathString, which would throw if (_virtualPath == null && HttpRuntime.AppDomainAppVirtualPathObject == null) { Debug.Assert(_appRelativeVirtualPath != null); return _appRelativeVirtualPath; } return VirtualPathString; } // Copy a set of flags from another VirtualPath object private void CopyFlagsFrom(VirtualPath virtualPath, int mask) { flags.IntegerValue |= virtualPath.flags.IntegerValue & mask; } internal static string GetVirtualPathString(VirtualPath virtualPath) { return virtualPath == null ? null : virtualPath.VirtualPathString; } internal static string GetVirtualPathStringNoTrailingSlash(VirtualPath virtualPath) { return virtualPath == null ? null : virtualPath.VirtualPathStringNoTrailingSlash; } internal static string GetAppRelativeVirtualPathString(VirtualPath virtualPath) { return virtualPath == null ? null : virtualPath.AppRelativeVirtualPathString; } // Same as GetAppRelativeVirtualPathString, but returns "" instead of null internal static string GetAppRelativeVirtualPathStringOrEmpty(VirtualPath virtualPath) { return virtualPath == null ? String.Empty : virtualPath.AppRelativeVirtualPathString; } // Default Create method public static VirtualPath Create(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAllPath); } public static VirtualPath CreateTrailingSlash(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAllPath | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath CreateAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAllPath | VirtualPathOptions.AllowNull); } public static VirtualPath CreateAbsolute(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath); } public static VirtualPath CreateNonRelative(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath); } public static VirtualPath CreateAbsoluteTrailingSlash(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath CreateNonRelativeTrailingSlash(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath CreateAbsoluteAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowNull); } public static VirtualPath CreateNonRelativeAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath | VirtualPathOptions.AllowNull); } public static VirtualPath CreateNonRelativeTrailingSlashAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath | VirtualPathOptions.AllowNull | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath Create(string virtualPath, VirtualPathOptions options) { // Trim it first, so that blank strings (e.g. " ") get treated as empty if (virtualPath != null) virtualPath = virtualPath.Trim(); // If it's empty, check whether we allow it if (String.IsNullOrEmpty(virtualPath)) { if ((options & VirtualPathOptions.AllowNull) != 0) return null; throw new ArgumentNullException("virtualPath"); } // Check for invalid characters if (ContainsIllegalVirtualPathChars(virtualPath)) { throw new HttpException(SR.GetString(SR.Invalid_vpath, virtualPath)); } // Flip ----lashes, and remove duplicate slashes string fixedUpVirtualPath = UrlPath.FixVirtualPathSlashes(virtualPath); // If we're supposed to fail on malformed path, check whether FixVirtualPathSlashes // had to do anything. if ((options & VirtualPathOptions.FailIfMalformed) != 0 && !Object.ReferenceEquals(virtualPath, fixedUpVirtualPath)) { throw new HttpException(SR.GetString(SR.Invalid_vpath, virtualPath)); } virtualPath = fixedUpVirtualPath; // Make sure it ends with a trailing slash if requested if ((options & VirtualPathOptions.EnsureTrailingSlash) != 0) virtualPath = UrlPath.AppendSlashToPathIfNeeded(virtualPath); VirtualPath virtualPathObject = new VirtualPath(); if (UrlPath.IsAppRelativePath(virtualPath)) { virtualPath = UrlPath.ReduceVirtualPath(virtualPath); if (virtualPath[0] == UrlPath.appRelativeCharacter) { if ((options & VirtualPathOptions.AllowAppRelativePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowAppRelativePath, virtualPath)); } virtualPathObject._appRelativeVirtualPath = virtualPath; } else { // It's possible for the path to become absolute after calling Reduce, // even though it started with "~/". e.g. if the app is "/app" and the path is // "~/../hello.aspx", it becomes "/hello.aspx", which is absolute if ((options & VirtualPathOptions.AllowAbsolutePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowAbsolutePath, virtualPath)); } virtualPathObject._virtualPath = virtualPath; } } else { if (virtualPath[0] != '/') { if ((options & VirtualPathOptions.AllowRelativePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowRelativePath, virtualPath)); } // Don't Reduce relative paths, since the Reduce method is broken (e.g. "../foo.aspx" --> "/foo.aspx!") // virtualPathObject._virtualPath = virtualPath; } else { if ((options & VirtualPathOptions.AllowAbsolutePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowAbsolutePath, virtualPath)); } virtualPathObject._virtualPath = UrlPath.ReduceVirtualPath(virtualPath); } } virtualPathObject.ValidateState(); return virtualPathObject; } // Debug only method to check that the object is in a consistent state [System.Diagnostics.Conditional("DBG")] private void ValidateState() { #if DBG Debug.Assert(_virtualPath != null || _appRelativeVirtualPath != null); if (_virtualPath != null) { CheckValidVirtualPath(_virtualPath); } if (_appRelativeVirtualPath != null) { Debug.Assert(UrlPath.IsAppRelativePath(_appRelativeVirtualPath)); CheckValidVirtualPath(_appRelativeVirtualPath); } #endif } #if DBG private static void CheckValidVirtualPath(string virtualPath) { Debug.Assert(!ContainsIllegalVirtualPathChars(virtualPath)); Debug.Assert(virtualPath.IndexOf('\\') < 0); } #endif private static bool ContainsIllegalVirtualPathChars(string virtualPath) { if (!s_VerCompatRegLookedUp) LookUpRegForVerCompat(); return virtualPath.IndexOfAny(s_illegalVirtualPathChars) >= 0; } [RegistryPermission(SecurityAction.Assert, Unrestricted=true)] private static void LookUpRegForVerCompat() { lock(s_VerCompatLock) { if (s_VerCompatRegLookedUp) return; try { object o = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET", "VerificationCompatibility", 0); if (o != null && (o is int || o is uint) && ((int)o) == 1) s_illegalVirtualPathChars = s_illegalVirtualPathChars_VerCompat; s_VerCompatRegLookedUp = true; } catch { // ignore exceptions } } } } [Flags] internal enum VirtualPathOptions { AllowNull = 0x00000001, EnsureTrailingSlash = 0x00000002, AllowAbsolutePath = 0x00000004, AllowAppRelativePath = 0x00000008, AllowRelativePath = 0x00000010, FailIfMalformed = 0x00000020, AllowAllPath = AllowAbsolutePath | AllowAppRelativePath | AllowRelativePath, } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web { using System.Globalization; using System.Collections; using System.IO; using System.Web.Util; using System.Web.Hosting; using System.Web.Caching; using System.Security.Permissions; using Microsoft.Win32; [Serializable] internal sealed class VirtualPath : IComparable { private static char[] s_illegalVirtualPathChars = new char[] { ':', '?', '*', '\0' }; private static char[] s_illegalVirtualPathChars_VerCompat = new char[] { '\0' }; private static bool s_VerCompatRegLookedUp = false; private static object s_VerCompatLock = new object(); private string _appRelativeVirtualPath; private string _virtualPath; // const masks into the BitVector32 private const int isWithinAppRootComputed = 0x00000001; private const int isWithinAppRoot = 0x00000002; private const int appRelativeAttempted = 0x00000004; #pragma warning disable 0649 private SimpleBitVector32 flags; #pragma warning restore 0649 internal static VirtualPath RootVirtualPath = VirtualPath.Create("/"); private VirtualPath() { } // This is called to set the appropriate virtual path field when we already know // that the path is generally well formed. private VirtualPath(string virtualPath) { if (UrlPath.IsAppRelativePath(virtualPath)) { _appRelativeVirtualPath = virtualPath; } else { _virtualPath = virtualPath; } } int IComparable.CompareTo(object obj) { VirtualPath virtualPath = obj as VirtualPath; // Make sure we're compared to another VirtualPath if (virtualPath == null) throw new ArgumentException(); // Check if it's the same object if (virtualPath == this) return 0; return StringComparer.InvariantCultureIgnoreCase.Compare( this.VirtualPathString, virtualPath.VirtualPathString); } public string VirtualPathString { get { if (_virtualPath == null) { Debug.Assert(_appRelativeVirtualPath != null); // This is not valid if we don't know the app path if (HttpRuntime.AppDomainAppVirtualPathObject == null) { throw new HttpException(SR.GetString(SR.VirtualPath_CantMakeAppAbsolute, _appRelativeVirtualPath)); } if (_appRelativeVirtualPath.Length == 1) { _virtualPath = HttpRuntime.AppDomainAppVirtualPath; } else { _virtualPath = HttpRuntime.AppDomainAppVirtualPathString + _appRelativeVirtualPath.Substring(2); } } return _virtualPath; } } internal string VirtualPathStringNoTrailingSlash { get { return UrlPath.RemoveSlashFromPathIfNeeded(VirtualPathString); } } // Return the virtual path string if we have it, otherwise null internal string VirtualPathStringIfAvailable { get { return _virtualPath; } } internal string AppRelativeVirtualPathStringOrNull { get { if (_appRelativeVirtualPath == null) { Debug.Assert(_virtualPath != null); // If we already tried to get it and couldn't, return null if (flags[appRelativeAttempted]) return null; // This is not valid if we don't know the app path if (HttpRuntime.AppDomainAppVirtualPathObject == null) { throw new HttpException(SR.GetString(SR.VirtualPath_CantMakeAppRelative, _virtualPath)); } _appRelativeVirtualPath = UrlPath.MakeVirtualPathAppRelativeOrNull(_virtualPath); // Remember that we've attempted it flags[appRelativeAttempted] = true; // It could be null if it's not under the app root if (_appRelativeVirtualPath == null) return null; ValidateState(); } return _appRelativeVirtualPath; } } // Return the app relative path if possible. Otherwise, settle for the absolute. public string AppRelativeVirtualPathString { get { string appRelativeVirtualPath = AppRelativeVirtualPathStringOrNull; return (appRelativeVirtualPath != null) ? appRelativeVirtualPath : _virtualPath; } } // Return the app relative virtual path string if we have it, otherwise null internal string AppRelativeVirtualPathStringIfAvailable { get { return _appRelativeVirtualPath; } } // Return the virtual string that's either app relative or not, depending on which // one we already have internally. If we have both, we return absolute internal string VirtualPathStringWhicheverAvailable { get { return _virtualPath != null ? _virtualPath : _appRelativeVirtualPath; } } public string Extension { get { return UrlPath.GetExtension(VirtualPathString); } } public string FileName { get { return UrlPath.GetFileName(VirtualPathStringNoTrailingSlash); } } // If it's relative, combine it with the app root public VirtualPath CombineWithAppRoot() { return HttpRuntime.AppDomainAppVirtualPathObject.Combine(this); } public VirtualPath Combine(VirtualPath relativePath) { if (relativePath == null) throw new ArgumentNullException("relativePath"); // If it's not relative, return it unchanged if (!relativePath.IsRelative) return relativePath; // The base of the combine should never be relative FailIfRelativePath(); // Get either _appRelativeVirtualPath or _virtualPath string virtualPath = VirtualPathStringWhicheverAvailable; // Combine it with the relative virtualPath = UrlPath.Combine(virtualPath, relativePath.VirtualPathString); // Set the appropriate virtual path in the new object return new VirtualPath(virtualPath); } // This simple version of combine should only be used when the relative // path is known to be relative. It's more efficient, but doesn't do any // sanity checks. internal VirtualPath SimpleCombine(string relativePath) { return SimpleCombine(relativePath, false /*addTrailingSlash*/); } internal VirtualPath SimpleCombineWithDir(string directoryName) { return SimpleCombine(directoryName, true /*addTrailingSlash*/); } private VirtualPath SimpleCombine(string filename, bool addTrailingSlash) { // The left part should always be a directory Debug.Assert(HasTrailingSlash); // The right part should not start or end with a slash Debug.Assert(filename[0] != '/' && !UrlPath.HasTrailingSlash(filename)); // Use either _appRelativeVirtualPath or _virtualPath string virtualPath = VirtualPathStringWhicheverAvailable + filename; if (addTrailingSlash) virtualPath += "/"; // Set the appropriate virtual path in the new object VirtualPath combinedVirtualPath = new VirtualPath(virtualPath); // Copy some flags over to avoid having to recalculate them combinedVirtualPath.CopyFlagsFrom(this, isWithinAppRootComputed | isWithinAppRoot | appRelativeAttempted); combinedVirtualPath.ValidateState(); return combinedVirtualPath; } public VirtualPath MakeRelative(VirtualPath toVirtualPath) { VirtualPath resultVirtualPath = new VirtualPath(); // Neither path can be relative FailIfRelativePath(); toVirtualPath.FailIfRelativePath(); // Set it directly since we know the slashes are already ok resultVirtualPath._virtualPath = UrlPath.MakeRelative(this.VirtualPathString, toVirtualPath.VirtualPathString); resultVirtualPath.ValidateState(); return resultVirtualPath; } public string MapPath() { return HostingEnvironment.MapPath(this); } internal string MapPathInternal() { return HostingEnvironment.MapPathInternal(this); } internal string MapPathInternal(bool permitNull) { return HostingEnvironment.MapPathInternal(this, permitNull); } internal string MapPathInternal(VirtualPath baseVirtualDir, bool allowCrossAppMapping) { return HostingEnvironment.MapPathInternal(this, baseVirtualDir, allowCrossAppMapping); } ///////////// VirtualPathProvider wrapper methods ///////////// public string GetFileHash(IEnumerable virtualPathDependencies) { return HostingEnvironment.VirtualPathProvider.GetFileHash(this, virtualPathDependencies); } public CacheDependency GetCacheDependency(IEnumerable virtualPathDependencies, DateTime utcStart) { return HostingEnvironment.VirtualPathProvider.GetCacheDependency( this, virtualPathDependencies, utcStart); } public bool FileExists() { return HostingEnvironment.VirtualPathProvider.FileExists(this); } public bool DirectoryExists() { return HostingEnvironment.VirtualPathProvider.DirectoryExists(this); } public VirtualFile GetFile() { return HostingEnvironment.VirtualPathProvider.GetFile(this); } public VirtualDirectory GetDirectory() { Debug.Assert(this.HasTrailingSlash); return HostingEnvironment.VirtualPathProvider.GetDirectory(this); } public string GetCacheKey() { return HostingEnvironment.VirtualPathProvider.GetCacheKey(this); } public Stream OpenFile() { return VirtualPathProvider.OpenFile(this); } ///////////// end of VirtualPathProvider methods ///////////// internal bool HasTrailingSlash { get { if (_virtualPath != null) { return UrlPath.HasTrailingSlash(_virtualPath); } else { return UrlPath.HasTrailingSlash(_appRelativeVirtualPath); } } } public bool IsWithinAppRoot { get { // If we don't already know it, compute it and cache it if (!flags[isWithinAppRootComputed]) { if (HttpRuntime.AppDomainIdInternal == null) { Debug.Assert(false); return true; // app domain not initialized } if (flags[appRelativeAttempted]) { // If we already tried to get the app relative path, we can tell whether // it's in the app root by checking whether it's not null flags[isWithinAppRoot] = (_appRelativeVirtualPath != null); } else { flags[isWithinAppRoot] = UrlPath.IsEqualOrSubpath(HttpRuntime.AppDomainAppVirtualPathString, VirtualPathString); } flags[isWithinAppRootComputed] = true; } return flags[isWithinAppRoot]; } } internal void FailIfNotWithinAppRoot() { if (!this.IsWithinAppRoot) { throw new ArgumentException(SR.GetString(SR.Cross_app_not_allowed, this.VirtualPathString)); } } internal void FailIfRelativePath() { if (this.IsRelative) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowRelativePath, _virtualPath)); } } public bool IsRelative { get { // Note that we don't need to check for "~/", since _virtualPath never contains // app relative paths (_appRelativeVirtualPath does) return _virtualPath != null && _virtualPath[0] != '/'; } } public bool IsRoot { get { return _virtualPath == "/"; } } public VirtualPath Parent { get { // Getting the parent doesn't make much sense on relative paths FailIfRelativePath(); // "/" doesn't have a parent, so return null if (IsRoot) return null; // Get either _appRelativeVirtualPath or _virtualPath string virtualPath = VirtualPathStringWhicheverAvailable; // Get rid of the ending slash, otherwise we end up with Parent("/app/sub/") == "/app/sub/" virtualPath = UrlPath.RemoveSlashFromPathIfNeeded(virtualPath); // But if it's just "~", use the absolute path instead to get the parent if (virtualPath == "~") virtualPath = VirtualPathStringNoTrailingSlash; int index = virtualPath.LastIndexOf('/'); Debug.Assert(index >= 0); // e.g. the parent of "/blah" is "/" if (index == 0) return RootVirtualPath; // // Get the parent virtualPath = virtualPath.Substring(0, index + 1); // Set the appropriate virtual path in the new object return new VirtualPath(virtualPath); } } internal static VirtualPath Combine(VirtualPath v1, VirtualPath v2) { // If the first is null, use the app root instead if (v1 == null) { v1 = HttpRuntime.AppDomainAppVirtualPathObject; } // If the first is still null, return the second, unless it's relative if (v1 == null) { v2.FailIfRelativePath(); return v2; } return v1.Combine(v2); } public static bool operator == (VirtualPath v1, VirtualPath v2) { return VirtualPath.Equals(v1, v2); } public static bool operator != (VirtualPath v1, VirtualPath v2) { return !VirtualPath.Equals(v1, v2); } public static bool Equals(VirtualPath v1, VirtualPath v2) { // Check if it's the same object if ((Object)v1 == (Object)v2) { return true; } if ((Object)v1 == null || (Object)v2 == null) { return false; } return EqualsHelper(v1, v2); } public override bool Equals(object value) { if (value == null) return false; VirtualPath virtualPath = value as VirtualPath; if ((object)virtualPath == null) { Debug.Assert(false); return false; } return EqualsHelper(virtualPath, this); } private static bool EqualsHelper(VirtualPath v1, VirtualPath v2) { return StringComparer.InvariantCultureIgnoreCase.Compare( v1.VirtualPathString, v2.VirtualPathString) == 0; } public override int GetHashCode() { return StringComparer.InvariantCultureIgnoreCase.GetHashCode(VirtualPathString); } public override String ToString() { // If we only have the app relative path, and we don't know the app root, return // the app relative path instead of accessing VirtualPathString, which would throw if (_virtualPath == null && HttpRuntime.AppDomainAppVirtualPathObject == null) { Debug.Assert(_appRelativeVirtualPath != null); return _appRelativeVirtualPath; } return VirtualPathString; } // Copy a set of flags from another VirtualPath object private void CopyFlagsFrom(VirtualPath virtualPath, int mask) { flags.IntegerValue |= virtualPath.flags.IntegerValue & mask; } internal static string GetVirtualPathString(VirtualPath virtualPath) { return virtualPath == null ? null : virtualPath.VirtualPathString; } internal static string GetVirtualPathStringNoTrailingSlash(VirtualPath virtualPath) { return virtualPath == null ? null : virtualPath.VirtualPathStringNoTrailingSlash; } internal static string GetAppRelativeVirtualPathString(VirtualPath virtualPath) { return virtualPath == null ? null : virtualPath.AppRelativeVirtualPathString; } // Same as GetAppRelativeVirtualPathString, but returns "" instead of null internal static string GetAppRelativeVirtualPathStringOrEmpty(VirtualPath virtualPath) { return virtualPath == null ? String.Empty : virtualPath.AppRelativeVirtualPathString; } // Default Create method public static VirtualPath Create(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAllPath); } public static VirtualPath CreateTrailingSlash(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAllPath | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath CreateAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAllPath | VirtualPathOptions.AllowNull); } public static VirtualPath CreateAbsolute(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath); } public static VirtualPath CreateNonRelative(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath); } public static VirtualPath CreateAbsoluteTrailingSlash(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath CreateNonRelativeTrailingSlash(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath CreateAbsoluteAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowNull); } public static VirtualPath CreateNonRelativeAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath | VirtualPathOptions.AllowNull); } public static VirtualPath CreateNonRelativeTrailingSlashAllowNull(string virtualPath) { return Create(virtualPath, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath | VirtualPathOptions.AllowNull | VirtualPathOptions.EnsureTrailingSlash); } public static VirtualPath Create(string virtualPath, VirtualPathOptions options) { // Trim it first, so that blank strings (e.g. " ") get treated as empty if (virtualPath != null) virtualPath = virtualPath.Trim(); // If it's empty, check whether we allow it if (String.IsNullOrEmpty(virtualPath)) { if ((options & VirtualPathOptions.AllowNull) != 0) return null; throw new ArgumentNullException("virtualPath"); } // Check for invalid characters if (ContainsIllegalVirtualPathChars(virtualPath)) { throw new HttpException(SR.GetString(SR.Invalid_vpath, virtualPath)); } // Flip ----lashes, and remove duplicate slashes string fixedUpVirtualPath = UrlPath.FixVirtualPathSlashes(virtualPath); // If we're supposed to fail on malformed path, check whether FixVirtualPathSlashes // had to do anything. if ((options & VirtualPathOptions.FailIfMalformed) != 0 && !Object.ReferenceEquals(virtualPath, fixedUpVirtualPath)) { throw new HttpException(SR.GetString(SR.Invalid_vpath, virtualPath)); } virtualPath = fixedUpVirtualPath; // Make sure it ends with a trailing slash if requested if ((options & VirtualPathOptions.EnsureTrailingSlash) != 0) virtualPath = UrlPath.AppendSlashToPathIfNeeded(virtualPath); VirtualPath virtualPathObject = new VirtualPath(); if (UrlPath.IsAppRelativePath(virtualPath)) { virtualPath = UrlPath.ReduceVirtualPath(virtualPath); if (virtualPath[0] == UrlPath.appRelativeCharacter) { if ((options & VirtualPathOptions.AllowAppRelativePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowAppRelativePath, virtualPath)); } virtualPathObject._appRelativeVirtualPath = virtualPath; } else { // It's possible for the path to become absolute after calling Reduce, // even though it started with "~/". e.g. if the app is "/app" and the path is // "~/../hello.aspx", it becomes "/hello.aspx", which is absolute if ((options & VirtualPathOptions.AllowAbsolutePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowAbsolutePath, virtualPath)); } virtualPathObject._virtualPath = virtualPath; } } else { if (virtualPath[0] != '/') { if ((options & VirtualPathOptions.AllowRelativePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowRelativePath, virtualPath)); } // Don't Reduce relative paths, since the Reduce method is broken (e.g. "../foo.aspx" --> "/foo.aspx!") // virtualPathObject._virtualPath = virtualPath; } else { if ((options & VirtualPathOptions.AllowAbsolutePath) == 0) { throw new ArgumentException(SR.GetString(SR.VirtualPath_AllowAbsolutePath, virtualPath)); } virtualPathObject._virtualPath = UrlPath.ReduceVirtualPath(virtualPath); } } virtualPathObject.ValidateState(); return virtualPathObject; } // Debug only method to check that the object is in a consistent state [System.Diagnostics.Conditional("DBG")] private void ValidateState() { #if DBG Debug.Assert(_virtualPath != null || _appRelativeVirtualPath != null); if (_virtualPath != null) { CheckValidVirtualPath(_virtualPath); } if (_appRelativeVirtualPath != null) { Debug.Assert(UrlPath.IsAppRelativePath(_appRelativeVirtualPath)); CheckValidVirtualPath(_appRelativeVirtualPath); } #endif } #if DBG private static void CheckValidVirtualPath(string virtualPath) { Debug.Assert(!ContainsIllegalVirtualPathChars(virtualPath)); Debug.Assert(virtualPath.IndexOf('\\') < 0); } #endif private static bool ContainsIllegalVirtualPathChars(string virtualPath) { if (!s_VerCompatRegLookedUp) LookUpRegForVerCompat(); return virtualPath.IndexOfAny(s_illegalVirtualPathChars) >= 0; } [RegistryPermission(SecurityAction.Assert, Unrestricted=true)] private static void LookUpRegForVerCompat() { lock(s_VerCompatLock) { if (s_VerCompatRegLookedUp) return; try { object o = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET", "VerificationCompatibility", 0); if (o != null && (o is int || o is uint) && ((int)o) == 1) s_illegalVirtualPathChars = s_illegalVirtualPathChars_VerCompat; s_VerCompatRegLookedUp = true; } catch { // ignore exceptions } } } } [Flags] internal enum VirtualPathOptions { AllowNull = 0x00000001, EnsureTrailingSlash = 0x00000002, AllowAbsolutePath = 0x00000004, AllowAppRelativePath = 0x00000008, AllowRelativePath = 0x00000010, FailIfMalformed = 0x00000020, AllowAllPath = AllowAbsolutePath | AllowAppRelativePath | AllowRelativePath, } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NativeMethods.cs
- HttpProcessUtility.cs
- ConfigurationManagerHelperFactory.cs
- BaseCollection.cs
- ValidationSummary.cs
- PathGradientBrush.cs
- RtType.cs
- OracleFactory.cs
- DataGridViewCellMouseEventArgs.cs
- CompiledRegexRunner.cs
- WebProxyScriptElement.cs
- RPIdentityRequirement.cs
- MaskedTextProvider.cs
- _ListenerResponseStream.cs
- DesignerActionList.cs
- ImportContext.cs
- ToolStripItemImageRenderEventArgs.cs
- ViewCellRelation.cs
- LambdaCompiler.Address.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- WebBrowser.cs
- XmlReader.cs
- CDSCollectionETWBCLProvider.cs
- DataGridItemCollection.cs
- SafeNativeMethodsOther.cs
- safesecurityhelperavalon.cs
- ListMarkerLine.cs
- CharEnumerator.cs
- DataGridViewHitTestInfo.cs
- BroadcastEventHelper.cs
- AssemblyHash.cs
- DependencyObjectValidator.cs
- FocusTracker.cs
- EncryptedPackageFilter.cs
- BoundColumn.cs
- StoragePropertyMapping.cs
- CodeNamespaceImportCollection.cs
- LinkDescriptor.cs
- PointLight.cs
- DesignerHelpers.cs
- StyleXamlParser.cs
- DefaultValueTypeConverter.cs
- TrustVersion.cs
- ScrollPatternIdentifiers.cs
- Menu.cs
- HttpMethodAttribute.cs
- PersonalizationState.cs
- MenuItemCollection.cs
- CustomPopupPlacement.cs
- recordstatescratchpad.cs
- KeyedHashAlgorithm.cs
- StructuralObject.cs
- Decorator.cs
- ListViewTableCell.cs
- TreeIterators.cs
- ListenerBinder.cs
- StateInitialization.cs
- SqlGenericUtil.cs
- XmlSchemaSet.cs
- UICuesEvent.cs
- DelegateOutArgument.cs
- AuditLog.cs
- SiteMapNode.cs
- ServiceDescriptionReflector.cs
- DataColumnCollection.cs
- ListDictionaryInternal.cs
- ListViewUpdateEventArgs.cs
- TiffBitmapDecoder.cs
- HtmlWindowCollection.cs
- MatrixIndependentAnimationStorage.cs
- ListViewHitTestInfo.cs
- CheckBoxField.cs
- AmbientProperties.cs
- CallContext.cs
- DelegatingHeader.cs
- SamlSubjectStatement.cs
- OleDbPermission.cs
- FlowDocumentReader.cs
- PriorityBindingExpression.cs
- ParameterModifier.cs
- SystemUdpStatistics.cs
- WrappedKeySecurityTokenParameters.cs
- QfeChecker.cs
- WebPartUserCapability.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- DefaultProxySection.cs
- DataBinder.cs
- TiffBitmapDecoder.cs
- PresentationSource.cs
- DataGridViewLinkColumn.cs
- ObjectParameter.cs
- HttpProfileGroupBase.cs
- CaseInsensitiveComparer.cs
- IdentityNotMappedException.cs
- InstanceContextMode.cs
- ListCollectionView.cs
- EventLog.cs
- Matrix3DStack.cs
- MetadataException.cs
- RuntimeArgumentHandle.cs