diff --git a/chrome/content/zotero/preferences/preferences_search.js b/chrome/content/zotero/preferences/preferences_search.js index 591cec7ac..6dfe00021 100644 --- a/chrome/content/zotero/preferences/preferences_search.js +++ b/chrome/content/zotero/preferences/preferences_search.js @@ -162,139 +162,121 @@ Zotero_Preferences.Search = { * if a newer version is available */ checkPDFToolsDownloadVersion: function () { - var url = Zotero.Fulltext.pdfToolsDownloadBaseURL - + Zotero.platform.replace(' ', '-') + '.latest'; + var url = Zotero.Fulltext.pdfToolsDownloadBaseURL + 'latest.json'; // Find latest version for this platform var self = this; var sent = Zotero.HTTP.doGet(url, function (xmlhttp) { try { - if (xmlhttp.status == 200) { - var converterIsRegistered = Zotero.Fulltext.pdfConverterIsRegistered(); - var infoIsRegistered = Zotero.Fulltext.pdfInfoIsRegistered(); - var bothRegistered = converterIsRegistered && infoIsRegistered; + if (xmlhttp.status != 200) { + throw new Error("Unexpected response code " + xmlhttp.status); + } + + var platform = Zotero.platform.replace(/\s/g, '-'); + var json = JSON.parse(xmlhttp.responseText); + var latestVersion = json[platform] || json['default']; + + Zotero.debug("Latest PDF tools version for " + platform + " is " + latestVersion); + + var converterIsRegistered = Zotero.Fulltext.pdfConverterIsRegistered(); + var infoIsRegistered = Zotero.Fulltext.pdfInfoIsRegistered(); + var bothRegistered = converterIsRegistered && infoIsRegistered; + + // Install if not installed, version unknown, outdated, or + // Xpdf 3.02/3.04 (to upgrade to Poppler), + var converterVersionAvailable = (!converterIsRegistered || + Zotero.Fulltext.pdfConverterVersion == 'UNKNOWN' + || latestVersion > Zotero.Fulltext.pdfConverterVersion + || (latestVersion != '3.02' && Zotero.Fulltext.pdfConverterVersion == '3.02') + || (latestVersion != '3.02' && latestVersion != '3.04' && Zotero.Fulltext.pdfConverterVersion == '3.04')); + var infoVersionAvailable = (!infoIsRegistered || + Zotero.Fulltext.pdfInfoVersion == 'UNKNOWN' + || latestVersion > Zotero.Fulltext.pdfInfoVersion + || (latestVersion != '3.02' && Zotero.Fulltext.pdfInfoVersion == '3.02') + || (latestVersion != '3.02' && latestVersion != '3.04' && Zotero.Fulltext.pdfInfoVersion == '3.04')); + var bothAvailable = converterVersionAvailable && infoVersionAvailable; + + // Up to date -- disable update button + if (!converterVersionAvailable && !infoVersionAvailable) { + var button = document.getElementById('pdftools-update-button'); + button.setAttribute('label', Zotero.getString('zotero.preferences.update.upToDate')); + button.setAttribute('disabled', true); + } + // New version available -- display update prompt + else { + var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]. + createInstance(Components.interfaces.nsIPromptService); + var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) + + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL); - var converterVersion = xmlhttp.responseText.split(/\s/)[0]; - var infoVersion = xmlhttp.responseText.split(/\s/)[1]; + var msg = Zotero.getString('zotero.preferences.search.pdf.available' + + ((converterIsRegistered || infoIsRegistered) ? 'Updates' : 'Downloads'), + [Zotero.platform, 'zotero.org']) + '\n\n'; - // Install if not installed, version unknown, Xpdf 3.02 (to upgrade to Poppler), - // or outdated - var converterVersionAvailable = converterVersion && - (!converterIsRegistered || - 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 != '3.02' && Zotero.Fulltext.pdfInfoVersion == '3.02') - || infoVersion > Zotero.Fulltext.pdfInfoVersion); - var bothAvailable = converterVersionAvailable && infoVersionAvailable; - - /* - Zotero.debug(converterIsRegistered); - Zotero.debug(infoIsRegistered); - Zotero.debug(converterVersion); - Zotero.debug(infoVersion); - Zotero.debug(Zotero.Fulltext.pdfConverterVersion); - Zotero.debug(Zotero.Fulltext.pdfInfoVersion); - Zotero.debug(converterVersionAvailable); - Zotero.debug(infoVersionAvailable); - */ - - // Up to date -- disable update button - if (!converterVersionAvailable && !infoVersionAvailable) { - var button = document.getElementById('pdftools-update-button'); - button.setAttribute('label', Zotero.getString('zotero.preferences.update.upToDate')); - button.setAttribute('disabled', true); + if (converterVersionAvailable) { + let tvp = Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform', + [Zotero.Fulltext.pdfConverterName, latestVersion]); + msg += '- ' + tvp + '\n'; } - // New version available -- display update prompt - else { - var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]. - createInstance(Components.interfaces.nsIPromptService); - var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) - + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL); + if (infoVersionAvailable) { + let tvp = Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform', + [Zotero.Fulltext.pdfInfoName, latestVersion]); + msg += '- ' + tvp + '\n'; + } + msg += '\n'; + msg += Zotero.getString('zotero.preferences.search.pdf.zoteroCanInstallVersion' + + (bothAvailable ? 's' : '')); + + var index = ps.confirmEx(null, + converterIsRegistered ? + Zotero.getString('general.updateAvailable') : '', + msg, + buttonFlags, + converterIsRegistered ? + Zotero.getString('general.upgrade') : + Zotero.getString('general.install'), + null, null, null, {}); + + if (index == 0) { + document.getElementById('pdftools-update-button').disabled = true; + var str = Zotero.getString('zotero.preferences.search.pdf.downloading'); + document.getElementById('pdftools-update-button').setAttribute('label', str); - var msg = Zotero.getString('zotero.preferences.search.pdf.available' - + ((converterIsRegistered || infoIsRegistered) ? 'Updates' : 'Downloads'), - [Zotero.platform, 'zotero.org']) + '\n\n'; - - if (converterVersionAvailable) { - let tvp = Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform', - [Zotero.Fulltext.pdfConverterName, converterVersion]); - msg += '- ' + tvp + '\n'; - } - if (infoVersionAvailable) { - let tvp = Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform', - [Zotero.Fulltext.pdfInfoName, infoVersion]); - msg += '- ' + tvp + '\n'; - } - msg += '\n'; - msg += Zotero.getString('zotero.preferences.search.pdf.zoteroCanInstallVersion' - + (bothAvailable ? 's' : '')); - - var index = ps.confirmEx(null, - converterIsRegistered ? - Zotero.getString('general.updateAvailable') : '', - msg, - buttonFlags, - converterIsRegistered ? - Zotero.getString('general.upgrade') : - Zotero.getString('general.install'), - null, null, null, {}); - - if (index == 0) { - var installVersions = { - converter: converterVersionAvailable ? - converterVersion : null, - info: infoVersionAvailable ? - infoVersion : null - }; - - 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 (converterVersionAvailable && infoVersionAvailable) { + Zotero.Fulltext.downloadPDFTool('converter', latestVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdftotext"); + return; + } + Zotero.Fulltext.downloadPDFTool('info', latestVersion, function (success) { if (!success) { self.onPDFToolsDownloadError("Error downloading pdfinfo"); return; } self.updatePDFToolsStatus(); }); - } + }); + } + else if (converterVersionAvailable) { + Zotero.Fulltext.downloadPDFTool('converter', latestVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdftotext"); + return; + } + self.updatePDFToolsStatus(); + }); + } + else { + Zotero.Fulltext.downloadPDFTool('info', latestVersion, function (success) { + if (!success) { + self.onPDFToolsDownloadError("Error downloading pdfinfo"); + return; + } + self.updatePDFToolsStatus(); + }); } } } - // Version not found for platform - else if (xmlhttp.status == 404) { - self.onPDFToolsDownloadError(404); - } } catch (e) { self.onPDFToolsDownloadError(e); diff --git a/chrome/content/zotero/xpcom/fulltext.js b/chrome/content/zotero/xpcom/fulltext.js index ea1d5b359..ee433cb8a 100644 --- a/chrome/content/zotero/xpcom/fulltext.js +++ b/chrome/content/zotero/xpcom/fulltext.js @@ -55,7 +55,7 @@ Zotero.Fulltext = new function(){ //this.clearItemContent = clearItemContent; this.purgeUnusedWords = purgeUnusedWords; - this.__defineGetter__("pdfToolsDownloadBaseURL", function() { return 'http://www.zotero.org/download/xpdf/'; }); + this.__defineGetter__("pdfToolsDownloadBaseURL", function() { return 'https://www.zotero.org/download/xpdf/'; }); this.__defineGetter__("pdfToolsName", function() { return 'Xpdf'; }); this.__defineGetter__("pdfToolsURL", function() { return 'http://www.foolabs.com/xpdf/'; }); this.__defineGetter__("pdfConverterName", function() { return 'pdftotext'; }); @@ -82,9 +82,11 @@ Zotero.Fulltext = new function(){ var _pdfConverterVersion = null; var _pdfConverterFileName = null; + var _pdfConverterScript = null; // nsIFile of hidden window script on Windows var _pdfConverter = null; // nsIFile to executable var _pdfInfoVersion = null; var _pdfInfoFileName = null; + var _pdfInfoScript = null; // nsIFile of redirection script var _pdfInfo = null; // nsIFile to executable var _idleObserverIsRegistered = false; @@ -179,7 +181,7 @@ Zotero.Fulltext = new function(){ var fileName = this.pdfInfoFileName; } - var spec = this.pdfToolsDownloadBaseURL + fileName + '-' + version; + var spec = this.pdfToolsDownloadBaseURL + version + "/" + fileName; var uri = ioService.newURI(spec, null, null); var file = Zotero.getTempDirectory(); @@ -202,15 +204,43 @@ Zotero.Fulltext = new function(){ Zotero.File.putContentsAsync(file, is) .then(function () { + var scriptExt = _getScriptExtension(); + // On Windows, write out script to hide pdftotext console window + if (tool == 'converter') { + if (Zotero.isWin) { + var content = Zotero.File.getContentsFromURL('resource://zotero/hide.' + scriptExt); + var scriptFile = Zotero.getTempDirectory(); + scriptFile.append('pdftotext.' + scriptExt); + Zotero.File.putContents(scriptFile, content); + } + } + // Write out output redirection script for pdfinfo + else if (tool == 'info') { + var content = Zotero.File.getContentsFromURL('resource://zotero/redirect.' + scriptExt); + var scriptFile = Zotero.getTempDirectory(); + scriptFile.append('pdfinfo.' + scriptExt); + Zotero.File.putContents(scriptFile, content); + } + // Set permissions to 755 if (Zotero.isMac) { file.permissions = 33261; + if (scriptFile) { + scriptFile.permissions = 33261; + } } else if (Zotero.isLinux) { file.permissions = 493; + if (scriptFile) { + scriptFile.permissions = 493; + } } var destDir = Zotero.getZoteroDirectory() + // Move redirect script and executable into data dir + if (scriptFile) { + scriptFile.moveTo(destDir, null); + } file.moveTo(destDir, null); // Write the version number to a file @@ -223,6 +253,11 @@ Zotero.Fulltext = new function(){ if (callback) { callback(true); } + }) + .catch(function (e) { + Zotero.debug(e, 1); + Components.utils.reportError(e); + callback(false); }); }); } @@ -274,10 +309,42 @@ Zotero.Fulltext = new function(){ return false; } + // If scripts exist, use those instead + switch (tool) { + case 'converter': + if (Zotero.isWin) { + var script = Zotero.getZoteroDirectory(); + script.append('pdftotext.' + _getScriptExtension()) + if (script.exists()) { + Zotero.debug(script.leafName + " registered"); + _pdfConverterScript = script; + } + } + break; + + case 'info': + var script = Zotero.getZoteroDirectory(); + script.append('pdfinfo.' + _getScriptExtension()) + // The redirection script is necessary to run pdfinfo + if (!script.exists()) { + Zotero.debug(script.leafName + " not found -- PDF statistics disabled"); + return false; + } + Zotero.debug(toolName + " redirection script registered"); + _pdfInfoScript = script; + break; + } + var versionFile = exec.parent; versionFile.append(fileName + '.version'); if (versionFile.exists()) { - var version = Zotero.File.getSample(versionFile).split(/[\r\n\s]/)[0]; + try { + var version = Zotero.File.getSample(versionFile).split(/[\r\n\s]/)[0]; + } + catch (e) { + Zotero.debug(e, 1); + Components.utils.reportError(e); + } } if (!version) { var version = 'UNKNOWN'; @@ -295,7 +362,7 @@ Zotero.Fulltext = new function(){ break; } - Zotero.debug(toolName + ' version ' + version + ' registered at ' + exec.path); + Zotero.debug(toolName + ' version ' + version + ' registered'); return true; } @@ -529,16 +596,19 @@ Zotero.Fulltext = new function(){ } cacheFile.append(this.pdfConverterCacheFile); - if (_pdfInfo) { + if (_pdfInfoScript) { var infoFile = cacheFile.parent; infoFile.append(this.pdfInfoCacheFile); - Zotero.debug('Running pdfinfo "' + file.path + '" "' + infoFile.path + '"'); - var proc = Components.classes["@mozilla.org/process/util;1"]. - createInstance(Components.interfaces.nsIProcess); - proc.init(_pdfInfo); + var args = [_pdfInfo.path, file.path, infoFile.path]; + + Zotero.debug("Running " + _pdfInfoScript.path + ' ' + + args.map(arg => "'" + arg + "'").join(' ')); + + var proc = Components.classes["@mozilla.org/process/util;1"] + .createInstance(Components.interfaces.nsIProcess); + proc.init(_pdfInfoScript); - var args = [file.path, infoFile.path]; try { proc.runw(true, args, args.length); var totalPages = this.getTotalPagesFromFile(itemID); @@ -551,15 +621,12 @@ Zotero.Fulltext = new function(){ Zotero.debug(this.pdfInfoName + " is not available"); } - Zotero.debug('Running pdftotext -enc UTF-8 -nopgbrk ' - + (allPages ? '' : '-l ' + maxPages) + ' "' + file.path + '" "' - + cacheFile.path + '"'); + var args = [] + if (_pdfConverterScript) { + args.push(_pdfConverter.path); + } + args.push('-enc', 'UTF-8', '-nopgbrk'); - var proc = Components.classes["@mozilla.org/process/util;1"]. - createInstance(Components.interfaces.nsIProcess); - proc.init(_pdfConverter); - - var args = ['-enc', 'UTF-8', '-nopgbrk']; if (allPages) { if (totalPages) { var pagesIndexed = totalPages; @@ -570,6 +637,20 @@ Zotero.Fulltext = new function(){ var pagesIndexed = Math.min(maxPages, totalPages); } args.push(file.path, cacheFile.path); + + var proc = Components.classes["@mozilla.org/process/util;1"] + .createInstance(Components.interfaces.nsIProcess); + if (_pdfConverterScript) { + Zotero.debug("Running " + _pdfConverterScript.path + ' ' + + args.map(arg => "'" + arg + "'").join(' ')); + proc.init(_pdfConverterScript); + } + else { + Zotero.debug("Running " + _pdfConverter.path + ' ' + + args.map(arg => "'" + arg + "'").join(' ')); + proc.init(_pdfConverter); + } + try { proc.runw(true, args, args.length); } @@ -1679,4 +1760,9 @@ Zotero.Fulltext = new function(){ return w; }); } + + function _getScriptExtension() { + return Zotero.isWin ? 'vbs' : 'sh'; + } + } diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js index 1ea3154b3..c512936e2 100644 --- a/chrome/content/zotero/xpcom/schema.js +++ b/chrome/content/zotero/xpcom/schema.js @@ -1590,6 +1590,9 @@ Zotero.Schema = new function(){ var styleUpdates = xmlhttp.responseXML.getElementsByTagName('style'); var updatePDFTools = function () { + // No updates for PPC + if (Zotero.platform == 'MacPPC') return; + let pdfToolsUpdates = xmlhttp.responseXML.getElementsByTagName('pdftools'); if (pdfToolsUpdates.length) { let availableVersion = pdfToolsUpdates[0].getAttribute('version'); diff --git a/resource/hide.vbs b/resource/hide.vbs new file mode 100644 index 000000000..9f233e2bd --- /dev/null +++ b/resource/hide.vbs @@ -0,0 +1,24 @@ +Option Explicit + +Dim WshShell, fso, exe, args, I + +Set WshShell = Wscript.CreateObject("Wscript.Shell") +Set fso = WScript.CreateObject("Scripting.FileSystemObject") + +If WScript.Arguments.Count = 0 Then + WScript.Echo "Usage: hidden.vbs program.exe [args...]" + WScript.Quit 1 +End If + +exe = WScript.Arguments(0) +If Not(fso.FileExists(exe)) Then + WScript.Echo "Executable not found: " & exe + WScript.Quit 1 +End If + +args = "" +For I = 1 to WScript.Arguments.Count - 1 + args = args & " " & chr(34) & WScript.Arguments(I) & chr(34) +Next + +WshShell.Run exe & args, 0, true diff --git a/resource/redirect.sh b/resource/redirect.sh new file mode 100644 index 000000000..05342e273 --- /dev/null +++ b/resource/redirect.sh @@ -0,0 +1,6 @@ +#!/bin/sh +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then + echo "Usage: $0 cmd source output.txt" + exit 1 +fi +"$1" "$2" > "$3" diff --git a/resource/redirect.vbs b/resource/redirect.vbs new file mode 100644 index 000000000..4f1e7a3f2 --- /dev/null +++ b/resource/redirect.vbs @@ -0,0 +1,33 @@ +Option Explicit + +Dim WshShell +Dim fso +Dim exe, src, dest + +Set WshShell = Wscript.CreateObject("Wscript.Shell") +Set fso = WScript.CreateObject("Scripting.FileSystemObject") + +If Not(Wscript.Arguments.Count = 3) Then + Wscript.Echo "Usage: redirect.vbs <.exe file> " + WScript.Quit 1 +End If + +exe = WScript.Arguments(0) +src = WScript.Arguments(1) +dest = WScript.Arguments(2) +If Not(fso.FileExists(exe)) Then + WScript.Echo "Executable not found: " & exe + WScript.Quit 1 +End If + +If Not(fso.FileExists(src)) Then + WScript.Echo "Source file not found: " & src + WScript.Quit 1 +End If + +If Not(fso.FolderExists(Left(dest, InstrRev(dest, "\")))) Then + WScript.Echo "Destination folder not found: " & Left(dest, InstrRev(dest, "\")) + WScript.Quit 1 +End If + +WshShell.Run "%comspec% /c " & exe & " " & chr(34) & src & chr(34) & " > " & chr(34) & dest & chr(34), 0, true