void ParseString(String url, bool parsed)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
if (url.Length == 0)
{
throw new FormatException(Environment.GetResourceString("Format_StringZeroLength"));
}
int index;
String temp = url;
String intermediate = "";
// If there are any hex or unicode characters in the url, translate those
// into the proper character.
if (!parsed)
{
do
{
index = temp.IndexOf('%');
if (index == -1)
{
intermediate += temp;
break;
}
if (temp.Length - index < 1)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
if (temp[index + 1] == 'u' || temp[index + 1] == 'U')
{
if (temp.Length - index < 5)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
// We have a unicode character specified in hex
char c = (char)(Hex.ConvertHexDigit(temp[index + 2]) << 12 |
Hex.ConvertHexDigit(temp[index + 3]) << 8 |
Hex.ConvertHexDigit(temp[index + 4]) << 4 |
Hex.ConvertHexDigit(temp[index + 5]));
intermediate += temp.Substring(0, index) + c;
temp = temp.Substring(index + 6);
}
else
{
// we have a hex character.
if (temp.Length - index < 2)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
char c = (char)(Hex.ConvertHexDigit(temp[index + 1]) << 4 | Hex.ConvertHexDigit(temp[index + 2]));
intermediate += temp.Substring(0, index) + c;
temp = temp.Substring(index + 3);
}
} while (true);
temp = intermediate;
url = temp;
}
// 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
index = temp.IndexOf(':');
if (index == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
else if (index != -1 &&
temp.Length > index + 1)
{
if (String.Compare(temp.Substring(0, index), "file", true, CultureInfo.InvariantCulture) == 0)
{
m_protocol = "file";
temp = temp.Substring(index + 1);
}
else if (temp[index + 1] != '\\')
{
if (temp.Length > index + 2 &&
temp[index + 1] == '/' &&
temp[index + 2] == '/')
{
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'))
{
continue;
}
else
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
}
temp = url.Substring(index + 3);
}
else
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
}
else
{
m_protocol = m_defaultProtocol;
temp = url;
}
}
else
{
m_protocol = m_defaultProtocol;
temp = url;
}
// Parse out the site info.
// 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:"
bool fileProtocol;
if (String.Compare(m_protocol, "file", true, CultureInfo.InvariantCulture) == 0)
{
index = temp.IndexOfAny(m_fileEnd);
fileProtocol = true;
if (String.Compare(temp, 0, "\\\\?\\", 0, 4, true, CultureInfo.InvariantCulture) == 0 ||
String.Compare(temp, 0, "\\\\.\\", 0, 4, true, CultureInfo.InvariantCulture) == 0)
{
temp = temp.Substring(4);
}
}
else
{
index = temp.IndexOfAny(m_siteEnd);
fileProtocol = false;
}
temp = temp.Replace('\\', '/');
// If we find a '/' in the first character of the string and we are using the 'file'
// protocol, just ignore it.
if (fileProtocol)
{
// Remove any '/' before the local site information.
// ex. file://///d:/complus
// ex. file:///d:/complus
temp = temp.TrimStart(new char[] { '/' });
index = temp.IndexOfAny(m_fileEnd, 0);
if (index != -1 &&
((index == 2 &&
temp[index - 1] != ':' &&
temp[index - 1] != '|') ||
index != 2) &&
index != temp.Length - 1)
{
int tempIndex = temp.Substring(index + 1).IndexOfAny(m_fileEnd);
if (tempIndex != -1)
{
index = tempIndex + index + 1;
}
else
{
index = -1;
}
}
}
// Check if there is a port number and parse that out.
if (index != -1 && temp[index] == ':')
{
int tempIndex = temp.IndexOf('/');
if (tempIndex == -1)
{
m_port = Int32.Parse(temp.Substring(index + 1));
if (m_port < 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUrl"));
}
temp = temp.Substring(0, index);
index = -1;
}
else
{
m_port = Int32.Parse(temp.Substring(index + 1, tempIndex - index - 1));
temp = temp.Substring(0, index) + temp.Substring(tempIndex);
}
}
if (index == -1)
{
if (fileProtocol)
{
String localSite = temp;
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_siteString = null;
m_localSite = new LocalSiteString(localSite);
if (localSite[localSite.Length - 1] == '*')
{
m_directory = new DirectoryString("*", false);
}
else
{
m_directory = new DirectoryString();
}
}
else
{
m_localSite = null;
m_siteString = new SiteString(temp);
m_directory = new DirectoryString();
}
}
else
{
String site = temp.Substring(0, index);
if (fileProtocol)
{
String localSite = site;
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 >= '-' && c <= ':') ||
(c == '|') || (c == '$') ||
(c == '_') ||
(spacesAllowed && c == ' '))
{
continue;
}
else
{
useSmallCharToUpper = false;
break;
}
}
if (useSmallCharToUpper)
{
localSite = String.SmallCharToUpper(localSite);
}
else
{
localSite = localSite.ToUpper(CultureInfo.InvariantCulture);
}
m_siteString = null;
m_localSite = new LocalSiteString(localSite);
}
else
{
m_localSite = null;
m_siteString = new SiteString(site);
}
// Finally we parse out the directory string
// ex. http://www.microsoft.com/complus -> m_directory = "complus"
String directoryString = temp.Substring(index + 1);
if (directoryString.Length == 0)
{
m_directory = new DirectoryString();
}
else
{
m_directory = new DirectoryString(directoryString, fileProtocol);
}
}
String builtUrl;
if (fileProtocol)
{
String directory = m_directory.ToString();
String localSite = m_localSite.ToString();
builtUrl = "file://" + localSite;
if (directory != null && !directory.Equals("") && (!directory.Equals("*") || localSite.IndexOf('*') == -1))
{
builtUrl += "/" + directory;
}
}
else
{
builtUrl = m_protocol + "://" + m_siteString.ToString();
if (m_port != -1)
{
builtUrl += ":" + m_port;
}
builtUrl += "/" + m_directory.ToString();
}
m_fullurl = builtUrl;
}