From be38be66f74b265258c6c02ec9d28ddbed2b7e06 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Sun, 29 Jan 2012 15:15:23 -0500 Subject: [PATCH] Don't unpack xpi --- chrome.manifest | 2 +- chrome/content/zotero/xpcom/file.js | 14 +- chrome/content/zotero/xpcom/locateManager.js | 9 +- chrome/content/zotero/xpcom/schema.js | 257 +++++++++---------- chrome/content/zotero/xpcom/zotero.js | 12 - install.rdf | 1 - engines.json => resource/schema/engines.json | 0 repotime.txt => resource/schema/repotime.txt | 0 system.sql => resource/schema/system.sql | 0 triggers.sql => resource/schema/triggers.sql | 0 userdata.sql => resource/schema/userdata.sql | 0 11 files changed, 142 insertions(+), 153 deletions(-) rename engines.json => resource/schema/engines.json (100%) rename repotime.txt => resource/schema/repotime.txt (100%) rename system.sql => resource/schema/system.sql (100%) rename triggers.sql => resource/schema/triggers.sql (100%) rename userdata.sql => resource/schema/userdata.sql (100%) diff --git a/chrome.manifest b/chrome.manifest index 9fb84a5809..5012c41ecc 100644 --- a/chrome.manifest +++ b/chrome.manifest @@ -1,6 +1,6 @@ content zotero chrome/content/zotero/ content zotero-platform chrome/content/zotero-platform/ platform -content zotero-resource resource/ +resource zotero resource/ locale zotero en-US chrome/locale/en-US/zotero/ locale zotero af-ZA chrome/locale/af-ZA/zotero/ diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js index 03bcb325db..18beacba37 100644 --- a/chrome/content/zotero/xpcom/file.js +++ b/chrome/content/zotero/xpcom/file.js @@ -85,9 +85,16 @@ Zotero.File = new function(){ function getContents(file, charset, maxLength){ - var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]. - createInstance(Components.interfaces.nsIFileInputStream); - fis.init(file, 0x01, 0664, 0); + var fis; + if(file instanceof Components.interfaces.nsIInputStream) { + fis = file; + } else if(file instanceof Components.interfaces.nsIFile) { + fis = Components.classes["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + fis.init(file, 0x01, 0664, 0); + } else { + throw new Error("File is not an nsIInputStream or nsIFile"); + } if (charset){ charset = Zotero.CharacterSets.getName(charset); @@ -150,6 +157,7 @@ Zotero.File = new function(){ var xmlhttp = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(); xmlhttp.open('GET', url, false); + xmlhttp.overrideMimeType("text/plain"); xmlhttp.send(null); return xmlhttp.responseText; } diff --git a/chrome/content/zotero/xpcom/locateManager.js b/chrome/content/zotero/xpcom/locateManager.js index aa0a11d71f..b6260d7fd6 100644 --- a/chrome/content/zotero/xpcom/locateManager.js +++ b/chrome/content/zotero/xpcom/locateManager.js @@ -68,7 +68,7 @@ Zotero.LocateManager = new function() { * Gets all default search engines (not currently used) */ this.getDefaultEngines = function() [new LocateEngine(engine) - for each(engine in JSON.parse(Zotero.File.getContents(_getDefaultFile())))]; + for each(engine in JSON.parse(Zotero.File.getContentsFromURL(_getDefaultFile())))]; /** * Returns an array of all search engines @@ -131,7 +131,8 @@ Zotero.LocateManager = new function() { locateDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0700); // copy default file to new locate dir - _getDefaultFile().copyTo(locateDir, LOCATE_FILE_NAME); + Zotero.File.putContents(_jsonFile, + Zotero.File.getContentsFromURL(_getDefaultFile())); // reread locate engines this.init(); @@ -170,9 +171,7 @@ Zotero.LocateManager = new function() { * Gets the JSON file containing the engine info for the default engines */ function _getDefaultFile() { - var defaultFile = Zotero.getInstallDirectory(); - defaultFile.append(LOCATE_FILE_NAME); - return defaultFile; + return "resource://zotero/schema/"+LOCATE_FILE_NAME; } diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js index 1e2d987e37..1d821be503 100644 --- a/chrome/content/zotero/xpcom/schema.js +++ b/chrome/content/zotero/xpcom/schema.js @@ -31,7 +31,8 @@ Zotero.Schema = new function(){ var _dbVersions = []; var _schemaVersions = []; var _repositoryTimer; - var _remoteUpdateInProgress = false; + var _remoteUpdateInProgress = false, + _localUpdateInProgress = false; var self = this; @@ -207,19 +208,12 @@ Zotero.Schema = new function(){ } try { - var up4 = this.updateBundledFiles(); + var up4 = this.updateBundledFiles(null, null, up2 || up3); } catch (e) { Zotero.debug(e); Zotero.logError(e); } - - if (up2 || up3 || up4) { - // Run a manual scraper update if upgraded and pref set - if (Zotero.Prefs.get('automaticScraperUpdates')){ - this.updateFromRepository(2); - } - } } finally { Zotero.UnresponsiveScriptIndicator.enable(); @@ -441,13 +435,56 @@ Zotero.Schema = new function(){ * since deleting uses a single version table key, * it should only be updated the last time through */ - this.updateBundledFiles = function (mode, skipDeleteUpdate) { + this.updateBundledFiles = function(mode, skipDeleteUpdate, runRemoteUpdateWhenComplete) { + if(_localUpdateInProgress) return; + _localUpdateInProgress = true; + + // Get path to addon and then call updateBundledFilesCallback, potentially asynchronously + if(Zotero.isStandalone) { + var appChrome = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties) + .get("AChrom", Components.interfaces.nsIFile); + _updateBundledFilesCallback(appChrome.parent, mode, skipDeleteUpdate, + runRemoteUpdateWhenComplete); + } else if(Zotero.isFx4) { + Components.utils.import("resource://gre/modules/AddonManager.jsm"); + AddonManager.getAddonByID(ZOTERO_CONFIG['GUID'], + function(addon) { + _updateBundledFilesCallback( + addon.getResourceURI().QueryInterface(Components.interfaces.nsIFileURL).file, + mode, skipDeleteUpdate, runRemoteUpdateWhenComplete); + }); + } else { + var gExtensionManager = Components.classes["@mozilla.org/extensions/manager;1"] + .getService(Components.interfaces.nsIExtensionManager); + var itemLocation = gExtensionManager.getInstallLocation(ZOTERO_CONFIG['GUID']) + .getItemLocation(ZOTERO_CONFIG['GUID']); + _updateBundledFilesCallback(itemLocation, mode, skipDeleteUpdate, + runRemoteUpdateWhenComplete); + } + } + + /** + * Callback to update bundled files, after finding the path to the Zotero install location + */ + function _updateBundledFilesCallback(installLocation, mode, skipDeleteUpdate, + runRemoteUpdateWhenComplete) { + _localUpdateInProgress = false; + if (!mode) { - var up1 = this.updateBundledFiles('translators', true); - var up2 = this.updateBundledFiles('styles'); + var up1 = _updateBundledFilesCallback(installLocation, 'translators', true, false); + var up2 = _updateBundledFilesCallback(installLocation, 'styles', false, + runRemoteUpdateWhenComplete); return up1 && up2; } + var xpiZipReader, isUnpacked = installLocation.isDirectory(); + if(!isUnpacked) { + xpiZipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"] + .createInstance(Components.interfaces.nsIZipReader); + xpiZipReader.open(installLocation); + } + switch (mode) { case "translators": var titleField = 'label'; @@ -470,17 +507,10 @@ Zotero.Schema = new function(){ var Mode = mode[0].toUpperCase() + mode.substr(1); var Modes = Mode + "s"; - var extDir = Zotero.getInstallDirectory(); - - var repotime = extDir.clone(); - repotime.append('repotime.txt'); - repotime = Zotero.File.getContents(repotime); + var repotime = Zotero.File.getContentsFromURL("resource://zotero/schema/repotime.txt"); var date = Zotero.Date.sqlToDate(repotime, true); repotime = Zotero.Date.toUnixTimestamp(date); - var zipFile = extDir.clone(); - zipFile.append(modes + ".zip"); - var fileNameRE = new RegExp("^[^\.].+\\" + fileExt + "$"); var destDir = Zotero["get" + Modes + "Directory"](); @@ -505,13 +535,20 @@ Zotero.Schema = new function(){ var sql = "SELECT version FROM version WHERE schema='delete'"; var lastVersion = Zotero.DB.valueQuery(sql); - var deleted = extDir.clone(); - deleted.append('deleted.txt'); - // In source builds, deleted.txt is in the translators directory - if (!deleted.exists()) { - deleted = extDir.clone(); - deleted.append('translators'); + if(isUnpacked) { + var deleted = installLocation.clone(); deleted.append('deleted.txt'); + // In source builds, deleted.txt is in the translators directory + if (!deleted.exists()) { + deleted = installLocation.clone(); + deleted.append('translators'); + deleted.append('deleted.txt'); + } + if (!deleted.exists()) { + deleted = false; + } + } else { + var deleted = xpiZipReader.getInputStream("deleted.txt"); } deleted = Zotero.File.getContents(deleted); @@ -598,26 +635,47 @@ Zotero.Schema = new function(){ var sql = "SELECT version FROM version WHERE schema=?"; var lastModTime = Zotero.DB.valueQuery(sql, modes); + var zipFileName = modes + ".zip", zipFile; + if(isUnpacked) { + zipFile = installLocation.clone(); + zipFile.append(zipFileName); + if(!zipFile.exists()) zipFile = undefined; + } else { + if(xpiZipReader.hasEntry(zipFileName)) { + zipFile = xpiZipReader.getEntry(zipFileName); + } + } + // XPI installation - if (zipFile.exists()) { + if (zipFile) { var modTime = Math.round(zipFile.lastModifiedTime / 1000); if (!forceReinstall && lastModTime && modTime <= lastModTime) { - Zotero.debug("Installed " + modes + " are up-to-date with " + modes + ".zip"); + Zotero.debug("Installed " + modes + " are up-to-date with " + zipFileName); return false; } - Zotero.debug("Updating installed " + modes + " from " + modes + ".zip"); + Zotero.debug("Updating installed " + modes + " from " + zipFileName); if (mode == 'translator') { // Parse translators.index - var indexFile = extDir.clone(); - indexFile.append('translators.index'); - if (!indexFile.exists()) { - Components.utils.reportError("translators.index not found in Zotero.Schema.updateBundledFiles()"); - return false; + var indexFile; + if(isUnpacked) { + indexFile = installLocation.clone(); + indexFile.append('translators.index'); + if (!indexFile.exists()) { + Components.utils.reportError("translators.index not found in Zotero.Schema.updateBundledFiles()"); + return false; + } + } else { + if(!xpiZipReader.hasEntry("translators.index")) { + Components.utils.reportError("translators.index not found in Zotero.Schema.updateBundledFiles()"); + return false; + } + var indexFile = xpiZipReader.getInputStream("translators.index"); } - var indexFile = Zotero.File.getContents(indexFile); + + indexFile = Zotero.File.getContents(indexFile); indexFile = indexFile.split("\n"); var index = {}; for each(var line in indexFile) { @@ -652,8 +710,12 @@ Zotero.Schema = new function(){ } var zipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"] - .getService(Components.interfaces.nsIZipReader); - zipReader.open(zipFile); + .createInstance(Components.interfaces.nsIZipReader); + if(isUnpacked) { + zipReader.open(zipFile); + } else { + zipReader.openInner(xpiZipReader, zipFileName); + } var tmpDir = Zotero.getTempDirectory(); if (mode == 'translator') { @@ -742,10 +804,11 @@ Zotero.Schema = new function(){ } zipReader.close(); + if(xpiZipReader) xpiZipReader.close(); } // Source installation else { - var sourceDir = extDir.clone(); + var sourceDir = installLocation.clone(); sourceDir.append(modes); if (!sourceDir.exists()) { Components.utils.reportError("No " + modes + " ZIP file or directory " @@ -850,6 +913,13 @@ Zotero.Schema = new function(){ Zotero.DB.commitTransaction(); Zotero[Modes].init(); + + if (runRemoteUpdateWhenComplete) { + // Run a manual scraper update if upgraded and pref set + if (Zotero.Prefs.get('automaticScraperUpdates')){ + Zotero.Schema.updateFromRepository(2); + } + } return true; } @@ -898,6 +968,12 @@ Zotero.Schema = new function(){ return false; } } + + if (_localUpdateInProgress) { + Zotero.debug('A local update is already in progress -- delaying repository check', 4); + _setRepositoryTimer(600); + return false; + } if (Zotero.locked) { Zotero.debug('Zotero is locked -- delaying repository check', 4); @@ -973,22 +1049,13 @@ Zotero.Schema = new function(){ translatorsDir.remove(true); Zotero.getTranslatorsDirectory(); // recreate directory Zotero.Translators.init(); - this.updateBundledFiles('translators'); + this.updateBundledFiles('translators', null, false); var stylesDir = Zotero.getStylesDirectory(); stylesDir.remove(true); Zotero.getStylesDirectory(); // recreate directory Zotero.Styles.init(); - this.updateBundledFiles('styles'); - - // Run a manual update from repository if pref set - if (Zotero.Prefs.get('automaticScraperUpdates')) { - this.updateFromRepository(2, function () { - if (callback) { - callback(); - } - }); - } + this.updateBundledFiles('styles', null, true); if (callback) { callback(); @@ -1128,31 +1195,10 @@ Zotero.Schema = new function(){ * Retrieve the version from the top line of the schema SQL file */ function _getSchemaSQLVersion(schema){ - if (!schema){ - throw ('Schema type not provided to _getSchemaSQLVersion()'); - } - - var schemaFile = schema + '.sql'; - - if (_schemaVersions[schema]){ - return _schemaVersions[schema]; - } - - var file = Zotero.getInstallDirectory(); - file.append(schemaFile); - - // Open an input stream from file - var istream = Components.classes["@mozilla.org/network/file-input-stream;1"] - .createInstance(Components.interfaces.nsIFileInputStream); - istream.init(file, 0x01, 0444, 0); - istream.QueryInterface(Components.interfaces.nsILineInputStream); - - var line = {}; + var sql = _getSchemaSQL(schema); // Fetch the schema version from the first line of the file - istream.readLine(line); - var schemaVersion = line.value.match(/-- ([0-9]+)/)[1]; - istream.close(); + var schemaVersion = sql.match(/^-- ([0-9]+)/)[1]; _schemaVersions[schema] = schemaVersion; return schemaVersion; @@ -1169,33 +1215,7 @@ Zotero.Schema = new function(){ throw ('Schema type not provided to _getSchemaSQL()'); } - var schemaFile = schema + '.sql'; - - // We pull the schema from an external file so we only have to process - // it when necessary - var file = Zotero.getInstallDirectory(); - file.append(schemaFile); - - // Open an input stream from file - var istream = Components.classes["@mozilla.org/network/file-input-stream;1"] - .createInstance(Components.interfaces.nsIFileInputStream); - istream.init(file, 0x01, 0444, 0); - istream.QueryInterface(Components.interfaces.nsILineInputStream); - - var line = {}, sql = '', hasmore; - - // Skip the first line, which contains the schema version - istream.readLine(line); - //var schemaVersion = line.value.match(/-- ([0-9]+)/)[1]; - - do { - hasmore = istream.readLine(line); - sql += line.value + "\n"; - } while(hasmore); - - istream.close(); - - return sql; + return Zotero.File.getContentsFromURL("resource://zotero/schema/"+schema+".sql"); } @@ -1208,39 +1228,14 @@ Zotero.Schema = new function(){ * Returns the SQL statements as a string for feeding into query() */ function _getDropCommands(schema){ - if (!schema){ - throw ('Schema type not provided to _getSchemaSQL()'); + var sql = _getSchemaSQL(schema); + + const re = /(?:[\r\n]|^)CREATE (TABLE|INDEX) IF NOT EXISTS ([^\s]+)/; + var m, str=""; + while(matches = re.exec(sql)) { + str += "DROP " + matches[1] + " IF EXISTS " + matches[2] + ";\n"; } - var schemaFile = schema + '.sql'; - - // We pull the schema from an external file so we only have to process - // it when necessary - var file = Zotero.getInstallDirectory(); - file.append(schemaFile); - - // Open an input stream from file - var istream = Components.classes["@mozilla.org/network/file-input-stream;1"] - .createInstance(Components.interfaces.nsIFileInputStream); - istream.init(file, 0x01, 0444, 0); - istream.QueryInterface(Components.interfaces.nsILineInputStream); - - var line = {}, str = '', hasmore; - - // Skip the first line, which contains the schema version - istream.readLine(line); - - do { - hasmore = istream.readLine(line); - var matches = - line.value.match(/CREATE (TABLE|INDEX) IF NOT EXISTS ([^\s]+)/); - if (matches){ - str += "DROP " + matches[1] + " IF EXISTS " + matches[2] + ";\n"; - } - } while(hasmore); - - istream.close(); - return str; } @@ -1309,7 +1304,7 @@ Zotero.Schema = new function(){ } try { - Zotero.Schema.updateBundledFiles(); + Zotero.Schema.updateBundledFiles(null, null, true); } catch (e) { Zotero.debug(e); diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index 681281c037..364b03b019 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -46,7 +46,6 @@ const ZOTERO_CONFIG = { this.init = init; this.stateCheck = stateCheck; this.getProfileDirectory = getProfileDirectory; - this.getInstallDirectory = getInstallDirectory; this.getZoteroDirectory = getZoteroDirectory; this.getStorageDirectory = getStorageDirectory; this.getZoteroDatabase = getZoteroDatabase; @@ -808,17 +807,6 @@ const ZOTERO_CONFIG = { .get("ProfD", Components.interfaces.nsIFile); } - - function getInstallDirectory() { - var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] - .getService(Components.interfaces.nsIChromeRegistry); - var ioService = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var zoteroURI = ioService.newURI("chrome://zotero-resource/content/", "UTF-8", null); - zoteroURI = cr.convertChromeURL(zoteroURI).QueryInterface(Components.interfaces.nsIFileURL); - return zoteroURI.file.parent.parent; - } - function getDefaultProfile(prefDir) { // find profiles.ini file var profilesIni = prefDir.clone(); diff --git a/install.rdf b/install.rdf index fc669edbc7..a7af36a1d4 100644 --- a/install.rdf +++ b/install.rdf @@ -19,7 +19,6 @@ chrome://zotero/skin/zotero_z_32px.png https://www.zotero.org/download/update-source.rdf 2 - true diff --git a/engines.json b/resource/schema/engines.json similarity index 100% rename from engines.json rename to resource/schema/engines.json diff --git a/repotime.txt b/resource/schema/repotime.txt similarity index 100% rename from repotime.txt rename to resource/schema/repotime.txt diff --git a/system.sql b/resource/schema/system.sql similarity index 100% rename from system.sql rename to resource/schema/system.sql diff --git a/triggers.sql b/resource/schema/triggers.sql similarity index 100% rename from triggers.sql rename to resource/schema/triggers.sql diff --git a/userdata.sql b/resource/schema/userdata.sql similarity index 100% rename from userdata.sql rename to resource/schema/userdata.sql