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
- RevocationPoint.cs
- PrintDialog.cs
- Compiler.cs
- Semaphore.cs
- Buffer.cs
- FamilyMapCollection.cs
- ConditionalExpression.cs
- HttpContext.cs
- HMACSHA512.cs
- NamedPipeActivation.cs
- TraceSection.cs
- TransformedBitmap.cs
- WebAdminConfigurationHelper.cs
- VariantWrapper.cs
- ColorPalette.cs
- XhtmlBasicLinkAdapter.cs
- XmlNode.cs
- Light.cs
- SecurityIdentifierElementCollection.cs
- StringStorage.cs
- DbDataRecord.cs
- Tablet.cs
- ExchangeUtilities.cs
- WindowsListViewScroll.cs
- AsymmetricAlgorithm.cs
- LocalBuilder.cs
- SupportingTokenSpecification.cs
- XmlTextEncoder.cs
- MatrixIndependentAnimationStorage.cs
- BaseDataBoundControl.cs
- FontStretchConverter.cs
- PersistenceTypeAttribute.cs
- ImageFormatConverter.cs
- ToolboxItemLoader.cs
- IndexedEnumerable.cs
- TimersDescriptionAttribute.cs
- IndexedWhereQueryOperator.cs
- Semaphore.cs
- ExpressionBinding.cs
- FieldNameLookup.cs
- GPPOINT.cs
- DispatcherObject.cs
- PersianCalendar.cs
- SectionVisual.cs
- iisPickupDirectory.cs
- BuildResult.cs
- TextLineBreak.cs
- JournalEntryStack.cs
- basevalidator.cs
- CallSiteHelpers.cs
- BmpBitmapEncoder.cs
- WindowsToolbarItemAsMenuItem.cs
- SQLStringStorage.cs
- HtmlWindow.cs
- SqlConnectionPoolProviderInfo.cs
- MemberDomainMap.cs
- PropertyOverridesDialog.cs
- MaskDescriptor.cs
- PageFunction.cs
- TabItemWrapperAutomationPeer.cs
- CompositeKey.cs
- KeyFrames.cs
- objectquery_tresulttype.cs
- TextTreeInsertElementUndoUnit.cs
- ThicknessAnimationUsingKeyFrames.cs
- TlsSspiNegotiation.cs
- Style.cs
- SqlColumnizer.cs
- ProjectionCamera.cs
- ContentElement.cs
- MsmqIntegrationInputMessage.cs
- SqlBooleanMismatchVisitor.cs
- CodeExporter.cs
- XmlSchemaRedefine.cs
- ListenerChannelContext.cs
- TerminatorSinks.cs
- RichTextBox.cs
- DeferredElementTreeState.cs
- DuplicateWaitObjectException.cs
- FunctionMappingTranslator.cs
- DurableInstance.cs
- DateTimeParse.cs
- DispatcherHookEventArgs.cs
- CollectionType.cs
- PersistenceParticipant.cs
- RtfControlWordInfo.cs
- PropertyFilterAttribute.cs
- FilterableAttribute.cs
- ManagementObject.cs
- AvTraceDetails.cs
- ResourceProviderFactory.cs
- ArraySortHelper.cs
- AsymmetricAlgorithm.cs
- TextTreePropertyUndoUnit.cs
- UInt32Storage.cs
- XhtmlBasicPhoneCallAdapter.cs
- UnsafeNativeMethods.cs
- ProtocolsSection.cs
- Rect3D.cs
- Stacktrace.cs