diff --git a/mozilla/netwerk/base/src/nsStandardURL.cpp b/mozilla/netwerk/base/src/nsStandardURL.cpp index e9ea09f2442..62acbe104a5 100644 --- a/mozilla/netwerk/base/src/nsStandardURL.cpp +++ b/mozilla/netwerk/base/src/nsStandardURL.cpp @@ -65,6 +65,8 @@ PRBool nsStandardURL::gInitialized = PR_FALSE; PRBool nsStandardURL::gEscapeUTF8 = PR_TRUE; PRBool nsStandardURL::gAlwaysEncodeInUTF8 = PR_TRUE; PRBool nsStandardURL::gEncodeQueryInUTF8 = PR_TRUE; +PRBool nsStandardURL::gShowPunycode = PR_FALSE; +nsIPrefBranch *nsStandardURL::gIDNWhitelistPrefBranch = nsnull; #if defined(PR_LOGGING) // @@ -138,6 +140,8 @@ end: #define NS_NET_PREF_ENABLEIDN "network.enableIDN" #define NS_NET_PREF_ALWAYSENCODEINUTF8 "network.standard-url.encode-utf8" #define NS_NET_PREF_ENCODEQUERYINUTF8 "network.standard-url.encode-query-utf8" +#define NS_NET_PREF_SHOWPUNYCODE "network.IDN_show_punycode" +#define NS_NET_PREF_IDNWHITELIST "network.IDN.whitelist." NS_IMPL_ISUPPORTS1(nsStandardURL::nsPrefObserver, nsIObserver) @@ -311,8 +315,17 @@ nsStandardURL::InitGlobalObjects() prefBranch->AddObserver(NS_NET_PREF_ALWAYSENCODEINUTF8, obs.get(), PR_FALSE); prefBranch->AddObserver(NS_NET_PREF_ENCODEQUERYINUTF8, obs.get(), PR_FALSE); prefBranch->AddObserver(NS_NET_PREF_ENABLEIDN, obs.get(), PR_FALSE); + prefBranch->AddObserver(NS_NET_PREF_SHOWPUNYCODE, obs.get(), PR_FALSE); PrefsChanged(prefBranch, nsnull); + + nsCOMPtr prefs = do_QueryInterface(prefBranch); + if (prefs) { + nsCOMPtr branch; + if (NS_SUCCEEDED(prefs->GetBranch( NS_NET_PREF_IDNWHITELIST, + getter_AddRefs(branch) ))) + NS_ADDREF(gIDNWhitelistPrefBranch = branch); + } } } @@ -321,6 +334,7 @@ nsStandardURL::ShutdownGlobalObjects() { NS_IF_RELEASE(gIDN); NS_IF_RELEASE(gCharsetMgr); + NS_IF_RELEASE(gIDNWhitelistPrefBranch); } //---------------------------------------------------------------------------- @@ -381,7 +395,7 @@ nsStandardURL::NormalizeIDN(const nsCSubstring &host, nsCString &result) // If host is ACE, then convert to UTF-8. Else, if host is already UTF-8, // then make sure it is normalized per IDN. - // this function returns PR_TRUE if normalization succeeds. + // this function returns PR_TRUE iff it writes something to |result|. // NOTE: As a side-effect this function sets mHostEncoding. While it would // be nice to avoid side-effects in this function, the implementation of @@ -391,13 +405,23 @@ nsStandardURL::NormalizeIDN(const nsCSubstring &host, nsCString &result) NS_ASSERTION(mHostEncoding == eEncoding_ASCII, "unexpected default encoding"); - PRBool isASCII; - if (gIDN && - NS_SUCCEEDED(gIDN->ConvertToDisplayIDN(host, &isASCII, result))) { - if (!isASCII) - mHostEncoding = eEncoding_UTF8; - - return PR_TRUE; + if (IsASCII(host)) { + PRBool isACE; + if (gIDN && + NS_SUCCEEDED(gIDN->IsACE(host, &isACE)) && isACE && + NS_SUCCEEDED(ACEtoDisplayIDN(host, result))) { + mHostEncoding = eEncoding_UTF8; + return PR_TRUE; + } + } + else { + mHostEncoding = eEncoding_UTF8; + if (gIDN && NS_SUCCEEDED(UTF8toDisplayIDN(host, result))) { + // normalization could result in an ASCII only hostname + if (IsASCII(result)) + mHostEncoding = eEncoding_ASCII; + return PR_TRUE; + } } result.Truncate(); @@ -837,10 +861,68 @@ nsStandardURL::PrefsChanged(nsIPrefBranch *prefs, const char *pref) gEncodeQueryInUTF8 = val; LOG(("encode query in UTF-8 %s\n", gEncodeQueryInUTF8 ? "enabled" : "disabled")); } + + if (PREF_CHANGED(NS_NET_PREF_SHOWPUNYCODE)) { + if (GOT_PREF(NS_NET_PREF_SHOWPUNYCODE, val)) + gShowPunycode = val; + LOG(("show punycode %s\n", gShowPunycode ? "enabled" : "disabled")); + } #undef PREF_CHANGED #undef GOT_PREF } +/* static */ nsresult +nsStandardURL::ACEtoDisplayIDN(const nsCSubstring &host, nsCString &result) +{ + if (gShowPunycode || !IsInWhitelist(host)) { + result = host; + return NS_OK; + } + + return gIDN->ConvertACEtoUTF8(host, result); +} + +/* static */ nsresult +nsStandardURL::UTF8toDisplayIDN(const nsCSubstring &host, nsCString &result) +{ + // We have to normalize the hostname before testing against the domain + // whitelist. See bug 315411. + + nsCAutoString temp; + if (gShowPunycode || NS_FAILED(gIDN->Normalize(host, temp))) + return gIDN->ConvertUTF8toACE(host, result); + + PRBool isACE = PR_FALSE; + gIDN->IsACE(temp, &isACE); + + // If host is converted to ACE by the normalizer, then the host may contain + // unsafe characters. See bug 283016, bug 301694, and bug 309311. + + if (!isACE && !IsInWhitelist(temp)) + return gIDN->ConvertUTF8toACE(temp, result); + + result = temp; + return NS_OK; +} + +/* static */ PRBool +nsStandardURL::IsInWhitelist(const nsCSubstring &host) +{ + PRInt32 pos; + PRBool safe; + + // XXX This code uses strings inefficiently. + + if (gIDNWhitelistPrefBranch && + (pos = nsCAutoString(host).RFind(".")) != kNotFound && + NS_SUCCEEDED(gIDNWhitelistPrefBranch-> + GetBoolPref(nsCAutoString(Substring(host, pos + 1)).get(), + &safe))) + return safe; + + return PR_FALSE; +} + //---------------------------------------------------------------------------- // nsStandardURL::nsISupports //---------------------------------------------------------------------------- diff --git a/mozilla/netwerk/base/src/nsStandardURL.h b/mozilla/netwerk/base/src/nsStandardURL.h index c5058187a1e..a33e8da2ee4 100644 --- a/mozilla/netwerk/base/src/nsStandardURL.h +++ b/mozilla/netwerk/base/src/nsStandardURL.h @@ -221,6 +221,11 @@ private: static void PrefsChanged(nsIPrefBranch *prefs, const char *pref); + // IDN routines + static nsresult ACEtoDisplayIDN(const nsCSubstring &in, nsCString &out); + static nsresult UTF8toDisplayIDN(const nsCSubstring &in, nsCString &out); + static PRBool IsInWhitelist(const nsCSubstring &host); + // mSpec contains the normalized version of the URL spec (UTF-8 encoded). nsCString mSpec; PRInt32 mDefaultPort; @@ -271,6 +276,8 @@ private: static PRBool gEscapeUTF8; static PRBool gAlwaysEncodeInUTF8; static PRBool gEncodeQueryInUTF8; + static PRBool gShowPunycode; + static nsIPrefBranch *gIDNWhitelistPrefBranch; }; #define NS_THIS_STANDARDURL_IMPL_CID \ diff --git a/mozilla/netwerk/dns/public/nsIIDNService.idl b/mozilla/netwerk/dns/public/nsIIDNService.idl index 93a0ad22342..64a53fb8ffd 100644 --- a/mozilla/netwerk/dns/public/nsIIDNService.idl +++ b/mozilla/netwerk/dns/public/nsIIDNService.idl @@ -25,7 +25,6 @@ * gagan@netscape.com, * nhotta@netscape.com, * william.tan@i-dns.net - * dwitte@stanford.edu * * * Alternatively, the contents of this file may be used under the terms of @@ -59,7 +58,7 @@ * http://search.ietf.org/internet-drafts/draft-ietf-idn-idna-06.txt */ -[scriptable, uuid(a592a60e-3621-4f19-a318-2bf233cfad3e)] +[scriptable, uuid(7B67747E-A8C4-4832-80C7-39EBB0C11F94)] interface nsIIDNService : nsISupports { /** @@ -87,12 +86,4 @@ interface nsIIDNService : nsISupports * for callers that want early normalization. */ AUTF8String normalize(in AUTF8String input); - - /** - * Normalizes and converts a host to UTF-8 if the host is in the IDN - * whitelist, otherwise converts it to ACE. This is useful for display - * purposes and to ensure an encoding consistent with nsIURI::GetHost(). - * If the result is ASCII or ACE encoded, |isASCII| will be true. - */ - AUTF8String convertToDisplayIDN(in AUTF8String input, out boolean isASCII); }; diff --git a/mozilla/netwerk/dns/src/nsIDNService.cpp b/mozilla/netwerk/dns/src/nsIDNService.cpp index 972f0f26a02..766eeef4b91 100644 --- a/mozilla/netwerk/dns/src/nsIDNService.cpp +++ b/mozilla/netwerk/dns/src/nsIDNService.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -57,8 +57,6 @@ static const PRUint32 kMaxDNSNodeLen = 63; #define NS_NET_PREF_IDNTESTBED "network.IDN_testbed" #define NS_NET_PREF_IDNPREFIX "network.IDN_prefix" #define NS_NET_PREF_IDNBLACKLIST "network.IDN.blacklist_chars" -#define NS_NET_PREF_SHOWPUNYCODE "network.IDN_show_punycode" -#define NS_NET_PREF_IDNWHITELIST "network.IDN.whitelist." inline PRBool isOnlySafeChars(const nsAFlatString& in, const nsAFlatString& blacklist) @@ -79,19 +77,13 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsIDNService, nsresult nsIDNService::Init() { - nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) - prefs->GetBranch(NS_NET_PREF_IDNWHITELIST, getter_AddRefs(mIDNWhitelistPrefBranch)); - - nsCOMPtr prefInternal(do_QueryInterface(prefs)); + nsCOMPtr prefInternal(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefInternal) { prefInternal->AddObserver(NS_NET_PREF_IDNTESTBED, this, PR_TRUE); prefInternal->AddObserver(NS_NET_PREF_IDNPREFIX, this, PR_TRUE); prefInternal->AddObserver(NS_NET_PREF_IDNBLACKLIST, this, PR_TRUE); - prefInternal->AddObserver(NS_NET_PREF_SHOWPUNYCODE, this, PR_TRUE); prefsChanged(prefInternal, nsnull); } - return NS_OK; } @@ -130,11 +122,6 @@ void nsIDNService::prefsChanged(nsIPrefBranch *prefBranch, const PRUnichar *pref else mIDNBlacklist.Truncate(); } - if (!pref || NS_LITERAL_STRING(NS_NET_PREF_SHOWPUNYCODE).Equals(pref)) { - PRBool val; - if (NS_SUCCEEDED(prefBranch->GetBoolPref(NS_NET_PREF_SHOWPUNYCODE, &val))) - mShowPunycode = val; - } } nsIDNService::nsIDNService() @@ -295,52 +282,6 @@ NS_IMETHODIMP nsIDNService::Normalize(const nsACString & input, nsACString & out return NS_OK; } -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 - nsCAutoString lower(input); - ToLowerCase(lower); - - PRBool isACE; - IsACE(lower, &isACE); - - if (isACE && !mShowPunycode && isInWhitelist(lower)) { - // ConvertACEtoUTF8() can't fail, but might return the original ACE string - ConvertACEtoUTF8(lower, _retval); - *_isASCII = IsASCII(_retval); - } else { - *_isASCII = PR_TRUE; - } - } else { - if (mShowPunycode && NS_SUCCEEDED(ConvertUTF8toACE(input, _retval))) { - *_isASCII = PR_TRUE; - return NS_OK; - } - - // We have to normalize the hostname before testing against the domain - // whitelist. See bug 315411. - rv = Normalize(input, _retval); - if (NS_FAILED(rv)) return rv; - - // 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; -} - //----------------------------------------------------------------------------- static void utf16ToUcs4(const nsAString& in, PRUint32 *out, PRUint32 outBufLen, PRUint32 *outLen) @@ -629,21 +570,3 @@ nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out) return NS_OK; } - -PRBool nsIDNService::isInWhitelist(const nsACString &host) -{ - if (mIDNWhitelistPrefBranch) { - // truncate trailing dots first - nsCAutoString tld(host); - tld.Trim("."); - PRInt32 pos = tld.RFind("."); - - PRBool safe; - if (pos != kNotFound && - NS_SUCCEEDED(mIDNWhitelistPrefBranch->GetBoolPref(tld.get() + pos + 1, &safe))) - return safe; - } - - return PR_FALSE; -} - diff --git a/mozilla/netwerk/dns/src/nsIDNService.h b/mozilla/netwerk/dns/src/nsIDNService.h index 40d7b86cc74..2625dead5af 100644 --- a/mozilla/netwerk/dns/src/nsIDNService.h +++ b/mozilla/netwerk/dns/src/nsIDNService.h @@ -75,7 +75,6 @@ private: nsresult encodeToACE(const nsAString& in, nsACString& out); nsresult stringPrep(const nsAString& in, nsAString& out); nsresult decodeACE(const nsACString& in, nsACString& out); - PRBool isInWhitelist(const nsACString &host); void prefsChanged(nsIPrefBranch *prefBranch, const PRUnichar *pref); PRBool mMultilingualTestBed; // if true generates extra node for mulitlingual testbed @@ -83,8 +82,6 @@ private: nsCOMPtr mNormalizer; char mACEPrefix[kACEPrefixLen+1]; nsXPIDLString mIDNBlacklist; - PRBool mShowPunycode; - nsCOMPtr mIDNWhitelistPrefBranch; }; #endif // nsIDNService_h__