From d6e19a9f25cb779dd486d0c6c1a69d545dde5712 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 28 Mar 2015 18:37:55 -0400 Subject: [PATCH] Automatic PDF tool upgrading If automatic translator/style updates are enabled, at least one of the PDF tools is installed, and the repo returns a more recent version number than what's installed, automatically upgrade the tools. (Version 3.02 counts as lower, since Poppler's version numbers are lower.) If an error occurs, wait increasing amounts of time to try the downloads again, up to one week. --- .../zotero/preferences/preferences_search.js | 180 +++++------------- chrome/content/zotero/xpcom/fulltext.js | 72 +++++++ chrome/content/zotero/xpcom/schema.js | 82 ++++++++ 3 files changed, 200 insertions(+), 134 deletions(-) diff --git a/chrome/content/zotero/preferences/preferences_search.js b/chrome/content/zotero/preferences/preferences_search.js index 5f7743c05..591cec7ac 100644 --- a/chrome/content/zotero/preferences/preferences_search.js +++ b/chrome/content/zotero/preferences/preferences_search.js @@ -177,14 +177,18 @@ Zotero_Preferences.Search = { var converterVersion = xmlhttp.responseText.split(/\s/)[0]; var infoVersion = xmlhttp.responseText.split(/\s/)[1]; + // Install if not installed, version unknown, Xpdf 3.02 (to upgrade to Poppler), + // or outdated var converterVersionAvailable = converterVersion && (!converterIsRegistered || - Zotero.Fulltext.pdfConverterVersion == 'UNKNOWN' || - converterVersion > Zotero.Fulltext.pdfConverterVersion); + Zotero.Fulltext.pdfConverterVersion == 'UNKNOWN' + || (converterVersion != '3.02' && Zotero.Fulltext.pdfConverterVersion == '3.02') + || converterVersion > Zotero.Fulltext.pdfConverterVersion); var infoVersionAvailable = infoVersion && (!infoIsRegistered || - Zotero.Fulltext.pdfInfoVersion == 'UNKNOWN' || - infoVersion > Zotero.Fulltext.pdfInfoVersion); + Zotero.Fulltext.pdfInfoVersion == 'UNKNOWN' + || (infoVersion != '3.02' && Zotero.Fulltext.pdfInfoVersion == '3.02') + || infoVersion > Zotero.Fulltext.pdfInfoVersion); var bothAvailable = converterVersionAvailable && infoVersionAvailable; /* @@ -246,7 +250,44 @@ Zotero_Preferences.Search = { info: infoVersionAvailable ? infoVersion : null }; - self.installPDFTools(installVersions); + + document.getElementById('pdftools-update-button').disabled = true; + var str = Zotero.getString('zotero.preferences.search.pdf.downloading'); + document.getElementById('pdftools-update-button').setAttribute('label', str); + + if (converterVersionAvailable && infoVersionAvailable) { + Zotero.Fulltext.downloadPDFTool('converter', converterVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdftotext"); + return; + } + Zotero.Fulltext.downloadPDFTool('info', infoVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdfinfo"); + return; + } + self.updatePDFToolsStatus(); + }); + }); + } + else if (converterVersionAvailable) { + Zotero.Fulltext.downloadPDFTool('converter', converterVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdftotext"); + return; + } + self.updatePDFToolsStatus(); + }); + } + else { + Zotero.Fulltext.downloadPDFTool('info', infoVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdfinfo"); + return; + } + self.updatePDFToolsStatus(); + }); + } } } } @@ -267,135 +308,6 @@ Zotero_Preferences.Search = { }, - /* - * Begin installation of specified PDF tools from server -- does a HEAD call to - * make sure file exists and then calls downloadPDFTool() if so - */ - installPDFTools: function (installVersions) { - if (!installVersions) { - installVersions = { - converter: true, - info: true - }; - } - - // We install the converter first if it's available - var url = Zotero.Fulltext.pdfToolsDownloadBaseURL; - if (installVersions.converter) { - var tool = 'converter'; - var version = installVersions.converter; - url += Zotero.Fulltext.pdfConverterFileName + '-' + installVersions.converter; - } - else if (installVersions.info) { - var tool = 'info'; - var version = installVersions.info; - url += Zotero.Fulltext.pdfInfoFileName + '-' + installVersions.info; - } - else { - return; - } - - // Find latest version for this platform - var self = this; - var sent = Zotero.HTTP.doHead(url, function (xmlhttp) { - try { - if (xmlhttp.status == 200) { - // If doing both and on converter, chain pdfinfo - if (installVersions.converter && installVersions.info) { - self.downloadPDFTool(tool, version, function () { - return self.installPDFTools({ info: installVersions.info }); - }); - } - else { - self.downloadPDFTool(tool, version); - } - } - // Version not found for platform - else if (xmlhttp.status == 404) { - self.onPDFToolsDownloadError(404); - } - } - catch (e) { - self.onPDFToolsDownloadError(e); - } - }); - - // Browser is offline - if (!sent) { - self.onPDFToolsDownloadError(); - } - }, - - - /* - * Download and install specified PDF tool - */ - downloadPDFTool: function (tool, version, callback) { - var ioService = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - - if (tool == 'converter') { - var fileName = Zotero.Fulltext.pdfConverterFileName; - } - else { - var fileName = Zotero.Fulltext.pdfInfoFileName; - } - - - var url = Zotero.Fulltext.pdfToolsDownloadBaseURL + fileName + '-' + version; - var uri = ioService.newURI(url, null, null); - - var file = Zotero.getZoteroDirectory(); - file.append(fileName); - var fileURL = ioService.newFileURI(file); - - const nsIWBP = Components.interfaces.nsIWebBrowserPersist; - var wbp = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] - .createInstance(nsIWBP); - - var self = this; - var progressListener = new Zotero.WebProgressFinishListener(function () { - // Set permissions to 755 - if (Zotero.isMac) { - file.permissions = 33261; - } - else if (Zotero.isLinux) { - file.permissions = 493; - } - - // Write the version number to a file - var versionFile = Zotero.getZoteroDirectory(); - versionFile.append(fileName + '.version'); - Zotero.File.putContents(versionFile, version + ''); - - Zotero.Fulltext.registerPDFTool(tool); - - // Used to install info tool after converter - if (callback) { - callback(); - } - // If done - else { - self.updatePDFToolsStatus(); - } - }); - - /* - var tr = Components.classes["@mozilla.org/transfer;1"]. - createInstance(Components.interfaces.nsITransfer); - tr.init(uri, fileURL, "", null, null, null, wbp); - */ - - document.getElementById('pdftools-update-button').disabled = true; - var str = Zotero.getString('zotero.preferences.search.pdf.downloading'); - document.getElementById('pdftools-update-button').setAttribute('label', str); - - wbp.progressListener = progressListener; - Zotero.debug("Saving " + uri.spec + " to " + fileURL.spec); - Zotero.Utilities.Internal.saveURI(wbp, uri, fileURL); - }, - - onPDFToolsDownloadError: function (e) { if (e == 404) { var str = Zotero.getString('zotero.preferences.search.pdf.toolDownloadsNotAvailable', diff --git a/chrome/content/zotero/xpcom/fulltext.js b/chrome/content/zotero/xpcom/fulltext.js index 7be7f087a..ea1d5b359 100644 --- a/chrome/content/zotero/xpcom/fulltext.js +++ b/chrome/content/zotero/xpcom/fulltext.js @@ -164,6 +164,78 @@ Zotero.Fulltext = new function(){ } + /* + * Download and install latest PDF tool + */ + this.downloadPDFTool = function (tool, version, callback) { + try { + var ioService = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + + if (tool == 'converter') { + var fileName = this.pdfConverterFileName; + } + else { + var fileName = this.pdfInfoFileName; + } + + var spec = this.pdfToolsDownloadBaseURL + fileName + '-' + version; + var uri = ioService.newURI(spec, null, null); + + var file = Zotero.getTempDirectory(); + file.append(fileName); + + Components.utils.import("resource://gre/modules/NetUtil.jsm"); + Components.utils.import("resource://gre/modules/FileUtils.jsm"); + + Zotero.debug("Saving " + uri.spec + " to " + file.path); + var output = FileUtils.openSafeFileOutputStream(file); + NetUtil.asyncFetch(uri, function (is, status) { + if (!Components.isSuccessCode(status)) { + Zotero.debug(status, 1); + Components.utils.reportError(status); + if (callback) { + callback(false); + } + return; + } + + Zotero.File.putContentsAsync(file, is) + .then(function () { + // Set permissions to 755 + if (Zotero.isMac) { + file.permissions = 33261; + } + else if (Zotero.isLinux) { + file.permissions = 493; + } + + var destDir = Zotero.getZoteroDirectory() + file.moveTo(destDir, null); + + // Write the version number to a file + var versionFile = destDir.clone(); + versionFile.append(fileName + '.version'); + Zotero.File.putContents(versionFile, version + ''); + + Zotero.Fulltext.registerPDFTool(tool); + + if (callback) { + callback(true); + } + }); + }); + } + catch (e) { + Zotero.debug(e, 1); + Components.utils.reportError(e); + if (callback) { + callback(false); + } + } + }; + + /* * Looks for pdftotext-{platform}[.exe] in the Zotero data directory * diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js index b46a0bfc0..8376e733d 100644 --- a/chrome/content/zotero/xpcom/schema.js +++ b/chrome/content/zotero/xpcom/schema.js @@ -1589,6 +1589,78 @@ Zotero.Schema = new function(){ var translatorUpdates = xmlhttp.responseXML.getElementsByTagName('translator'); var styleUpdates = xmlhttp.responseXML.getElementsByTagName('style'); + var updatePDFTools = function () { + let pdfToolsUpdates = xmlhttp.responseXML.getElementsByTagName('pdftools'); + if (pdfToolsUpdates.length) { + let availableVersion = pdfToolsUpdates[0].getAttribute('version'); + let installInfo = false; + let installConverter = false; + + // Don't auto-install if not installed + if (!Zotero.Fulltext.pdfInfoIsRegistered() && !Zotero.Fulltext.pdfConverterIsRegistered()) { + return; + } + + if (Zotero.Fulltext.pdfInfoIsRegistered()) { + let currentVersion = Zotero.Fulltext.pdfInfoVersion; + if (currentVersion < availableVersion || currentVersion == '3.02' + || currentVersion == 'UNKNOWN') { + installInfo = true; + } + } + if (Zotero.Fulltext.pdfConverterIsRegistered()) { + let currentVersion = Zotero.Fulltext.pdfConverterVersion; + if (currentVersion < availableVersion || currentVersion == '3.02' + || currentVersion == 'UNKNOWN') { + installConverter = true; + } + } + + let prefKey = 'pdfToolsInstallError'; + let lastTry = 0, delay = 43200000; // half a day, so doubles to a day initially + try { + [lastTry, delay] = Zotero.Prefs.get(prefKey).split(';'); + } + catch (e) {} + + // Allow an additional minute, since repo updates might not be exact + if (Date.now() < (parseInt(lastTry) + parseInt(delay) - 60000)) { + Zotero.debug("Now enough time since last PDF tools installation failure -- skipping", 2); + return; + } + + var checkResult = function (success) { + if (success) { + try { + Zotero.Prefs.clear(prefKey); + } + catch (e) {} + } + else { + // Keep doubling delay, to a max of 1 week + Zotero.Prefs.set(prefKey, Date.now() + ";" + Math.min(delay * 2, 7*24*60*60*1000)); + + let msg = "Error downloading PDF tool"; + Zotero.debug(msg, 1); + throw new Error(msg); + } + }; + + if (installConverter && installInfo) { + Zotero.Fulltext.downloadPDFTool('converter', availableVersion, function (success) { + checkResult(success); + Zotero.Fulltext.downloadPDFTool('info', availableVersion, checkResult); + }); + } + else if (installConverter) { + Zotero.Fulltext.downloadPDFTool('converter', availableVersion, checkResult); + } + else { + Zotero.Fulltext.downloadPDFTool('info', availableVersion, checkResult); + } + } + }; + Zotero.DB.beginTransaction(); // TODO: clear DB version 'sync' from removed _updateDBVersion() @@ -1609,6 +1681,11 @@ Zotero.Schema = new function(){ _setRepositoryTimer(ZOTERO_CONFIG['REPOSITORY_CHECK_INTERVAL']); } _remoteUpdateInProgress = false; + + setTimeout(function () { + updatePDFTools(); + }); + return -1; } @@ -1640,6 +1717,11 @@ Zotero.Schema = new function(){ _setRepositoryTimer(ZOTERO_CONFIG['REPOSITORY_CHECK_INTERVAL']); } _remoteUpdateInProgress = false; + + setTimeout(function () { + updatePDFTools(); + }); + return true; }