Changed location.href to force escape 8 bit if the href contains 8 bit, bug 40469, r=ftang, sr=jst.

This commit is contained in:
nhotta%netscape.com 2001-11-14 23:45:23 +00:00
Родитель 6638bbd7cf
Коммит 4637350292
1 изменённых файлов: 97 добавлений и 1 удалений

Просмотреть файл

@ -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<nsIJSContextStack> 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<nsIScriptGlobalObject> nativeGlob;
nsJSUtils::GetDynamicScriptGlobal(cx, getter_AddRefs(nativeGlob));
NS_ENSURE_TRUE(nativeGlob, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(nativeGlob);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMDocument> domDoc;
rv = window->GetDocument(getter_AddRefs(domDoc));
NS_ENSURE_SUCCESS(rv, rv);
if (!domDoc)
return NS_OK;
nsCOMPtr<nsIDocument> 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 <nsICharsetConverterManager2> ccm2 = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIAtom> charsetAtom;
rv = ccm2->GetCharsetAtom(charset.get(), getter_AddRefs(charsetAtom));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUnicodeEncoder> 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<nsIURI> 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<nsIDocShellLoadInfo> loadInfo;