Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Security / Util / URLString.cs / 1 / URLString.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // URLString // // Implementation of membership condition for zones // namespace System.Security.Util { using System; using System.Collections; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Globalization; using System.Text; using System.IO; [Serializable] internal sealed class URLString : SiteString { private String m_protocol; [OptionalField(VersionAdded = 2)] private String m_userpass; private SiteString m_siteString; private int m_port; #if !PLATFORM_UNIX private LocalSiteString m_localSite; #endif // !PLATFORM_UNIX private DirectoryString m_directory; private const String m_defaultProtocol = "file"; [OptionalField(VersionAdded = 2)] private bool m_parseDeferred; [OptionalField(VersionAdded = 2)] private String m_urlOriginal; [OptionalField(VersionAdded = 2)] private bool m_parsedOriginal; // legacy field from v1.x, not used in v2 and beyond. Retained purely for serialization compatability. private String m_fullurl; [OnDeserialized] public void OnDeserialized(StreamingContext ctx) { if (m_urlOriginal == null) { // pre-v2 deserialization. Need to fix-up fields here m_parseDeferred = false; m_parsedOriginal = false; // Dont care what this value is - never used m_userpass = ""; m_urlOriginal = m_fullurl; m_fullurl = null; } } [OnSerializing] private void OnSerializing(StreamingContext ctx) { if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) { DoDeferredParse(); m_fullurl = m_urlOriginal; } } [OnSerialized] private void OnSerialized(StreamingContext ctx) { if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) { m_fullurl = null; } } public URLString() { m_protocol = ""; m_userpass = ""; m_siteString = new SiteString(); m_port = -1; #if !PLATFORM_UNIX m_localSite = null; #endif // !PLATFORM_UNIX m_directory = new DirectoryString(); m_parseDeferred = false; } private void DoDeferredParse() { if (m_parseDeferred) { ParseString(m_urlOriginal, m_parsedOriginal); m_parseDeferred = false; } } public URLString(string url) : this(url, false, false) {} public URLString(string url, bool parsed) : this(url, parsed, false) {} internal URLString(string url, bool parsed, bool doDeferredParsing) { m_port = -1; m_userpass = ""; DoFastChecks(url); m_urlOriginal = url; m_parsedOriginal = parsed; m_parseDeferred = true; if (doDeferredParsing) DoDeferredParse(); } // Converts %XX and %uYYYY to the actual characters (I.e. Unesacpes any escape characters present in the URL) private String UnescapeURL(String url) { StringBuilder intermediate = new StringBuilder(url.Length); int Rindex = 0; // index into temp that gives the rest of the string to be processed int index; int braIndex = -1; int ketIndex = -1; braIndex = url.IndexOf('[',Rindex); if (braIndex != -1) ketIndex = url.IndexOf(']', braIndex); do { index = url.IndexOf( '%', Rindex); if (index == -1) { intermediate = intermediate.Append(url, Rindex, (url.Length - Rindex)); break; } // if we hit a '%' in the middle of an IPv6 address, dont process that if (index > braIndex && index < ketIndex) { intermediate = intermediate.Append(url, Rindex, (ketIndex - Rindex+1)); Rindex = ketIndex+1; continue; } if (url.Length - index < 2) // Check that there is at least 1 char after the '%' throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); if (url[index+1] == 'u' || url[index+1] == 'U') { if (url.Length - index < 6) // example: "%u004d" is 6 chars long throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); // We have a unicode character specified in hex try { char c = (char)(Hex.ConvertHexDigit( url[index+2] ) << 12 | Hex.ConvertHexDigit( url[index+3] ) << 8 | Hex.ConvertHexDigit( url[index+4] ) << 4 | Hex.ConvertHexDigit( url[index+5] )); intermediate = intermediate.Append(url, Rindex, index - Rindex); intermediate = intermediate.Append(c); } catch(ArgumentException) // Hex.ConvertHexDigit can throw an "out of range" ArgumentException { throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); } Rindex = index + 6 ; //update the 'seen' length } else { // we have a hex character. if (url.Length - index < 3) // example: "%4d" is 3 chars long throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); try { char c = (char)(Hex.ConvertHexDigit( url[index+1] ) << 4 | Hex.ConvertHexDigit( url[index+2] )); intermediate = intermediate.Append(url, Rindex, index - Rindex); intermediate = intermediate.Append(c); } catch(ArgumentException) // Hex.ConvertHexDigit can throw an "out of range" ArgumentException { throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); } Rindex = index + 3; // update the 'seen' length } } while (true); return intermediate.ToString(); } // Helper Function for ParseString: // Search for the end of the protocol info and grab the actual protocol string // ex. http://www.microsoft.com/complus would have a protocol string of http private String ParseProtocol(String url) { String temp; int index = url.IndexOf( ':' ); if (index == 0) { throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); } else if (index == -1) { m_protocol = m_defaultProtocol; temp = url; } else if (url.Length > index + 1) { if (index == m_defaultProtocol.Length && String.Compare(url, 0, m_defaultProtocol, 0, index, StringComparison.OrdinalIgnoreCase) == 0) { m_protocol = m_defaultProtocol; temp = url.Substring( index + 1 ); } else if (url[index+1] != '\\') { #if !PLATFORM_UNIX if (url.Length > index + 2 && url[index+1] == '/' && url[index+2] == '/') #else if (url.Length > index + 1 && url[index+1] == '/' ) // UNIX style "file:/home/me" is allowed, so account for that #endif // !PLATFORM_UNIX { m_protocol = url.Substring( 0, index ); for (int i = 0; i < m_protocol.Length; ++i) { char c = m_protocol[i]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '+') || (c == '.') || (c == '-')) { continue; } else { throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); } } #if !PLATFORM_UNIX temp = url.Substring( index + 3 ); #else // In UNIX, we don't know how many characters we'll have to skip past. // Skip past \, /, and : // for ( int j=index ; j= '0' && temp[portIndex+1] <= '9' ) { int tempIndex = temp.IndexOf( '/', Rindex); if (tempIndex == -1) { m_port = Int32.Parse( temp.Substring(portIndex + 1), CultureInfo.InvariantCulture ); if (m_port < 0) throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); temp = temp.Substring( Rindex, portIndex - Rindex ); } else if (tempIndex > portIndex) { m_port = Int32.Parse( temp.Substring(portIndex + 1, tempIndex - portIndex - 1), CultureInfo.InvariantCulture ); temp = temp.Substring( Rindex, portIndex - Rindex ) + temp.Substring( tempIndex ); } else throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); } else throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); } else { // Chop of the user/pass portion if any temp = temp.Substring(Rindex); } return temp; } // This does three things: // 1. It makes the following modifications to the start of the string: // a. \\?\ and \\?/ => // b. \\.\ and \\./ => // 2. If isFileUrl is true, converts all slashes to front slashes and strips leading // front slashes. See comment by code. // 3. Throws a PathTooLongException if the length of the resulting URL is >= MAX_PATH. // This is done to prevent security issues due to canonicalization truncations. // Remove this method when the Path class supports "\\?\" internal static String PreProcessForExtendedPathRemoval(String url, bool isFileUrl) { // This is the modified URL that we will return StringBuilder modifiedUrl = new StringBuilder(url); // ITEM 1 - remove extended path characters. { // Keep track of where we are in both the comparison and altered strings. int curCmpIdx = 0; int curModIdx = 0; // If all the '\' have already been converted to '/', just check for //?/ or //./ if ((url.Length - curCmpIdx) >= 4 && (String.Compare(url, curCmpIdx, "//?/", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(url, curCmpIdx, "//./", 0, 4, StringComparison.OrdinalIgnoreCase) == 0)) { modifiedUrl.Remove(curModIdx, 4); curCmpIdx += 4; } else { if (isFileUrl) { // We need to handle an indefinite number of leading front slashes for file URLs since we could // get something like: // file://\\?\ // file:/\\?\ // file:\\?\ // etc... while (url[curCmpIdx] == '/') { curCmpIdx++; curModIdx++; } } // Remove the extended path characters if ((url.Length - curCmpIdx) >= 4 && (String.Compare(url, curCmpIdx, "\\\\?\\", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(url, curCmpIdx, "\\\\?/", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(url, curCmpIdx, "\\\\.\\", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(url, curCmpIdx, "\\\\./", 0, 4, StringComparison.OrdinalIgnoreCase) == 0)) { modifiedUrl.Remove(curModIdx, 4); curCmpIdx += 4; } } } // ITEM 2 - convert all slashes to forward slashes, and strip leading slashes. if (isFileUrl) { modifiedUrl.Replace('\\', '/'); int slashCount = 0; while (slashCount < modifiedUrl.Length && modifiedUrl[slashCount] == '/') { slashCount++; } modifiedUrl.Remove(0, slashCount); } // ITEM 3 - If the path is greater than or equal (due to terminating NULL in windows) MAX_PATH, we throw. if (modifiedUrl.Length >= Path.MAX_PATH) { throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); } // Create the result string from the StringBuilder return modifiedUrl.ToString(); } // Do any misc massaging of data in the URL private String PreProcessURL(String url, bool isFileURL) { #if !PLATFORM_UNIX if (isFileURL) { // Remove when the Path class supports "\\?\" url = PreProcessForExtendedPathRemoval(url, true); } else { url = url.Replace('\\', '/'); } return url; #else // Remove superfluous '/' // For UNIX, the file path would look something like: // file:///home/johndoe/here // file:/home/johndoe/here // file:../johndoe/here // file:~/johndoe/here String temp = url; int nbSlashes = 0; while(nbSlashes 2) temp = temp.Substring(nbSlashes-1, temp.Length - (nbSlashes-1)); else if (2 == nbSlashes) /* it's a relative path */ temp = temp.Substring(nbSlashes, temp.Length - nbSlashes); return temp; #endif // !PLATFORM_UNIX } private void ParseFileURL(String url) { String temp = url; #if !PLATFORM_UNIX int index = temp.IndexOf( '/'); if (index != -1 && ((index == 2 && temp[index-1] != ':' && temp[index-1] != '|') || index != 2) && index != temp.Length - 1) { // Also, if it is a UNC share, we want m_localSite to // be of the form "computername/share", so if the first // fileEnd character found is a slash, do some more parsing // to find the proper end character. int tempIndex = temp.IndexOf( '/', index+1); if (tempIndex != -1) index = tempIndex; else index = -1; } String localSite; if (index == -1) localSite = temp; else localSite = temp.Substring(0,index); if (localSite.Length == 0) throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) ); int i; bool spacesAllowed; if (localSite[0] == '\\' && localSite[1] == '\\') { spacesAllowed = true; i = 2; } else { i = 0; spacesAllowed = false; } bool useSmallCharToUpper = true; for (; i < localSite.Length; ++i) { char c = localSite[i]; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '-') || (c == '/') || (c == ':') || (c == '|') || (c == '.') || (c == '*') || (c == '$') || (spacesAllowed && c == ' ')) { continue; } else { useSmallCharToUpper = false; break; } } if (useSmallCharToUpper) localSite = String.SmallCharToUpper( localSite ); else localSite = localSite.ToUpper(CultureInfo.InvariantCulture); m_localSite = new LocalSiteString( localSite ); if (index == -1) { if (localSite[localSite.Length-1] == '*') m_directory = new DirectoryString( "*", false ); else m_directory = new DirectoryString(); } else { String directoryString = temp.Substring( index + 1 ); if (directoryString.Length == 0) { m_directory = new DirectoryString(); } else { m_directory = new DirectoryString( directoryString, true); } } #else // !PLATFORM_UNIX m_directory = new DirectoryString( temp, true); #endif // !PLATFORM_UNIX m_siteString = null; return; } private void ParseNonFileURL(String url) { String temp = url; int index = temp.IndexOf('/'); if (index == -1) { #if !PLATFORM_UNIX m_localSite = null; // for drive letter #endif // !PLATFORM_UNIX m_siteString = new SiteString( temp ); m_directory = new DirectoryString(); } else { #if !PLATFORM_UNIX String site = temp.Substring( 0, index ); m_localSite = null; m_siteString = new SiteString( site ); String directoryString = temp.Substring( index + 1 ); if (directoryString.Length == 0) { m_directory = new DirectoryString(); } else { m_directory = new DirectoryString( directoryString, false ); } #else String directoryString = temp.Substring( index + 1 ); String site = temp.Substring( 0, index ); m_directory = new DirectoryString( directoryString, false ); m_siteString = new SiteString( site ); #endif //!PLATFORM_UNIX } return; } void DoFastChecks( String url ) { if (url == null) { throw new ArgumentNullException( "url" ); } if (url.Length == 0) { throw new FormatException(Environment.GetResourceString("Format_StringZeroLength")); } } // NOTE: // 1. We support URLs that follow the common Internet scheme syntax // ( ://user:pass@ : / ) and all windows file URLs. // 2. In the general case we parse of the site and create a SiteString out of it // (which supports our wildcarding scheme). In the case of files we don't support // wildcarding and furthermore SiteString doesn't like ':' and '|' which can appear // in file urls so we just keep that info in a separate string and set the // SiteString to null. // // ex. http://www.microsoft.com/complus -> m_siteString = "www.microsoft.com" m_localSite = null // ex. file:///c:/complus/mscorlib.dll -> m_siteString = null m_localSite = "c:" // ex. file:///c|/complus/mscorlib.dll -> m_siteString = null m_localSite = "c:" void ParseString( String url, bool parsed ) { // If there are any escaped hex or unicode characters in the url, translate those // into the proper character. if (!parsed) { url = UnescapeURL(url); } // Identify the protocol and strip the protocol info from the string, if present. String temp = ParseProtocol(url); bool fileProtocol = (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) == 0); // handle any special preocessing...removing extra characters, etc. temp = PreProcessURL(temp, fileProtocol); if (fileProtocol) { ParseFileURL(temp); } else { // Check if there is a port number and parse that out. temp = ParsePort(temp); ParseNonFileURL(temp); // Note: that we allow DNS and Netbios names for non-file protocols (since sitestring will check // that the hostname satisfies these two protocols. DNS-only checking can theoretically be added // here but that would break all the programs that use '_' (which is fairly common, yet illegal). // If this needs to be done at any point, add a call to m_siteString.IsLegalDNSName(). } } public String Scheme { get { DoDeferredParse(); return m_protocol; } } public String Host { get { DoDeferredParse(); if (m_siteString != null) { return m_siteString.ToString(); } else { #if !PLATFORM_UNIX return m_localSite.ToString(); #else return( "" ); #endif // !PLATFORM_UNIX } } } public String Port { get { DoDeferredParse(); if (m_port == -1) return null; else return m_port.ToString(CultureInfo.InvariantCulture); } } public String Directory { get { DoDeferredParse(); return m_directory.ToString(); } } public String GetFileName() { DoDeferredParse(); #if !PLATFORM_UNIX if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) != 0) return null; String intermediateDirectory = this.Directory.Replace( '/', '\\' ); String directory = this.Host.Replace( '/', '\\' ); int directorySlashIndex = directory.IndexOf( '\\' ); if (directorySlashIndex == -1) { if (directory.Length != 2 || !(directory[1] == ':' || directory[1] == '|')) { directory = "\\\\" + directory; } } else if (directorySlashIndex > 2 || (directorySlashIndex == 2 && directory[1] != ':' && directory[1] != '|')) { directory = "\\\\" + directory; } directory += "\\" + intermediateDirectory; return directory; #else // In Unix, directory contains the full pathname // (this is what we get in Win32) if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase ) != 0) return null; return this.Directory; #endif // !PLATFORM_UNIX } public String GetDirectoryName() { DoDeferredParse(); #if !PLATFORM_UNIX if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase ) != 0) return null; String intermediateDirectory = this.Directory.Replace( '/', '\\' ); int slashIndex = 0; for (int i = intermediateDirectory.Length; i > 0; i--) { if (intermediateDirectory[i-1] == '\\') { slashIndex = i; break; } } String directory = this.Host.Replace( '/', '\\' ); int directorySlashIndex = directory.IndexOf( '\\' ); if (directorySlashIndex == -1) { if (directory.Length != 2 || !(directory[1] == ':' || directory[1] == '|')) { directory = "\\\\" + directory; } } else if (directorySlashIndex > 2 || (directorySlashIndex == 2 && directory[1] != ':' && directory[1] != '|')) { directory = "\\\\" + directory; } directory += "\\"; if (slashIndex > 0) { directory += intermediateDirectory.Substring( 0, slashIndex ); } return directory; #else if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) != 0) return null; String directory = this.Directory.ToString(); int slashIndex = 0; for (int i = directory.Length; i > 0; i--) { if (directory[i-1] == '/') { slashIndex = i; break; } } if (slashIndex > 0) { directory = directory.Substring( 0, slashIndex ); } return directory; #endif // !PLATFORM_UNIX } public override SiteString Copy() { return new URLString( m_urlOriginal, m_parsedOriginal ); } public override bool IsSubsetOf( SiteString site ) { if (site == null) { return false; } URLString url = site as URLString; if (url == null) { return false; } DoDeferredParse(); url.DoDeferredParse(); URLString normalUrl1 = this.SpecialNormalizeUrl(); URLString normalUrl2 = url.SpecialNormalizeUrl(); if (String.Compare( normalUrl1.m_protocol, normalUrl2.m_protocol, StringComparison.OrdinalIgnoreCase) == 0 && normalUrl1.m_directory.IsSubsetOf( normalUrl2.m_directory )) { #if !PLATFORM_UNIX if (normalUrl1.m_localSite != null) { // We do a little extra processing in here for local files since we allow // both : and | forms of urls. return normalUrl1.m_localSite.IsSubsetOf( normalUrl2.m_localSite ); } else #endif // !PLATFORM_UNIX { if (normalUrl1.m_port != normalUrl2.m_port) return false; return normalUrl2.m_siteString != null && normalUrl1.m_siteString.IsSubsetOf( normalUrl2.m_siteString ); } } else { return false; } } public override String ToString() { return m_urlOriginal; } public override bool Equals(Object o) { DoDeferredParse(); if (o == null || !(o is URLString)) return false; else return this.Equals( (URLString)o ); } public override int GetHashCode() { DoDeferredParse(); TextInfo info = CultureInfo.InvariantCulture.TextInfo; int accumulator = 0; if (this.m_protocol != null) accumulator = info.GetCaseInsensitiveHashCode( this.m_protocol ); #if !PLATFORM_UNIX if (this.m_localSite != null) { accumulator = accumulator ^ this.m_localSite.GetHashCode(); } else { accumulator = accumulator ^ this.m_siteString.GetHashCode(); } accumulator = accumulator ^ this.m_directory.GetHashCode(); #else accumulator = accumulator ^ info.GetCaseInsensitiveHashCode(this.m_urlOriginal); #endif // !PLATFORM_UNIX return accumulator; } public bool Equals( URLString url ) { return CompareUrls( this, url ); } public static bool CompareUrls( URLString url1, URLString url2 ) { if (url1 == null && url2 == null) return true; if (url1 == null || url2 == null) return false; url1.DoDeferredParse(); url2.DoDeferredParse(); URLString normalUrl1 = url1.SpecialNormalizeUrl(); URLString normalUrl2 = url2.SpecialNormalizeUrl(); // Compare protocol (case insensitive) if (String.Compare( normalUrl1.m_protocol, normalUrl2.m_protocol, StringComparison.OrdinalIgnoreCase) != 0) return false; // Do special processing for file urls if (String.Compare( normalUrl1.m_protocol, "file", StringComparison.OrdinalIgnoreCase) == 0) { #if !PLATFORM_UNIX if (!normalUrl1.m_localSite.IsSubsetOf( normalUrl2.m_localSite ) || !normalUrl2.m_localSite.IsSubsetOf( normalUrl1.m_localSite )) return false; #else return url1.IsSubsetOf( url2 ) && url2.IsSubsetOf( url1 ); #endif // !PLATFORM_UNIX } else { if (String.Compare( normalUrl1.m_userpass, normalUrl2.m_userpass, StringComparison.Ordinal) != 0) return false; if (!normalUrl1.m_siteString.IsSubsetOf( normalUrl2.m_siteString ) || !normalUrl2.m_siteString.IsSubsetOf( normalUrl1.m_siteString )) return false; if (url1.m_port != url2.m_port) return false; } if (!normalUrl1.m_directory.IsSubsetOf( normalUrl2.m_directory ) || !normalUrl2.m_directory.IsSubsetOf( normalUrl1.m_directory )) return false; return true; } internal String NormalizeUrl() { StringBuilder builtUrl = new StringBuilder(); DoDeferredParse(); if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) == 0) { #if !PLATFORM_UNIX builtUrl = builtUrl.AppendFormat("FILE:///{0}/{1}", m_localSite.ToString(), m_directory.ToString()); #else builtUrl = builtUrl.AppendFormat("FILE:///{0}", m_directory.ToString()); #endif // !PLATFORM_UNIX } else { builtUrl = builtUrl.AppendFormat("{0}://{1}{2}", m_protocol, m_userpass, m_siteString.ToString()); if (m_port != -1) builtUrl = builtUrl.AppendFormat("{0}",m_port); builtUrl = builtUrl.AppendFormat("/{0}", m_directory.ToString()); } return builtUrl.ToString().ToUpper(CultureInfo.InvariantCulture); } #if !PLATFORM_UNIX internal URLString SpecialNormalizeUrl() { // Under WinXP, file protocol urls can be mapped to // drives that aren't actually file protocol underneath // due to drive mounting. This code attempts to figure // out what a drive is mounted to and create the // url is maps to. DoDeferredParse(); if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) != 0) { return this; } else { String localSite = m_localSite.ToString(); if (localSite.Length == 2 && (localSite[1] == '|' || localSite[1] == ':')) { String deviceName = _GetDeviceName( localSite ); if (deviceName != null) { if (deviceName.IndexOf( "://", StringComparison.Ordinal ) != -1) { URLString u = new URLString( deviceName + "/" + this.m_directory.ToString() ); u.DoDeferredParse(); // Presumably the caller of SpecialNormalizeUrl wants a fully parsed URL return u; } else { URLString u = new URLString( "file://" + deviceName + "/" + this.m_directory.ToString() ); u.DoDeferredParse();// Presumably the caller of SpecialNormalizeUrl wants a fully parsed URL return u; } } else return this; } else { return this; } } } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern String _GetDeviceName( String driveLetter ); #else internal URLString SpecialNormalizeUrl() { return this; } #endif // !PLATFORM_UNIX } [Serializable] internal class DirectoryString : SiteString { private bool m_checkForIllegalChars; private new static char[] m_separators = { '/' }; // From KB #Q177506, file/folder illegal characters are \ / : * ? " < > | protected static char[] m_illegalDirectoryCharacters = { '\\', ':', '*', '?', '"', '<', '>', '|' }; public DirectoryString() { m_site = ""; m_separatedSite = new ArrayList(); } public DirectoryString( String directory, bool checkForIllegalChars ) { m_site = directory; m_checkForIllegalChars = checkForIllegalChars; m_separatedSite = CreateSeparatedString( directory ); } private ArrayList CreateSeparatedString( String directory ) { ArrayList list = new ArrayList(); if (directory == null || directory.Length == 0) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); } String[] separatedArray = directory.Split( m_separators ); for (int index = 0; index < separatedArray.Length; ++index) { if (separatedArray[index] == null || separatedArray[index].Equals( "" )) { // this case is fine, we just ignore it the extra separators. } else if (separatedArray[index].Equals( "*" )) { if (index != separatedArray.Length-1) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); } list.Add( separatedArray[index] ); } else if (m_checkForIllegalChars && separatedArray[index].IndexOfAny( m_illegalDirectoryCharacters ) != -1) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); } else { list.Add( separatedArray[index] ); } } return list; } public virtual bool IsSubsetOf( DirectoryString operand ) { return this.IsSubsetOf( operand, true ); } public virtual bool IsSubsetOf( DirectoryString operand, bool ignoreCase ) { if (operand == null) { return false; } else if (operand.m_separatedSite.Count == 0) { return this.m_separatedSite.Count == 0 || this.m_separatedSite.Count > 0 && String.Compare( (String)this.m_separatedSite[0], "*", StringComparison.Ordinal) == 0; } else if (this.m_separatedSite.Count == 0) { return String.Compare( (String)operand.m_separatedSite[0], "*", StringComparison.Ordinal) == 0; } else { return base.IsSubsetOf( operand, ignoreCase ); } } } #if !PLATFORM_UNIX [Serializable] internal class LocalSiteString : SiteString { private new static char[] m_separators = { '/' }; public LocalSiteString( String site ) { m_site = site.Replace( '|', ':'); if (m_site.Length > 2 && m_site.IndexOf( ':' ) != -1) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); m_separatedSite = CreateSeparatedString( m_site ); } private ArrayList CreateSeparatedString( String directory ) { ArrayList list = new ArrayList(); if (directory == null || directory.Length == 0) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); } String[] separatedArray = directory.Split( m_separators ); for (int index = 0; index < separatedArray.Length; ++index) { if (separatedArray[index] == null || separatedArray[index].Equals( "" )) { if (index < 2 && directory[index] == '/') { list.Add( '/' ); } else if (index != separatedArray.Length-1) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); } } else if (separatedArray[index].Equals( "*" )) { if (index != separatedArray.Length-1) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl")); } list.Add( separatedArray[index] ); } else { list.Add( separatedArray[index] ); } } return list; } public virtual bool IsSubsetOf( LocalSiteString operand ) { return this.IsSubsetOf( operand, true ); } public virtual bool IsSubsetOf( LocalSiteString operand, bool ignoreCase ) { if (operand == null) { return false; } else if (operand.m_separatedSite.Count == 0) { return this.m_separatedSite.Count == 0 || this.m_separatedSite.Count > 0 && String.Compare( (String)this.m_separatedSite[0], "*", StringComparison.Ordinal) == 0; } else if (this.m_separatedSite.Count == 0) { return String.Compare( (String)operand.m_separatedSite[0], "*", StringComparison.Ordinal) == 0; } else { return base.IsSubsetOf( operand, ignoreCase ); } } } #endif // !PLATFORM_UNIX }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EmbeddedMailObjectsCollection.cs
- ObjectItemAttributeAssemblyLoader.cs
- EntityDataSourceConfigureObjectContextPanel.cs
- PtsContext.cs
- SafeProcessHandle.cs
- ValidationPropertyAttribute.cs
- XsdBuilder.cs
- WebColorConverter.cs
- ResourceSet.cs
- StateDesigner.CommentLayoutGlyph.cs
- QueryExtender.cs
- ProfilePropertySettings.cs
- XmlFormatWriterGenerator.cs
- ToolStripDropDown.cs
- NullableDecimalSumAggregationOperator.cs
- EpmCustomContentWriterNodeData.cs
- Journaling.cs
- Verify.cs
- SpecialNameAttribute.cs
- RoutedEventConverter.cs
- ExpressionEditorAttribute.cs
- RawAppCommandInputReport.cs
- GraphicsPath.cs
- LinkTarget.cs
- ComboBox.cs
- TextServicesDisplayAttribute.cs
- GradientBrush.cs
- SqlInternalConnection.cs
- ObjectListCommandCollection.cs
- StubHelpers.cs
- RectValueSerializer.cs
- Nullable.cs
- StringDictionary.cs
- PartialTrustHelpers.cs
- GetParentChain.cs
- SqlCacheDependencyDatabaseCollection.cs
- SqlCommand.cs
- CodeGotoStatement.cs
- OSFeature.cs
- Site.cs
- XmlParserContext.cs
- DropDownHolder.cs
- JoinElimination.cs
- ExtractedStateEntry.cs
- RemoveStoryboard.cs
- HttpRequestCacheValidator.cs
- VarRefManager.cs
- MulticastDelegate.cs
- StringValidator.cs
- XmlExtensionFunction.cs
- SamlAttributeStatement.cs
- InputScopeManager.cs
- __Filters.cs
- Helpers.cs
- AppearanceEditorPart.cs
- RestHandlerFactory.cs
- BasicKeyConstraint.cs
- HttpHandlerAction.cs
- EncoderParameters.cs
- HebrewNumber.cs
- DataTemplateKey.cs
- DataListCommandEventArgs.cs
- AsyncContentLoadedEventArgs.cs
- OutputCacheProfile.cs
- InfiniteTimeSpanConverter.cs
- OleDbParameterCollection.cs
- DuplicateDetector.cs
- ToolStripItemDataObject.cs
- BindingGraph.cs
- Convert.cs
- SerializationEventsCache.cs
- DynamicRendererThreadManager.cs
- AttachedPropertyInfo.cs
- QueryStringParameter.cs
- Point.cs
- SchemaImporterExtensionElementCollection.cs
- WebPartConnectionsDisconnectVerb.cs
- DropTarget.cs
- SocketInformation.cs
- SecondaryIndexDefinition.cs
- MobileTextWriter.cs
- SimpleWorkerRequest.cs
- EditingCommands.cs
- SafeSystemMetrics.cs
- WorkflowServiceAttributesTypeConverter.cs
- VSWCFServiceContractGenerator.cs
- ValueTable.cs
- EllipticalNodeOperations.cs
- TypeConverterHelper.cs
- BinaryCommonClasses.cs
- LiteralControl.cs
- ArrangedElement.cs
- MenuItem.cs
- PropertyGeneratedEventArgs.cs
- OdbcUtils.cs
- RoleService.cs
- NativeMethods.cs
- EncoderParameters.cs
- x509utils.cs
- WebProxyScriptElement.cs