NS_IMETHODIMP nsIDNService::ConvertToDisplayIDN(const nsACString & input, PRBool * _isASCII, nsACString & _retval) { // If host is ACE, then convert to UTF-8 if the host is in the IDN whitelist. // Else, if host is already UTF-8, then make sure it is normalized per IDN. nsresult rv; if (IsASCII(input)) { // first, canonicalize the host to lowercase, for whitelist lookup _retval = input; ToLowerCase(_retval); PRBool isACE; IsACE(_retval, &isACE); if (isACE && !mShowPunycode && isInWhitelist(_retval)) { // ConvertACEtoUTF8() can't fail, but might return the original ACE string nsCAutoString temp(_retval); ConvertACEtoUTF8(temp, _retval); *_isASCII = IsASCII(_retval); } else { *_isASCII = PR_TRUE; } } else { // We have to normalize the hostname before testing against the domain // whitelist (see bug 315411), and to ensure the entire string gets // normalized. rv = Normalize(input, _retval); if (NS_FAILED(rv)) return rv; if (mShowPunycode && NS_SUCCEEDED(ConvertUTF8toACE(_retval, _retval))) { *_isASCII = PR_TRUE; return NS_OK; } // normalization could result in an ASCII-only hostname. alternatively, if // the host is converted to ACE by the normalizer, then the host may contain // unsafe characters, so leave it ACE encoded. see bug 283016, bug 301694, and bug 309311. *_isASCII = IsASCII(_retval); if (!*_isASCII && !isInWhitelist(_retval)) { *_isASCII = PR_TRUE; return ConvertUTF8toACE(_retval, _retval); } } return NS_OK; }
nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out, bool allowUnassigned) { bool isAce; IsACE(in, &isAce); if (!isAce) { out.Assign(in); return NS_OK; } // RFC 3490 - 4.2 ToUnicode // The ToUnicode output never contains more code points than its input. punycode_uint output_length = in.Length() - kACEPrefixLen + 1; punycode_uint *output = new punycode_uint[output_length]; NS_ENSURE_TRUE(output, NS_ERROR_OUT_OF_MEMORY); enum punycode_status status = punycode_decode(in.Length() - kACEPrefixLen, PromiseFlatCString(in).get() + kACEPrefixLen, &output_length, output, nullptr); if (status != punycode_success) { delete [] output; return NS_ERROR_FAILURE; } // UCS4 -> UTF8 output[output_length] = 0; nsAutoString utf16; ucs4toUtf16(output, utf16); delete [] output; if (!isOnlySafeChars(utf16, mIDNBlacklist)) return NS_ERROR_FAILURE; CopyUTF16toUTF8(utf16, out); // Validation: encode back to ACE and compare the strings nsAutoCString ace; nsresult rv = UTF8toACE(out, ace, allowUnassigned); NS_ENSURE_SUCCESS(rv, rv); if (!ace.Equals(in, nsCaseInsensitiveCStringComparator())) return NS_ERROR_FAILURE; return NS_OK; }