示例#1
0
        internal static bool TryGetUnicodeEquivalent(string hostname, ref ValueStringBuilder dest)
        {
            Debug.Assert(ReferenceEquals(hostname, UriHelper.StripBidiControlCharacters(hostname, hostname)));

            int curPos = 0;

            // We run a loop where for every label
            // a) if label is ascii and no ace then we lowercase it
            // b) if label is ascii and ace and not valid idn then just lowercase it
            // c) if label is ascii and ace and is valid idn then get its unicode eqvl
            // d) if label is unicode then clean it by running it through idnmapping
            do
            {
                if (curPos != 0)
                {
                    dest.Append('.');
                }

                bool asciiLabel = true;

                //find the dot or hit the end
                int newPos;
                for (newPos = curPos; (uint)newPos < (uint)hostname.Length; newPos++)
                {
                    char c = hostname[newPos];

                    if (c == '.')
                    {
                        break;
                    }

                    if (c > '\x7F')
                    {
                        asciiLabel = false;

                        if ((c == '\u3002') || // IDEOGRAPHIC FULL STOP
                            (c == '\uFF0E') || // FULLWIDTH FULL STOP
                            (c == '\uFF61'))   // HALFWIDTH IDEOGRAPHIC FULL STOP
                        {
                            break;
                        }
                    }
                }

                if (!asciiLabel)
                {
                    try
                    {
                        string asciiForm = s_idnMapping.GetAscii(hostname, curPos, newPos - curPos);

                        dest.Append(s_idnMapping.GetUnicode(asciiForm));
                    }
                    catch (ArgumentException)
                    {
                        return(false);
                    }
                }
                else
                {
                    bool aceValid = false;

                    if ((uint)(curPos + 3) < (uint)hostname.Length &&
                        hostname[curPos] == 'x' &&
                        hostname[curPos + 1] == 'n' &&
                        hostname[curPos + 2] == '-' &&
                        hostname[curPos + 3] == '-')
                    {
                        // check ace validity
                        try
                        {
                            dest.Append(s_idnMapping.GetUnicode(hostname, curPos, newPos - curPos));
                            aceValid = true;
                        }
                        catch (ArgumentException)
                        {
                            // not valid ace so treat it as a normal ascii label
                        }
                    }

                    if (!aceValid)
                    {
                        // for invalid aces we just lowercase the label
                        ReadOnlySpan <char> slice = hostname.AsSpan(curPos, newPos - curPos);
                        int charsWritten          = slice.ToLowerInvariant(dest.AppendSpan(slice.Length));
                        Debug.Assert(charsWritten == slice.Length);
                    }
                }

                curPos = newPos + 1;
            } while (curPos < hostname.Length);

            return(true);
        }