From 2c2e9d314ddfcdf1925da409ef1f7970e3434b42 Mon Sep 17 00:00:00 2001 From: "nhotta%netscape.com" Date: Wed, 14 Nov 2001 23:45:23 +0000 Subject: [PATCH] Changed location.href to force escape 8 bit if the href contains 8 bit, bug 40469, r=ftang, sr=jst. git-svn-id: svn://10.0.0.236/trunk@108102 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/dom/src/base/nsLocation.cpp | 98 ++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/mozilla/dom/src/base/nsLocation.cpp b/mozilla/dom/src/base/nsLocation.cpp index 045b3505c53..1587d02ff19 100644 --- a/mozilla/dom/src/base/nsLocation.cpp +++ b/mozilla/dom/src/base/nsLocation.cpp @@ -61,6 +61,91 @@ #include "nsXPIDLString.h" #include "nsDOMError.h" #include "nsDOMClassInfo.h" +#include "nsICharsetConverterManager.h" +#include "nsICharsetConverterManager2.h" + + +static nsresult EscapeNonAsciiInURI(nsAReadableString& aHref, nsAWritableCString& aEscapedHref) +{ + aEscapedHref.Truncate(0); + + nsresult rv; + + // Get a document charset, no escaping in case of failure. + nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + JSContext *cx; + + rv = stack->Peek(&cx); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr nativeGlob; + nsJSUtils::GetDynamicScriptGlobal(cx, getter_AddRefs(nativeGlob)); + NS_ENSURE_TRUE(nativeGlob, NS_ERROR_FAILURE); + + nsCOMPtr window = do_QueryInterface(nativeGlob); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr domDoc; + rv = window->GetDocument(getter_AddRefs(domDoc)); + NS_ENSURE_SUCCESS(rv, rv); + if (!domDoc) + return NS_OK; + + nsCOMPtr doc(do_QueryInterface(domDoc)); + NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); + + nsAutoString charset; + rv = doc->GetDocumentCharacterSet(charset); + NS_ENSURE_SUCCESS(rv, rv); + + // Convert from Unicode to a document charset. + nsCOMPtr ccm2 = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr charsetAtom; + rv = ccm2->GetCharsetAtom(charset.get(), getter_AddRefs(charsetAtom)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr encoder; + rv = ccm2->GetUnicodeEncoder(charsetAtom, getter_AddRefs(encoder)); + NS_ENSURE_SUCCESS(rv, rv); + + const nsAFlatString &tmp = PromiseFlatString(aHref); + PRInt32 len; + + rv = encoder->GetMaxLength(tmp.get(), tmp.Length(), &len); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 bufferLen = len; + char* buffer = (char *) nsMemory::Alloc(bufferLen); + NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); + + rv = encoder->Convert(tmp.get(), &len, buffer, &bufferLen); + if (NS_FAILED(rv)) { + nsMemory::Free(buffer); + return rv; + } + + // Escape any 8 bit data. + const char* hexChars = "0123456789ABCDEF"; + for (PRUint32 i = 0; i < (PRUint32) len; i++) { + unsigned char c = (unsigned char) buffer[i]; + if (c < 128) { + aEscapedHref.Append((char) c); + } + else { + aEscapedHref.Append('%'); + aEscapedHref.Append(hexChars[c >> 4]); /* high nibble */ + aEscapedHref.Append(hexChars[c & 0x0f]); /* low nibble */ + } + } + + nsMemory::Free(buffer); + + return rv; +} LocationImpl::LocationImpl(nsIDocShell *aDocShell) { @@ -416,7 +501,18 @@ LocationImpl::SetHrefWithBase(const nsAReadableString& aHref, nsresult result; nsCOMPtr newUri; - result = NS_NewURI(getter_AddRefs(newUri), aHref, aBase); + // 'aHref' is supposed to be already escaped by the script + // but if it contains 8 bit characters without escaped then force to escape it. + // This is for comptibility reason, some of the existing pages do not escape hrefs + // and they are working on 4.x. + nsCAutoString escapedHref; + if (!nsCRT::IsAscii(PromiseFlatString(aHref).get())) + (void) EscapeNonAsciiInURI(aHref, escapedHref); + + if (escapedHref.IsEmpty()) + result = NS_NewURI(getter_AddRefs(newUri), aHref, aBase); + else + result = NS_NewURI(getter_AddRefs(newUri), escapedHref.get(), aBase); if (newUri && mDocShell) { nsCOMPtr loadInfo;