diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index 8860f0fe573..e8b6b023a13 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -2806,8 +2806,13 @@ nsGenericElement::TriggerLink(nsIPresContext* aPresContext, nsCOMPtr securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); nsCOMPtr absURI; - if (NS_SUCCEEDED(rv)) - rv = NS_NewURI(getter_AddRefs(absURI), absURLSpec, nsnull, aBaseURL); + if (NS_SUCCEEDED(rv)) { + nsAutoString docCharset; + if (NS_SUCCEEDED(mDocument->GetDocumentCharacterSet(docCharset))) + rv = NS_NewURI(getter_AddRefs(absURI), absURLSpec, NS_LossyConvertUCS2toASCII(docCharset).get(), aBaseURL); + else + rv = NS_NewURI(getter_AddRefs(absURI), absURLSpec, nsnull, aBaseURL); + } if (NS_SUCCEEDED(rv)) proceed = securityManager->CheckLoadURI(aBaseURL, absURI, nsIScriptSecurityManager::STANDARD); diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index c72930cc99f..07d13bb9525 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -575,11 +575,27 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent, // Fall through, this seems like the most reasonable action case eLinkVerb_Replace: { + // get a charset of the document and use is as originCharset + nsAutoString docCharset; + nsCOMPtr presShell; + nsDocShell::GetPresShell(getter_AddRefs(presShell)); + if (presShell) + { + nsCOMPtr doc; + presShell->GetDocument(getter_AddRefs(doc)); + if (doc && + NS_FAILED(doc->GetDocumentCharacterSet(docCharset))) + docCharset.Truncate(); + } + // for now, just hack the verb to be view-link-clicked // and down in the load document code we'll detect this and // set the correct uri loader command nsCOMPtr uri; - NS_NewURI(getter_AddRefs(uri), nsDependentString(aURLSpec), nsnull); + NS_NewURI(getter_AddRefs(uri), nsDependentString(aURLSpec), + docCharset.IsEmpty() + ? nsnull + : NS_LossyConvertUCS2toASCII(docCharset).get()); // No URI object? This may indicate the URLspec is for an // unrecognized protocol. Embedders might still be interested diff --git a/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp b/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp index 2f6edc71541..b98ced4d6fc 100644 --- a/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp +++ b/mozilla/dom/src/jsurl/nsJSProtocolHandler.cpp @@ -768,6 +768,57 @@ nsJSProtocolHandler::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) return rv; } +nsresult +nsJSProtocolHandler::EnsureUTF8Spec(const nsAFlatCString &aSpec, const char *aCharset, + nsACString &aUTF8Spec) +{ + aUTF8Spec.Truncate(); + + // assume UTF-8 if the spec contains unescaped non ASCII + if (!nsCRT::IsAscii(aSpec.get())) + return NS_OK; + + nsCAutoString unescapedSpec; + NS_UnescapeURL(aSpec.get(), aSpec.Length(), + esc_OnlyNonASCII, unescapedSpec); + + if (IsASCII(unescapedSpec)) + return NS_OK; + + nsresult rv; + if (!mCharsetConverterManager) { + mCharsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + } + nsCOMPtr charsetAtom; + rv = mCharsetConverterManager->GetCharsetAtom2(aCharset, getter_AddRefs(charsetAtom)); + NS_ENSURE_SUCCESS(rv, rv); + + if (mCharsetAtom != charsetAtom) { + rv = mCharsetConverterManager->GetUnicodeDecoder(charsetAtom, + getter_AddRefs(mUnicodeDecoder)); + NS_ENSURE_SUCCESS(rv, rv); + mCharsetAtom = charsetAtom; + } + + PRInt32 srcLen = unescapedSpec.Length(); + PRInt32 dstLen; + rv = mUnicodeDecoder->GetMaxLength(unescapedSpec.get(), srcLen, &dstLen); + NS_ENSURE_SUCCESS(rv, rv); + + PRUnichar *ustr = (PRUnichar *) nsMemory::Alloc(dstLen * sizeof(PRUnichar)); + NS_ENSURE_TRUE(ustr, NS_ERROR_OUT_OF_MEMORY); + + rv = mUnicodeDecoder->Convert(unescapedSpec.get(), &srcLen, ustr, &dstLen); + if (NS_SUCCEEDED(rv)) { + NS_ConvertUCS2toUTF8 rawUTF8Spec(ustr, dstLen); + NS_EscapeURL(rawUTF8Spec, esc_AlwaysCopy | esc_OnlyNonASCII, aUTF8Spec); + } + nsMemory::Free(ustr); + + return rv; +} + //////////////////////////////////////////////////////////////////////////////// // nsIProtocolHandler methods: @@ -815,26 +866,17 @@ nsJSProtocolHandler::NewURI(const nsACString &aSpec, if (NS_FAILED(rv)) return rv; - if (IsASCII(aSpec)) - rv = url->SetSpec(aSpec); + if (!aCharset || !nsCRT::strcasecmp("UTF-8", aCharset)) + rv = url->SetSpec(aSpec); else { - // need special encoding for unicode characters... - // XXXdarin iterate over the UTF-8 chars instead - NS_ConvertUTF8toUCS2 ucsSpec(aSpec); - nsCAutoString encSpec; - - char buf[6+1]; // space for \uXXXX plus a NUL at the end - for (const PRUnichar *uch = ucsSpec.get(); *uch; ++uch) { - if (*uch > 0x7F) { - PR_snprintf(buf, sizeof(buf), "\\u%.4x", *uch); - encSpec.Append(buf); - } - else { - // it's ASCII so we're safe... - encSpec.Append(char(*uch)); - } - } - rv = url->SetSpec(encSpec); + nsCAutoString utf8Spec; + rv = EnsureUTF8Spec(PromiseFlatCString(aSpec), aCharset, utf8Spec); + if (NS_SUCCEEDED(rv)) { + if (utf8Spec.IsEmpty()) + rv = url->SetSpec(aSpec); + else + rv = url->SetSpec(utf8Spec); + } } if (NS_FAILED(rv)) { diff --git a/mozilla/dom/src/jsurl/nsJSProtocolHandler.h b/mozilla/dom/src/jsurl/nsJSProtocolHandler.h index e039dd80c8e..e8dd2254be4 100644 --- a/mozilla/dom/src/jsurl/nsJSProtocolHandler.h +++ b/mozilla/dom/src/jsurl/nsJSProtocolHandler.h @@ -40,6 +40,8 @@ #define nsJSProtocolHandler_h___ #include "nsIProtocolHandler.h" +#include "nsICharsetConverterManager.h" +#include "nsICharsetConverterManager2.h" #define NS_JSPROTOCOLHANDLER_CID \ { /* bfc310d2-38a0-11d3-8cd3-0060b0fc14a3 */ \ @@ -67,6 +69,13 @@ public: nsresult Init(); protected: + + nsresult EnsureUTF8Spec(const nsAFlatCString &aSpec, const char *aCharset, + nsACString &aUTF8Spec); + + nsCOMPtr mCharsetConverterManager; + nsCOMPtr mCharsetAtom; + nsCOMPtr mUnicodeDecoder; }; #endif /* nsJSProtocolHandler_h___ */