From 455fb87a487970611ae17ccb542ee1fd60ff551b Mon Sep 17 00:00:00 2001
From: roytam1
Date: Tue, 1 May 2018 14:29:08 +0800
Subject: [PATCH] import changes from thunderbird-2.0.0.24
---
chrome/src/nsChromeRegistry.cpp | 41 +-
toolkit/components/build/nsToolkitCompsCID.h | 7 +
.../components/build/nsToolkitCompsModule.cpp | 6 +
.../commandlines/public/Makefile.in | 1 +
.../public/nsICommandLineValidator.idl | 70 ++
.../commandlines/src/nsCommandLine.cpp | 100 ++-
.../downloads/src/nsDownloadManager.cpp | 14 +-
toolkit/components/feeds/src/FeedProcessor.js | 58 +-
.../feeds/test/xml/rfc4287/feed_logo.xml | 4 +-
.../xml/rss2/item_guid_isPermaLink_false.xml | 20 +
.../item_guid_isPermaLink_false_uppercase.xml | 20 +
.../item_guid_isPermaLink_true_uppercase.xml | 20 +
.../item_guid_isPermaLink_unknown_value.xml | 20 +
toolkit/components/help/content/help.js | 6 +
.../history/src/nsGlobalHistory.cpp | 2 +-
toolkit/components/nsDefaultCLH.js | 50 +-
.../passwordmgr/base/nsPasswordManager.cpp | 123 +++-
.../passwordmgr/base/nsPasswordManager.h | 6 +
toolkit/components/remote/Makefile.in | 2 +-
.../components/remote/nsPhRemoteService.cpp | 193 ++++++
toolkit/components/remote/nsPhRemoteService.h | 69 ++
.../satchel/src/nsFormFillController.cpp | 59 +-
.../satchel/src/nsFormFillController.h | 3 +
.../components/satchel/src/nsFormHistory.cpp | 10 +-
.../satchel/src/nsStorageFormHistory.cpp | 2 +-
.../content/enchash-decrypter.js | 55 +-
.../url-classifier/content/listmanager.js | 13 +-
.../url-classifier/content/request-backoff.js | 8 +-
.../url-classifier/content/trtable.js | 23 +-
.../content/url-canonicalizer.js | 354 ----------
.../url-classifier/public/Makefile.in | 1 +
.../public/nsIUrlClassifierUtils.idl | 57 ++
.../components/url-classifier/src/Makefile.in | 1 +
.../src/nsUrlClassifierDBService.cpp | 52 +-
.../src/nsUrlClassifierTable.js | 1 -
.../src/nsUrlClassifierUtils.cpp | 103 +++
.../url-classifier/src/nsUrlClassifierUtils.h | 67 ++
.../url-classifier/tests/Makefile.in | 34 +
.../tests/TestUrlClassifierUtils.cpp | 195 ++++++
toolkit/content/charsetOverlay.js | 20 +-
toolkit/content/commonDialog.js | 2 +-
toolkit/content/contentAreaUtils.js | 19 +-
toolkit/content/license.html | 57 +-
toolkit/content/widgets/tabbrowser.xml | 5 +-
toolkit/content/widgets/textbox.xml | 2 +-
toolkit/library/Makefile.in | 10 +-
toolkit/library/nsStaticXULComponents.cpp | 10 +-
.../locales/en-US/chrome/global/license.dtd | 2 +-
.../downloads/src/nsHelperAppDlg.js.in | 9 +-
.../mozapps/extensions/content/extensions.js | 11 +-
.../extensions/src/nsExtensionManager.js.in | 149 ++++-
toolkit/mozapps/installer/package-name.mk | 19 +
toolkit/mozapps/installer/packager.mk | 9 +-
.../mozapps/installer/windows/nsis/common.nsh | 622 +++++++++++++++++-
.../installer/windows/nsis/makensis.mk | 6 +-
.../installer/windows/nsis/version.nsh | 1 +
.../content/pluginInstallerDatasource.js | 32 +-
.../plugins/content/pluginInstallerService.js | 7 +-
.../plugins/content/pluginInstallerWizard.js | 10 +-
toolkit/mozapps/update/src/nsPostUpdateWin.js | 49 +-
.../mozapps/update/src/nsUpdateService.js.in | 135 ++--
.../update/src/updater/archivereader.cpp | 5 +
.../English.lproj/InfoPlist.strings.in | 2 +-
.../update/src/updater/progressui_win.cpp | 71 +-
.../mozapps/update/src/updater/updater.cpp | 71 +-
toolkit/themes/pmstripe/global/jar.mn | 4 +
toolkit/xre/nsAppRunner.cpp | 302 ++++++---
toolkit/xre/nsAppRunner.h | 10 +
toolkit/xre/nsXREDirProvider.cpp | 74 ++-
toolkit/xre/nsXREDirProvider.h | 7 +
xpinstall/wizard/windows/builder/Makefile.in | 4 +-
xpinstall/wizard/windows/builder/build.pl | 9 +-
xulrunner/app/Makefile.in | 7 +-
xulrunner/app/mozilla.in | 3 +-
xulrunner/app/xulrunner.exe.manifest | 10 +-
xulrunner/app/xulrunner.js | 16 +
xulrunner/installer/Makefile.in | 41 ++
xulrunner/installer/mac/Makefile.in | 57 +-
xulrunner/setup/nsXULAppInstall.js | 3 +-
xulrunner/stub/nsXULStub.cpp | 32 +-
80 files changed, 2958 insertions(+), 826 deletions(-)
create mode 100644 toolkit/components/commandlines/public/nsICommandLineValidator.idl
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
create mode 100644 toolkit/components/remote/nsPhRemoteService.cpp
create mode 100644 toolkit/components/remote/nsPhRemoteService.h
delete mode 100644 toolkit/components/url-classifier/content/url-canonicalizer.js
create mode 100644 toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl
create mode 100644 toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
create mode 100644 toolkit/components/url-classifier/src/nsUrlClassifierUtils.h
create mode 100644 toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp
diff --git a/chrome/src/nsChromeRegistry.cpp b/chrome/src/nsChromeRegistry.cpp
index a1e3a918..71622c70 100644
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -666,13 +666,33 @@ nsChromeRegistry::Canonify(nsIURL* aChromeURL)
aChromeURL->SetPath(path);
}
else {
- nsCAutoString filePath;
- rv = aChromeURL->GetFilePath(filePath);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (filePath.Find(NS_LITERAL_CSTRING("..")) != -1 ||
- filePath.FindChar(':') != -1) {
- return NS_ERROR_DOM_BAD_URI;
+ // prevent directory traversals ("..")
+ // path is already unescaped once, but uris can get unescaped twice
+ const char* pos = path.BeginReading();
+ const char* end = path.EndReading();
+ while (pos < end) {
+ switch (*pos) {
+ case ':':
+ return NS_ERROR_DOM_BAD_URI;
+ case '.':
+ if (pos[1] == '.')
+ return NS_ERROR_DOM_BAD_URI;
+ break;
+ case '%':
+ // chrome: URIs with double-escapes are trying to trick us.
+ // watch for %2e, and %25 in case someone triple unescapes
+ if (pos[1] == '2' &&
+ ( pos[2] == 'e' || pos[2] == 'E' ||
+ pos[2] == '5' ))
+ return NS_ERROR_DOM_BAD_URI;
+ break;
+ case '?':
+ case '#':
+ // ignore query or ref part, we're done
+ pos = end;
+ continue;
+ }
+ ++pos;
}
}
@@ -1965,7 +1985,7 @@ CheckVersionFlag(const nsSubstring& aFlag, const nsSubstring& aData,
const nsSubstring& aValue, nsIVersionComparator* aChecker,
TriState& aResult)
{
- if (! (aData.Length() > aFlag.Length() + 2))
+ if (aData.Length() < aFlag.Length() + 2)
return PR_FALSE;
if (!StringBeginsWith(aData, aFlag))
@@ -2006,6 +2026,9 @@ CheckVersionFlag(const nsSubstring& aFlag, const nsSubstring& aData,
return PR_FALSE;
}
+ if (testdata.Length() == 0)
+ return PR_FALSE;
+
if (aResult != eOK) {
if (!aChecker) {
aResult = eBad;
@@ -2388,7 +2411,7 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
nsCOMPtr chromeuri, resolveduri;
rv = io->NewURI(nsDependentCString(chrome), nsnull, nsnull,
getter_AddRefs(chromeuri));
- rv |= io->NewURI(nsDependentCString(resolved), nsnull, nsnull,
+ rv |= io->NewURI(nsDependentCString(resolved), nsnull, manifestURI,
getter_AddRefs(resolveduri));
if (NS_FAILED(rv))
continue;
diff --git a/toolkit/components/build/nsToolkitCompsCID.h b/toolkit/components/build/nsToolkitCompsCID.h
index 92ffe624..65fb0a1a 100644
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -80,6 +80,9 @@
#define NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID \
"@mozilla.org/url-classifier/streamupdater;1"
+#define NS_URLCLASSIFIERUTILS_CONTRACTID \
+ "@mozilla.org/url-classifier/utils;1"
+
#define NS_SCRIPTABLEUNESCAPEHTML_CONTRACTID "@mozilla.org/feed-unescapehtml;1"
/////////////////////////////////////////////////////////////////////////////
@@ -131,6 +134,10 @@
#define NS_URLCLASSIFIERSTREAMUPDATER_CID \
{ 0xc2be6dc0, 0xef1e, 0x4abd, { 0x86, 0xa2, 0x4f, 0x86, 0x4d, 0xdc, 0x57, 0xf6} }
+// {b7b2ccec-7912-4ea6-a548-b038447004bd}
+#define NS_URLCLASSIFIERUTILS_CID \
+{ 0xb7b2ccec, 0x7912, 0x4ea6, { 0xa5, 0x48, 0xb0, 0x38, 0x44, 0x70, 0x04, 0xbd} }
+
// {10f2f5f0-f103-4901-980f-ba11bd70d60d}
#define NS_SCRIPTABLEUNESCAPEHTML_CID \
{ 0x10f2f5f0, 0xf103, 0x4901, { 0x98, 0x0f, 0xba, 0x11, 0xbd, 0x70, 0xd6, 0x0d} }
diff --git a/toolkit/components/build/nsToolkitCompsModule.cpp b/toolkit/components/build/nsToolkitCompsModule.cpp
index d4c0b351..a3906359 100644
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -76,6 +76,7 @@
#ifdef MOZ_URL_CLASSIFIER
#include "nsUrlClassifierDBService.h"
#include "nsUrlClassifierStreamUpdater.h"
+#include "nsUrlClassifierUtils.h"
#endif
#ifdef MOZ_FEEDS
#include "nsScriptableUnescapeHTML.h"
@@ -117,6 +118,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSingleSignonPrompt)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsUrlClassifierDBService,
nsUrlClassifierDBService::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierStreamUpdater)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierUtils)
#endif
#ifdef MOZ_FEEDS
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableUnescapeHTML)
@@ -242,6 +244,10 @@ static const nsModuleComponentInfo components[] =
NS_URLCLASSIFIERSTREAMUPDATER_CID,
NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID,
nsUrlClassifierStreamUpdaterConstructor },
+ { "Url Classifier Utils",
+ NS_URLCLASSIFIERUTILS_CID,
+ NS_URLCLASSIFIERUTILS_CONTRACTID,
+ nsUrlClassifierUtilsConstructor },
#endif
#ifdef MOZ_FEEDS
{ "Unescape HTML",
diff --git a/toolkit/components/commandlines/public/Makefile.in b/toolkit/components/commandlines/public/Makefile.in
index 64890e04..03420076 100644
--- a/toolkit/components/commandlines/public/Makefile.in
+++ b/toolkit/components/commandlines/public/Makefile.in
@@ -49,6 +49,7 @@ XPIDLSRCS = \
nsICommandLine.idl \
nsICommandLineRunner.idl \
nsICommandLineHandler.idl \
+ nsICommandLineValidator.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk
diff --git a/toolkit/components/commandlines/public/nsICommandLineValidator.idl b/toolkit/components/commandlines/public/nsICommandLineValidator.idl
new file mode 100644
index 00000000..327070d1
--- /dev/null
+++ b/toolkit/components/commandlines/public/nsICommandLineValidator.idl
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla toolkit.
+ *
+ * The Initial Developer of the Original Code is
+ * Robert Strong
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsICommandLine;
+
+/**
+ * Validates arguments on the command line of an XUL application.
+ *
+ * Each validator is registered in the category "command-line-validator".
+ * The entries in this category are read in alphabetical order, and each
+ * category value is treated as a service contractid implementing this
+ * interface.
+ *
+ * By convention, validator with ordinary priority should begin with "m".
+ *
+ * Example:
+ * Category Entry Value
+ * command-line-validator b-browser @mozilla.org/browser/clh;1
+ * command-line-validator m-edit @mozilla.org/composer/clh;1
+ * command-line-validator m-irc @mozilla.org/chatzilla/clh;1
+ *
+ */
+
+[scriptable, uuid(5ecaa593-7660-4a3a-957a-92d5770671c7)]
+interface nsICommandLineValidator : nsISupports
+{
+ /**
+ * Process the command-line validators in the proper order, calling
+ * "validate()" on each.
+ *
+ * @throws NS_ERROR_ABORT if any validator throws NS_ERROR_ABORT. All other
+ * errors thrown by validators will be silently ignored.
+ */
+ void validate(in nsICommandLine aCommandLine);
+};
diff --git a/toolkit/components/commandlines/src/nsCommandLine.cpp b/toolkit/components/commandlines/src/nsCommandLine.cpp
index b8e2ebdd..926e9308 100644
--- a/toolkit/components/commandlines/src/nsCommandLine.cpp
+++ b/toolkit/components/commandlines/src/nsCommandLine.cpp
@@ -39,6 +39,7 @@
#include "nsICategoryManager.h"
#include "nsICommandLineHandler.h"
+#include "nsICommandLineValidator.h"
#include "nsIDOMWindow.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
@@ -85,12 +86,17 @@ public:
protected:
~nsCommandLine() { }
- typedef nsresult (*EnumerateCallback)(nsICommandLineHandler* aHandler,
+ typedef nsresult (*EnumerateHandlersCallback)(nsICommandLineHandler* aHandler,
+ nsICommandLine* aThis,
+ void *aClosure);
+ typedef nsresult (*EnumerateValidatorsCallback)(nsICommandLineValidator* aValidator,
nsICommandLine* aThis,
void *aClosure);
void appendArg(const char* arg);
- nsresult EnumerateHandlers(EnumerateCallback aCallback, void *aClosure);
+ void resolveShortcutURL(nsILocalFile* aFile, nsACString& outURL);
+ nsresult EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure);
+ nsresult EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure);
nsStringArray mArgs;
PRUint32 mState;
@@ -439,18 +445,27 @@ nsCommandLine::ResolveURI(const nsAString& aArgument, nsIURI* *aResult)
nsCOMPtr io = do_GetIOService();
NS_ENSURE_TRUE(io, NS_ERROR_OUT_OF_MEMORY);
+ nsCOMPtr workingDirURI;
+ if (mWorkingDir) {
+ io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI));
+ }
+
nsCOMPtr lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
rv = lf->InitWithPath(aArgument);
if (NS_SUCCEEDED(rv)) {
lf->Normalize();
+ nsCAutoString url;
+ // Try to resolve the url for .url files.
+ resolveShortcutURL(lf, url);
+ if (!url.IsEmpty()) {
+ return io->NewURI(url,
+ nsnull,
+ workingDirURI,
+ aResult);
+ }
return io->NewFileURI(lf, aResult);
}
- nsCOMPtr workingDirURI;
- if (mWorkingDir) {
- io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI));
- }
-
return io->NewURI(NS_ConvertUTF16toUTF8(aArgument),
nsnull,
workingDirURI,
@@ -470,6 +485,22 @@ nsCommandLine::appendArg(const char* arg)
mArgs.AppendString(warg);
}
+void
+nsCommandLine::resolveShortcutURL(nsILocalFile* aFile, nsACString& outURL)
+{
+ nsCOMPtr fph;
+ nsresult rv = NS_GetFileProtocolHandler(getter_AddRefs(fph));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr uri;
+ rv = fph->ReadURLFile(aFile, getter_AddRefs(uri));
+ if (NS_FAILED(rv))
+ return;
+
+ uri->GetSpec(outURL);
+}
+
NS_IMETHODIMP
nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir,
PRUint32 aState)
@@ -536,7 +567,7 @@ nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir,
}
nsresult
-nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure)
+nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure)
{
nsresult rv;
@@ -578,6 +609,55 @@ nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure)
return rv;
}
+nsresult
+nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure)
+{
+ nsresult rv;
+
+ nsCOMPtr catman
+ (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr entenum;
+ rv = catman->EnumerateCategory("command-line-validator",
+ getter_AddRefs(entenum));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr strenum (do_QueryInterface(entenum));
+ NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
+
+ nsCAutoString entry;
+ PRBool hasMore;
+ while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
+ strenum->GetNext(entry);
+
+ nsXPIDLCString contractID;
+ rv = catman->GetCategoryEntry("command-line-validator",
+ entry.get(),
+ getter_Copies(contractID));
+ if (!contractID)
+ continue;
+
+ nsCOMPtr clv(do_GetService(contractID.get()));
+ if (!clv)
+ continue;
+
+ rv = (aCallback)(clv, this, aClosure);
+ if (rv == NS_ERROR_ABORT)
+ break;
+
+ rv = NS_OK;
+ }
+
+ return rv;
+}
+
+static nsresult
+EnumValidate(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void*)
+{
+ return aValidator->Validate(aThis);
+}
+
static nsresult
EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*)
{
@@ -589,6 +669,10 @@ nsCommandLine::Run()
{
nsresult rv;
+ rv = EnumerateValidators(EnumValidate, nsnull);
+ if (rv == NS_ERROR_ABORT)
+ return rv;
+
rv = EnumerateHandlers(EnumRun, nsnull);
if (rv == NS_ERROR_ABORT)
return rv;
diff --git a/toolkit/components/downloads/src/nsDownloadManager.cpp b/toolkit/components/downloads/src/nsDownloadManager.cpp
index 720529a3..d74799ad 100644
--- a/toolkit/components/downloads/src/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/src/nsDownloadManager.cpp
@@ -74,6 +74,12 @@
#include
#endif
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define BYTES_TO_KBYTES(bytes) ((PRFloat64)((PRInt64)(bytes >> 8) / 4 + .5))
+#else
+#define BYTES_TO_KBYTES(bytes) ((PRFloat64)bytes / 1024.0 + .5)
+#endif
+
/* Outstanding issues/todo:
* 1. Implement pause/resume.
*/
@@ -480,8 +486,8 @@ nsDownloadManager::AssertProgressInfoFor(const PRUnichar* aPath)
internalDownload->GetTransferInformation();
// convert from bytes to kbytes for progress display
- PRInt64 current = (PRFloat64)transferInfo.mCurrBytes / 1024 + .5;
- PRInt64 max = (PRFloat64)transferInfo.mMaxBytes / 1024 + .5;
+ PRInt64 current = BYTES_TO_KBYTES(transferInfo.mCurrBytes);
+ PRInt64 max = BYTES_TO_KBYTES(transferInfo.mMaxBytes);
nsAutoString currBytes; currBytes.AppendInt(current);
nsAutoString maxBytes; maxBytes.AppendInt(max);
@@ -2330,14 +2336,14 @@ nsDownload::GetPercentComplete(PRInt32* aPercentComplete)
NS_IMETHODIMP
nsDownload::GetAmountTransferred(PRUint64* aAmountTransferred)
{
- *aAmountTransferred = ((PRFloat64)mCurrBytes / 1024.0 + .5);
+ *aAmountTransferred = BYTES_TO_KBYTES(mCurrBytes);
return NS_OK;
}
NS_IMETHODIMP
nsDownload::GetSize(PRUint64* aSize)
{
- *aSize = ((PRFloat64)mMaxBytes / 1024 + .5);
+ *aSize = BYTES_TO_KBYTES(mMaxBytes);
return NS_OK;
}
diff --git a/toolkit/components/feeds/src/FeedProcessor.js b/toolkit/components/feeds/src/FeedProcessor.js
index 2f199139..c10d3aae 100644
--- a/toolkit/components/feeds/src/FeedProcessor.js
+++ b/toolkit/components/feeds/src/FeedProcessor.js
@@ -333,7 +333,7 @@ Feed.prototype = {
categories: ["categories", "dc:subject"],
rights: ["atom03:rights","atom:rights"],
cloud: ["cloud"],
- image: ["image", "rss1:image"],
+ image: ["image", "rss1:image", "atom:logo"],
textInput: ["textInput", "rss1:textinput"],
skipDays: ["skipDays"],
skipHours: ["skipHours"],
@@ -355,6 +355,11 @@ Feed.prototype = {
if (bagHasKey(this.fields, "links"))
this._atomLinksToURI();
+ // Resolve relative image links
+ if (this.image && bagHasKey(this.image, "url")) {
+ this._resolveImageLink();
+ }
+
this._resetBagMembersToRawText([this.searchLists.subtitle,
this.searchLists.title]);
},
@@ -363,22 +368,36 @@ Feed.prototype = {
var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
var alternates = findAtomLinks("alternate", links);
if (alternates.length > 0) {
- try {
- var href = alternates[0].getPropertyAsAString("href");
- var base;
- if (bagHasKey(alternates[0], "xml:base"))
- base = strToURI(alternates[0].getPropertyAsAString("xml:base"),
- this.baseURI);
- else
- base = this.baseURI;
- this.link = strToURI(alternates[0].getPropertyAsAString("href"), base);
- }
- catch(e) {
- LOG(e);
- }
+ var href = alternates[0].getPropertyAsAString("href");
+ var base;
+ if (bagHasKey(alternates[0], "xml:base"))
+ base = alternates[0].getPropertyAsAString("xml:base");
+ this.link = this._resolveURI(href, base);
}
},
+ _resolveImageLink: function Feed_resolveImageLink() {
+ var base;
+ if (bagHasKey(this.image, "xml:base"))
+ base = this.image.getPropertyAsAString("xml:base");
+ var url = this._resolveURI(this.image.getPropertyAsAString("url"), base);
+ if (url)
+ this.image.setPropertyAsAString("url", url.spec);
+ },
+
+ _resolveURI: function Feed_resolveURI(linkSpec, baseSpec) {
+ var uri = null;
+ try {
+ var base = baseSpec ? strToURI(baseSpec, this.baseURI) : this.baseURI;
+ uri = strToURI(linkSpec, base);
+ }
+ catch(e) {
+ LOG(e);
+ }
+
+ return uri;
+ },
+
// reset the bag to raw contents, not text constructs
_resetBagMembersToRawText: function Feed_resetBagMembers(fieldLists) {
for (var i=0; itest title
- http://example.org/logo.jpg
+ logo.jpg
\ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
new file mode 100644
index 00000000..c2a1ad86
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
new file mode 100644
index 00000000..9ff2505c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
new file mode 100644
index 00000000..bc4fdc0e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
new file mode 100644
index 00000000..4dce8c39
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/help/content/help.js b/toolkit/components/help/content/help.js
index d4ab24c3..714ad4b6 100644
--- a/toolkit/components/help/content/help.js
+++ b/toolkit/components/help/content/help.js
@@ -137,6 +137,12 @@ function init() {
helpGlossaryPanel = document.getElementById("help-glossary-panel");
helpBrowser = document.getElementById("help-content");
+ // Turn off unnecessary features for security
+ helpBrowser.docShell.allowJavascript = false;
+ helpBrowser.docShell.allowPlugins = false;
+ helpBrowser.docShell.allowSubframes = false;
+ helpBrowser.docShell.allowMetaRedirects = false;
+
strBundle = document.getElementById("bundle_help");
emptySearchText = strBundle.getString("emptySearchText");
diff --git a/toolkit/components/history/src/nsGlobalHistory.cpp b/toolkit/components/history/src/nsGlobalHistory.cpp
index 852867a5..3fa2d0b1 100644
--- a/toolkit/components/history/src/nsGlobalHistory.cpp
+++ b/toolkit/components/history/src/nsGlobalHistory.cpp
@@ -1524,7 +1524,7 @@ nsGlobalHistory::GetSource(nsIRDFResource* aProperty,
// XXX We could be more forgiving here, and check for literal
// values as well.
nsCOMPtr target = do_QueryInterface(aTarget);
- if (IsURLInHistory(target))
+ if (target && IsURLInHistory(target))
return CallQueryInterface(aTarget, aSource);
}
diff --git a/toolkit/components/nsDefaultCLH.js b/toolkit/components/nsDefaultCLH.js
index 84e4423c..19f150a7 100644
--- a/toolkit/components/nsDefaultCLH.js
+++ b/toolkit/components/nsDefaultCLH.js
@@ -47,6 +47,9 @@ const nsIModule = Components.interfaces.nsIModule;
const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
const nsISupportsString = Components.interfaces.nsISupportsString;
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
+const nsIProperties = Components.interfaces.nsIProperties;
+const nsIFile = Components.interfaces.nsIFile;
+const nsISimpleEnumerator = Components.interfaces.nsISimpleEnumerator;
/**
* This file provides a generic default command-line handler.
@@ -59,6 +62,12 @@ const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
* It doesn't do anything if the pref "toolkit.defaultChromeURI" is unset.
*/
+function getDirectoryService()
+{
+ return Components.classes["@mozilla.org/file/directory_service;1"]
+ .getService(nsIProperties);
+}
+
var nsDefaultCLH = {
/* nsISupports */
@@ -74,8 +83,41 @@ var nsDefaultCLH = {
/* nsICommandLineHandler */
handle : function clh_handle(cmdLine) {
+
+ var printDir;
+ while (printDir = cmdLine.handleFlagWithParam("print-xpcom-dir", false)) {
+ var out = "print-xpcom-dir(\"" + printDir + "\"): ";
+ try {
+ out += getDirectoryService().get(printDir, nsIFile).path;
+ }
+ catch (e) {
+ out += "";
+ }
+
+ dump(out + "\n");
+ Components.utils.reportError(out);
+ }
+
+ var printDirList;
+ while (printDirList = cmdLine.handleFlagWithParam("print-xpcom-dirlist",
+ false)) {
+ out = "print-xpcom-dirlist(\"" + printDirList + "\"): ";
+ try {
+ var list = getDirectoryService().get(printDirList,
+ nsISimpleEnumerator);
+ while (list.hasMoreElements())
+ out += list.getNext().QueryInterface(nsIFile).path + ";";
+ }
+ catch (e) {
+ out += "";
+ }
+
+ dump(out + "\n");
+ Components.utils.reportError(out);
+ }
+
if (cmdLine.preventDefault)
- return;
+ return;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(nsIPrefBranch);
@@ -86,9 +128,9 @@ var nsDefaultCLH = {
.getService(Components.interfaces.nsIWindowMediator);
var win = windowMediator.getMostRecentWindow(singletonWindowType);
if (win) {
- win.focus();
- cmdLine.preventDefault = true;
- return;
+ win.focus();
+ cmdLine.preventDefault = true;
+ return;
}
}
catch (e) { }
diff --git a/toolkit/components/passwordmgr/base/nsPasswordManager.cpp b/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
index cdb5dc58..e6038efd 100644
--- a/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
+++ b/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
@@ -373,6 +373,11 @@ nsPasswordManager::AddUser(const nsACString& aHost,
if (aUser.IsEmpty() && aPassword.IsEmpty())
return NS_OK;
+ // Reject values that would cause problems when parsing the storage file
+ nsresult rv = CheckLoginValues(aHost,
+ EmptyString(), EmptyString(), EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
// Check for an existing entry for this host + user
if (!aHost.IsEmpty()) {
SignonHashEntry *hashEnt;
@@ -440,6 +445,11 @@ nsPasswordManager::RemoveUser(const nsACString& aHost, const nsAString& aUser)
NS_IMETHODIMP
nsPasswordManager::AddReject(const nsACString& aHost)
{
+ // Reject values that would cause problems when parsing the storage file
+ nsresult rv = CheckLoginValues(aHost,
+ EmptyString(), EmptyString(), EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
mRejectTable.Put(aHost, 1);
WritePasswords(mSignonFile);
return NS_OK;
@@ -611,6 +621,11 @@ nsPasswordManager::AddUserFull(const nsACString& aKey,
if (aUser.IsEmpty() && aPassword.IsEmpty())
return NS_OK;
+ // Reject values that would cause problems when parsing the storage file
+ nsresult rv = CheckLoginValues(aKey, aUserFieldName,
+ aPassFieldName, EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
// Check for an existing entry for this host + user
if (!aKey.IsEmpty()) {
SignonHashEntry *hashEnt;
@@ -795,7 +810,7 @@ nsPasswordManager::Observe(nsISupports* aSubject,
obsService->AddObserver(this, "profile-after-change", PR_TRUE);
} else if (!strcmp(aTopic, "profile-after-change"))
- nsCOMPtr pm = do_GetService(NS_PASSWORDMANAGER_CONTRACTID);
+ LoadPasswords();
return NS_OK;
}
@@ -1023,10 +1038,14 @@ nsPasswordManager::Notify(nsIContent* aFormNode,
if (NS_SUCCEEDED(GetActionRealm(formElement, formActionOrigin)) &&
!entry->actionOrigin.Equals(formActionOrigin)) {
- // update the action URL
- entry->actionOrigin.Assign(formActionOrigin);
- writePasswords = PR_TRUE;
+ // Reject values that would cause problems when parsing the storage file
+ if (NS_SUCCEEDED(CheckLoginValues(EmptyCString(), EmptyString(),
+ EmptyString(), formActionOrigin))) {
+ // update the action URL
+ entry->actionOrigin.Assign(formActionOrigin);
+ writePasswords = PR_TRUE;
+ }
}
if (writePasswords)
@@ -1101,9 +1120,23 @@ nsPasswordManager::Notify(nsIContent* aFormNode,
return NS_OK;
}
+ // Reject values that would cause problems when parsing the storage file
+ // We do this after prompting, lest any code somehow change the values
+ // during the prompting.
+ nsresult rv = CheckLoginValues(realm,
+ entry->userField, entry->passField,
+ entry->actionOrigin);
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+
AddSignonData(realm, entry);
WritePasswords(mSignonFile);
} else if (selection == 2) {
+ // Reject values that would cause problems when parsing the storage file
+ // We do this after prompting, lest any code run from prompt context.
+ nsresult rv = CheckLoginValues(realm, EmptyString(),
+ EmptyString(), EmptyCString());
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+
AddReject(realm);
}
}
@@ -1914,6 +1947,7 @@ nsPasswordManager::FillDocument(nsIDOMDocument* aDomDoc)
inputField->GetValue(oldUserValue);
userField = inputField;
foundNode = inputField;
+ // Only the case differs, so CheckLoginValues() unneeded.
e->userField.Assign(name);
break;
}
@@ -1973,8 +2007,15 @@ nsPasswordManager::FillDocument(nsIDOMDocument* aDomDoc)
temp->GetValue(oldPassValue);
passField = temp;
- if ((e->passField).IsEmpty())
- passField->GetName(e->passField);
+ if ((e->passField).IsEmpty()) {
+ nsAutoString passName;
+ passField->GetName(passName);
+
+ // Reject values that would cause problems when parsing the storage file
+ if (NS_SUCCEEDED(CheckLoginValues(EmptyCString(), EmptyString(),
+ passName, EmptyCString())))
+ e->passField.Assign(passName);
+ }
} else {
continue;
}
@@ -2098,8 +2139,9 @@ nsPasswordManager::FillPassword(nsIDOMEvent* aEvent)
nsCOMPtr form = do_QueryInterface(formEl);
nsCAutoString formActionOrigin;
GetActionRealm(form, formActionOrigin);
- if (NS_FAILED(GetActionRealm(form, formActionOrigin)) ||
- !foundEntry->actionOrigin.Equals(formActionOrigin))
+ if (NS_FAILED(GetActionRealm(form, formActionOrigin)))
+ return NS_OK;
+ if (!foundEntry->actionOrigin.IsEmpty() && !foundEntry->actionOrigin.Equals(formActionOrigin))
return NS_OK;
nsCOMPtr foundNode;
@@ -2197,3 +2239,68 @@ nsPasswordManager::GetActionRealm(nsIForm* aForm, nsCString& aURL)
aURL.Assign(formActionOrigin);
return NS_OK;
}
+
+/* static */ PRBool
+nsPasswordManager::BadCharacterPresent(const nsAString &aString)
+{
+ if (aString.FindChar('\r') >= 0)
+ return PR_TRUE;
+ if (aString.FindChar('\n') >= 0)
+ return PR_TRUE;
+ if (aString.FindChar('\0') >= 0)
+ return PR_TRUE;
+
+ return PR_FALSE;
+}
+
+/* static */ nsresult
+nsPasswordManager::CheckLoginValues(const nsACString &aHost,
+ const nsAString &aUserField,
+ const nsAString &aPassField,
+ const nsACString &aActionOrigin)
+{
+ // aHost
+ if (BadCharacterPresent(NS_ConvertUTF8toUTF16(aHost))) {
+ NS_WARNING("Login rejected, bad character in aHost");
+ return NS_ERROR_FAILURE;
+ }
+ // The aHost arg is used for both login entry hostnames and reject entry
+ // hostnames ("never for this site"). A value of "." is not allowed for
+ // reject entries. It's technically ok for login entries, but to keep the
+ // code simple we'll disallow it anyway.
+ if (aHost.EqualsLiteral(".")) {
+ NS_WARNING("Login rejected, aHost can not be just a period");
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // aUserField
+ if (BadCharacterPresent(aUserField)) {
+ NS_WARNING("Login rejected, bad character in aUserField");
+ return NS_ERROR_FAILURE;
+ }
+ if (aUserField.EqualsLiteral(".")) {
+ NS_WARNING("Login rejected, aUserField can not be just a period");
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // aPassField
+ if (BadCharacterPresent(aPassField)) {
+ NS_WARNING("Login rejected, bad character in aPassField");
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // aActionOrigin
+ if (BadCharacterPresent(NS_ConvertUTF8toUTF16(aActionOrigin))) {
+ NS_WARNING("Login rejected, bad character in aActionOrigin");
+ return NS_ERROR_FAILURE;
+ }
+ if (aActionOrigin.EqualsLiteral(".")) {
+ NS_WARNING("Login rejected, aActionOrigin can not be just a period");
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
diff --git a/toolkit/components/passwordmgr/base/nsPasswordManager.h b/toolkit/components/passwordmgr/base/nsPasswordManager.h
index 655d2b09..0d723cdd 100644
--- a/toolkit/components/passwordmgr/base/nsPasswordManager.h
+++ b/toolkit/components/passwordmgr/base/nsPasswordManager.h
@@ -153,6 +153,12 @@ protected:
static nsresult GetActionRealm(nsIForm* aForm, nsCString& aURL);
+ static PRBool BadCharacterPresent(const nsAString &aString);
+ static nsresult CheckLoginValues(const nsACString &aHost,
+ const nsAString &aUserField,
+ const nsAString &aPassField,
+ const nsACString &aActionOrigin);
+
static PLDHashOperator PR_CALLBACK FindEntryEnumerator(const nsACString& aKey,
SignonHashEntry* aEntry,
void* aUserData);
diff --git a/toolkit/components/remote/Makefile.in b/toolkit/components/remote/Makefile.in
index 293663d9..87e4bb3b 100644
--- a/toolkit/components/remote/Makefile.in
+++ b/toolkit/components/remote/Makefile.in
@@ -71,7 +71,7 @@ CPPSRCS += nsGTKRemoteService.cpp
endif
ifeq (photon,$(MOZ_WIDGET_TOOLKIT))
-CPPSRCS += nsPhMozRemoteHelper.cpp
+CPPSRCS += nsPhRemoteService.cpp
endif
include $(topsrcdir)/config/rules.mk
diff --git a/toolkit/components/remote/nsPhRemoteService.cpp b/toolkit/components/remote/nsPhRemoteService.cpp
new file mode 100644
index 00000000..d62ee298
--- /dev/null
+++ b/toolkit/components/remote/nsPhRemoteService.cpp
@@ -0,0 +1,193 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard.
+ * Portions created by Christopher Blizzard are Copyright (C)
+ * Christopher Blizzard. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adrian Mardare
+ * Max Feil
+ */
+
+#include
+#include
+#include
+#include "nsIGenericFactory.h"
+#include "nsPhRemoteService.h"
+#include "nsIServiceManager.h"
+#include "nsCRT.h"
+
+#ifdef MOZ_XUL_APP
+#include "nsICommandLineRunner.h"
+#include "nsXULAppAPI.h"
+#else
+#include "nsISuiteRemoteService.h"
+#endif
+
+#include
+
+NS_IMPL_QUERY_INTERFACE2(nsPhRemoteService,
+ nsIRemoteService,
+ nsIObserver)
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPhRemoteService::AddRef()
+{
+ return 1;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPhRemoteService::Release()
+{
+ return 1;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::Startup(const char* aAppName, const char* aProfileName)
+{
+ NS_ASSERTION(aAppName, "Don't pass a null appname!");
+
+ if (mIsInitialized)
+ return NS_ERROR_ALREADY_INITIALIZED;
+
+ mIsInitialized = PR_TRUE;
+ mAppName = aAppName;
+ ToLowerCase(mAppName);
+
+ HandleCommandsFor(nsnull, nsnull);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::RegisterWindow(nsIDOMWindow* aWindow)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::Shutdown()
+{
+ if (!mIsInitialized)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ mIsInitialized = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::Observe(nsISupports* aSubject,
+ const char *aTopic,
+ const PRUnichar *aData)
+{
+ // This can be xpcom-shutdown or quit-application, but it's the same either
+ // way.
+ Shutdown();
+ return NS_OK;
+}
+
+#define MOZ_REMOTE_MSG_TYPE 100
+
+static void const * RemoteMsgHandler( PtConnectionServer_t *connection, void *user_data,
+ unsigned long type, void const *msg, unsigned len, unsigned *reply_len )
+{
+ nsresult rv;
+
+ if( type != MOZ_REMOTE_MSG_TYPE ) return NULL;
+
+ /* we are given strings and we reply with strings */
+ char *response = NULL;
+
+ // parse the command
+ nsCOMPtr cmdline
+ (do_CreateInstance("@mozilla.org/toolkit/command-line;1", &rv));
+ if (!NS_FAILED(rv)) {
+
+ // 1) Make sure that it looks remotely valid with parens
+ // 2) Treat ping() immediately and specially
+
+ nsCAutoString command((char *)msg);
+ PRInt32 p1, p2;
+ p1 = command.FindChar('(');
+ p2 = command.FindChar(')');
+
+ if (p1 != kNotFound && p2 != kNotFound && p1 != 0 && p2 >= p1) {
+ command.Truncate(p1);
+ command.Trim(" ", PR_TRUE, PR_TRUE);
+ ToLowerCase(command);
+
+ //printf("Processing xremote command: %s\n", command.get());
+
+ if (!command.EqualsLiteral("ping")) {
+ char* argv[3] = {"dummyappname", "-remote", (char *)msg};
+ rv = cmdline->Init(3, argv, nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
+ if (!NS_FAILED(rv)) {
+ rv = cmdline->Run();
+ if (NS_ERROR_ABORT == rv)
+ response = "500 command not parseable";
+ if (NS_FAILED(rv))
+ response = "509 internal error";
+ } else
+ response = "509 internal error";
+ }
+ } else
+ response = "500 command not parseable";
+ } else
+ response = "509 internal error";
+
+ PtConnectionReply( connection, response ? strlen(response) : 0, response );
+
+ return ( void * ) 1; /* return any non NULL value to indicate we handled the message */
+}
+
+static void client_connect( PtConnector_t *cntr, PtConnectionServer_t *csrvr, void *data )
+{
+ static PtConnectionMsgHandler_t handlers[] = { { 0, RemoteMsgHandler } };
+ PtConnectionAddMsgHandlers( csrvr, handlers, sizeof(handlers)/sizeof(handlers[0]) );
+}
+
+
+void
+nsPhRemoteService::HandleCommandsFor( nsIWidget *aWidget, nsIWeakReference* aWindow )
+{
+ static PRBool ConnectorCreated = PR_FALSE;
+
+///* ATENTIE */ printf( "aProgram=%s aProfile=%s aWidget=%p\n", aProgram?aProgram:"NULL", aProfile?aProfile:"NULL", aWidget );
+
+ if( !ConnectorCreated ) {
+ char RemoteServerName[128];
+ sprintf( RemoteServerName, "%s_RemoteServer", (char *) mAppName.get() );
+ /* create a connector for the remote control */
+ PtConnectorCreate( RemoteServerName, client_connect, NULL );
+ ConnectorCreated = PR_TRUE;
+ }
+ return;
+}
+
+// {C0773E90-5799-4eff-AD03-3EBCD85624AC}
+#define NS_REMOTESERVICE_CID \
+ { 0xc0773e90, 0x5799, 0x4eff, { 0xad, 0x3, 0x3e, 0xbc, 0xd8, 0x56, 0x24, 0xac } }
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsPhRemoteService)
+
+static const nsModuleComponentInfo components[] =
+{
+ { "Remote Service",
+ NS_REMOTESERVICE_CID,
+ "@mozilla.org/toolkit/remote-service;1",
+ nsPhRemoteServiceConstructor
+ }
+};
+
+NS_IMPL_NSGETMODULE(RemoteServiceModule, components)
diff --git a/toolkit/components/remote/nsPhRemoteService.h b/toolkit/components/remote/nsPhRemoteService.h
new file mode 100644
index 00000000..b6686b68
--- /dev/null
+++ b/toolkit/components/remote/nsPhRemoteService.h
@@ -0,0 +1,69 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adrian Mardare
+ * Max Feil
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsPhRemoteService_h__
+#define __nsPhRemoteService_h__
+
+#include "nsIRemoteService.h"
+#include "nsIObserver.h"
+#include "nsString.h"
+
+class nsIWeakReference;
+
+class nsPhRemoteService : public nsIRemoteService,
+ public nsIObserver
+{
+public:
+ // We will be a static singleton, so don't use the ordinary methods.
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREMOTESERVICE
+ NS_DECL_NSIOBSERVER
+
+ nsPhRemoteService() { mIsInitialized = PR_FALSE; }
+
+private:
+ ~nsPhRemoteService() { }
+
+ void HandleCommandsFor(nsIWidget *aWidget,
+ nsIWeakReference* aWindow);
+ PRBool mIsInitialized;
+ nsCString mAppName;
+
+};
+
+#endif /* __nsPhRemoteService_h__ */
diff --git a/toolkit/components/satchel/src/nsFormFillController.cpp b/toolkit/components/satchel/src/nsFormFillController.cpp
index 29f5a269..f9ca10f7 100644
--- a/toolkit/components/satchel/src/nsFormFillController.cpp
+++ b/toolkit/components/satchel/src/nsFormFillController.cpp
@@ -468,36 +468,34 @@ nsFormFillController::OnSearchComplete()
}
NS_IMETHODIMP
-nsFormFillController::OnTextEntered(PRBool *_retval)
+nsFormFillController::OnTextEntered(PRBool* aPrevent)
{
+ NS_ENSURE_ARG(aPrevent);
+ NS_ENSURE_TRUE(mFocusedInput, NS_OK);
// Fire off a DOMAutoComplete event
nsCOMPtr domDoc;
mFocusedInput->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr doc = do_QueryInterface(domDoc);
+ NS_ENSURE_STATE(doc);
nsCOMPtr event;
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
- if (!event) {
- NS_ERROR("Could not create DOM Event");
- return NS_ERROR_FAILURE;
- }
+ nsCOMPtr privateEvent(do_QueryInterface(event));
+ NS_ENSURE_STATE(privateEvent);
event->InitEvent(NS_LITERAL_STRING("DOMAutoComplete"), PR_TRUE, PR_TRUE);
- nsCOMPtr privateEvent(do_QueryInterface(event));
- if (privateEvent) {
- // XXXjst: We mark this event as a trusted event, it's up to the
- // callers of this to ensure that it's only called from trusted
- // code.
- privateEvent->SetTrusted(PR_TRUE);
- }
+ // XXXjst: We mark this event as a trusted event, it's up to the
+ // callers of this to ensure that it's only called from trusted
+ // code.
+ privateEvent->SetTrusted(PR_TRUE);
nsCOMPtr targ = do_QueryInterface(mFocusedInput);
PRBool defaultActionEnabled;
targ->DispatchEvent(event, &defaultActionEnabled);
-
+ *aPrevent = !defaultActionEnabled;
return NS_OK;
}
@@ -994,10 +992,6 @@ nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow)
target->AddEventListener(NS_LITERAL_STRING("contextmenu"),
NS_STATIC_CAST(nsIDOMContextMenuListener *, this),
PR_TRUE);
-
- target->AddEventListener(NS_LITERAL_STRING("keypress"),
- NS_STATIC_CAST(nsIDOMKeyListener *, this),
- PR_TRUE);
}
void
@@ -1053,10 +1047,32 @@ nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
target->RemoveEventListener(NS_LITERAL_STRING("contextmenu"),
NS_STATIC_CAST(nsIDOMContextMenuListener *, this),
PR_TRUE);
+}
- target->RemoveEventListener(NS_LITERAL_STRING("keypress"),
- NS_STATIC_CAST(nsIDOMKeyListener *, this),
- PR_TRUE);
+void
+nsFormFillController::AddKeyListener(nsIDOMHTMLInputElement *aInput)
+{
+ if (!aInput)
+ return;
+
+ nsCOMPtr target = do_QueryInterface(aInput);
+
+ target->AddEventListener(NS_LITERAL_STRING("keypress"),
+ NS_STATIC_CAST(nsIDOMKeyListener *, this),
+ PR_TRUE);
+ }
+
+void
+nsFormFillController::RemoveKeyListener()
+{
+ if (!mFocusedInput)
+ return;
+
+ nsCOMPtr target = do_QueryInterface(mFocusedInput);
+
+ target->RemoveEventListener(NS_LITERAL_STRING("keypress"),
+ NS_STATIC_CAST(nsIDOMKeyListener *, this),
+ PR_TRUE);
}
void
@@ -1074,6 +1090,7 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
// Cache the popup for the focused docShell
mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup));
+ AddKeyListener(aInput);
mFocusedInput = aInput;
// Now we are the autocomplete controller's bitch
@@ -1083,6 +1100,8 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
void
nsFormFillController::StopControllingInput()
{
+ RemoveKeyListener();
+
// Reset the controller's input, but not if it has been switched
// to another input already, which might happen if the user switches
// focus by clicking another autocomplete textbox
diff --git a/toolkit/components/satchel/src/nsFormFillController.h b/toolkit/components/satchel/src/nsFormFillController.h
index a0c25bf5..b57cf656 100644
--- a/toolkit/components/satchel/src/nsFormFillController.h
+++ b/toolkit/components/satchel/src/nsFormFillController.h
@@ -127,6 +127,9 @@ protected:
void AddWindowListeners(nsIDOMWindow *aWindow);
void RemoveWindowListeners(nsIDOMWindow *aWindow);
+ void AddKeyListener(nsIDOMHTMLInputElement *aInput);
+ void RemoveKeyListener();
+
void StartControllingInput(nsIDOMHTMLInputElement *aInput);
void StopControllingInput();
diff --git a/toolkit/components/satchel/src/nsFormHistory.cpp b/toolkit/components/satchel/src/nsFormHistory.cpp
index f8c281cd..f9cbe0af 100644
--- a/toolkit/components/satchel/src/nsFormHistory.cpp
+++ b/toolkit/components/satchel/src/nsFormHistory.cpp
@@ -73,6 +73,10 @@ static void SwapBytes(PRUnichar* aDest, const PRUnichar* aSrc, PRUint32 aLen)
#define PREF_FORMFILL_BRANCH "browser.formfill."
#define PREF_FORMFILL_ENABLE "enable"
+// upper bounds on saved form data, more isn't useful.
+#define FORMFILL_NAME_MAX_LEN 1000
+#define FORMFILL_VALUE_MAX_LEN 4000
+
static const char *kFormHistoryFileName = "formhistory.dat";
NS_INTERFACE_MAP_BEGIN(nsFormHistory)
@@ -626,7 +630,11 @@ nsFormHistory::AppendRow(const nsAString &aName, const nsAString &aValue, nsIMdb
if (!mTable)
return NS_ERROR_NOT_INITIALIZED;
- PRBool exists;
+ if (aName.Length() > FORMFILL_NAME_MAX_LEN ||
+ aValue.Length() > FORMFILL_VALUE_MAX_LEN)
+ return NS_ERROR_INVALID_ARG;
+
+ PRBool exists = PR_TRUE;
EntryExists(aName, aValue, &exists);
if (exists)
return NS_OK;
diff --git a/toolkit/components/satchel/src/nsStorageFormHistory.cpp b/toolkit/components/satchel/src/nsStorageFormHistory.cpp
index cd5ba539..cb1aaf4d 100644
--- a/toolkit/components/satchel/src/nsStorageFormHistory.cpp
+++ b/toolkit/components/satchel/src/nsStorageFormHistory.cpp
@@ -228,7 +228,7 @@ nsFormHistory::AddEntry(const nsAString &aName, const nsAString &aValue)
mozStorageTransaction transaction(mDBConn, PR_FALSE);
- PRBool exists;
+ PRBool exists = PR_TRUE;
EntryExists(aName, aValue, &exists);
if (!exists) {
mozStorageStatementScoper scope(mDBInsertNameValue);
diff --git a/toolkit/components/url-classifier/content/enchash-decrypter.js b/toolkit/components/url-classifier/content/enchash-decrypter.js
index 5d495012..3a25e70f 100644
--- a/toolkit/components/url-classifier/content/enchash-decrypter.js
+++ b/toolkit/components/url-classifier/content/enchash-decrypter.js
@@ -74,18 +74,15 @@ PROT_EnchashDecrypter.SALT_LENGTH = PROT_EnchashDecrypter.DATABASE_SALT.length;
PROT_EnchashDecrypter.MAX_DOTS = 5;
PROT_EnchashDecrypter.REs = {};
-PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS =
- new RegExp("[\x01-\x1f\x7f-\xff]+");
-PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS_GLOBAL =
+PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS_GLOBAL =
new RegExp("[\x01-\x1f\x7f-\xff]+", "g");
-PROT_EnchashDecrypter.REs.FIND_END_DOTS = new RegExp("^\\.+|\\.+$");
-PROT_EnchashDecrypter.REs.FIND_END_DOTS_GLOBAL =
+PROT_EnchashDecrypter.REs.FIND_END_DOTS_GLOBAL =
new RegExp("^\\.+|\\.+$", "g");
-PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS = new RegExp("\\.{2,}");
-PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS_GLOBAL =
+PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS_GLOBAL =
new RegExp("\\.{2,}", "g");
-PROT_EnchashDecrypter.REs.FIND_TRAILING_DOTS = new RegExp("\\.+$");
-PROT_EnchashDecrypter.REs.POSSIBLE_IP =
+PROT_EnchashDecrypter.REs.FIND_TRAILING_SPACE =
+ new RegExp("^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}) ");
+PROT_EnchashDecrypter.REs.POSSIBLE_IP =
new RegExp("^((?:0x[0-9a-f]+|[0-9\\.])+)$", "i");
PROT_EnchashDecrypter.REs.FIND_BAD_OCTAL = new RegExp("(^|\\.)0\\d*[89]");
PROT_EnchashDecrypter.REs.IS_OCTAL = new RegExp("^0[0-7]*$");
@@ -171,12 +168,17 @@ PROT_EnchashDecrypter.prototype.parseRegExps = function(data) {
* type -url.
*
* @param url String to canonicalize
+ * @param opt_collapseSlashes Boolean true if we want to collapse slashes in
+ * the path
*
* @returns String containing the canonicalized url (maximally url-decoded
* with hostname normalized, then specially url-encoded)
*/
-PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url) {
- var escapedUrl = PROT_URLCanonicalizer.canonicalizeURL_(url);
+PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url,
+ opt_collapseSlashes) {
+ var urlUtils = Cc["@mozilla.org/url-classifier/utils;1"]
+ .getService(Ci.nsIUrlClassifierUtils);
+ var escapedUrl = urlUtils.canonicalizeURL(url);
// Normalize the host
var host = this.getCanonicalHost(escapedUrl);
if (!host) {
@@ -189,6 +191,13 @@ PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url) {
.getService(Ci.nsIIOService);
var urlObj = ioService.newURI(escapedUrl, null, null);
urlObj.host = host;
+ if (opt_collapseSlashes) {
+ // Collapse multiple slashes in the path into a single slash.
+ // We end up collapsing slashes in the query string, but it's unlikely
+ // that this would lead to a false positive and it's much simpler to do
+ // this.
+ urlObj.path = urlObj.path.replace(/\/+/g, "/");
+ }
return urlObj.asciiSpec;
}
@@ -243,8 +252,19 @@ PROT_EnchashDecrypter.prototype.getCanonicalHost = function(str, opt_maxDots) {
}
PROT_EnchashDecrypter.prototype.parseIPAddress_ = function(host) {
-
- host = host.replace(this.REs_.FIND_TRAILING_DOTS_GLOBAL, "");
+ if (host.length <= 15) {
+ // The Windows resolver allows a 4-part dotted decimal IP address to
+ // have a space followed by any old rubbish, so long as the total length
+ // of the string doesn't get above 15 characters. So, "10.192.95.89 xy"
+ // is resolved to 10.192.95.89.
+ // If the string length is greater than 15 characters, e.g.
+ // "10.192.95.89 xy.wildcard.example.com", it will be resolved through
+ // DNS.
+ var match = this.REs_.FIND_TRAILING_SPACE.exec(host);
+ if (match) {
+ host = match[1];
+ }
+ }
if (!this.REs_.POSSIBLE_IP.test(host))
return "";
@@ -264,13 +284,14 @@ PROT_EnchashDecrypter.prototype.parseIPAddress_ = function(host) {
}
if (canon != "")
parts[k] = canon;
+ else
+ return "";
}
return parts.join(".");
}
PROT_EnchashDecrypter.prototype.canonicalNum_ = function(num, bytes, octal) {
-
if (bytes < 0)
return "";
var temp_num;
@@ -292,8 +313,10 @@ PROT_EnchashDecrypter.prototype.canonicalNum_ = function(num, bytes, octal) {
temp_num = -1;
} else if (this.REs_.IS_HEX.test(num)) {
-
- num = this.lastNChars_(num, 8);
+ var matches = this.REs_.IS_HEX.exec(num);
+ if (matches) {
+ num = matches[1];
+ }
temp_num = parseInt(num, 16);
if (isNaN(temp_num))
diff --git a/toolkit/components/url-classifier/content/listmanager.js b/toolkit/components/url-classifier/content/listmanager.js
index 9885ae10..6b2396b5 100644
--- a/toolkit/components/url-classifier/content/listmanager.js
+++ b/toolkit/components/url-classifier/content/listmanager.js
@@ -552,11 +552,14 @@ PROT_ListManager.prototype.downloadError_ = function(status) {
status = 500;
}
status = parseInt(status, 10);
- this.requestBackoff_.noteServerResponse(status);
-
- // Try again in a minute
- this.currentUpdateChecker_ =
- new G_Alarm(BindToObject(this.checkForUpdates, this), 60000);
+ var isError = this.requestBackoff_.noteServerResponse(status);
+ if (isError) {
+ // Try again in a minute. We'll hit backoff if this is an error. If
+ // it's not an error, we just ignore the response and try again during
+ // our regular check interval.
+ this.currentUpdateChecker_ =
+ new G_Alarm(BindToObject(this.checkForUpdates, this), 60000);
+ }
}
PROT_ListManager.prototype.QueryInterface = function(iid) {
diff --git a/toolkit/components/url-classifier/content/request-backoff.js b/toolkit/components/url-classifier/content/request-backoff.js
index b4ba54da..67598a70 100644
--- a/toolkit/components/url-classifier/content/request-backoff.js
+++ b/toolkit/components/url-classifier/content/request-backoff.js
@@ -87,10 +87,13 @@ RequestBackoff.prototype.canMakeRequest = function() {
}
/**
- * Notify this object of the last server response. If it's an error,
+ * Notify this object of the last server response. If it's an error, we
+ * check to see if we should trigger a backoff.
+ * @return Boolean true if this counts as an error.
*/
RequestBackoff.prototype.noteServerResponse = function(status) {
- if (this.isErrorStatus_(status)) {
+ var isError = this.isErrorStatus_(status);
+ if (isError) {
var now = Date.now();
this.errorTimes_.push(now);
@@ -117,6 +120,7 @@ RequestBackoff.prototype.noteServerResponse = function(status) {
this.nextRequestTime_ = 0;
this.backoffTriggered_ = false;
}
+ return isError;
}
/**
diff --git a/toolkit/components/url-classifier/content/trtable.js b/toolkit/components/url-classifier/content/trtable.js
index 7f81db19..c077cd63 100644
--- a/toolkit/components/url-classifier/content/trtable.js
+++ b/toolkit/components/url-classifier/content/trtable.js
@@ -75,17 +75,18 @@ UrlClassifierTableUrl.inherits(UrlClassifierTable);
* Look up a URL in a URL table
*/
UrlClassifierTableUrl.prototype.exists = function(url, callback) {
- // PROT_URLCanonicalizer.canonicalizeURL_ is the old way of canonicalizing a
- // URL. Unfortunately, it doesn't normalize numeric domains so alternate IP
- // formats (hex, octal, etc) won't trigger a match.
- // this.enchashDecrypter_.getCanonicalUrl does the right thing and
- // normalizes a URL to 4 decimal numbers, but the update server may still be
- // giving us encoded IP addresses. So to be safe, we check both cases.
- var oldCanonicalized = PROT_URLCanonicalizer.canonicalizeURL_(url);
- var canonicalized = this.enchashDecrypter_.getCanonicalUrl(url);
- G_Debug(this, "Looking up: " + url + " (" + oldCanonicalized + " and " +
- canonicalized + ")");
- (new ExistsMultiQuerier([oldCanonicalized, canonicalized],
+ var urlUtils = Cc["@mozilla.org/url-classifier/utils;1"]
+ .getService(Ci.nsIUrlClassifierUtils);
+ // We plan on having the server collapse multiple slashes in the path.
+ // Until this happens, we check both the raw url and the url with multiple
+ // slashes removed.
+ var urls = [
+ this.enchashDecrypter_.getCanonicalUrl(url),
+ this.enchashDecrypter_.getCanonicalUrl(url, true) /* collapse slashes */
+ ];
+
+ G_Debug(this, "Looking up: " + url + " (" + urls + ")");
+ (new ExistsMultiQuerier(urls,
this.name,
callback)).run();
}
diff --git a/toolkit/components/url-classifier/content/url-canonicalizer.js b/toolkit/components/url-classifier/content/url-canonicalizer.js
deleted file mode 100644
index 474f88f8..00000000
--- a/toolkit/components/url-classifier/content/url-canonicalizer.js
+++ /dev/null
@@ -1,354 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Fritz Schneider (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-// This is the class we use to canonicalize URLs for TRTables of type
-// url. We maximally URL-decode the URL, treating +'s as if they're
-// not special. We then specially URL-encode it (we encode ASCII
-// values [0, 32] (whitespace or unprintable), 37 (%), [127, 255]
-// (unprintable)).
-//
-// This mapping is not a function. That is, multiple URLs can map to
-// the same canonical representation. However this is OK because
-// collisions happen only when there are weird characters (e.g.,
-// nonprintables), and the canonical representation makes us robust
-// to some weird kinds of encoding we could see.
-//
-// All members are static at this point -- this is basically a namespace.
-
-
-/**
- * Create a new URLCanonicalizer. Useless because members are static.
- *
- * @constructor
- */
-function PROT_URLCanonicalizer() {
- throw new Error("No need to instantiate a canonicalizer at this point.");
-}
-
-PROT_URLCanonicalizer.debugZone = "urlcanonicalizer";
-
-PROT_URLCanonicalizer.hexChars_ = "0123456789ABCDEF";
-
-/**
- * Helper funciton to (maybe) convert a two-character hex string into its
- * decimal numerical equivalent
- *
- * @param hh String of length two that might be a valid hex sequence
- *
- * @returns Number: NaN if hh wasn't valid hex, else the appropriate decimal
- * value
- */
-PROT_URLCanonicalizer.hexPairToInt_ = function(hh) {
- return Number("0x" + hh);
-}
-
-/**
- * Helper function to hex-encode a number
- *
- * @param val Number in range [0, 255]
- *
- * @returns String containing the hex representation of that number (sans 0x)
- */
-PROT_URLCanonicalizer.toHex_ = function(val) {
- var retVal = PROT_URLCanonicalizer.hexChars_.charAt((val >> 4) & 15) +
- PROT_URLCanonicalizer.hexChars_.charAt(val & 15);
- return retVal;
-}
-
-/**
- * Canonicalize a URL. DON'T USE THIS DIRECTLY. Use
- * PROT_EnchashDecrypter.prototype.getCanonicalUrl instead. This method
- * url-decodes a string, but it doesn't normalize the hostname. The method
- * in EnchashDecrypter first calls this method, then normalizes the hostname.
- *
- * @param url String to canonicalize
- *
- * @returns String containing the canonicalized url (maximally url-decoded,
- * then specially url-encoded)
- */
-PROT_URLCanonicalizer.canonicalizeURL_ = function(url) {
- var arrayOfASCIIVals = PROT_URLCanonicalizer.fullyDecodeURL_(url);
- return PROT_URLCanonicalizer.specialEncodeURL_(arrayOfASCIIVals);
-}
-
-/**
- * Maximally URL-decode a URL. This breaks the semantics of the URL, but
- * we don't care because we're using it for lookup, not for navigation.
- * We break multi-byte UTF-8 escape sequences as well, but we don't care
- * so long as they canonicalize the same way consistently (they do).
- *
- * @param url String containing the URL to maximally decode. Should ONLY
- * contain characters with UCS codepoints U+0001 to U+00FF
- * (the ASCII set minus null).
- *
- * @returns Array of ASCII values corresponding to the decoded sequence of
- * characters in the url
- */
-PROT_URLCanonicalizer.fullyDecodeURL_ = function(url) {
-
- // The goals here are: simplicity, correctness, and most of all
- // portability; we want the same implementation of canonicalization
- // wherever we use it so as to to minimize the chances of
- // inconsistency. For example, we have to do this canonicalization
- // on URLs we get from third parties, and at the lookup server when
- // we get a request.
- //
- // The following implementation should translate easily to any
- // language that supports arrays and pointers or references. Note
- // that arrays are pointer types in JavaScript, so foo = [some,
- // array] points foo at the array; it doesn't copy it. The
- // implementation is efficient (linear) so long as most %'s in the
- // url belong to valid escape sequences and there aren't too many
- // doubly-escaped values.
-
- // The basic idea is to copy current input to output, decoding escape
- // sequences as we see them, until we decode a %. At that point we start
- // copying into the "next iteration buffer" instead of the output buffer;
- // we do this so we can accomodate multiply-escaped strings. When we hit
- // the end of the input, we take the "next iteration buffer" as our input,
- // and start over.
-
- var nextIteration = url.split("");
- var output = [];
-
- while (nextIteration.length) {
-
- var decodedAPercent = false;
- var thisIteration = nextIteration;
- var nextIteration = [];
-
- var i = 0;
- while (i < thisIteration.length) {
-
- var c = thisIteration[i];
- if (c == "%" && i + 2 < thisIteration.length) {
-
- // Peek ahead to see if we have a valid HH sequence
- var asciiVal =
- PROT_URLCanonicalizer.hexPairToInt_(thisIteration[i + 1] +
- thisIteration[i + 2]);
- if (!isNaN(asciiVal)) {
- i += 2; // Valid HH sequence; consume it
-
- if (asciiVal == 0) // We special case nulls
- asciiVal = 1;
-
- c = String.fromCharCode(asciiVal);
- if (c == "%")
- decodedAPercent = true;
- }
- }
-
- if (decodedAPercent)
- nextIteration[nextIteration.length] = c;
- else
- output[output.length] = c.charCodeAt(0);
-
- ++i;
- }
- }
-
- return output;
-}
-
-/**
- * Maximally URL-decode a URL (same as fullyDecodeURL_ except that it
- * returns a string). Useful for making unittests more readable.
- *
- * @param url String containing the URL to maximally decode. Should ONLY
- * contain characters with UCS codepoints U+0001 to U+00FF
- * (the ASCII set minus null).
- *
- * @returns String containing the decoded URL
- */
-PROT_URLCanonicalizer.fullyDecodeURLAsString_ = function(url) {
- var arrayOfASCIIVals = PROT_URLCanonicalizer.fullyDecodeURL_(url);
- var s = "";
- for (var i = 0; i < arrayOfASCIIVals.length; i++)
- s += String.fromCharCode(arrayOfASCIIVals[i]);
- return s;
-}
-
-/**
- * Specially URL-encode the given array of ASCII values. We want to encode
- * the charcters: [0, 32], 37, [127, 255].
- *
- * @param arrayOfASCIIValues Array of ascii values (numbers) to encode
- *
- * @returns String corresonding to the escaped URL
- */
-PROT_URLCanonicalizer.specialEncodeURL_ = function(arrayOfASCIIValues) {
-
- var output = [];
- for (var i = 0; i < arrayOfASCIIValues.length; i++) {
- var n = arrayOfASCIIValues[i];
-
- if (n <= 32 || n == 37 || n >= 127)
- output.push("%" + ((!n) ? "01" : PROT_URLCanonicalizer.toHex_(n)));
- else
- output.push(String.fromCharCode(n));
- }
-
- return output.join("");
-}
-
-
-#ifdef DEBUG
-/**
- * Lame unittesting function
- */
-function TEST_PROT_URLCanonicalizer() {
- if (G_GDEBUG) {
- var z = "urlcanonicalizer UNITTEST";
- G_debugService.enableZone(z);
-
- G_Debug(z, "Starting");
-
-
- // ------ TEST HEX GOTCHA ------
-
- var hexify = PROT_URLCanonicalizer.toHex_;
- var shouldHaveLeadingZeros = hexify(0) + hexify(1);
- G_Assert(z, shouldHaveLeadingZeros == "0001",
- "Need to append leading zeros to hex rep value <= 15 !")
-
-
- // ------ TEST DECODING ------
-
- // For convenience, shorten the function name
- var dec = PROT_URLCanonicalizer.fullyDecodeURLAsString_;
-
- // Test empty string
- G_Assert(z, dec("") == "", "decoding empty string");
-
- // Test decoding of all characters
- var allCharsEncoded = "";
- var allCharsEncodedLowercase = "";
- var allCharsAsString = "";
- // Special case null
- allCharsEncoded += "%01";
- allCharsEncodedLowercase += "%01";
- allCharsAsString += String.fromCharCode(1);
- for (var i = 1; i < 256; i++) {
- allCharsEncoded += "%" + PROT_URLCanonicalizer.toHex_(i);
- allCharsEncodedLowercase += "%" +
- PROT_URLCanonicalizer.toHex_(i).toLowerCase();
- allCharsAsString += String.fromCharCode(i);
- }
- G_Assert(z, dec(allCharsEncoded) == allCharsAsString, "decoding escaped");
- G_Assert(z, dec(allCharsEncodedLowercase) == allCharsAsString,
- "decoding lowercase");
-
- // Test %-related edge cases
- G_Assert(z, dec("%") == "%", "1 percent");
- G_Assert(z, dec("%xx") == "%xx", "1 percent, two non-hex");
- G_Assert(z, dec("%%") == "%%", "2 percent");
- G_Assert(z, dec("%%%") == "%%%", "3 percent");
- G_Assert(z, dec("%%%%") == "%%%%", "4 percent");
- G_Assert(z, dec("%1") == "%1", "1 percent, one nonhex");
- G_Assert(z, dec("%1z") == "%1z", "1 percent, two nonhex");
- G_Assert(z, dec("a%1z") == "a%1z", "nonhex, 1 percent, two nonhex");
- G_Assert(z, dec("abc%d%e%fg%hij%klmno%") == "abc%d%e%fg%hij%klmno%",
- "lots of percents, no hex");
-
- // Test repeated %-decoding. Note: %25 --> %, %32 --> 2, %35 --> 5
- G_Assert(z, dec("%25") == "%", "single-encoded %");
- G_Assert(z, dec("%25%32%35") == "%", "double-encoded %");
- G_Assert(z, dec("asdf%25%32%35asd") == "asdf%asd", "double-encoded % 2");
- G_Assert(z, dec("%%%25%32%35asd%%") == "%%%asd%%", "double-encoded % 3");
- G_Assert(z, dec("%25%32%35%25%32%35%25%32%35") == "%%%",
- "sequenctial double-encoded %");
- G_Assert(z, dec("%2525252525252525") == "%", "many-encoded %");
- G_Assert(z, dec("%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B") == "~a!b@c#d$e%f^00&11*22(33)44_55+",
- "4x-encoded string");
-
-
- // ------ TEST ENCODING ------
-
- // For convenience, shorten the function name
- var enc = PROT_URLCanonicalizer.specialEncodeURL_;
-
- // Test empty string
- G_Assert(z, enc([]) == "", "encoding empty array");
-
- // Test that all characters we shouldn't encode ([33-36],[38,126]) are not.
- var no = [];
- var noAsString = "";
- for (var i = 33; i < 127; i++)
- if (i != 37) { // skip %
- no.push(i);
- noAsString += String.fromCharCode(i);
- }
- G_Assert(z, enc(no) == noAsString, "chars to not encode");
-
- // Test that all the chars that we should encode [0,32],37,[127,255] are
- var yes = [];
- var yesAsString = "";
- var yesExpectedString = "";
- // Special case 0
- yes.push(0);
- yesAsString += String.fromCharCode(1);
- yesExpectedString += "%01";
- for (var i = 1; i < 256; i++)
- if (i < 33 || i == 37 || i > 126) {
- yes.push(i);
- yesAsString += String.fromCharCode(i);
- var hex = i.toString(16).toUpperCase();
- yesExpectedString += "%" + ((i < 16) ? "0" : "") + hex;
- }
- G_Assert(z, enc(yes) == yesExpectedString, "chars to encode");
- // Can't use decodeURIComponent or encodeURIComponent to test b/c UTF-8
-
-
- // ------ TEST COMPOSITION ------
-
- // For convenience, shorten function name:
- var c = PROT_URLCanonicalizer.canonicalizeURL_;
-
- G_Assert(z, c("http://www.google.com") == "http://www.google.com",
- "http://www.google.com");
- G_Assert(z, c("http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/") == "http://168.188.99.26/.secure/www.ebay.com/",
- "fully encoded ebay");
- G_Assert(z, c("http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/") == "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/",
- "long url with spaces that stays same");
-
- // TODO: MORE!
-
- G_Debug(z, "PASSED");
- }
-}
-#endif
diff --git a/toolkit/components/url-classifier/public/Makefile.in b/toolkit/components/url-classifier/public/Makefile.in
index a0a185bb..65193d2a 100644
--- a/toolkit/components/url-classifier/public/Makefile.in
+++ b/toolkit/components/url-classifier/public/Makefile.in
@@ -11,6 +11,7 @@ XPIDL_MODULE = url-classifier
XPIDLSRCS = nsIUrlClassifierDBService.idl \
nsIUrlClassifierStreamUpdater.idl \
nsIUrlClassifierTable.idl \
+ nsIUrlClassifierUtils.idl \
nsIUrlListManager.idl \
$(NULL)
diff --git a/toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl b/toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl
new file mode 100644
index 00000000..0795df79
--- /dev/null
+++ b/toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl
@@ -0,0 +1,57 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Google, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+/**
+ * Some utility methods used by the url classifier.
+ */
+
+[scriptable, uuid(9afd3add-eadc-409f-a187-e3bf60e47290)]
+interface nsIUrlClassifierUtils : nsISupports
+{
+ /**
+ * Canonicalize a URL. DON'T USE THIS DIRECTLY. Use
+ * PROT_EnchashDecrypter.prototype.getCanonicalUrl instead. This method
+ * url-decodes a string, but it doesn't normalize the hostname. The method
+ * in EnchashDecrypter first calls this method, then normalizes the hostname.
+ *
+ * @param url String to canonicalize
+ *
+ * @returns String containing the canonicalized url (maximally url-decoded,
+ * then specially url-encoded)
+ */
+ ACString canonicalizeURL(in ACString url);
+};
diff --git a/toolkit/components/url-classifier/src/Makefile.in b/toolkit/components/url-classifier/src/Makefile.in
index 705b3782..204f7bf3 100644
--- a/toolkit/components/url-classifier/src/Makefile.in
+++ b/toolkit/components/url-classifier/src/Makefile.in
@@ -21,6 +21,7 @@ REQUIRES = necko \
CPPSRCS = \
nsUrlClassifierDBService.cpp \
nsUrlClassifierStreamUpdater.cpp \
+ nsUrlClassifierUtils.cpp \
$(NULL)
LOCAL_INCLUDES = \
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
index bbe1ca30..f739fb87 100644
--- a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
@@ -86,6 +86,10 @@ static PRMonitor *gMonitor = nsnull;
// Thread that we do the updates on.
static PRThread* gDbBackgroundThread = nsnull;
+// Once we've committed to shutting down, don't do work in the background
+// thread.
+static PRBool gShuttingDownThread = PR_FALSE;
+
static const char* kNEW_TABLE_SUFFIX = "_new";
@@ -264,6 +268,9 @@ nsUrlClassifierDBServiceWorker::Exists(const nsACString& tableName,
const nsACString& key,
nsIUrlClassifierCallback *c)
{
+ if (gShuttingDownThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
@@ -309,6 +316,9 @@ NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::CheckTables(const nsACString & tableNames,
nsIUrlClassifierCallback *c)
{
+ if (gShuttingDownThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
@@ -351,6 +361,9 @@ NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::UpdateTables(const nsACString& updateString,
nsIUrlClassifierCallback *c)
{
+ if (gShuttingDownThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
LOG(("Updating tables\n"));
nsresult rv = OpenDb();
@@ -498,6 +511,11 @@ nsUrlClassifierDBServiceWorker::Finish(nsIUrlClassifierCallback *c)
if (!mHasPendingUpdate)
return NS_OK;
+ if (gShuttingDownThread) {
+ mConnection->RollbackTransaction();
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
nsresult rv = NS_OK;
for (PRUint32 i = 0; i < mTableUpdateLines.Length(); ++i) {
rv = MaybeSwapTables(mTableUpdateLines[i]);
@@ -843,8 +861,10 @@ PR_STATIC_CALLBACK(void) DestroyHandler(PLEvent *ev);
nsUrlClassifierDBService::~nsUrlClassifierDBService()
{
sUrlClassifierDBService = nsnull;
- PR_DestroyMonitor(gMonitor);
- gMonitor = nsnull;
+ if (gMonitor) {
+ PR_DestroyMonitor(gMonitor);
+ gMonitor = nsnull;
+ }
}
nsresult
@@ -883,7 +903,8 @@ nsUrlClassifierDBService::Init()
if (!observerService)
return NS_ERROR_FAILURE;
- observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+ observerService->AddObserver(this, "profile-before-change", PR_FALSE);
+ observerService->AddObserver(this, "xpcom-shutdown", PR_FALSE);
return NS_OK;
}
@@ -1056,9 +1077,12 @@ NS_IMETHODIMP
nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
- if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
- Shutdown();
- }
+ NS_ASSERTION(strcmp(aTopic, "profile-before-change") == 0 ||
+ strcmp(aTopic, "xpcom-shutdown") == 0,
+ "Unexpected observer topic");
+
+ Shutdown();
+
return NS_OK;
}
@@ -1082,6 +1106,11 @@ nsUrlClassifierDBService::EnsureThreadStarted()
nsresult
nsUrlClassifierDBService::Shutdown()
{
+ LOG(("shutting down db service\n"));
+
+ if (!gDbBackgroundThread)
+ return NS_OK;
+
nsresult rv;
EnsureThreadStarted();
@@ -1095,8 +1124,10 @@ nsUrlClassifierDBService::Shutdown()
mWorker,
PROXY_ASYNC,
getter_AddRefs(proxy));
- proxy->CloseDb();
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = proxy->CloseDb();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post close db event");
+ }
}
PLEvent* ev = new PLEvent;
@@ -1107,8 +1138,9 @@ nsUrlClassifierDBService::Shutdown()
}
LOG(("joining background thread"));
- rv = PR_JoinThread(gDbBackgroundThread);
- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to join background thread");
+ gShuttingDownThread = PR_TRUE;
+ PRStatus ok = PR_JoinThread(gDbBackgroundThread);
+ NS_ASSERTION(ok == PR_SUCCESS, "failed to join background thread");
gDbBackgroundThread = nsnull;
return NS_OK;
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierTable.js b/toolkit/components/url-classifier/src/nsUrlClassifierTable.js
index 5a2465e6..43b5ba64 100644
--- a/toolkit/components/url-classifier/src/nsUrlClassifierTable.js
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierTable.js
@@ -42,7 +42,6 @@ const Ci = Components.interfaces;
#include ../content/js/lang.js
#include ../content/enchash-decrypter.js
#include ../content/multi-querier.js
-#include ../content/url-canonicalizer.js
#include ../content/trtable.js
var modScope = this;
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
new file mode 100644
index 00000000..2a269abc
--- /dev/null
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsEscape.h"
+#include "nsString.h"
+#include "nsUrlClassifierUtils.h"
+
+static char int_to_hex_digit(PRInt32 i)
+{
+ NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit");
+ return NS_STATIC_CAST(char, ((i < 10) ? (i + '0') : ((i - 10) + 'A')));
+}
+
+
+nsUrlClassifierUtils::nsUrlClassifierUtils()
+{
+}
+
+NS_IMPL_ISUPPORTS1(nsUrlClassifierUtils, nsIUrlClassifierUtils)
+
+/* ACString canonicalizeURL (in ACString url); */
+NS_IMETHODIMP
+nsUrlClassifierUtils::CanonicalizeURL(const nsACString & url, nsACString & _retval)
+{
+ nsCAutoString decodedUrl(url);
+ nsCAutoString temp;
+ while (NS_UnescapeURL(decodedUrl.get(), decodedUrl.Length(), 0, temp)) {
+ decodedUrl.Assign(temp);
+ temp.Truncate();
+ }
+ SpecialEncode(decodedUrl, _retval);
+ return NS_OK;
+}
+
+// This function will encode all "special" characters in typical url
+// encoding, that is %hh where h is a valid hex digit. See the comment in
+// the header file for details.
+PRBool
+nsUrlClassifierUtils::SpecialEncode(const nsACString & url, nsACString & _retval)
+{
+ PRBool changed = PR_FALSE;
+ const char* curChar = url.BeginReading();
+ const char* end = url.EndReading();
+
+ while (curChar != end) {
+ unsigned char c = NS_STATIC_CAST(unsigned char, *curChar);
+ if (ShouldURLEscape(c)) {
+ // We don't want to deal with 0, as it can break certain strings, just
+ // encode as one.
+ if (c == 0)
+ c = 1;
+
+ _retval.Append('%');
+ _retval.Append(int_to_hex_digit(c / 16));
+ _retval.Append(int_to_hex_digit(c % 16));
+
+ changed = PR_TRUE;
+ } else {
+ _retval.Append(*curChar);
+ }
+ curChar++;
+ }
+ return changed;
+}
+
+PRBool
+nsUrlClassifierUtils::ShouldURLEscape(const unsigned char c) const
+{
+ return c <= 32 || c == '%' || c >=127;
+}
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierUtils.h b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.h
new file mode 100644
index 00000000..e9b0958c
--- /dev/null
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.h
@@ -0,0 +1,67 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsUrlClassifierUtils_h_
+#define nsUrlClassifierUtils_h_
+
+#include "nsIUrlClassifierUtils.h"
+
+class nsUrlClassifierUtils : public nsIUrlClassifierUtils
+{
+public:
+ nsUrlClassifierUtils();
+ ~nsUrlClassifierUtils() {};
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIURLCLASSIFIERUTILS
+
+ // This function will encode all "special" characters in typical url encoding,
+ // that is %hh where h is a valid hex digit. The characters which are encoded
+ // by this function are any ascii characters under 32(control characters and
+ // space), 37(%), and anything 127 or above (special characters). Url is the
+ // string to encode, ret is the encoded string. Function returns true if
+ // ret != url.
+ PRBool SpecialEncode(const nsACString & url, nsACString & _retval);
+
+private:
+ // Disallow copy constructor
+ nsUrlClassifierUtils(const nsUrlClassifierUtils&);
+
+ // Function to tell if we should encode a character.
+ PRBool ShouldURLEscape(const unsigned char c) const;
+};
+
+#endif // nsUrlClassifierUtils_h_
diff --git a/toolkit/components/url-classifier/tests/Makefile.in b/toolkit/components/url-classifier/tests/Makefile.in
index 6bc0c7f6..4b7bac8b 100644
--- a/toolkit/components/url-classifier/tests/Makefile.in
+++ b/toolkit/components/url-classifier/tests/Makefile.in
@@ -43,5 +43,39 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
+MODULE = test_url-classifier
+
+MOZILLA_INTERNAL_API = 1
+
+REQUIRES = \
+ string \
+ url-classifier \
+ xpcom \
+ $(NULL)
+
+# simple c++ tests (no xpcom)
+CPPSRCS = \
+ TestUrlClassifierUtils.cpp \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../src \
+ -I$(srcdir)/../public \
+ $(NULL)
+
+LIBS = \
+ ../src/$(LIB_PREFIX)urlclassifier_s.$(LIB_SUFFIX) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
include $(topsrcdir)/config/rules.mk
+check::
+ @echo Running tests...
+ @$(EXIT_ON_ERROR) \
+ for f in $(SIMPLE_PROGRAMS); do \
+ $(RUN_TEST_PROGRAM) $(DIST)/bin/$$f; \
+ done
diff --git a/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp b/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp
new file mode 100644
index 00000000..1d0f07da
--- /dev/null
+++ b/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp
@@ -0,0 +1,195 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include
+#include
+#include "nsEscape.h"
+#include "nsString.h"
+#include "nsUrlClassifierUtils.h"
+
+static int gTotalTests = 0;
+static int gPassedTests = 0;
+
+static char int_to_hex_digit(PRInt32 i) {
+ NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit");
+ return NS_STATIC_CAST(char, ((i < 10) ? (i + '0') : ((i - 10) + 'A')));
+}
+
+static void CheckEquals(nsCString & expected, nsCString & actual)
+{
+ if (!(expected).Equals((actual))) {
+ fprintf(stderr, "FAILED: expected |%s| but was |%s|\n", (expected).get(),
+ (actual).get());
+ } else {
+ gPassedTests++;
+ }
+ gTotalTests++;
+}
+
+void TestUnescapeHelper(const char* in, const char* expected)
+{
+ nsCString out, strIn(in), strExp(expected);
+ nsUrlClassifierUtils utils;
+
+ NS_UnescapeURL(strIn.get(), strIn.Length(), esc_AlwaysCopy, out);
+ CheckEquals(strExp, out);
+}
+
+// Make sure Unescape from nsEncode.h's unescape does what the server does.
+void TestUnescape()
+{
+ // test empty string
+ TestUnescapeHelper("\0", "\0");
+
+ // Test docoding of all characters.
+ nsCString allCharsEncoded, allCharsEncodedLowercase, allCharsAsString;
+ for (PRInt32 i = 1; i < 256; ++i) {
+ allCharsEncoded.Append('%');
+ allCharsEncoded.Append(int_to_hex_digit(i / 16));
+ allCharsEncoded.Append((int_to_hex_digit(i % 16)));
+
+ allCharsEncodedLowercase.Append('%');
+ allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i / 16)));
+ allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i % 16)));
+
+ allCharsAsString.Append(NS_STATIC_CAST(char, i));
+ }
+
+ nsUrlClassifierUtils utils;
+ nsCString out;
+ NS_UnescapeURL(allCharsEncoded.get(), allCharsEncoded.Length(), esc_AlwaysCopy, out);
+ CheckEquals(allCharsAsString, out);
+
+ out.Truncate();
+ NS_UnescapeURL(allCharsEncodedLowercase.get(), allCharsEncodedLowercase.Length(), esc_AlwaysCopy, out);
+ CheckEquals(allCharsAsString, out);
+
+ // Test %-related edge cases
+ TestUnescapeHelper("%", "%");
+ TestUnescapeHelper("%xx", "%xx");
+ TestUnescapeHelper("%%", "%%");
+ TestUnescapeHelper("%%%", "%%%");
+ TestUnescapeHelper("%%%%", "%%%%");
+ TestUnescapeHelper("%1", "%1");
+ TestUnescapeHelper("%1z", "%1z");
+ TestUnescapeHelper("a%1z", "a%1z");
+ TestUnescapeHelper("abc%d%e%fg%hij%klmno%", "abc%d%e%fg%hij%klmno%");
+
+ // A few more tests
+ TestUnescapeHelper("%25", "%");
+ TestUnescapeHelper("%25%32%35", "%25");
+}
+
+void TestEncodeHelper(const char* in, const char* expected)
+{
+ nsCString out, strIn(in), strExp(expected);
+ nsUrlClassifierUtils utils;
+
+ utils.SpecialEncode(strIn, out);
+ CheckEquals(strExp, out);
+}
+
+void TestEnc()
+{
+ // Test empty string
+ TestEncodeHelper("", "");
+
+ // Test that all characters we shouldn't encode ([33-36],[38,126]) are not.
+ nsCString noenc;
+ for (PRInt32 i = 33; i < 127; i++) {
+ if (i != 37) { // skip %
+ noenc.Append(NS_STATIC_CAST(char, i));
+ }
+ }
+ nsUrlClassifierUtils utils;
+ nsCString out;
+ utils.SpecialEncode(noenc, out);
+ CheckEquals(noenc, out);
+
+ // Test that all the chars that we should encode [0,32],37,[127,255] are
+ nsCString yesAsString, yesExpectedString;
+ for (PRInt32 i = 1; i < 256; i++) {
+ if (i < 33 || i == 37 || i > 126) {
+ yesAsString.Append(NS_STATIC_CAST(char, i));
+ yesExpectedString.Append('%');
+ yesExpectedString.Append(int_to_hex_digit(i / 16));
+ yesExpectedString.Append(int_to_hex_digit(i % 16));
+ }
+ }
+
+ out.Truncate();
+ utils.SpecialEncode(yesAsString, out);
+ CheckEquals(yesExpectedString, out);
+}
+
+void TestCanonicalizeHelper(const char* in, const char* expected)
+{
+ nsCString out, strIn(in), strExp(expected);
+ nsUrlClassifierUtils utils;
+
+ nsresult rv = utils.CanonicalizeURL(strIn, out);
+ NS_ASSERTION(rv == NS_OK, "com didn't return NS_OK");
+ CheckEquals(strExp, out);
+}
+
+void TestCanonicalize()
+{
+ // Test repeated %-decoding. Note: %25 --> %, %32 --> 2, %35 --> 5
+ TestCanonicalizeHelper("%25", "%25");
+ TestCanonicalizeHelper("%25%32%35", "%25");
+ TestCanonicalizeHelper("asdf%25%32%35asd", "asdf%25asd");
+ TestCanonicalizeHelper("%%%25%32%35asd%%", "%25%25%25asd%25%25");
+ TestCanonicalizeHelper("%25%32%35%25%32%35%25%32%35", "%25%25%25");
+ TestCanonicalizeHelper("%25", "%25");
+ TestCanonicalizeHelper("%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B",
+ "~a!b@c#d$e%25f^00&11*22(33)44_55+");
+
+ TestCanonicalizeHelper("", "");
+ TestCanonicalizeHelper("http://www.google.com", "http://www.google.com");
+ TestCanonicalizeHelper("http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/",
+ "http://168.188.99.26/.secure/www.ebay.com/");
+ TestCanonicalizeHelper("http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/",
+ "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/");
+}
+
+int main(int argc, char **argv)
+{
+ TestUnescape();
+ TestEnc();
+ TestCanonicalize();
+ printf("%d of %d tests passed\n", gPassedTests, gTotalTests);
+ return (gPassedTests != gTotalTests);
+}
diff --git a/toolkit/content/charsetOverlay.js b/toolkit/content/charsetOverlay.js
index 7dcbabf3..420936e1 100644
--- a/toolkit/content/charsetOverlay.js
+++ b/toolkit/content/charsetOverlay.js
@@ -126,21 +126,19 @@ function SetForcedCharset(charset)
var gPrevCharset = null;
function UpdateCurrentCharset()
{
- var menuitem = null;
-
- // exctract the charset from DOM
+ // extract the charset from DOM
var wnd = document.commandDispatcher.focusedWindow;
if ((window == wnd) || (wnd == null)) wnd = window.content;
- menuitem = document.getElementById('charset.' + wnd.document.characterSet);
+ // Uncheck previous item
+ if (gPrevCharset) {
+ var pref_item = document.getElementById('charset.' + gPrevCharset);
+ if (pref_item)
+ pref_item.setAttribute('checked', 'false');
+ }
+
+ var menuitem = document.getElementById('charset.' + wnd.document.characterSet);
if (menuitem) {
- // uncheck previously checked item to workaround Mac checkmark problem
- // bug 98625
- if (gPrevCharset) {
- var pref_item = document.getElementById('charset.' + gPrevCharset);
- if (pref_item)
- pref_item.setAttribute('checked', 'false');
- }
menuitem.setAttribute('checked', 'true');
}
}
diff --git a/toolkit/content/commonDialog.js b/toolkit/content/commonDialog.js
index 4d1eac59..d4463f94 100644
--- a/toolkit/content/commonDialog.js
+++ b/toolkit/content/commonDialog.js
@@ -221,7 +221,7 @@ function commonDialogFocus(aEvent)
var script = "document.documentElement.getButton('accept').disabled = false; ";
script += "document.documentElement.getButton('extra1').disabled = false; ";
script += "document.documentElement.getButton('extra2').disabled = false;";
- setTimeout(script, 250);
+ setTimeout(script, 1000);
}
}
diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js
index 17c8425e..5361849b 100644
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -334,7 +334,7 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
saveAsType == kSaveAsType_Text) ?
"text/plain" : aContentType,
target : fileURL,
- postData : isDocument ? getPostData() : null,
+ postData : isDocument ? getPostData(aDocument) : null,
bypassCache : aShouldBypassCache
};
@@ -707,14 +707,16 @@ function appendFiltersForContentType(aFilePicker, aContentType, aFileExtension,
aFilePicker.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
}
-
-function getPostData()
+function getPostData(aDocument)
{
try {
- var sessionHistory = getWebNavigation().sessionHistory;
- var entry = sessionHistory.getEntryAtIndex(sessionHistory.index, false);
- entry = entry.QueryInterface(Components.interfaces.nsISHEntry);
- return entry.postData;
+ var sessionHistory = aDocument.defaultView
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .sessionHistory;
+ return sessionHistory.getEntryAtIndex(sessionHistory.index, false)
+ .QueryInterface(Components.interfaces.nsISHEntry)
+ .postData;
}
catch (e) {
}
@@ -900,6 +902,9 @@ function getNormalizedLeafName(aFile, aDefaultExtension)
// Remove trailing dots and spaces on windows
aFile = aFile.replace(/[\s.]+$/, "");
#endif
+
+ // Remove leading dots
+ aFile = aFile.replace(/^\.+/, "");
// Fix up the file name we're saving to to include the default extension
var i = aFile.lastIndexOf(".");
diff --git a/toolkit/content/license.html b/toolkit/content/license.html
index e8b63aab..ba93122d 100644
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -701,11 +701,12 @@ under either the MPL or the [___] License."
-
Aaron Leventhal,
+Aaron Schulman,
ActiveState Tool Corp,
Akkana Peck,
Alex Fritze,
@@ -714,6 +715,7 @@ Alexander Surkov,
Andreas Otte,
Andreas Premstaller,
Andrew Thompson,
+ArentJan Banck,
Asaf Romano,
Axel Hecht,
Ben Bucksch,
@@ -727,9 +729,12 @@ Brendan Eich,
Brian Bober,
Brian Ryner,
Brian Stell,
+Bruce Davidson,
Bruno Haible,
+Calum Robinson,
Cedric Chantepie,
Chiaki Koufugata,
+Chris McAfee,
Christian Biesinger,
Christopher A. Aillon,
Christopher Blizzard,
@@ -740,6 +745,7 @@ Conrad Carlen,
Crocodile Clips Ltd,
Cyrus Patel,
Dainis Jonitis,
+Dan Mosedale,
Daniel Brooks,
Daniel Glazman,
Daniel Kouril,
@@ -756,18 +762,20 @@ Digital Creations 2 Inc,
Doron Rosenberg,
Doug Turner,
Elika J. Etemad,
+Eric Belhaire,
Eric Hodel,
Esben Mose Hansen,
Frank Schönheit,
Fredrik Holmqvist,
Gavin Sharp,
+Geoff Beier,
Gervase Markham,
Giorgio Maone,
-Google,
Google Inc,
+Håkan Waara,
+Henri Torgemane,
Heriot-Watt University,
Hewlett-Packard Company,
-Håkan Waara,
i-DNS.net International,
Ian Hickson,
Ian Oeschger,
@@ -780,8 +788,10 @@ James Ross,
Jamie Zawinski,
Jan Varga,
Jason Barnabe,
+Jean-Francois Ducarroz,
Jeff Tsai,
Jeff Walden,
+Jefferson Software Inc,
Joe Hewitt,
Joey Minta,
John B. Keiser,
@@ -790,27 +800,36 @@ John Fairhurst,
John Wolfe,
Jonas Sicking,
Jonathan Watt,
+Josh Aas,
Josh Soref,
Juan Lang,
Jungshik Shin,
+Jussi Kukkonen,
Karsten Düsterloh,
Keith Visco,
Ken Herron,
+Kevin Gerich,
Kipp E.B. Hickman,
L. David Baron,
Lixto GmbH,
Makoto Kato,
+Marc Bevand,
Marco Manfredini,
Marco Pesenti Gritti,
Mark Hammond,
Mark Mentovai,
Markus G. Kuhn,
+Matt Judy,
+Matthew Willis,
+Merle Sterling,
Michael J. Fromberger,
Michal Ceresna,
Michiel van Leeuwen,
Mike Connor,
Mike Pinkerton,
+Mike Potter,
Mike Shaver,
+MITRE Corporation,
Mozdev Group,
Mozilla Corporation,
Mozilla Foundation,
@@ -822,16 +841,21 @@ Netscape Commmunications Corp,
Netscape Communications Corporation,
New Dimensions Consulting,
Novell Inc,
+OEone Corporation,
Olli Pettay,
Oracle Corporation,
Owen Taylor,
Paul Ashford,
-Paul Kocher of Cryptography Research,
+Paul Kocher,
Paul Sandoz,
Peter Annema,
Peter Hartshorn,
Peter Van der Beken,
+Phil Ringnalda,
+Philipp Kewisch,
Pierre Chanial,
+Prachi Gauriar,
+Qualcomm Inc,
R.J. Keller,
Rajiv Dayal,
Ramalingam Saravanan,
@@ -858,25 +882,29 @@ Sergei Dolgov,
Seth Spitzer,
Shy Shalom,
Silverstone Interactive,
+Simdesk Technologies Inc,
Simon Bünzli,
Simon Fraser,
Simon Montagu,
+Simon Paquet,
Simon Wilkinson,
+Sqlite Project,
Srilatha Moturi,
+Stefan Sitter,
+Stephen Horlander,
Steve Swanson,
+Stuart Morgan,
Stuart Parmenter,
Sun Microsystems Inc,
-The MITRE Corporation,
-The Mozilla Corporation,
-The sqlite Project,
-The University of Queensland,
Tim Copperfield,
Tom Germeau,
Tomas Müller,
+University of Queensland,
Vincent Béron,
Vladimir Vukicevic,
+Wolfgang Rosenauer,
YAMASHITA Makoto,
-Zack Rusin and
+Zack Rusin,
Zero-Knowledge Systems.
@@ -2175,8 +2203,13 @@ SOFTWARE.
Other Required Notices
-
This software is based in part on the work of the Independent
- JPEG Group.
+
+
This software is based in part on the work of the Independent
+ JPEG Group.