Esempio n. 1
0
        /// <summary>Converts a host name into its idn equivalent.</summary>
        internal static string IdnEquivalent(string hostname)
        {
            if (hostname.Length == 0)
            {
                return(hostname);
            }

            // check if only ascii chars
            // special case since idnmapping will not lowercase if only ascii present
            bool allAscii = true;

            foreach (char c in hostname)
            {
                if (c > 0x7F)
                {
                    allAscii = false;
                    break;
                }
            }

            if (allAscii)
            {
                // just lowercase for ascii
                return(hostname.ToLowerInvariant());
            }

            string bidiStrippedHost = UriHelper.StripBidiControlCharacters(hostname, hostname);

            try
            {
                string asciiForm = s_idnMapping.GetAscii(bidiStrippedHost);
                if (ContainsCharactersUnsafeForNormalizedHost(asciiForm))
                {
                    throw new UriFormatException(SR.net_uri_BadUnicodeHostForIdn);
                }
                return(asciiForm);
            }
            catch (ArgumentException)
            {
                throw new UriFormatException(SR.net_uri_BadUnicodeHostForIdn);
            }
        }
Esempio n. 2
0
        internal static unsafe string?UnicodeEquivalent(char *hostname, int start, int end, ref bool allAscii, ref bool atLeastOneValidIdn)
        {
            // hostname already validated
            allAscii           = true;
            atLeastOneValidIdn = false;
            string?idn = null;

            if (end <= start)
            {
                return(idn);
            }

            string unescapedHostname = UriHelper.StripBidiControlCharacters(new ReadOnlySpan <char>(hostname + start, end - start));

            string?unicodeEqvlHost = null;
            int    curPos          = 0;
            int    newPos          = 0;
            int    length          = unescapedHostname.Length;
            bool   asciiLabel      = true;
            bool   foundAce        = false;
            bool   checkedAce      = false;
            bool   foundDot        = false;


            // 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
            {
                asciiLabel = true;
                foundAce   = false;
                checkedAce = false;
                foundDot   = false;

                //find the dot or hit the end
                newPos = curPos;
                while (newPos < length)
                {
                    char c = unescapedHostname[newPos];
                    if (!checkedAce)
                    {
                        checkedAce = true;
                        if ((newPos + 3 < length) && (c == 'x') && IsIdnAce(unescapedHostname, newPos))
                        {
                            foundAce = true;
                        }
                    }
                    if (asciiLabel && (c > '\x7F'))
                    {
                        asciiLabel = false;
                        allAscii   = false;
                    }
                    if ((c == '.') || (c == '\u3002') ||    //IDEOGRAPHIC FULL STOP
                        (c == '\uFF0E') ||                  //FULLWIDTH FULL STOP
                        (c == '\uFF61'))                    //HALFWIDTH IDEOGRAPHIC FULL STOP
                    {
                        foundDot = true;
                        break;
                    }
                    ++newPos;
                }

                if (!asciiLabel)
                {
                    string asciiForm = unescapedHostname.Substring(curPos, newPos - curPos);
                    try
                    {
                        asciiForm = s_idnMapping.GetAscii(asciiForm);
                    }
                    catch (ArgumentException)
                    {
                        throw new UriFormatException(SR.net_uri_BadUnicodeHostForIdn);
                    }

                    unicodeEqvlHost += s_idnMapping.GetUnicode(asciiForm);
                    if (foundDot)
                    {
                        unicodeEqvlHost += ".";
                    }
                }
                else
                {
                    bool aceValid = false;
                    if (foundAce)
                    {
                        // check ace validity
                        try
                        {
                            unicodeEqvlHost += s_idnMapping.GetUnicode(unescapedHostname, curPos, newPos - curPos);
                            if (foundDot)
                            {
                                unicodeEqvlHost += ".";
                            }
                            aceValid           = true;
                            atLeastOneValidIdn = true;
                        }
                        catch (ArgumentException)
                        {
                            // not valid ace so treat it as a normal ascii label
                        }
                    }

                    if (!aceValid)
                    {
                        // for invalid aces we just lowercase the label
                        unicodeEqvlHost += unescapedHostname.Substring(curPos, newPos - curPos).ToLowerInvariant();
                        if (foundDot)
                        {
                            unicodeEqvlHost += ".";
                        }
                    }
                }

                curPos = newPos + (foundDot ? 1 : 0);
            } while (curPos < length);

            return(unicodeEqvlHost);
        }
Esempio n. 3
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);
        }