diff --git a/mozilla/content/base/src/nsContentSink.cpp b/mozilla/content/base/src/nsContentSink.cpp index 8da28d2fbbe..2baf780dc5b 100644 --- a/mozilla/content/base/src/nsContentSink.cpp +++ b/mozilla/content/base/src/nsContentSink.cpp @@ -63,6 +63,7 @@ #include "nsHTMLAtoms.h" #include "nsIDOMWindowInternal.h" #include "nsIPrincipal.h" +#include "nsIPrefBranch.h" #include "nsIScriptSecurityManager.h" #include "nsIScriptGlobalObject.h" #include "nsNetCID.h" @@ -277,6 +278,60 @@ nsContentSink::ScriptEvaluated(nsresult aResult, return NS_OK; } +typedef PRBool (* PR_CALLBACK HeaderCallback)(nsIHttpChannel* aChannel); + +struct HeaderData { + char* const name; + // The function returns true if and only if it's OK to process the header + HeaderCallback checkFunc; +}; + +PR_STATIC_CALLBACK(PRBool) +ContentLocationOK(nsIHttpChannel* aChannel) +{ + // Some servers are known to send bogus content-location headers. + // We blacklist them here. See bug 238654. + NS_PRECONDITION(aChannel, "Must have a channel"); + + nsCAutoString serverHeader; + nsresult rv = + aChannel->GetResponseHeader(NS_LITERAL_CSTRING("server"), serverHeader); + if (NS_FAILED(rv) || serverHeader.IsEmpty()) { + return PR_TRUE; + } + + nsCOMPtr prefBranch = + do_GetService("@mozilla.org/preferences-service;1"); + if (!prefBranch) { + return PR_TRUE; + } + + nsXPIDLCString serverList; + rv = prefBranch->GetCharPref("browser.content-location.bogus-servers", + getter_Copies(serverList)); + if (NS_FAILED(rv) || serverList.IsEmpty()) { + return PR_TRUE; + } + + // The server list is a comma-separated list; server names + // containing commas use periods instead. + serverHeader.ReplaceChar(',', '.'); + + PRUint32 cur = 0; + do { + PRInt32 comma = serverList.FindChar(',', cur); + if (comma == kNotFound) { + comma = serverList.Length(); + } + if (StringBeginsWith(serverHeader, Substring(serverList, cur, comma-cur))) { + return PR_FALSE; + } + cur = comma + 1; + } while (cur < serverList.Length()); + + return PR_TRUE; +} + nsresult nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel) { @@ -285,26 +340,29 @@ nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel) if (!httpchannel) { return NS_OK; } - - static const char *const headers[] = { - "link", - "default-style", - "content-style-type", - "content-location", + + static const HeaderData headers[] = { + { "link", nsnull }, + { "default-style", nsnull }, + { "content-style-type", nsnull }, + { "content-location", ContentLocationOK }, // add more http headers if you need - 0 + { 0, nsnull } }; - const char *const *name = headers; + const HeaderData *data = headers; nsCAutoString tmp; - while (*name) { - nsresult rv = httpchannel->GetResponseHeader(nsDependentCString(*name), tmp); - if (NS_SUCCEEDED(rv) && !tmp.IsEmpty()) { - nsCOMPtr key = do_GetAtom(*name); - ProcessHeaderData(key, NS_ConvertASCIItoUCS2(tmp)); + while (data->name) { + if (!data->checkFunc || data->checkFunc(httpchannel)) { + nsresult rv = + httpchannel->GetResponseHeader(nsDependentCString(data->name), tmp); + if (NS_SUCCEEDED(rv) && !tmp.IsEmpty()) { + nsCOMPtr key = do_GetAtom(data->name); + ProcessHeaderData(key, NS_ConvertASCIItoUCS2(tmp)); + } } - ++name; + ++data; } return NS_OK; diff --git a/mozilla/modules/libpref/src/init/all.js b/mozilla/modules/libpref/src/init/all.js index d73f6eb0be4..a6ea4c5db48 100644 --- a/mozilla/modules/libpref/src/init/all.js +++ b/mozilla/modules/libpref/src/init/all.js @@ -94,6 +94,12 @@ pref("browser.helperApps.alwaysAsk.force", false); pref("browser.helperApps.neverAsk.saveToDisk", ""); pref("browser.helperApps.neverAsk.openFile", ""); +// Blacklist of servers whose content-location headers are unreliable +// and should be ignored. This is a comma-separated list of server +// names, with no spaces before or after the commas. If the server +// name you want to add here contains a comma, use a period instead. +pref("browser.content-location.bogus-servers", "Microsoft-IIS/4.0,Microsoft-IIS/5.0,Microsoft-IIS/6.0,Oracle9iAS/9.0.2,Oracle9iAS (1.0.2.2.1)"); + // xxxbsmedberg: where should prefs for the toolkit go? pref("browser.chrome.toolbar_tips", true); // 0 = Pictures Only, 1 = Text Only, 2 = Pictures and Text