static UriParser() { m_Table[HttpUri.SchemeName] = HttpUri; HttpsUri = new BuiltInUriParser("https", 0x1bb, HttpUri.m_Flags); m_Table[HttpsUri.SchemeName] = HttpsUri; FtpUri = new BuiltInUriParser("ftp", 0x15, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.CanonicalizeAsFilePath | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.MustHaveAuthority); m_Table[FtpUri.SchemeName] = FtpUri; FileUri = new BuiltInUriParser("file", -1, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.UnEscapeDotsAndSlashes | UriSyntaxFlags.CanonicalizeAsFilePath | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowDOSPath | UriSyntaxFlags.FileLikeUri | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MustHaveAuthority); m_Table[FileUri.SchemeName] = FileUri; GopherUri = new BuiltInUriParser("gopher", 70, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.MustHaveAuthority); m_Table[GopherUri.SchemeName] = GopherUri; NntpUri = new BuiltInUriParser("nntp", 0x77, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.MustHaveAuthority); m_Table[NntpUri.SchemeName] = NntpUri; NewsUri = new BuiltInUriParser("news", -1, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath); m_Table[NewsUri.SchemeName] = NewsUri; MailToUri = new BuiltInUriParser("mailto", 0x19, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.MailToLikeUri | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo); m_Table[MailToUri.SchemeName] = MailToUri; UuidUri = new BuiltInUriParser("uuid", -1, NewsUri.m_Flags); m_Table[UuidUri.SchemeName] = UuidUri; TelnetUri = new BuiltInUriParser("telnet", 0x17, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.MustHaveAuthority); m_Table[TelnetUri.SchemeName] = TelnetUri; LdapUri = new BuiltInUriParser("ldap", 0x185, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.MustHaveAuthority); m_Table[LdapUri.SchemeName] = LdapUri; NetTcpUri = new BuiltInUriParser("net.tcp", 0x328, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.UnEscapeDotsAndSlashes | UriSyntaxFlags.CanonicalizeAsFilePath | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MustHaveAuthority); m_Table[NetTcpUri.SchemeName] = NetTcpUri; NetPipeUri = new BuiltInUriParser("net.pipe", -1, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.UnEscapeDotsAndSlashes | UriSyntaxFlags.CanonicalizeAsFilePath | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MustHaveAuthority); m_Table[NetPipeUri.SchemeName] = NetPipeUri; VsMacrosUri = new BuiltInUriParser("vsmacros", -1, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.UnEscapeDotsAndSlashes | UriSyntaxFlags.CanonicalizeAsFilePath | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.AllowDOSPath | UriSyntaxFlags.FileLikeUri | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MustHaveAuthority); m_Table[VsMacrosUri.SchemeName] = VsMacrosUri; }
static UriParser() { s_table = new LowLevelDictionary <string, UriParser>(c_InitialTableSize); s_tempTable = new LowLevelDictionary <string, UriParser>(c_InitialTableSize); //Now we will call for the instance constructors that will interrupt this static one. // Below we simulate calls into FetchSyntax() but avoid using lock() and other things redundant for a .cctor HttpUri = new BuiltInUriParser("http", 80, HttpSyntaxFlags); s_table[HttpUri.SchemeName] = HttpUri; //HTTP HttpsUri = new BuiltInUriParser("https", 443, HttpUri._flags); s_table[HttpsUri.SchemeName] = HttpsUri; //HTTPS cloned from HTTP WsUri = new BuiltInUriParser("ws", 80, HttpSyntaxFlags); s_table[WsUri.SchemeName] = WsUri; // WebSockets WssUri = new BuiltInUriParser("wss", 443, HttpSyntaxFlags); s_table[WssUri.SchemeName] = WssUri; // Secure WebSockets FtpUri = new BuiltInUriParser("ftp", 21, FtpSyntaxFlags); s_table[FtpUri.SchemeName] = FtpUri; //FTP FileUri = new BuiltInUriParser("file", NoDefaultPort, s_fileSyntaxFlags); s_table[FileUri.SchemeName] = FileUri; //FILE GopherUri = new BuiltInUriParser("gopher", 70, GopherSyntaxFlags); s_table[GopherUri.SchemeName] = GopherUri; //GOPHER NntpUri = new BuiltInUriParser("nntp", 119, NntpSyntaxFlags); s_table[NntpUri.SchemeName] = NntpUri; //NNTP NewsUri = new BuiltInUriParser("news", NoDefaultPort, NewsSyntaxFlags); s_table[NewsUri.SchemeName] = NewsUri; //NEWS MailToUri = new BuiltInUriParser("mailto", 25, MailtoSyntaxFlags); s_table[MailToUri.SchemeName] = MailToUri; //MAILTO UuidUri = new BuiltInUriParser("uuid", NoDefaultPort, NewsUri._flags); s_table[UuidUri.SchemeName] = UuidUri; //UUID cloned from NEWS TelnetUri = new BuiltInUriParser("telnet", 23, TelnetSyntaxFlags); s_table[TelnetUri.SchemeName] = TelnetUri; //TELNET LdapUri = new BuiltInUriParser("ldap", 389, LdapSyntaxFlags); s_table[LdapUri.SchemeName] = LdapUri; //LDAP NetTcpUri = new BuiltInUriParser("net.tcp", 808, NetTcpSyntaxFlags); s_table[NetTcpUri.SchemeName] = NetTcpUri; NetPipeUri = new BuiltInUriParser("net.pipe", NoDefaultPort, NetPipeSyntaxFlags); s_table[NetPipeUri.SchemeName] = NetPipeUri; VsMacrosUri = new BuiltInUriParser("vsmacros", NoDefaultPort, VsmacrosSyntaxFlags); s_table[VsMacrosUri.SchemeName] = VsMacrosUri; //VSMACROS }
// // a Uri.TryCreate() method goes through here. // internal static Uri CreateHelper(string uriString, bool dontEscape, UriKind uriKind, ref UriFormatException e) { // if (!Enum.IsDefined(typeof(UriKind), uriKind)) -- We currently believe that Enum.IsDefined() is too slow // to be used here. if ((int)uriKind < (int)UriKind.RelativeOrAbsolute || (int)uriKind > (int)UriKind.Relative) { #if MONO if (uriKind != DotNetRelativeOrAbsolute) #endif throw new ArgumentException(SR.GetString(SR.net_uri_InvalidUriKind, uriKind)); } UriParser syntax = null; Flags flags = Flags.Zero; ParsingError err = ParseScheme(uriString, ref flags, ref syntax); if (dontEscape) { flags |= Flags.UserEscaped; } // We won't use User factory for these errors if (err != ParsingError.None) { // If it looks as a relative Uri, custom factory is ignored if (uriKind != UriKind.Absolute && err <= ParsingError.LastRelativeUriOkErrIndex) { return(new Uri((flags & Flags.UserEscaped), null, uriString)); } return(null); } // Cannot be relative Uri if came here Uri result = new Uri(flags, syntax, uriString); // Validate instance using ether built in or a user Parser try { result.InitializeUri(err, uriKind, out e); if (e == null) { return(result); } return(null); } catch (UriFormatException ee) { Debug.Assert(!syntax.IsSimple, "A UriPraser threw on InitializeAndValidate."); e = ee; // A precaution since custom Parser should never throw in this case. return(null); } }
internal static UriParser GetSyntax(string lwrCaseScheme) { UriParser ret = null; s_table.TryGetValue(lwrCaseScheme, out ret); if (ret == null) { s_tempTable.TryGetValue(lwrCaseScheme, out ret); } return(ret); }
internal UriParser InternalOnNewUri() { UriParser parser = this.OnNewUri(); if (this != parser) { parser.m_Scheme = this.m_Scheme; parser.m_Port = this.m_Port; parser.m_Flags = this.m_Flags; } return(parser); }
// // These are simple internal wrappers that will call virtual protected methods // (to avoid "protected internal" siganures in the public docs) // internal UriParser InternalOnNewUri() { UriParser effectiveParser = OnNewUri(); if ((object)this != (object)effectiveParser) { effectiveParser.m_Scheme = m_Scheme; effectiveParser.m_Port = m_Port; effectiveParser.m_Flags = m_Flags; } return(effectiveParser); }
// // These are simple internal wrappers that will call virtual protected methods // (to avoid "protected internal" siganures in the public docs) // internal UriParser InternalOnNewUri() { UriParser effectiveParser = OnNewUri(); if ((object)this != (object)effectiveParser) { effectiveParser._scheme = _scheme; effectiveParser._port = _port; effectiveParser._flags = _flags; } return(effectiveParser); }
// // Is a Uri scheme known to System.Uri? // public static bool IsKnownScheme(string schemeName) { ArgumentNullException.ThrowIfNull(schemeName); if (!Uri.CheckSchemeName(schemeName)) { throw new ArgumentOutOfRangeException(nameof(schemeName)); } UriParser?syntax = UriParser.GetSyntax(schemeName.ToLowerInvariant()); return(syntax != null && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri)); }
public static bool IsKnownScheme(string schemeName) { if (schemeName == null) { throw new ArgumentNullException("schemeName"); } if (!CheckSchemeName(schemeName)) { throw new ArgumentOutOfRangeException("schemeName"); } UriParser syntax = GetSyntax(schemeName.ToLower(CultureInfo.InvariantCulture)); return((syntax != null) && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri)); }
public override string ToString() { StringBuilder builder = new StringBuilder(); builder.Append(scheme); // note: mailto and news use ':', not "://", as their delimiter if (UriParser.IsKnownScheme(scheme)) { builder.Append(Uri.GetSchemeDelimiter(scheme)); } else { builder.Append(host.Length > 0 ? Uri.SchemeDelimiter : ":"); } if (username != String.Empty) { builder.Append(username); if (password != String.Empty) { builder.Append(":" + password); } builder.Append('@'); } if (host.Length > 0) { builder.Append(host); if (port > 0) { builder.Append(":" + port); } } if (path != String.Empty && builder [builder.Length - 1] != '/' && path.Length > 0 && path [0] != '/' && host.Length > 0) { builder.Append('/'); } builder.Append(path); builder.Append(query); builder.Append(fragment); return(builder.ToString()); }
private static void InternalRegister(Hashtable table, UriParser uriParser, string schemeName, int defaultPort) { uriParser.SchemeName = schemeName; uriParser.DefaultPort = defaultPort; if (uriParser is GenericUriParser) { table.Add(schemeName, uriParser); } else { DefaultUriParser defaultUriParser = new DefaultUriParser(); defaultUriParser.SchemeName = schemeName; defaultUriParser.DefaultPort = defaultPort; table.Add(schemeName, defaultUriParser); } uriParser.OnRegister(schemeName, defaultPort); }
private static void InternalRegister(Hashtable table, System.UriParser uriParser, string schemeName, int defaultPort) { uriParser.SchemeName = schemeName; uriParser.DefaultPort = defaultPort; if (uriParser is System.GenericUriParser) { table.Add(schemeName, uriParser); } else { table.Add(schemeName, new DefaultUriParser { SchemeName = schemeName, DefaultPort = defaultPort }); } uriParser.OnRegister(schemeName, defaultPort); }
// *no* check version private static void InternalRegister(Hashtable table, UriParser uriParser, string schemeName, int defaultPort) { uriParser.SchemeName = schemeName; uriParser.DefaultPort = defaultPort; // FIXME: MS doesn't seems to call most inherited parsers if (uriParser is GenericUriParser) { table.Add(schemeName, uriParser); } else { DefaultUriParser parser = new DefaultUriParser(); parser.SchemeName = schemeName; parser.DefaultPort = defaultPort; table.Add(schemeName, parser); } // note: we cannot set schemeName and defaultPort inside OnRegister uriParser.OnRegister(schemeName, defaultPort); }
public override string ToString() { if ((this.m_username.Length == 0) && (this.m_password.Length > 0)) { throw new UriFormatException(SR.GetString("net_uri_BadUserPassword")); } if (this.m_scheme.Length != 0) { UriParser syntax = UriParser.GetSyntax(this.m_scheme); if (syntax != null) { this.m_schemeDelimiter = (syntax.InFact(UriSyntaxFlags.MustHaveAuthority) || (((this.m_host.Length != 0) && syntax.NotAny(UriSyntaxFlags.MailToLikeUri)) && syntax.InFact(UriSyntaxFlags.OptionalAuthority))) ? System.Uri.SchemeDelimiter : ":"; } else { this.m_schemeDelimiter = (this.m_host.Length != 0) ? System.Uri.SchemeDelimiter : ":"; } } string str = (this.m_scheme.Length != 0) ? (this.m_scheme + this.m_schemeDelimiter) : string.Empty; string[] strArray = new string[] { str, this.m_username, (this.m_password.Length > 0) ? (":" + this.m_password) : string.Empty, (this.m_username.Length > 0) ? "@" : string.Empty, this.m_host, ((this.m_port != -1) && (this.m_host.Length > 0)) ? (":" + this.m_port) : string.Empty, (((this.m_host.Length > 0) && (this.m_path.Length != 0)) && (this.m_path[0] != '/')) ? "/" : string.Empty, this.m_path, this.m_query, this.m_fragment }; return(string.Concat(strArray)); }
// // Static Registration methods // // // Registers a custom Uri parser based on a scheme string // public static void Register(UriParser uriParser, string schemeName, int defaultPort) { ArgumentNullException.ThrowIfNull(uriParser); ArgumentNullException.ThrowIfNull(schemeName); if (schemeName.Length == 1) { throw new ArgumentOutOfRangeException(nameof(schemeName)); } if (!Uri.CheckSchemeName(schemeName)) { throw new ArgumentOutOfRangeException(nameof(schemeName)); } if ((defaultPort > 0xFFFF || defaultPort < 0) && defaultPort != -1) { throw new ArgumentOutOfRangeException(nameof(defaultPort)); } schemeName = schemeName.ToLowerInvariant(); FetchSyntax(uriParser, schemeName, defaultPort); }
//schemeStr must be in lower case! internal static UriParser FindOrFetchAsUnknownV1Syntax(string lwrCaseScheme) { // check may be other thread just added one UriParser syntax = (UriParser)m_Table[lwrCaseScheme]; if (syntax != null) { return(syntax); } syntax = (UriParser)m_TempTable[lwrCaseScheme]; if (syntax != null) { return(syntax); } lock (m_Table) { if (m_TempTable.Count >= c_MaxCapacity) { m_TempTable = new System.Collections.Hashtable(c_InitialTableSize); } syntax = new BuiltInUriParser(lwrCaseScheme, NoDefaultPort, UnknownV1SyntaxFlags); m_TempTable[lwrCaseScheme] = syntax; return(syntax); } }
internal static UriParser FindOrFetchAsUnknownV1Syntax(string lwrCaseScheme) { UriParser parser = (UriParser)m_Table[lwrCaseScheme]; if (parser != null) { return(parser); } parser = (UriParser)m_TempTable[lwrCaseScheme]; if (parser != null) { return(parser); } lock (m_Table) { if (m_TempTable.Count >= 0x200) { m_TempTable = new Hashtable(0x19); } parser = new BuiltInUriParser(lwrCaseScheme, -1, UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowDOSPath | UriSyntaxFlags.V1_UnknownUri | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.OptionalAuthority); m_TempTable[lwrCaseScheme] = parser; return(parser); } }
/// <summary>Associates a scheme and port number with a <see cref="T:System.UriParser" />.</summary> /// <param name="uriParser">The URI parser to register.</param> /// <param name="schemeName">The name of the scheme that is associated with this parser.</param> /// <param name="defaultPort">The default port number for the specified scheme.</param> /// <exception cref="T:System.ArgumentNullException"> /// <paramref name="uriParser" /> parameter is null- or -<paramref name="schemeName" /> parameter is null.</exception> /// <exception cref="T:System.ArgumentOutOfRangeException"> /// <paramref name="schemeName" /> parameter is not valid- or -<paramref name="defaultPort" /> parameter is not valid. The <paramref name="defaultPort" /> parameter must be not be less than zero or greater than 65,534.</exception> public static void Register(System.UriParser uriParser, string schemeName, int defaultPort) { if (uriParser == null) { throw new ArgumentNullException("uriParser"); } if (schemeName == null) { throw new ArgumentNullException("schemeName"); } if (defaultPort < -1 || defaultPort >= 65535) { throw new ArgumentOutOfRangeException("defaultPort"); } System.UriParser.CreateDefaults(); string text = schemeName.ToLower(CultureInfo.InvariantCulture); if (System.UriParser.table[text] != null) { string text2 = Locale.GetText("Scheme '{0}' is already registred."); throw new InvalidOperationException(text2); } System.UriParser.InternalRegister(System.UriParser.table, uriParser, text, defaultPort); }
public static bool TryParseComponents(string uri, UriKind kind, out UriElements elements, out string error) { uri = uri.Trim(); ParserState state = new ParserState(uri, kind); elements = state.elements; error = null; if (uri.Length == 0 && (kind == UriKind.Relative || kind == UriKind.RelativeOrAbsolute)) { state.elements.isAbsoluteUri = false; return(true); } if (uri.Length <= 1 && kind == UriKind.Absolute) { error = "Absolute URI is too short"; return(false); } bool ok = ParseFilePath(state) && ParseScheme(state); var scheme = state.elements.scheme; UriParser parser = null; if (!string.IsNullOrEmpty(scheme)) { parser = UriParser.GetParser(scheme); if (parser != null && !(parser is DefaultUriParser)) { return(true); } } ok = ok && ParseAuthority(state) && ParsePath(state) && ParseQuery(state) && ParseFragment(state); if (string.IsNullOrEmpty(state.elements.host) && (scheme == Uri.UriSchemeHttp || scheme == Uri.UriSchemeGopher || scheme == Uri.UriSchemeNntp || scheme == Uri.UriSchemeHttps || scheme == Uri.UriSchemeFtp)) { state.error = "Invalid URI: The Authority/Host could not be parsed."; } if (!string.IsNullOrEmpty(state.elements.host) && Uri.CheckHostName(state.elements.host) == UriHostNameType.Unknown) { state.error = "Invalid URI: The hostname could not be parsed."; } if (!string.IsNullOrEmpty(state.error)) { elements = null; error = state.error; return(false); } return(true); }
// Should never be used except by the below method private Uri(Flags flags, UriParser uriParser, string uri) { m_Flags = flags; m_Syntax = uriParser; m_String = uri; }
// // Static Registration methods // // // Registers a custom Uri parser based on a scheme string // public static void Register(UriParser uriParser, string schemeName, int defaultPort) { if (uriParser == null) throw new ArgumentNullException("uriParser"); if (schemeName == null) throw new ArgumentNullException("schemeName"); if (schemeName.Length == 1) throw new ArgumentOutOfRangeException("schemeName"); if (!Uri.CheckSchemeName(schemeName)) throw new ArgumentOutOfRangeException("schemeName"); if ((defaultPort >= 0xFFFF || defaultPort < 0) && defaultPort != -1) throw new ArgumentOutOfRangeException("defaultPort"); schemeName = schemeName.ToLower(); FetchSyntax(uriParser, schemeName, defaultPort); }
private static bool StaticIsFile(UriParser syntax) { return syntax.InFact(UriSyntaxFlags.FileLikeUri); }
private static unsafe char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery, bool readOnlyConfig) { fixed (char* str = ((char*) input)) { char* pStr = str; return UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery, readOnlyConfig); } }
private static unsafe bool CheckKnownSchemes(long *lptr, ushort nChars, ref UriParser syntax) => default; // 0x00000001809CF5A0-0x00000001809CFB50 private static unsafe ParsingError CheckSchemeSyntax(char *ptr, ushort length, ref UriParser syntax) => default; // 0x00000001809CFC90-0x00000001809CFDC0
private static unsafe ParsingError ParseScheme(string uriString, ref Flags flags, ref UriParser syntax) { int length = uriString.Length; if (length == 0) { return ParsingError.EmptyUriString; } if (length >= 0xfff0) { return ParsingError.SizeLimit; } fixed (char* str = ((char*) uriString)) { char* chPtr = str; ParsingError none = ParsingError.None; ushort num2 = ParseSchemeCheckImplicitFile(chPtr, (ushort) length, ref none, ref flags, ref syntax); if (none != ParsingError.None) { return none; } flags |= (Flags) num2; } return ParsingError.None; }
// // Uri(Uri , Uri ) // Note: a static Create() method should be used by users, not this .ctor // public Uri(Uri baseUri, Uri relativeUri) { if ((object)baseUri == null) throw new ArgumentNullException(nameof(baseUri)); if (!baseUri.IsAbsoluteUri) throw new ArgumentOutOfRangeException(nameof(baseUri)); CreateThisFromUri(relativeUri); string newUriString = null; UriFormatException e; bool dontEscape; if (baseUri.Syntax.IsSimple) { dontEscape = InFact(Flags.UserEscaped); relativeUri = ResolveHelper(baseUri, this, ref newUriString, ref dontEscape, out e); if (e != null) throw e; if (relativeUri != null) { if ((object)relativeUri != (object)this) CreateThisFromUri(relativeUri); return; } } else { dontEscape = false; newUriString = baseUri.Syntax.InternalResolve(baseUri, this, out e); if (e != null) throw e; } _flags = Flags.Zero; _info = null; _syntax = null; CreateThis(newUriString, dontEscape, UriKind.Absolute); }
// // This will compress any "\" "/../" "/./" "///" "/..../" /XXX.../, etc found in the input // // The passed syntax controls whether to use aggressive compression or the one specified in RFC 2396 // private static char[] Compress(char[] dest, ushort start, ref int destLength, UriParser syntax) { ushort slashCount = 0; ushort lastSlash = 0; ushort dotCount = 0; ushort removeSegments = 0; unchecked { //ushort i == -1 and start == -1 overflow is ok here ushort i = (ushort)((ushort)destLength - (ushort)1); start = (ushort)(start - 1); for (; i != start; --i) { char ch = dest[i]; if (ch == '\\' && syntax.InFact(UriSyntaxFlags.ConvertPathSlashes)) { dest[i] = ch = '/'; } // // compress multiple '/' for file URI // if (ch == '/') { ++slashCount; } else { if (slashCount > 1) { // else preserve repeated slashes lastSlash = (ushort)(i + 1); } slashCount = 0; } if (ch == '.') { ++dotCount; continue; } else if (dotCount != 0) { bool skipSegment = syntax.NotAny(UriSyntaxFlags.CanonicalizeAsFilePath) && (dotCount > 2 || ch != '/' || i == start); // // Cases: // /./ = remove this segment // /../ = remove this segment, mark next for removal // /....x = DO NOT TOUCH, leave as is // x.../ = DO NOT TOUCH, leave as is, except for V2 legacy mode // if (!skipSegment && ch == '/') { if ((lastSlash == i + dotCount + 1 // "/..../" || (lastSlash == 0 && i + dotCount + 1 == destLength)) // "/..." && (dotCount <= 2)) { // // /./ or /.<eos> or /../ or /..<eos> // // just reusing a variable slot we perform //dest.Remove(i+1, dotCount + (lastSlash==0?0:1)); lastSlash = (ushort)(i + 1 + dotCount + (lastSlash == 0 ? 0 : 1)); Buffer.BlockCopy(dest, lastSlash << 1, dest, (i + 1) << 1, (destLength - lastSlash) << 1); destLength -= (lastSlash - i - 1); lastSlash = i; if (dotCount == 2) { // // We have 2 dots in between like /../ or /..<eos>, // Mark next segment for removal and remove this /../ or /.. // ++removeSegments; } dotCount = 0; continue; } } // .NET 4.5 no longer removes trailing dots in a path segment x.../ or x...<eos> dotCount = 0; // // Here all other cases go such as // x.[..]y or /.[..]x or (/x.[...][/] && removeSegments !=0) } // // Now we may want to remove a segment because of previous /../ // if (ch == '/') { if (removeSegments != 0) { --removeSegments; // just reusing a variable slot we perform //dest.Remove(i+1, lastSlash - i); lastSlash = (ushort)(lastSlash + 1); Buffer.BlockCopy(dest, lastSlash << 1, dest, (i + 1) << 1, (destLength - lastSlash) << 1); destLength -= (lastSlash - i - 1); } lastSlash = i; } } start = (ushort)((ushort)start + (ushort)1); } //end of unchecked if ((ushort)destLength > start && syntax.InFact(UriSyntaxFlags.CanonicalizeAsFilePath)) { if (slashCount <= 1) { if (removeSegments != 0 && dest[start] != '/') { //remove first not rooted segment lastSlash = (ushort)(lastSlash + 1); Buffer.BlockCopy(dest, lastSlash << 1, dest, start << 1, (destLength - lastSlash) << 1); destLength -= lastSlash; } else if (dotCount != 0) { // If final string starts with a segment looking like .[...]/ or .[...]<eos> // then we remove this first segment if (lastSlash == dotCount + 1 || (lastSlash == 0 && dotCount + 1 == destLength)) { dotCount = (ushort)(dotCount + (lastSlash == 0 ? 0 : 1)); Buffer.BlockCopy(dest, dotCount << 1, dest, start << 1, (destLength - dotCount) << 1); destLength -= dotCount; } } } } return dest; }
private unsafe void CheckAuthorityHelperHandleDnsIri(char* pString, ushort start, int end, int startInput, bool iriParsing, bool hasUnicode, UriParser syntax, string userInfoString, ref Flags flags, ref bool justNormalized, ref string newHost, ref ParsingError err) { // comes here only if host has unicode chars and iri is on or idn is allowed flags |= Flags.DnsHostType; // check if intranet // if ((s_IdnScope == UriIdnScope.AllExceptIntranet) && IsIntranet(new string(pString, 0, end))) { flags |= Flags.IntranetUri; } if (AllowIdnStatic(syntax, flags)) { bool allAscii = true; bool atLeastOneIdn = false; string idnValue = DomainNameHelper.IdnEquivalent(pString, start, end, ref allAscii, ref atLeastOneIdn); string UniEquvlt = DomainNameHelper.UnicodeEquivalent(idnValue, pString, start, end); if (!allAscii) flags |= Flags.UnicodeHost; // we have a unicode host if (atLeastOneIdn) flags |= Flags.IdnHost; // we have at least one valid idn label if (allAscii && atLeastOneIdn && StaticNotAny(flags, Flags.HasUnicode)) { // original string location changed lazily _originalUnicodeString = _string; newHost = _originalUnicodeString.Substring(0, startInput) + (StaticInFact(flags, Flags.HasUserInfo) ? userInfoString : null); justNormalized = true; } else if (!iriParsing && (StaticInFact(flags, Flags.UnicodeHost) || StaticInFact(flags, Flags.IdnHost))) { // original string location changed lazily _originalUnicodeString = _string; newHost = _originalUnicodeString.Substring(0, startInput) + (StaticInFact(flags, Flags.HasUserInfo) ? userInfoString : null); justNormalized = true; } if (!(allAscii && !atLeastOneIdn)) { _dnsSafeHost = idnValue; newHost += UniEquvlt; justNormalized = true; } else if (allAscii && !atLeastOneIdn && iriParsing && hasUnicode) { newHost += UniEquvlt; justNormalized = true; } } else { if (hasUnicode) { string temp = UriHelper.StripBidiControlCharacter(pString, start, end - start); try { newHost += ((temp != null) ? temp.Normalize(NormalizationForm.FormC) : null); } catch (ArgumentException) { err = ParsingError.BadHostName; } justNormalized = true; } } flags |= Flags.HostUnicodeNormalized; }
private unsafe void CheckAuthorityHelperHandleAnyHostIri(char* pString, int startInput, int end, bool iriParsing, bool hasUnicode, UriParser syntax, ref Flags flags, ref string newHost, ref ParsingError err) { if (StaticNotAny(flags, Flags.HostUnicodeNormalized) && (AllowIdnStatic(syntax, flags) || (iriParsing && hasUnicode))) { // Normalize any other host or do idn string user = new string(pString, startInput, end - startInput); if (AllowIdnStatic(syntax, flags)) { bool allAscii = true; bool atLeastOneIdn = false; string UniEquvlt = DomainNameHelper.UnicodeEquivalent(pString, startInput, end, ref allAscii, ref atLeastOneIdn); if (((allAscii && atLeastOneIdn) || !allAscii) && !(iriParsing && hasUnicode)) { // original string location changed lazily _originalUnicodeString = _string; newHost = _originalUnicodeString.Substring(0, startInput); flags |= Flags.HasUnicode; } if (atLeastOneIdn || !allAscii) { newHost += UniEquvlt; string bidiStrippedHost = null; _dnsSafeHost = DomainNameHelper.IdnEquivalent(pString, startInput, end, ref allAscii, ref bidiStrippedHost); if (atLeastOneIdn) flags |= Flags.IdnHost; if (!allAscii) flags |= Flags.UnicodeHost; } else if (iriParsing && hasUnicode) { newHost += user; } } else { try { newHost += user.Normalize(NormalizationForm.FormC); } catch (ArgumentException) { err = ParsingError.BadHostName; } } flags |= Flags.HostUnicodeNormalized; } }
private void CreateUri(Uri baseUri, string relativeUri, bool dontEscape) { // Parse relativeUri and populate Uri internal data. CreateThis(relativeUri, dontEscape, UriKind.RelativeOrAbsolute); UriFormatException e; if (baseUri.Syntax.IsSimple) { // Resolve Uris if possible OR get merged Uri String to re-parse below Uri uriResult = ResolveHelper(baseUri, this, ref relativeUri, ref dontEscape, out e); if (e != null) throw e; // If resolved into a Uri then we build from that Uri if (uriResult != null) { if ((object)uriResult != (object)this) CreateThisFromUri(uriResult); return; } } else { dontEscape = false; relativeUri = baseUri.Syntax.InternalResolve(baseUri, this, out e); if (e != null) throw e; } _flags = Flags.Zero; _info = null; _syntax = null; // If not resolved, we reparse modified Uri string and populate Uri internal data. CreateThis(relativeUri, dontEscape, UriKind.Absolute); }
// // Checks the syntax of an authority component. It may also get a userInfo if present // Returns an error if no/mailformed authority found // Does not NOT touch m_Info // Returns position of the Path component // // Must be called in the ctor only private unsafe ushort CheckAuthorityHelper(char* pString, ushort idx, ushort length, ref ParsingError err, ref Flags flags, UriParser syntax, ref string newHost) { int end = length; char ch; int startInput = idx; ushort start = idx; newHost = null; bool justNormalized = false; bool iriParsing = (s_IriParsing && IriParsingStatic(syntax)); // perf bool hasUnicode = ((flags & Flags.HasUnicode) != 0); // perf bool hostNotUnicodeNormalized = ((flags & Flags.HostUnicodeNormalized) == 0); // perf UriSyntaxFlags syntaxFlags = syntax.Flags; // need to build new Iri'zed string if (hasUnicode && iriParsing && hostNotUnicodeNormalized) { newHost = _originalUnicodeString.Substring(0, startInput); } //Special case is an empty authority if (idx == length || ((ch = pString[idx]) == '/' || (ch == '\\' && StaticIsFile(syntax)) || ch == '#' || ch == '?')) { if (syntax.InFact(UriSyntaxFlags.AllowEmptyHost)) { flags &= ~Flags.UncPath; //UNC cannot have an empty hostname if (StaticInFact(flags, Flags.ImplicitFile)) err = ParsingError.BadHostName; else flags |= Flags.BasicHostType; } else err = ParsingError.BadHostName; if (hasUnicode && iriParsing && hostNotUnicodeNormalized) { flags |= Flags.HostUnicodeNormalized;// no host } return idx; } string userInfoString = null; // Attempt to parse user info first if ((syntaxFlags & UriSyntaxFlags.MayHaveUserInfo) != 0) { for (; start < end; ++start) { if (start == end - 1 || pString[start] == '?' || pString[start] == '#' || pString[start] == '\\' || pString[start] == '/') { start = idx; break; } else if (pString[start] == '@') { flags |= Flags.HasUserInfo; // Iri'ze userinfo if (iriParsing || (s_IdnScope != UriIdnScope.None)) { if (iriParsing && hasUnicode && hostNotUnicodeNormalized) { // Normalize user info userInfoString = IriHelper.EscapeUnescapeIri(pString, startInput, start + 1, UriComponents.UserInfo); newHost += userInfoString; } else { userInfoString = new string(pString, startInput, start - startInput + 1); } } ++start; ch = pString[start]; break; } } } // DNS name only optimization // Fo an overridden parsing the optimization is suppressed since hostname can be changed to anything bool dnsNotCanonical = ((syntaxFlags & UriSyntaxFlags.SimpleUserSyntax) == 0); if (ch == '[' && syntax.InFact(UriSyntaxFlags.AllowIPv6Host) && IPv6AddressHelper.IsValid(pString, (int)start + 1, ref end)) { flags |= Flags.IPv6HostType; _iriParsing = (s_IriParsing && IriParsingStatic(syntax)); if (hasUnicode && iriParsing && hostNotUnicodeNormalized) { newHost += new string(pString, start, end - start); flags |= Flags.HostUnicodeNormalized; justNormalized = true; } } else if (ch <= '9' && ch >= '0' && syntax.InFact(UriSyntaxFlags.AllowIPv4Host) && IPv4AddressHelper.IsValid(pString, (int)start, ref end, false, StaticNotAny(flags, Flags.ImplicitFile), syntax.InFact(UriSyntaxFlags.V1_UnknownUri))) { flags |= Flags.IPv4HostType; if (hasUnicode && iriParsing && hostNotUnicodeNormalized) { newHost += new string(pString, start, end - start); flags |= Flags.HostUnicodeNormalized; justNormalized = true; } } else if (((syntaxFlags & UriSyntaxFlags.AllowDnsHost) != 0) && !iriParsing && DomainNameHelper.IsValid(pString, start, ref end, ref dnsNotCanonical, StaticNotAny(flags, Flags.ImplicitFile))) { // comes here if there are only ascii chars in host with original parsing and no Iri flags |= Flags.DnsHostType; if (!dnsNotCanonical) { flags |= Flags.CanonicalDnsHost; } if ((s_IdnScope != UriIdnScope.None)) { // check if intranet // if ((s_IdnScope == UriIdnScope.AllExceptIntranet) && IsIntranet(new string(pString, 0, end))) { flags |= Flags.IntranetUri; } if (AllowIdnStatic(syntax, flags)) { bool allAscii = true; bool atLeastOneIdn = false; string idnValue = DomainNameHelper.UnicodeEquivalent(pString, start, end, ref allAscii, ref atLeastOneIdn); // did we find at least one valid idn if (atLeastOneIdn) { // need to switch string here since we didn't know beforehand there was an idn host if (StaticNotAny(flags, Flags.HasUnicode)) _originalUnicodeString = _string; // lazily switching strings flags |= Flags.IdnHost; // need to build string for this special scenario newHost = _originalUnicodeString.Substring(0, startInput) + userInfoString + idnValue; flags |= Flags.CanonicalDnsHost; _dnsSafeHost = new string(pString, start, end - start); justNormalized = true; } flags |= Flags.HostUnicodeNormalized; } } } else if (((syntaxFlags & UriSyntaxFlags.AllowDnsHost) != 0) && ((syntax.InFact(UriSyntaxFlags.AllowIriParsing) && hostNotUnicodeNormalized) || syntax.InFact(UriSyntaxFlags.AllowIdn)) && DomainNameHelper.IsValidByIri(pString, start, ref end, ref dnsNotCanonical, StaticNotAny(flags, Flags.ImplicitFile))) { CheckAuthorityHelperHandleDnsIri(pString, start, end, startInput, iriParsing, hasUnicode, syntax, userInfoString, ref flags, ref justNormalized, ref newHost, ref err); } else if ((syntaxFlags & UriSyntaxFlags.AllowUncHost) != 0) { // // This must remain as the last check before BasicHost type // if (UncNameHelper.IsValid(pString, start, ref end, StaticNotAny(flags, Flags.ImplicitFile))) { if (end - start <= UncNameHelper.MaximumInternetNameLength) flags |= Flags.UncHostType; } } // The deal here is that we won't allow '\' host terminator except for the File scheme // If we see '\' we try to make it a part of a Basic host if (end < length && pString[end] == '\\' && (flags & Flags.HostTypeMask) != Flags.HostNotParsed && !StaticIsFile(syntax)) { if (syntax.InFact(UriSyntaxFlags.V1_UnknownUri)) { err = ParsingError.BadHostName; flags |= Flags.UnknownHostType; return (ushort)end; } flags &= ~Flags.HostTypeMask; } // Here we have checked the syntax up to the end of host // The only thing that can cause an exception is the port value // Spend some (duplicated) cycles on that. else if (end < length && pString[end] == ':') { if (syntax.InFact(UriSyntaxFlags.MayHavePort)) { int port = 0; int startPort = end; for (idx = (ushort)(end + 1); idx < length; ++idx) { ushort val = (ushort)((ushort)pString[idx] - (ushort)'0'); if ((val >= 0) && (val <= 9)) { if ((port = (port * 10 + val)) > 0xFFFF) break; } else if (val == unchecked((ushort)('/' - '0')) || val == (ushort)('?' - '0') || val == unchecked((ushort)('#' - '0'))) { break; } else { // The second check is to keep compatibility with V1 until the UriParser is registered if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost) && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri)) { flags &= ~Flags.HostTypeMask; break; } else { err = ParsingError.BadPort; return idx; } } } // check on 0-ffff range if (port > 0xFFFF) { if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost)) { flags &= ~Flags.HostTypeMask; } else { err = ParsingError.BadPort; return idx; } } if (iriParsing && hasUnicode && justNormalized) { newHost += new string(pString, startPort, idx - startPort); } } else { flags &= ~Flags.HostTypeMask; } } // check on whether nothing has worked out if ((flags & Flags.HostTypeMask) == Flags.HostNotParsed) { //No user info for a Basic hostname flags &= ~Flags.HasUserInfo; // Some schemes do not allow HostType = Basic (plus V1 almost never understands this issue) // if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost)) { flags |= Flags.BasicHostType; for (end = idx; end < length; ++end) { if (pString[end] == '/' || (pString[end] == '?' || pString[end] == '#')) { break; } } CheckAuthorityHelperHandleAnyHostIri(pString, startInput, end, iriParsing, hasUnicode, syntax, ref flags, ref newHost, ref err); } else { // // ATTN V1 compat: V1 supports hostnames like ".." and ".", and so we do but only for unknown schemes. // if (syntax.InFact(UriSyntaxFlags.V1_UnknownUri)) { // Can assert here that the host is not empty so we will set dotFound // at least once or fail before exiting the loop bool dotFound = false; int startOtherHost = idx; for (end = idx; end < length; ++end) { if (dotFound && (pString[end] == '/' || pString[end] == '?' || pString[end] == '#')) break; else if (end < (idx + 2) && pString[end] == '.') { // allow one or two dots dotFound = true; } else { //failure err = ParsingError.BadHostName; flags |= Flags.UnknownHostType; return idx; } } //success flags |= Flags.BasicHostType; if (iriParsing && hasUnicode && StaticNotAny(flags, Flags.HostUnicodeNormalized)) { // Normalize any other host string user = new string(pString, startOtherHost, startOtherHost - end); try { newHost += user.Normalize(NormalizationForm.FormC); } catch (ArgumentException) { err = ParsingError.BadFormat; return idx; } flags |= Flags.HostUnicodeNormalized; } } else if (syntax.InFact(UriSyntaxFlags.MustHaveAuthority) || (syntax.InFact(UriSyntaxFlags.MailToLikeUri))) { err = ParsingError.BadHostName; flags |= Flags.UnknownHostType; return idx; } } } return (ushort)end; }
internal static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) => default; // 0x00000001809CB150-0x00000001809CB230 internal static unsafe char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) => default; // 0x00000001809CB230-0x00000001809CBC20
internal unsafe static char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { byte [] bytes = null; byte escapedReallocations = 0; bool escapeReserved = false; int next = start; bool iriParsing = Uri.IriParsingStatic(syntax) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); while (true) { // we may need to re-pin dest[] fixed(char *pDest = dest) { if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { while (start < end) { pDest[destPosition++] = pStr[start++]; } return(dest); } while (true) { char ch = (char)0; for (; next < end; ++next) { if ((ch = pStr[next]) == '%') { if ((unescapeMode & UnescapeMode.Unescape) == 0) { // re-escape, don't check anything else escapeReserved = true; } else if (next + 2 < end) { ch = EscapedAscii(pStr[next + 1], pStr[next + 2]); // Unescape a good sequence if full unescape is requested if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == Uri.c_DummyChar) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } continue; } } // re-escape % from an invalid sequence else if (ch == Uri.c_DummyChar) { if ((unescapeMode & UnescapeMode.Escape) != 0) { escapeReserved = true; } else { continue; // we should throw instead but since v1.0 woudl just print '%' } } // Do not unescape '%' itself unless full unescape is requested else if (ch == '%') { next += 2; continue; } // Do not unescape a reserved char unless full unescape is requested else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { next += 2; continue; } // Do not unescape a dangerous char unless it's V1ToStringFlags mode else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch)) { next += 2; continue; } else if (iriParsing && ((ch <= '\x9F' && IsNotSafeForUnescape(ch)) || (ch > '\x9F' && !IriHelper.CheckIriUnicodeRange(ch, isQuery)))) { // check if unenscaping gives a char ouside iri range // if it does then keep it escaped next += 2; continue; } // unescape escaped char or escape % break; } else if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } // keep a '%' as part of a bogus sequence continue; } else { escapeReserved = true; } // escape (escapeReserved==ture) or otheriwse unescape the sequence break; } else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) { continue; } else if ((unescapeMode & UnescapeMode.Escape) != 0) { // Could actually escape some of the characters if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F'))) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } } } //copy off previous characters from input while (start < next) { pDest[destPosition++] = pStr[start++]; } if (next != end) { //VsWhidbey#87423 if (escapeReserved) { //escape that char // Since this should be _really_ rare case, reallocate with constant size increase of 30 rsvd-type characters. if (escapedReallocations == 0) { escapedReallocations = 30; char[] newDest = new char[dest.Length + escapedReallocations * 3]; fixed(char *pNewDest = newDest) { for (int i = 0; i < destPosition; ++i) { pNewDest[i] = pDest[i]; } } dest = newDest; // re-pin new dest[] array goto dest_fixed_loop_break; } else { --escapedReallocations; EscapeAsciiChar(pStr[next], dest, ref destPosition); escapeReserved = false; start = ++next; continue; } } // unescaping either one Ascii or possibly multiple Unicode if (ch <= '\x7F') { //ASCII dest[destPosition++] = ch; next += 3; start = next; continue; } // Unicode int byteCount = 1; // lazy initialization of max size, will reuse the array for next sequences if ((object)bytes == null) { bytes = new byte[end - next]; } bytes[0] = (byte)ch; next += 3; while (next < end) { // Check on exit criterion if ((ch = pStr[next]) != '%' || next + 2 >= end) { break; } // already made sure we have 3 characters in str ch = EscapedAscii(pStr[next + 1], pStr[next + 2]); //invalid hex sequence ? if (ch == Uri.c_DummyChar) { break; } // character is not part of a UTF-8 sequence ? else if (ch < '\x80') { break; } else { //a UTF-8 sequence bytes[byteCount++] = (byte)ch; next += 3; } } Encoding noFallbackCharUTF8 = (Encoding)Encoding.UTF8.Clone(); noFallbackCharUTF8.EncoderFallback = new EncoderReplacementFallback(""); noFallbackCharUTF8.DecoderFallback = new DecoderReplacementFallback(""); char[] unescapedChars = new char[bytes.Length]; int charCount = noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0); start = next; // match exact bytes // Do not unescape chars not allowed by Iri // need to check for invalid utf sequences that may not have given any chars MatchUTF8Sequence(pDest, dest, ref destPosition, unescapedChars, charCount, bytes, byteCount, isQuery, iriParsing); } if (next == end) { goto done; } } dest_fixed_loop_break :; } } done : return(dest); }
static UriParser() { s_table = new LowLevelDictionary<string, UriParser>(c_InitialTableSize); s_tempTable = new LowLevelDictionary<string, UriParser>(c_InitialTableSize); //Now we will call for the instance constructors that will interrupt this static one. // Below we simulate calls into FetchSyntax() but avoid using lock() and other things redundant for a .cctor HttpUri = new BuiltInUriParser("http", 80, HttpSyntaxFlags); s_table[HttpUri.SchemeName] = HttpUri; //HTTP HttpsUri = new BuiltInUriParser("https", 443, HttpUri._flags); s_table[HttpsUri.SchemeName] = HttpsUri; //HTTPS cloned from HTTP WsUri = new BuiltInUriParser("ws", 80, HttpSyntaxFlags); s_table[WsUri.SchemeName] = WsUri; // WebSockets WssUri = new BuiltInUriParser("wss", 443, HttpSyntaxFlags); s_table[WssUri.SchemeName] = WssUri; // Secure WebSockets FtpUri = new BuiltInUriParser("ftp", 21, FtpSyntaxFlags); s_table[FtpUri.SchemeName] = FtpUri; //FTP FileUri = new BuiltInUriParser("file", NoDefaultPort, s_fileSyntaxFlags); s_table[FileUri.SchemeName] = FileUri; //FILE GopherUri = new BuiltInUriParser("gopher", 70, GopherSyntaxFlags); s_table[GopherUri.SchemeName] = GopherUri; //GOPHER NntpUri = new BuiltInUriParser("nntp", 119, NntpSyntaxFlags); s_table[NntpUri.SchemeName] = NntpUri; //NNTP NewsUri = new BuiltInUriParser("news", NoDefaultPort, NewsSyntaxFlags); s_table[NewsUri.SchemeName] = NewsUri; //NEWS MailToUri = new BuiltInUriParser("mailto", 25, MailtoSyntaxFlags); s_table[MailToUri.SchemeName] = MailToUri; //MAILTO UuidUri = new BuiltInUriParser("uuid", NoDefaultPort, NewsUri._flags); s_table[UuidUri.SchemeName] = UuidUri; //UUID cloned from NEWS TelnetUri = new BuiltInUriParser("telnet", 23, TelnetSyntaxFlags); s_table[TelnetUri.SchemeName] = TelnetUri; //TELNET LdapUri = new BuiltInUriParser("ldap", 389, LdapSyntaxFlags); s_table[LdapUri.SchemeName] = LdapUri; //LDAP NetTcpUri = new BuiltInUriParser("net.tcp", 808, NetTcpSyntaxFlags); s_table[NetTcpUri.SchemeName] = NetTcpUri; NetPipeUri = new BuiltInUriParser("net.pipe", NoDefaultPort, NetPipeSyntaxFlags); s_table[NetPipeUri.SchemeName] = NetPipeUri; VsMacrosUri = new BuiltInUriParser("vsmacros", NoDefaultPort, VsmacrosSyntaxFlags); s_table[VsMacrosUri.SchemeName] = VsMacrosUri; //VSMACROS }
internal unsafe static char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { byte [] bytes = null; byte escapedReallocations = 0; bool escapeReserved = false; int next = start; bool iriParsing = Uri.IriParsingStatic(syntax) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); while (true) { // we may need to re-pin dest[] fixed (char* pDest = dest) { if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { while (start < end) pDest[destPosition++] = pStr[start++]; return dest; } while (true) { char ch = (char)0; for (;next < end; ++next) { if ((ch = pStr[next]) == '%') { if ((unescapeMode & UnescapeMode.Unescape) == 0) { // re-escape, don't check anything else escapeReserved = true; } else if (next+2 < end) { ch = EscapedAscii(pStr[next+1], pStr[next+2]); // Unescape a good sequence if full unescape is requested if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == Uri.c_DummyChar) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } continue; } } // re-escape % from an invalid sequence else if (ch == Uri.c_DummyChar) { if ((unescapeMode & UnescapeMode.Escape) != 0) escapeReserved = true; else continue; // we should throw instead but since v1.0 woudl just print '%' } // Do not unescape '%' itself unless full unescape is requested else if (ch == '%') { next += 2; continue; } // Do not unescape a reserved char unless full unescape is requested else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { next += 2; continue; } // Do not unescape a dangerous char unless it's V1ToStringFlags mode else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch)) { next += 2; continue; } else if (iriParsing && ((ch <='\x9F' && IsNotSafeForUnescape(ch)) || (ch >'\x9F' &&!Uri.CheckIriUnicodeRange(ch, isQuery)))) { // check if unenscaping gives a char ouside iri range // if it does then keep it escaped next += 2; continue; } // unescape escaped char or escape % break; } else if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } // keep a '%' as part of a bogus sequence continue; } else { escapeReserved = true; } // escape (escapeReserved==ture) or otheriwse unescape the sequence break; } else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) { continue; } else if ((unescapeMode & UnescapeMode.Escape) != 0) { // Could actually escape some of the characters if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F'))) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } } } //copy off previous characters from input while (start < next) pDest[destPosition++] = pStr[start++]; if (next != end) { //VsWhidbey#87423 if (escapeReserved) { //escape that char // Since this should be _really_ rare case, reallocate with constant size increase of 30 rsvd-type characters. if (escapedReallocations == 0) { escapedReallocations = 30; char[] newDest = new char[dest.Length + escapedReallocations*3]; fixed (char *pNewDest = newDest) { for (int i = 0; i < destPosition; ++i) pNewDest[i] = pDest[i]; } dest = newDest; // re-pin new dest[] array goto dest_fixed_loop_break; } else { --escapedReallocations; EscapeAsciiChar(pStr[next], dest, ref destPosition); escapeReserved = false; start = ++next; continue; } } // unescaping either one Ascii or possibly multiple Unicode if (ch <= '\x7F') { //ASCII dest[destPosition++] = ch; next+=3; start = next; continue; } // Unicode int byteCount = 1; // lazy initialization of max size, will reuse the array for next sequences if ((object) bytes == null) bytes = new byte[end - next]; bytes[0] = (byte)ch; next+=3; while (next < end) { // Check on exit criterion if ((ch = pStr[next]) != '%' || next+2 >= end) break; // already made sure we have 3 characters in str ch = EscapedAscii(pStr[next+1], pStr[next+2]); //invalid hex sequence ? if (ch == Uri.c_DummyChar) break; // character is not part of a UTF-8 sequence ? else if (ch < '\x80') break; else { //a UTF-8 sequence bytes[byteCount++] = (byte)ch; next += 3; } } Encoding noFallbackCharUTF8 = (Encoding)Encoding.UTF8.Clone(); noFallbackCharUTF8.EncoderFallback = new EncoderReplacementFallback(""); noFallbackCharUTF8.DecoderFallback = new DecoderReplacementFallback(""); char[] unescapedChars = new char[bytes.Length]; int charCount = noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0); start = next; // match exact bytes // Do not unescape chars not allowed by Iri // need to check for invalid utf sequences that may not have given any chars MatchUTF8Sequence(pDest, dest, ref destPosition, unescapedChars, charCount, bytes, byteCount, isQuery, iriParsing); } if (next == end) goto done; } dest_fixed_loop_break: ; } } done: return dest; }
// Should never be used except by the below method private Uri(Flags flags, UriParser uriParser, string uri) { _flags = flags; _syntax = uriParser; _string = uri; }
} // 0x00000001809DB340-0x00000001809DB560 private static char[] Compress(char[] dest, ushort start, ref int destLength, UriParser syntax) => default; // 0x00000001809D0930-0x00000001809D0DE0
} // 0x00000001809CD7E0-0x00000001809CDD60 private unsafe void CheckAuthorityHelperHandleAnyHostIri(char *pString, int startInput, int end, bool iriParsing, bool hasUnicode, UriParser syntax, ref Flags flags, ref string newHost, ref ParsingError err) { } // 0x00000001809CD4E0-0x00000001809CD7E0
private static unsafe ushort ParseSchemeCheckImplicitFile(char* uriString, ushort length, ref ParsingError err, ref Flags flags, ref UriParser syntax) { ushort index = 0; while ((index < length) && IsLWS(uriString[index])) { index = (ushort) (index + 1); } ushort num2 = index; while ((num2 < length) && (uriString[num2] != ':')) { num2 = (ushort) (num2 + 1); } if (((IntPtr.Size != 4) || (num2 == length)) || ((num2 < (index + 3)) || !CheckKnownSchemes((long*) (uriString + index), (ushort) (num2 - index), ref syntax))) { char ch; if (((index + 2) >= length) || (num2 == index)) { err = ParsingError.BadFormat; return 0; } if (((ch = uriString[index + 1]) == ':') || (ch == '|')) { if (IsAsciiLetter(uriString[index])) { if (((ch = uriString[index + 2]) == '\\') || (ch == '/')) { flags |= Flags.AuthorityFound | Flags.DosPath | Flags.ImplicitFile; syntax = UriParser.FileUri; return index; } err = ParsingError.MustRootedPath; return 0; } if (ch == ':') { err = ParsingError.BadScheme; } else { err = ParsingError.BadFormat; } return 0; } if (((ch = uriString[index]) == '/') || (ch == '\\')) { if (((ch = uriString[index + 1]) == '\\') || (ch == '/')) { flags |= Flags.AuthorityFound | Flags.ImplicitFile | Flags.UncPath; syntax = UriParser.FileUri; index = (ushort) (index + 2); while ((index < length) && (((ch = uriString[index]) == '/') || (ch == '\\'))) { index = (ushort) (index + 1); } return index; } err = ParsingError.BadFormat; return 0; } if (num2 == length) { err = ParsingError.BadFormat; return 0; } if ((num2 - index) > 0x400) { err = ParsingError.SchemeLimit; return 0; } char* ptr = (char*) stackalloc byte[(((IntPtr) (num2 - index)) * 2)]; length = 0; while (index < num2) { length = (ushort) (length + 1); ptr[length] = uriString[index]; index = (ushort) (index + 1); } err = CheckSchemeSyntax(ptr, length, ref syntax); if (err != ParsingError.None) { return 0; } } return (ushort) (num2 + 1); }
private unsafe void CheckAuthorityHelperHandleDnsIri(char* pString, ushort start, int end, int startInput, bool iriParsing, bool hasUnicode, UriParser syntax, string userInfoString, ref Flags flags, ref bool justNormalized, ref string newHost, ref ParsingError err) { flags |= Flags.DnsHostType; if ((s_IdnScope == 1) && this.IsIntranet(new string(pString, 0, end))) { flags |= Flags.HostNotParsed | Flags.IntranetUri; } if (this.AllowIdnStatic(syntax, flags)) { bool allAscii = true; bool atLeastOneValidIdn = false; string idnHost = DomainNameHelper.IdnEquivalent(pString, start, end, ref allAscii, ref atLeastOneValidIdn); string str2 = DomainNameHelper.UnicodeEquivalent(idnHost, pString, start, end); if (!allAscii) { flags |= Flags.HostNotParsed | Flags.UnicodeHost; } if (atLeastOneValidIdn) { flags |= Flags.HostNotParsed | Flags.IdnHost; } if ((allAscii && atLeastOneValidIdn) && StaticNotAny(flags, Flags.HasUnicode)) { this.m_originalUnicodeString = this.m_String; newHost = this.m_originalUnicodeString.Substring(0, startInput) + (StaticInFact(flags, Flags.HasUserInfo) ? userInfoString : null); justNormalized = true; } else if (!iriParsing && (StaticInFact(flags, Flags.HostNotParsed | Flags.UnicodeHost) || StaticInFact(flags, Flags.HostNotParsed | Flags.IdnHost))) { this.m_originalUnicodeString = this.m_String; newHost = this.m_originalUnicodeString.Substring(0, startInput) + (StaticInFact(flags, Flags.HasUserInfo) ? userInfoString : null); justNormalized = true; } if (!allAscii || atLeastOneValidIdn) { this.m_DnsSafeHost = idnHost; newHost = newHost + str2; justNormalized = true; } else if ((allAscii && !atLeastOneValidIdn) && (iriParsing && hasUnicode)) { newHost = newHost + str2; justNormalized = true; } } else if (hasUnicode) { string str3 = StripBidiControlCharacter(pString, start, end - start); try { newHost = newHost + ((str3 != null) ? str3.Normalize(NormalizationForm.FormC) : null); } catch (ArgumentException) { err = ParsingError.BadHostName; } justNormalized = true; } flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; }
private unsafe void CheckAuthorityHelperHandleAnyHostIri(char* pString, int startInput, int end, bool iriParsing, bool hasUnicode, UriParser syntax, ref Flags flags, ref string newHost, ref ParsingError err) { if (StaticNotAny(flags, Flags.HostNotParsed | Flags.HostUnicodeNormalized) && (this.AllowIdnStatic(syntax, flags) || (iriParsing && hasUnicode))) { string str = new string(pString, startInput, end - startInput); if (this.AllowIdnStatic(syntax, flags)) { bool allAscii = true; bool atLeastOneValidIdn = false; string str2 = DomainNameHelper.UnicodeEquivalent(pString, startInput, end, ref allAscii, ref atLeastOneValidIdn); if (((allAscii && atLeastOneValidIdn) || !allAscii) && (!iriParsing || !hasUnicode)) { this.m_originalUnicodeString = this.m_String; newHost = this.m_originalUnicodeString.Substring(0, startInput); flags |= Flags.HasUnicode; } if (atLeastOneValidIdn || !allAscii) { newHost = newHost + str2; string bidiStrippedHost = null; this.m_DnsSafeHost = DomainNameHelper.IdnEquivalent(pString, startInput, end, ref allAscii, ref bidiStrippedHost); if (atLeastOneValidIdn) { flags |= Flags.HostNotParsed | Flags.IdnHost; } if (!allAscii) { flags |= Flags.HostNotParsed | Flags.UnicodeHost; } } else if (iriParsing && hasUnicode) { newHost = newHost + str; } } else { try { newHost = newHost + str.Normalize(NormalizationForm.FormC); } catch (ArgumentException) { err = ParsingError.BadHostName; } } flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; } }
private unsafe ushort CheckAuthorityHelper(char *pString, ushort idx, ushort length, ref ParsingError err, ref Flags flags, UriParser syntax, ref string newHost) => default; // 0x00000001809CDD60-0x00000001809CECF0 private unsafe void CheckAuthorityHelperHandleDnsIri(char *pString, ushort start, int end, int startInput, bool iriParsing, bool hasUnicode, UriParser syntax, string userInfoString, ref Flags flags, ref bool justNormalized, ref string newHost, ref ParsingError err) { } // 0x00000001809CD7E0-0x00000001809CDD60
private static unsafe char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery, bool readOnlyConfig) { byte[] bytes = null; byte num = 0; bool flag = false; int index = start; bool iriParsing = (s_IriParsing && (readOnlyConfig || (!readOnlyConfig && IriParsingStatic(syntax)))) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); Label_002E:; try { fixed (char* chRef = dest) { char ch; if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { while (start < end) { chRef[destPosition++] = pStr[start++]; } return dest; } Label_007F: ch = '\0'; while (index < end) { ch = pStr[index]; if (ch == '%') { if ((unescapeMode & UnescapeMode.Unescape) == UnescapeMode.CopyOnly) { flag = true; } else { if ((index + 2) < end) { ch = EscapedAscii(pStr[index + 1], pStr[index + 2]); if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == 0xffff) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { throw new UriFormatException(System.SR.GetString("net_uri_BadString")); } goto Label_01E8; } break; } if (ch == 0xffff) { if ((unescapeMode & UnescapeMode.Escape) == UnescapeMode.CopyOnly) { goto Label_01E8; } flag = true; break; } if (ch == '%') { index += 2; } else if (((ch == rsvd1) || (ch == rsvd2)) || (ch == rsvd3)) { index += 2; } else if (((unescapeMode & UnescapeMode.V1ToStringFlag) == UnescapeMode.CopyOnly) && IsNotSafeForUnescape(ch)) { index += 2; } else { if (!iriParsing || (((ch > '\x009f') || !IsNotSafeForUnescape(ch)) && ((ch <= '\x009f') || CheckIriUnicodeRange(ch, isQuery)))) { break; } index += 2; } goto Label_01E8; } if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { throw new UriFormatException(System.SR.GetString("net_uri_BadString")); } goto Label_01E8; } flag = true; } break; } if (((unescapeMode & (UnescapeMode.UnescapeAll | UnescapeMode.Unescape)) != (UnescapeMode.UnescapeAll | UnescapeMode.Unescape)) && ((unescapeMode & UnescapeMode.Escape) != UnescapeMode.CopyOnly)) { if (((ch == rsvd1) || (ch == rsvd2)) || (ch == rsvd3)) { flag = true; break; } if (((unescapeMode & UnescapeMode.V1ToStringFlag) == UnescapeMode.CopyOnly) && ((ch <= '\x001f') || ((ch >= '\x007f') && (ch <= '\x009f')))) { flag = true; break; } } Label_01E8: index++; } while (start < index) { chRef[destPosition++] = pStr[start++]; } if (index != end) { if (flag) { if (num == 0) { num = 30; char[] chArray = new char[dest.Length + (num * 3)]; fixed (char* chRef2 = chArray) { for (int i = 0; i < destPosition; i++) { chRef2[i] = chRef[i]; } } dest = chArray; goto Label_002E; } num = (byte) (num - 1); EscapeAsciiChar(pStr[index], dest, ref destPosition); flag = false; start = ++index; goto Label_007F; } if (ch <= '\x007f') { dest[destPosition++] = ch; index += 3; start = index; goto Label_007F; } int byteCount = 1; if (bytes == null) { bytes = new byte[end - index]; } bytes[0] = (byte) ch; index += 3; while (index < end) { if (((ch = pStr[index]) != '%') || ((index + 2) >= end)) { break; } ch = EscapedAscii(pStr[index + 1], pStr[index + 2]); if ((ch == 0xffff) || (ch < '\x0080')) { break; } bytes[byteCount++] = (byte) ch; index += 3; } Encoding encoding = Encoding.GetEncoding("utf-8", new EncoderReplacementFallback(""), new DecoderReplacementFallback("")); char[] chars = new char[bytes.Length]; int charCount = encoding.GetChars(bytes, 0, byteCount, chars, 0); if (charCount != 0) { start = index; MatchUTF8Sequence(chRef, dest, ref destPosition, chars, charCount, bytes, isQuery, iriParsing); } else { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { throw new UriFormatException(System.SR.GetString("net_uri_BadString")); } index = start + 3; start = index; dest[destPosition++] = (char) bytes[0]; } } if (index != end) { goto Label_007F; } return dest; } } finally { chRef = null; } return dest; }
public UriData(Uri uri, UriParser parser) { this.uri = uri; this.parser = parser; }
private static unsafe bool CheckKnownSchemes(long* lptr, ushort nChars, ref UriParser syntax) { switch ((lptr[0] | 0x20002000200020L)) { case 0x64006900750075L: if (nChars != 4) { break; } syntax = UriParser.UuidUri; return true; case 0x65006c00690066L: if (nChars != 4) { break; } syntax = UriParser.FileUri; return true; case 0x680070006f0067L: if ((nChars != 6) || ((*(((int*) (lptr + 1))) | 0x200020) != 0x720065)) { break; } syntax = UriParser.GopherUri; return true; case 0x2e00740065006eL: if ((nChars == 8) && ((lptr[1] | 0x20002000200020L) == 0x65007000690070L)) { syntax = UriParser.NetPipeUri; return true; } if ((nChars != 7) || ((lptr[1] | 0x20002000200020L) != 0x3a007000630074L)) { break; } syntax = UriParser.NetTcpUri; return true; case 0x3a007000740066L: if (nChars != 3) { break; } syntax = UriParser.FtpUri; return true; case 0x6c00690061006dL: if ((nChars != 6) || ((*(((int*) (lptr + 1))) | 0x200020) != 0x6f0074)) { break; } syntax = UriParser.MailToUri; return true; case 0x6e006c00650074L: if ((nChars != 6) || ((*(((int*) (lptr + 1))) | 0x200020) != 0x740065)) { break; } syntax = UriParser.TelnetUri; return true; case 0x7000610064006cL: if (nChars == 4) { syntax = UriParser.LdapUri; return true; } break; case 0x700074006e006eL: if (nChars != 4) { break; } syntax = UriParser.NntpUri; return true; case 0x70007400740068L: if (nChars == 4) { syntax = UriParser.HttpUri; return true; } if ((nChars != 5) || ((*(((ushort*) (lptr + 1))) | 0x20) != 0x73)) { break; } syntax = UriParser.HttpsUri; return true; case 0x7300770065006eL: if (nChars != 4) { break; } syntax = UriParser.NewsUri; return true; } return false; }
private static char[] Compress(char[] dest, ushort start, ref int destLength, UriParser syntax) { ushort num = 0; ushort num2 = 0; ushort num3 = 0; ushort num4 = 0; ushort index = (ushort) (((ushort) destLength) - 1); start = (ushort) (start - 1); while (index != start) { char ch = dest[index]; if ((ch == '\\') && syntax.InFact(UriSyntaxFlags.ConvertPathSlashes)) { dest[index] = ch = '/'; } if (ch == '/') { num = (ushort) (num + 1); } else { if (num > 1) { num2 = (ushort) (index + 1); } num = 0; } if (ch == '.') { num3 = (ushort) (num3 + 1); goto Label_017F; } if (num3 == 0) { goto Label_0148; } bool flag = syntax.NotAny(UriSyntaxFlags.CanonicalizeAsFilePath) && (((num3 > 2) || (ch != '/')) || (index == start)); if (!flag && (ch == '/')) { if ((num2 != ((index + num3) + 1)) && ((num2 != 0) || (((index + num3) + 1) != destLength))) { goto Label_0146; } num2 = (ushort) (((index + 1) + num3) + ((num2 == 0) ? 0 : 1)); Buffer.BlockCopy(dest, num2 << 1, dest, (index + 1) << 1, (destLength - num2) << 1); destLength -= (num2 - index) - 1; num2 = index; if (num3 == 2) { num4 = (ushort) (num4 + 1); } num3 = 0; goto Label_017F; } if ((!flag && (num4 == 0)) && ((num2 == ((index + num3) + 1)) || ((num2 == 0) && (((index + num3) + 1) == destLength)))) { num3 = (ushort) ((index + 1) + num3); Buffer.BlockCopy(dest, num3 << 1, dest, (index + 1) << 1, (destLength - num3) << 1); destLength -= (num3 - index) - 1; num2 = 0; num3 = 0; goto Label_017F; } Label_0146: num3 = 0; Label_0148: if (ch == '/') { if (num4 != 0) { num4 = (ushort) (num4 - 1); num2 = (ushort) (num2 + 1); Buffer.BlockCopy(dest, num2 << 1, dest, (index + 1) << 1, (destLength - num2) << 1); destLength -= (num2 - index) - 1; } num2 = index; } Label_017F: index = (ushort) (index - 1); } start = (ushort) (start + 1); if (((((ushort) destLength) > start) && syntax.InFact(UriSyntaxFlags.CanonicalizeAsFilePath)) && (num <= 1)) { if ((num4 != 0) && (dest[start] != '/')) { num2 = (ushort) (num2 + 1); Buffer.BlockCopy(dest, num2 << 1, dest, start << 1, (destLength - num2) << 1); destLength -= num2; return dest; } if ((num3 != 0) && ((num2 == (num3 + 1)) || ((num2 == 0) && ((num3 + 1) == destLength)))) { num3 = (ushort) (num3 + ((num2 == 0) ? 0 : 1)); Buffer.BlockCopy(dest, num3 << 1, dest, start << 1, (destLength - num3) << 1); destLength -= num3; } } return dest; }
private void CreateThisFromUri(Uri otherUri) { this.m_Info = null; this.m_Flags = otherUri.m_Flags; if (this.InFact(Flags.HostNotParsed | Flags.MinimalUriInfoSet)) { this.m_Flags &= ~(Flags.AllUriInfoSet | Flags.BackslashInPath | Flags.CannotDisplayCanonical | Flags.E_CannotDisplayCanonical | Flags.FirstSlashAbsent | Flags.MinimalUriInfoSet | Flags.ShouldBeCompressed); int path = otherUri.m_Info.Offset.Path; if (this.InFact(Flags.HostNotParsed | Flags.NotDefaultPort)) { while ((otherUri.m_String[path] != ':') && (path > otherUri.m_Info.Offset.Host)) { path--; } if (otherUri.m_String[path] != ':') { path = otherUri.m_Info.Offset.Path; } } this.m_Flags |= (Flags) path; } this.m_Syntax = otherUri.m_Syntax; this.m_String = otherUri.m_String; this.m_iriParsing = otherUri.m_iriParsing; if (otherUri.OriginalStringSwitched) { this.m_originalUnicodeString = otherUri.m_originalUnicodeString; } if (otherUri.AllowIdn && (otherUri.InFact(Flags.HostNotParsed | Flags.IdnHost) || otherUri.InFact(Flags.HostNotParsed | Flags.UnicodeHost))) { this.m_DnsSafeHost = otherUri.m_DnsSafeHost; } }
private void CreateUri(Uri baseUri, string relativeUri, bool dontEscape) { UriFormatException exception; this.CreateThis(relativeUri, dontEscape, UriKind.RelativeOrAbsolute); if (baseUri.Syntax.IsSimple) { Uri otherUri = ResolveHelper(baseUri, this, ref relativeUri, ref dontEscape, out exception); if (exception != null) { throw exception; } if (otherUri != null) { if (otherUri != this) { this.CreateThisFromUri(otherUri); } return; } } else { dontEscape = false; relativeUri = baseUri.Syntax.InternalResolve(baseUri, this, out exception); if (exception != null) { throw exception; } } this.m_Flags = Flags.HostNotParsed; this.m_Info = null; this.m_Syntax = null; this.CreateThis(relativeUri, dontEscape, UriKind.Absolute); }
private bool AllowIdnStatic(UriParser syntax, Flags flags) { if ((syntax == null) || ((syntax.Flags & UriSyntaxFlags.AllowIdn) == UriSyntaxFlags.None)) { return false; } return ((s_IdnScope == 2) || ((s_IdnScope == 1) && StaticNotAny(flags, Flags.HostNotParsed | Flags.IntranetUri))); }
// // This method will assume that any good Escaped Sequence will be unescaped in the output // - Assumes Dest.Length - detPosition >= end-start // - UnescapeLevel controls various modes of opearion // - Any "bad" escape sequence will remain as is or '%' will be escaped. // - destPosition tells the starting index in dest for placing the result. // On return destPosition tells the last character + 1 postion in the "dest" array. // - The control chars and chars passed in rsdvX parameters may be re-escaped depending on UnescapeLevel // - It is a RARE case when Unescape actually needs escaping some characteres mentioned above. // For this reason it returns a char[] that is usually the same ref as the input "dest" value. // internal unsafe static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { fixed(char *pStr = input) { return(UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery)); } }
private unsafe ushort CheckAuthorityHelper(char* pString, ushort idx, ushort length, ref ParsingError err, ref Flags flags, UriParser syntax, ref string newHost) { char ch; int end = length; int num2 = idx; ushort index = idx; newHost = null; bool justNormalized = false; bool iriParsing = s_IriParsing && IriParsingStatic(syntax); bool hasUnicode = (flags & Flags.HasUnicode) != Flags.HostNotParsed; bool flag4 = (flags & (Flags.HostNotParsed | Flags.HostUnicodeNormalized)) == Flags.HostNotParsed; UriSyntaxFlags flags2 = syntax.Flags; if ((hasUnicode && iriParsing) && flag4) { newHost = this.m_originalUnicodeString.Substring(0, num2); } if ((((idx == length) || ((ch = pString[idx]) == '/')) || ((ch == '\\') && StaticIsFile(syntax))) || ((ch == '#') || (ch == '?'))) { if (syntax.InFact(UriSyntaxFlags.AllowEmptyHost)) { flags &= ~(Flags.HostNotParsed | Flags.UncPath); if (StaticInFact(flags, Flags.HostNotParsed | Flags.ImplicitFile)) { err = ParsingError.BadHostName; } else { flags |= Flags.BasicHostType; } } else { err = ParsingError.BadHostName; } if ((hasUnicode && iriParsing) && flag4) { flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; } return idx; } string userInfoString = null; if ((flags2 & UriSyntaxFlags.MayHaveUserInfo) != UriSyntaxFlags.None) { while (index < end) { if (((index == (end - 1)) || (pString[index] == '?')) || (((pString[index] == '#') || (pString[index] == '\\')) || (pString[index] == '/'))) { index = idx; break; } if (pString[index] == '@') { flags |= Flags.HasUserInfo; if (iriParsing || (s_IdnScope != null)) { if ((iriParsing && hasUnicode) && flag4) { userInfoString = this.EscapeUnescapeIri(pString, num2, index + 1, UriComponents.UserInfo); try { userInfoString = userInfoString.Normalize(NormalizationForm.FormC); } catch (ArgumentException) { err = ParsingError.BadFormat; return idx; } newHost = newHost + userInfoString; } else { userInfoString = new string(pString, num2, (index - num2) + 1); } } index = (ushort) (index + 1); ch = pString[index]; break; } index = (ushort) (index + 1); } } bool notCanonical = (flags2 & UriSyntaxFlags.SimpleUserSyntax) == UriSyntaxFlags.None; if (((ch == '[') && syntax.InFact(UriSyntaxFlags.AllowIPv6Host)) && IPv6AddressHelper.IsValid(pString, index + 1, ref end)) { flags |= Flags.HostNotParsed | Flags.IPv6HostType; if (!s_ConfigInitialized) { InitializeUriConfig(); this.m_iriParsing = s_IriParsing && IriParsingStatic(syntax); } if ((hasUnicode && iriParsing) && flag4) { newHost = newHost + new string(pString, index, end - index); flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; justNormalized = true; } } else if (((ch <= '9') && (ch >= '0')) && (syntax.InFact(UriSyntaxFlags.AllowIPv4Host) && IPv4AddressHelper.IsValid(pString, index, ref end, false, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile)))) { flags |= Flags.HostNotParsed | Flags.IPv4HostType; if ((hasUnicode && iriParsing) && flag4) { newHost = newHost + new string(pString, index, end - index); flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; justNormalized = true; } } else if ((((flags2 & UriSyntaxFlags.AllowDnsHost) != UriSyntaxFlags.None) && !iriParsing) && DomainNameHelper.IsValid(pString, index, ref end, ref notCanonical, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile))) { flags |= Flags.DnsHostType; if (!notCanonical) { flags |= Flags.CanonicalDnsHost; } if (s_IdnScope != null) { if ((s_IdnScope == 1) && this.IsIntranet(new string(pString, 0, end))) { flags |= Flags.HostNotParsed | Flags.IntranetUri; } if (this.AllowIdnStatic(syntax, flags)) { bool allAscii = true; bool atLeastOneValidIdn = false; string str2 = DomainNameHelper.UnicodeEquivalent(pString, index, end, ref allAscii, ref atLeastOneValidIdn); if (atLeastOneValidIdn) { if (StaticNotAny(flags, Flags.HasUnicode)) { this.m_originalUnicodeString = this.m_String; } flags |= Flags.HostNotParsed | Flags.IdnHost; newHost = this.m_originalUnicodeString.Substring(0, num2) + userInfoString + str2; flags |= Flags.CanonicalDnsHost; this.m_DnsSafeHost = new string(pString, index, end - index); justNormalized = true; } flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; } } } else if ((((iriParsing || (s_IdnScope != null)) && ((flags2 & UriSyntaxFlags.AllowDnsHost) != UriSyntaxFlags.None)) && ((iriParsing && flag4) || this.AllowIdnStatic(syntax, flags))) && DomainNameHelper.IsValidByIri(pString, index, ref end, ref notCanonical, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile))) { this.CheckAuthorityHelperHandleDnsIri(pString, index, end, num2, iriParsing, hasUnicode, syntax, userInfoString, ref flags, ref justNormalized, ref newHost, ref err); } else if ((((s_IdnScope == null) && !s_IriParsing) && (((flags2 & UriSyntaxFlags.AllowUncHost) != UriSyntaxFlags.None) && UncNameHelper.IsValid(pString, index, ref end, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile)))) && ((end - index) <= 0x100)) { flags |= Flags.HostNotParsed | Flags.UncHostType; } if (((end < length) && (pString[end] == '\\')) && (((flags & (Flags.BasicHostType | Flags.IPv4HostType)) != Flags.HostNotParsed) && !StaticIsFile(syntax))) { if (syntax.InFact(UriSyntaxFlags.V1_UnknownUri)) { err = ParsingError.BadHostName; flags |= Flags.BasicHostType | Flags.IPv4HostType; return (ushort) end; } flags &= ~(Flags.BasicHostType | Flags.IPv4HostType); } else if ((end < length) && (pString[end] == ':')) { if (!syntax.InFact(UriSyntaxFlags.MayHavePort)) { flags &= ~(Flags.BasicHostType | Flags.IPv4HostType); } else { int num4 = 0; int startIndex = end; idx = (ushort) (end + 1); while (idx < length) { ushort num6 = pString[idx] - '0'; if ((num6 >= 0) && (num6 <= 9)) { num4 = (num4 * 10) + num6; if (num4 > 0xffff) { break; } } else { if (((num6 == 0xffff) || (num6 == 15)) || (num6 == 0xfff3)) { break; } if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost) && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri)) { flags &= ~(Flags.BasicHostType | Flags.IPv4HostType); break; } err = ParsingError.BadPort; return idx; } idx = (ushort) (idx + 1); } if (num4 > 0xffff) { if (!syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost)) { err = ParsingError.BadPort; return idx; } flags &= ~(Flags.BasicHostType | Flags.IPv4HostType); } if ((iriParsing && hasUnicode) && justNormalized) { newHost = newHost + new string(pString, startIndex, idx - startIndex); } } } if ((flags & (Flags.BasicHostType | Flags.IPv4HostType)) == Flags.HostNotParsed) { flags &= ~Flags.HasUserInfo; if (!syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost)) { if (!syntax.InFact(UriSyntaxFlags.V1_UnknownUri)) { if (syntax.InFact(UriSyntaxFlags.MustHaveAuthority)) { err = ParsingError.BadHostName; flags |= Flags.BasicHostType | Flags.IPv4HostType; return idx; } } else { bool flag8 = false; int num7 = idx; for (end = idx; end < length; end++) { if (flag8 && (((pString[end] == '/') || (pString[end] == '?')) || (pString[end] == '#'))) { break; } if ((end < (idx + 2)) && (pString[end] == '.')) { flag8 = true; } else { err = ParsingError.BadHostName; flags |= Flags.BasicHostType | Flags.IPv4HostType; return idx; } } flags |= Flags.BasicHostType; if ((iriParsing && hasUnicode) && StaticNotAny(flags, Flags.HostNotParsed | Flags.HostUnicodeNormalized)) { string str3 = new string(pString, num7, num7 - end); try { newHost = newHost + str3.Normalize(NormalizationForm.FormC); } catch (ArgumentException) { err = ParsingError.BadFormat; return idx; } flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized; } } } else { flags |= Flags.BasicHostType; end = idx; while (end < length) { if (((pString[end] == '/') || (pString[end] == '?')) || (pString[end] == '#')) { break; } end++; } this.CheckAuthorityHelperHandleAnyHostIri(pString, num2, end, iriParsing, hasUnicode, syntax, ref flags, ref newHost, ref err); } } return (ushort) end; }
// // This method will assume that any good Escaped Sequence will be unescaped in the output // - Assumes Dest.Length - detPosition >= end-start // - UnescapeLevel controls various modes of opearion // - Any "bad" escape sequence will remain as is or '%' will be escaped. // - destPosition tells the starting index in dest for placing the result. // On return destPosition tells the last character + 1 postion in the "dest" array. // - The control chars and chars passed in rsdvX parameters may be re-escaped depending on UnescapeLevel // - It is a RARE case when Unescape actually needs escaping some characteres mentioned above. // For this reason it returns a char[] that is usually the same ref as the input "dest" value. // internal unsafe static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { fixed (char *pStr = input) { return UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery); } }
private void InitializeUri(ParsingError err, UriKind uriKind, out UriFormatException e) { if (err == ParsingError.None) { if (this.IsImplicitFile) { if ((this.NotAny(Flags.DosPath) && (uriKind != UriKind.Absolute)) && ((uriKind == UriKind.Relative) || ((this.m_String.Length >= 2) && ((this.m_String[0] != '\\') || (this.m_String[1] != '\\'))))) { this.m_Syntax = null; this.m_Flags &= Flags.HostNotParsed | Flags.UserEscaped; e = null; return; } if ((uriKind == UriKind.Relative) && this.InFact(Flags.DosPath)) { this.m_Syntax = null; this.m_Flags &= Flags.HostNotParsed | Flags.UserEscaped; e = null; return; } } } else if (err > ParsingError.EmptyUriString) { this.m_String = null; e = GetException(err); return; } bool flag = false; if (!s_ConfigInitialized && this.CheckForConfigLoad(this.m_String)) { InitializeUriConfig(); } this.m_iriParsing = s_IriParsing && ((this.m_Syntax == null) || this.m_Syntax.InFact(UriSyntaxFlags.AllowIriParsing)); if (this.m_iriParsing && this.CheckForUnicode(this.m_String)) { this.m_Flags |= Flags.HasUnicode; flag = true; this.m_originalUnicodeString = this.m_String; } if (this.m_Syntax != null) { if (!this.m_Syntax.IsSimple) { this.m_Syntax = this.m_Syntax.InternalOnNewUri(); this.m_Flags |= Flags.HostNotParsed | Flags.UserDrivenParsing; this.m_Syntax.InternalValidate(this, out e); if (e == null) { if ((err != ParsingError.None) || this.InFact(Flags.ErrorOrParsingRecursion)) { this.SetUserDrivenParsing(); } else if (uriKind == UriKind.Relative) { e = GetException(ParsingError.CannotCreateRelative); } if (this.m_iriParsing && flag) { this.EnsureParseRemaining(); } } else if (((uriKind != UriKind.Absolute) && (err != ParsingError.None)) && (err <= ParsingError.EmptyUriString)) { this.m_Syntax = null; e = null; this.m_Flags &= Flags.HostNotParsed | Flags.UserEscaped; } } else { if ((err = this.PrivateParseMinimal()) != ParsingError.None) { if ((uriKind != UriKind.Absolute) && (err <= ParsingError.EmptyUriString)) { this.m_Syntax = null; e = null; this.m_Flags &= Flags.HostNotParsed | Flags.UserEscaped; } else { e = GetException(err); } } else if (uriKind == UriKind.Relative) { e = GetException(ParsingError.CannotCreateRelative); } else { e = null; } if (this.m_iriParsing && flag) { this.EnsureParseRemaining(); } } } else if (((err != ParsingError.None) && (uriKind != UriKind.Absolute)) && (err <= ParsingError.EmptyUriString)) { e = null; this.m_Flags &= Flags.HasUnicode | Flags.UserEscaped; if (this.m_iriParsing && flag) { this.m_String = this.EscapeUnescapeIri(this.m_originalUnicodeString, 0, this.m_originalUnicodeString.Length, 0); try { this.m_String = this.m_String.Normalize(NormalizationForm.FormC); } catch (ArgumentException) { e = GetException(ParsingError.BadFormat); } } } else { this.m_String = null; e = GetException(err); } }
private static unsafe ParsingError CheckSchemeSyntax(char *ptr, ushort length, ref UriParser syntax) => default; // 0x00000001809CFC90-0x00000001809CFDC0 private unsafe ushort CheckAuthorityHelper(char *pString, ushort idx, ushort length, ref ParsingError err, ref Flags flags, UriParser syntax, ref string newHost) => default; // 0x00000001809CDD60-0x00000001809CECF0
private static bool IriParsingStatic(UriParser syntax) { if (!s_IriParsing) { return false; } return (((syntax != null) && syntax.InFact(UriSyntaxFlags.AllowIriParsing)) || (syntax == null)); }
private static unsafe ParsingError CheckSchemeSyntax(char* ptr, ushort length, ref UriParser syntax) { char ch = ptr[0]; if ((ch < 'a') || (ch > 'z')) { if ((ch < 'A') || (ch > 'Z')) { return ParsingError.BadScheme; } ptr[0] = (char) (ch | ' '); } for (ushort i = 1; i < length; i = (ushort) (i + 1)) { char ch2 = ptr[i]; if ((ch2 < 'a') || (ch2 > 'z')) { if ((ch2 >= 'A') && (ch2 <= 'Z')) { ptr[i] = (char) (ch2 | ' '); } else if (((ch2 < '0') || (ch2 > '9')) && (((ch2 != '+') && (ch2 != '-')) && (ch2 != '.'))) { return ParsingError.BadScheme; } } } string lwrCaseScheme = new string(ptr, 0, length); syntax = UriParser.FindOrFetchAsUnknownV1Syntax(lwrCaseScheme); return ParsingError.None; }
// // Static Registration methods // // // Registers a custom Uri parser based on a scheme string // public static void Register(UriParser uriParser !!, string schemeName !!, int defaultPort)
public Uri(Uri baseUri, Uri relativeUri) { UriFormatException exception; bool flag; if (baseUri == null) { throw new ArgumentNullException("baseUri"); } if (!baseUri.IsAbsoluteUri) { throw new ArgumentOutOfRangeException("baseUri"); } this.CreateThisFromUri(relativeUri); string newUriString = null; if (baseUri.Syntax.IsSimple) { flag = this.InFact(Flags.HostNotParsed | Flags.UserEscaped); relativeUri = ResolveHelper(baseUri, this, ref newUriString, ref flag, out exception); if (exception != null) { throw exception; } if (relativeUri != null) { if (relativeUri != this) { this.CreateThisFromUri(relativeUri); } return; } } else { flag = false; newUriString = baseUri.Syntax.InternalResolve(baseUri, this, out exception); if (exception != null) { throw exception; } } this.m_Flags = Flags.HostNotParsed; this.m_Info = null; this.m_Syntax = null; this.CreateThis(newUriString, flag, UriKind.Absolute); }