From d35c2d9a4fae34f56756dfc663c505c019837ea3 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Wed, 29 Feb 2012 02:56:31 -0500 Subject: [PATCH 01/11] Be more careful about pageshow only fire with doc.readyState === "loading" --- chrome/content/zotero/xpcom/http.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index 9534b2ffc1..f19e698ab4 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -489,6 +489,11 @@ Zotero.HTTP = new function() { * @return {browser} Hidden browser used for loading */ this.processDocuments = function(urls, processor, done, exception, dontDelete, cookieSandbox) { + // (Approximately) how many seconds to wait if the document is left in the loading state and + // pageshow is called before we call pageshow with an incomplete document + const LOADING_STATE_TIMEOUT = 120; + + var firedLoadEvent; /** * Removes event listener for the load event and deletes the hidden browser */ @@ -504,6 +509,7 @@ Zotero.HTTP = new function() { var doLoad = function() { if(urls.length) { var url = urls.shift(); + firedLoadEvent = 0; try { Zotero.debug("loading "+url); hiddenBrowser.loadURI(url); @@ -529,7 +535,13 @@ Zotero.HTTP = new function() { var onLoad = function() { var doc = hiddenBrowser.contentDocument, url = doc.location.href.toString(); - if(url == "about:blank" || doc.readyState === "loading") return; + if(url == "about:blank") return; + if(doc.readyState === "loading" && firedLoadEvent < 120) { + // Try again in a second + firedLoadEvent++; + Zotero.setTimeout(onLoad, 1000); + return; + } if(url !== prevUrl) { // Just in case it fires too many times prevUrl = url; try { From d453a15066da487c43473ec40b1115215da67c30 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Wed, 29 Feb 2012 03:27:18 -0500 Subject: [PATCH 02/11] Fix middle-pane Date Added/Modified order for non-US Mac/Linux --- chrome/content/zotero/xpcom/date.js | 75 +++++------------------------ 1 file changed, 13 insertions(+), 62 deletions(-) diff --git a/chrome/content/zotero/xpcom/date.js b/chrome/content/zotero/xpcom/date.js index ba54e4e19e..a84c58f88b 100644 --- a/chrome/content/zotero/xpcom/date.js +++ b/chrome/content/zotero/xpcom/date.js @@ -667,68 +667,19 @@ Zotero.Date = new function(){ * Returns a string with y, m, and d (e.g. 'ymd', 'mdy') */ function getLocaleDateOrder(){ - if (_localeDateOrder) { - return _localeDateOrder; + if (!_localeDateOrder) { + switch (Zotero.locale.substr(3)) { + case 'US': // The United States + case 'FM': // The Federated States of Micronesia + case 'PW': // Palau + case 'PH': // The Philippines + _localeDateOrder = 'mdy'; + break; + + default: + _localeDateOrder = 'dmy'; + } } - - var date = new Date("October 5, 2006"); - var parts = date.toLocaleDateString().match(/([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)/); - - // The above only works on OS X and Linux, - // where toLocaleDateString() produces "10/05/2006" - if (!parts) { - var country = Zotero.locale.substr(3); - switch (country) { - // I don't know where this country list came from, but these - // are little-endian in Zotero.strToDate() - case 'US': // The United States - case 'FM': // The Federated States of Micronesia - case 'PW': // Palau - case 'PH': // The Philippines - return 'mdy'; - break; - - default: - return 'dmy'; - } - } - - switch (parseInt(parts[1])){ - case 2006: - var order = 'y'; - break; - case 10: - var order = 'm'; - break; - case 5: - var order = 'd'; - break; - } - switch (parseInt(parts[2])){ - case 2006: - order += 'y'; - break; - case 10: - order += 'm'; - break; - case 5: - order += 'd'; - break; - } - switch (parseInt(parts[3])){ - case 2006: - order += 'y'; - break; - case 10: - order += 'm'; - break; - case 5: - order += 'd'; - break; - } - - _localeDateOrder = order; - - return order; + return _localeDateOrder; } } \ No newline at end of file From 61c0f974c076aeec6eaabc43647f950c1c2e8434 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Wed, 29 Feb 2012 05:14:03 -0500 Subject: [PATCH 03/11] Add big-endian date countries and use different format based on order m/d/yy, yyyy-mm-dd, and d.m.yy, based on what seem to be the most common variants for each order. --- chrome/content/zotero/xpcom/date.js | 31 ++++++++++++++++++--- chrome/content/zotero/xpcom/itemTreeView.js | 28 +++++++++++++++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/chrome/content/zotero/xpcom/date.js b/chrome/content/zotero/xpcom/date.js index a84c58f88b..ccd7fc3626 100644 --- a/chrome/content/zotero/xpcom/date.js +++ b/chrome/content/zotero/xpcom/date.js @@ -662,20 +662,43 @@ Zotero.Date = new function(){ } /** - * Figure out the date order from the output of toLocaleDateString() + * Get the order of the date components based on the current locale * * Returns a string with y, m, and d (e.g. 'ymd', 'mdy') */ function getLocaleDateOrder(){ if (!_localeDateOrder) { - switch (Zotero.locale.substr(3)) { + switch (Zotero.locale.substr(-2)) { + // middle-endian case 'US': // The United States + case 'BZ': // Belize case 'FM': // The Federated States of Micronesia - case 'PW': // Palau + case 'PA': // Panama case 'PH': // The Philippines + case 'PW': // Palau + case 'ZW': // Zimbabwe _localeDateOrder = 'mdy'; break; - + + // big-endian + case 'fa': // Persian + case 'AL': // Albania + case 'CA': // Canada + case 'CN': // China + case 'HU': // Hungary + case 'JP': // Japan + case 'KE': // Kenya + case 'KR': // Korea + case 'LT': // Lithuania + case 'LV': // Latvia + case 'MN': // Mongolia + case 'SE': // Sweden + case 'TW': // Taiwan + case 'ZA': // South Africa + _localeDateOrder = 'ymd'; + break; + + // little-endian default: _localeDateOrder = 'dmy'; } diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js index 239db07346..28b23a8148 100644 --- a/chrome/content/zotero/xpcom/itemTreeView.js +++ b/chrome/content/zotero/xpcom/itemTreeView.js @@ -759,6 +759,18 @@ Zotero.ItemTreeView.prototype.getCellText = function(row, column) case 'zotero-items-column-accessDate': if (val) { var order = Zotero.Date.getLocaleDateOrder(); + if (order == 'mdy') { + order = 'mdy'; + var join = '/'; + } + else if (order == 'dmy') { + order = 'dmy'; + var join = '.'; + } + else if (order == 'ymd') { + order = 'YMD'; + var join = '-'; + } var date = Zotero.Date.sqlToDate(val, true); var parts = []; for (var i=0; i<3; i++) { @@ -767,16 +779,28 @@ Zotero.ItemTreeView.prototype.getCellText = function(row, column) parts.push(date.getFullYear().toString().substr(2)); break; + case 'Y': + parts.push(date.getFullYear()); + break; + case 'm': parts.push((date.getMonth() + 1)); break; - + + case 'M': + parts.push(Zotero.Utilities.lpad((date.getMonth() + 1).toString(), '0', 2)); + break; + case 'd': parts.push(date.getDate()); break; + + case 'D': + parts.push(Zotero.Utilities.lpad(date.getDate().toString(), '0', 2)); + break; } - val = parts.join('/'); + val = parts.join(join); val += ' ' + date.toLocaleTimeString(); } } From fc3b2c35384ad7aeb9534a829303089f48dad72c Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Thu, 1 Mar 2012 14:19:04 -0500 Subject: [PATCH 04/11] Work around Chrome's buggy localeCompare function --- chrome/content/zotero/tools/testTranslators/translatorTester.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chrome/content/zotero/tools/testTranslators/translatorTester.js b/chrome/content/zotero/tools/testTranslators/translatorTester.js index 117d9728f2..d6d9b36ffb 100644 --- a/chrome/content/zotero/tools/testTranslators/translatorTester.js +++ b/chrome/content/zotero/tools/testTranslators/translatorTester.js @@ -79,7 +79,7 @@ Zotero_TranslatorTesters = new function() { }; } else { strcmp = function (a, b) { - return a.localeCompare(b); + return a.toLowerCase().localeCompare(b.toLowerCase()); }; } From d514f02c34c2443fbfafe42c817e73b890059f90 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Thu, 1 Mar 2012 20:54:05 -0500 Subject: [PATCH 05/11] Normalize fields when creating and running translator tests --- .../tools/testTranslators/translatorTester.js | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/chrome/content/zotero/tools/testTranslators/translatorTester.js b/chrome/content/zotero/tools/testTranslators/translatorTester.js index d6d9b36ffb..eb101c3281 100644 --- a/chrome/content/zotero/tools/testTranslators/translatorTester.js +++ b/chrome/content/zotero/tools/testTranslators/translatorTester.js @@ -213,12 +213,39 @@ Zotero_TranslatorTester._sanitizeItem = function(item, forSave) { item = JSON.parse(JSON.stringify(item)); } catch(e) {}; - // remove fields to be ignored - const IGNORE_FIELDS = ["complete", "accessDate", "checkFields"]; - for(var j=0, n=IGNORE_FIELDS.length; j Date: Thu, 1 Mar 2012 23:26:48 -0500 Subject: [PATCH 06/11] Fix Chrome translator testing --- .../zotero/tools/testTranslators/translatorTester.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/chrome/content/zotero/tools/testTranslators/translatorTester.js b/chrome/content/zotero/tools/testTranslators/translatorTester.js index eb101c3281..c987bc1206 100644 --- a/chrome/content/zotero/tools/testTranslators/translatorTester.js +++ b/chrome/content/zotero/tools/testTranslators/translatorTester.js @@ -215,7 +215,7 @@ Zotero_TranslatorTester._sanitizeItem = function(item, forSave) { // remove fields that don't exist or aren't valid for this item type, and normalize base fields // to fields specific to this item - var fieldID, + var fieldID, itemFieldID, typeID = Zotero.ItemTypes.getID(item.itemType); const skipFields = ["note", "notes", "itemID", "attachments", "tags", "seeAlso", "itemType", "complete", "creators"]; @@ -227,14 +227,10 @@ Zotero_TranslatorTester._sanitizeItem = function(item, forSave) { continue; } - if(Zotero.ItemFields.isBaseField(fieldID)) { + if(itemFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(typeID, fieldID)) { var value = item[field]; - delete item[field]; - - var itemFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(typeID, fieldID); - if(itemFieldID) { - item[Zotero.ItemFields.getName(itemFieldID)] = value; - } + delete item[field]; + item[Zotero.ItemFields.getName(itemFieldID)] = value; continue; } From 86dda4e0183f6753c89fea4ba5b61cf694439c19 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 3 Mar 2012 05:57:16 -0500 Subject: [PATCH 07/11] Ignore a file sync error on Windows with long ad junk files For some reason on some Windows (XP, 7) systems a long path close to 255 characters long can pass destFile.create() and fail zipReader.extract(). This seems like a Mozilla bug, but until we find a better fix just ignore the error for the only files where we've seen it, which are advertising script artifacts with very long uninterrupted filenames (which we should skip when saving anyway). Also close zipReader after an extraction error --- chrome/content/zotero/xpcom/storage.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js index c2cde12672..e3a2bdd43b 100644 --- a/chrome/content/zotero/xpcom/storage.js +++ b/chrome/content/zotero/xpcom/storage.js @@ -1111,6 +1111,7 @@ Zotero.Sync.Storage = new function () { Components.utils.reportError(msg + " in " + funcName); continue; } + try { destFile.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644); } @@ -1234,6 +1235,20 @@ Zotero.Sync.Storage = new function () { } catch (e) { Zotero.debug(destFile.path); + + // For advertising junk files, ignore a bug on Windows where + // destFile.create() works but zipReader.extract() doesn't + // when the path length is close to 255. + if (destFile.leafName.match(/[a-zA-Z0-9]{130,}/)) { + var msg = "Ignoring error extracting '" + destFile.path + "'"; + Zotero.debug(msg, 2); + Zotero.debug(e, 2); + Components.utils.reportError(msg + " in " + funcName); + continue; + } + + zipReader.close(); + Zotero.File.checkFileAccessError(e, destFile, 'create'); } From 42cd7752affcd0fd63184e4af7b8df4ed3e35532 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Sun, 4 Mar 2012 20:35:42 -0500 Subject: [PATCH 08/11] Fix irregular syntax to please IE indexOf regexp --- chrome/content/zotero/xpcom/connector/cachedTypes.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/xpcom/connector/cachedTypes.js b/chrome/content/zotero/xpcom/connector/cachedTypes.js index b9433c6cfb..466eb94dcf 100644 --- a/chrome/content/zotero/xpcom/connector/cachedTypes.js +++ b/chrome/content/zotero/xpcom/connector/cachedTypes.js @@ -130,7 +130,8 @@ Zotero.Connector_Types = new function() { // mimics itemFields.js if(!field || !itemType) return false; - return itemType[4]/* fields */.indexOf(field[0]/* id */) !== -1; + /* fields */ /* id */ + return itemType[4].indexOf(field[0]) !== -1; }; this.getFieldIDFromTypeAndBase = function(typeIdOrName, fieldIdOrName) { From 36cfad3933ea4f4bf1947b7369c226f6a9b479b0 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Mon, 5 Mar 2012 23:14:55 -0500 Subject: [PATCH 09/11] Fix NS_ERROR_ILLEGAL_VALUE when passing a wrapped DOM document to a translator --- chrome/content/zotero/xpcom/translation/translate.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index 6653270e2a..c052ca6e90 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -1425,7 +1425,16 @@ Zotero.Translate.Web.prototype._getTranslatorsGetPotentialTranslators = function * Bind sandbox to document being translated */ Zotero.Translate.Web.prototype._getSandboxLocation = function() { - return ("defaultView" in this.document ? this.document.defaultView : this.document.location.toString()); + if("defaultView" in this.document) { + var defaultView = this.document.defaultView; + if("__wrappedDOMObject" in defaultView) { + return defaultView.__wrappedDOMObject; + } else { + return defaultView; + } + } else { + return this.document.location.toString(); + } } /** From 2facd4fcbdbc925dcbd6c85cc8b94bb5ae52ed52 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Mon, 5 Mar 2012 23:47:27 -0500 Subject: [PATCH 10/11] Fix cross-site document saving --- chrome/content/zotero/xpcom/translation/translate_item.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/chrome/content/zotero/xpcom/translation/translate_item.js b/chrome/content/zotero/xpcom/translation/translate_item.js index daf0b5a120..8420189001 100644 --- a/chrome/content/zotero/xpcom/translation/translate_item.js +++ b/chrome/content/zotero/xpcom/translation/translate_item.js @@ -310,6 +310,10 @@ Zotero.Translate.ItemSaver.prototype = { || downloadAssociatedFiles; if(!shouldAttach) return; + if(attachment.document && "__wrappedDOMObject" in attachment.document) { + attachment.document = attachment.document.__wrappedDOMObject; + } + if(attachment.snapshot === false || !this._saveFiles) { // if snapshot is explicitly set to false, attach as link if(attachment.document) { From d256caf94e03dfbd21f9dc37cea21e673b5e1bc6 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Mon, 5 Mar 2012 23:47:42 -0500 Subject: [PATCH 11/11] Make cross-site getTranslatorObject() work --- chrome/content/zotero/xpcom/translation/translate.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index c052ca6e90..061f949143 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -1425,13 +1425,10 @@ Zotero.Translate.Web.prototype._getTranslatorsGetPotentialTranslators = function * Bind sandbox to document being translated */ Zotero.Translate.Web.prototype._getSandboxLocation = function() { - if("defaultView" in this.document) { - var defaultView = this.document.defaultView; - if("__wrappedDOMObject" in defaultView) { - return defaultView.__wrappedDOMObject; - } else { - return defaultView; - } + if(this._parentTranslator) { + return this._parentTranslator._sandboxLocation; + } else if("defaultView" in this.document) { + return this.document.defaultView; } else { return this.document.location.toString(); }