System.Uri.Uri.ParseNoExceptions C# (CSharp) Method

ParseNoExceptions() private method

private ParseNoExceptions ( UriKind kind, string uriString ) : string
kind UriKind
uriString string
return string
		private string ParseNoExceptions (UriKind kind, string uriString)
		{
			//
			// From RFC 2396 :
			//
			//      ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
			//       12            3  4          5       6  7        8 9
			//			
			
			uriString = uriString.Trim();
			int len = uriString.Length;

			if (len == 0){
				if (kind == UriKind.Relative || kind == UriKind.RelativeOrAbsolute){
					isAbsoluteUri = false;
					return null;
				}
			}
			
			if (len <= 1 && (kind != UriKind.Relative))
				return "Absolute URI is too short";

			int pos = 0;

			// 1, 2
			// Identify Windows path, unix path, or standard URI.
			pos = uriString.IndexOf (':');
			if (pos == 0) {
				return "Invalid URI: The format of the URI could not be determined.";
			} else if (pos < 0) {
				// It must be Unix file path or Windows UNC
				if (uriString [0] == '/' && Path.DirectorySeparatorChar == '/'){
					ParseAsUnixAbsoluteFilePath (uriString);
#if NET_2_1 && !MONOTOUCH
					isAbsoluteUri = false;
#else
					if (kind == UriKind.Relative)
						isAbsoluteUri = false;
#endif
					
				} else if (uriString.Length >= 2 && uriString [0] == '\\' && uriString [1] == '\\')
					ParseAsWindowsUNC (uriString);
				else {
					/* Relative path */
					isAbsoluteUri = false;
					path = uriString;
				}
				return null;
			} else if (pos == 1) {
				if (!IsAlpha (uriString [0]))
					return "URI scheme must start with a letter.";
				// This means 'a:' == windows full path.
				string msg = ParseAsWindowsAbsoluteFilePath (uriString);
				if (msg != null)
					return msg;
				return null;
			} 

			// scheme
			scheme = uriString.Substring (0, pos).ToLower (CultureInfo.InvariantCulture);

			// Check scheme name characters as specified in RFC2396.
			// Note: different checks in 1.x and 2.0
			if (!CheckSchemeName (scheme)) 
				return Locale.GetText ("URI scheme must start with a letter and must consist of one of alphabet, digits, '+', '-' or '.' character.");

			// from here we're practically working on uriString.Substring(startpos,endpos-startpos)
			int startpos = pos + 1;
			int endpos = uriString.Length;

			// 8 fragment
			pos = uriString.IndexOf ('#', startpos);
			if (!IsUnc && pos != -1) {
				if (userEscaped)
					fragment = uriString.Substring (pos);
				else
					fragment = "#" + EscapeString (uriString.Substring (pos+1));

				endpos = pos;
			}

			// 6 query
			pos = uriString.IndexOf ('?', startpos, endpos-startpos);
			if (pos != -1) {
				query = uriString.Substring (pos, endpos-pos);
				endpos = pos;
				if (!userEscaped)
					query = EscapeString (query);
			}

			// 3
			if (IsPredefinedScheme (scheme) && scheme != UriSchemeMailto && scheme != UriSchemeNews && (
				(endpos-startpos < 2) ||
				(endpos-startpos >= 2 && uriString [startpos] == '/' && uriString [startpos+1] != '/')))				
				return "Invalid URI: The Authority/Host could not be parsed.";
			
			
			bool startsWithSlashSlash = endpos-startpos >= 2 && uriString [startpos] == '/' && uriString [startpos+1] == '/';
			bool unixAbsPath = scheme == UriSchemeFile && startsWithSlashSlash && (endpos-startpos == 2 || uriString [startpos+2] == '/');
			bool windowsFilePath = false;
			if (startsWithSlashSlash) {
				if (kind == UriKind.Relative)
					return "Absolute URI when we expected a relative one";
				
				if (scheme != UriSchemeMailto && scheme != UriSchemeNews)
					startpos += 2;

				if (scheme == UriSchemeFile) {
					int num_leading_slash = 2;
					for (int i = startpos; i < endpos; i++) {
						if (uriString [i] != '/')
							break;
						num_leading_slash++;
					}
					if (num_leading_slash >= 4) {
						unixAbsPath = false;
						while (startpos < endpos && uriString[startpos] == '/') {
							startpos++;
						}
					} else if (num_leading_slash >= 3) {
						startpos += 1;
					}
				}
				
				if (endpos - startpos > 1 && uriString [startpos + 1] == ':') {
					unixAbsPath = false;
					windowsFilePath = true;
				}

			} else if (!IsPredefinedScheme (scheme)) {
				path = uriString.Substring(startpos, endpos-startpos);
				isOpaquePart = true;
				return null;
			}

			// 5 path
			if (unixAbsPath) {
				pos = -1;
			} else {
				pos = uriString.IndexOf ('/', startpos, endpos-startpos);
				if (pos == -1 && windowsFilePath)
					pos = uriString.IndexOf ('\\', startpos, endpos-startpos);
			}

			if (pos == -1) {
				if ((scheme != Uri.UriSchemeMailto) &&
#if ONLY_1_1
				    (scheme != Uri.UriSchemeFile) &&
#endif
				    (scheme != Uri.UriSchemeNews))
					path = "/";
			} else {
				path = uriString.Substring (pos, endpos-pos);
				endpos = pos;
			}

			// 4.a user info
			if (unixAbsPath)
				pos = -1;
			else
				pos = uriString.IndexOf ('@', startpos, endpos-startpos);
			if (pos != -1) {
				userinfo = uriString.Substring (startpos, pos-startpos);
				startpos = pos + 1;
			}

			// 4.b port
			port = -1;
			if (unixAbsPath)
				pos = -1;
			else
				pos = uriString.LastIndexOf (':', endpos-1, endpos-startpos);
			if (pos != -1 && pos != endpos - 1) {
				string portStr = uriString.Substring(pos + 1, endpos - (pos + 1));
				if (portStr.Length > 0 && portStr[portStr.Length - 1] != ']') {
#if NET_2_0
					if (!Int32.TryParse (portStr, NumberStyles.Integer, CultureInfo.InvariantCulture, out port) ||
					    port < 0 || port > UInt16.MaxValue)
						return "Invalid URI: Invalid port number";
					endpos = pos;
#else
					try {
						port = (int) UInt32.Parse (portStr, CultureInfo.InvariantCulture);
						endpos = pos;
					} catch (Exception) {
						return "Invalid URI: Invalid port number";
					}
#endif
				} else {
					if (port == -1) {
						port = GetDefaultPort (scheme);
					}
				}
			} else {
				if (port == -1) {
					port = GetDefaultPort (scheme);
				}
			}
			
			// 4 authority
			uriString = uriString.Substring(startpos, endpos-startpos);
			host = uriString;

			if (unixAbsPath) {
				path = Reduce ('/' + uriString, true);
				host = String.Empty;
			} else if (host.Length == 2 && host [1] == ':') {
				// windows filepath
				path = host + path;
				host = String.Empty;
			} else if (isUnixFilePath) {
				uriString = "//" + uriString;
				host = String.Empty;
			} else if (scheme == UriSchemeFile) {
				isUnc = true;
			} else if (scheme == UriSchemeNews) {
				// no host for 'news', misinterpreted path
				if (host.Length > 0) {
					path = host;
					host = String.Empty;
				}
			} else if (host.Length == 0 &&
				   (scheme == UriSchemeHttp || scheme == UriSchemeGopher || scheme == UriSchemeNntp ||
				    scheme == UriSchemeHttps || scheme == UriSchemeFtp)) {
				return "Invalid URI: The hostname could not be parsed";
			}

			bool badhost = ((host.Length > 0) && (CheckHostName (host) == UriHostNameType.Unknown));
			if (!badhost && (host.Length > 1) && (host[0] == '[') && (host[host.Length - 1] == ']')) {
				IPv6Address ipv6addr;
				
				if (IPv6Address.TryParse (host, out ipv6addr))
					host = "[" + ipv6addr.ToString (true) + "]";
				else
					badhost = true;
			}
#if NET_2_0
			if (badhost && (Parser is DefaultUriParser || Parser == null))
				return Locale.GetText ("Invalid URI: The hostname could not be parsed. (" + host + ")");

			UriFormatException ex = null;
			if (Parser != null)
				Parser.InitializeAndValidate (this, out ex);
			if (ex != null)
				return ex.Message;
#else
			if (badhost)
				return Locale.GetText ("Invalid URI: The hostname could not be parsed. (" + host + ")");
#endif

			if ((scheme != Uri.UriSchemeMailto) &&
					(scheme != Uri.UriSchemeNews) &&
					(scheme != Uri.UriSchemeFile)) {
				path = Reduce (path, CompactEscaped (scheme));
			}

			return null;
		}