System.Uri.CheckAuthorityHelper C# (CSharp) Method

CheckAuthorityHelper() private method

private CheckAuthorityHelper ( char pString, ushort idx, ushort length, ParsingError &err, Flags &flags, UriParser syntax, string &newHost ) : ushort
pString char
idx ushort
length ushort
err ParsingError
flags Flags
syntax UriParser
newHost string
return ushort
        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, end - startOtherHost);
                            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;
        }