diff --git a/chrome/content/zotero/xpcom/connector/connector.js b/chrome/content/zotero/xpcom/connector/connector.js index 9efb4dd9f..08542e431 100644 --- a/chrome/content/zotero/xpcom/connector/connector.js +++ b/chrome/content/zotero/xpcom/connector/connector.js @@ -22,8 +22,10 @@ ***** END LICENSE BLOCK ***** */ + Zotero.Connector = new function() { const CONNECTOR_URI = "http://127.0.0.1:23119/"; + const CONNECTOR_SERVER_API_VERSION = 1; this.isOnline = true; this.haveRefreshedData = false; @@ -36,6 +38,18 @@ Zotero.Connector = new function() { Zotero.Connector.getData(); } + /** + * Checks if Zotero is online and passes current status to callback + * @param {Function} callback + */ + this.checkIsOnline = function(callback) { + if(Zotero.Connector.isOnline) { + callback(true); + } else { + Zotero.Connector.getData(callback); + } + } + function _getDataFile() { var dataFile = Zotero.getZoteroDirectory(); dataFile.append("connector.json"); @@ -76,9 +90,10 @@ Zotero.Connector = new function() { this.EXCEPTION_NOT_AVAILABLE = 0; this.EXCEPTION_BAD_REQUEST = 400; this.EXCEPTION_NO_ENDPOINT = 404; + this.EXCEPTION_INCOMPATIBLE_VERSION = 412; this.EXCEPTION_CONNECTOR_INTERNAL = 500; this.EXCEPTION_METHOD_NOT_IMPLEMENTED = 501; - this.EXCEPTION_CODES = [0, 400, 404, 500, 501]; + this.EXCEPTION_CODES = [0, 400, 404, 412, 500, 501]; /** * Updates Zotero's status depending on the success or failure of a request @@ -120,9 +135,9 @@ Zotero.Connector = new function() { */ this.getData = function(callback) { Zotero.HTTP.doPost(CONNECTOR_URI+"connector/getData", - JSON.stringify({"browser":Zotero.browser}), + JSON.stringify({"browser":Zotero.browser, "apiVersion":CONNECTOR_SERVER_API_VERSION}), function(req) { - var isOnline = req.status !== 0; + var isOnline = req.status !== 0 && req.status !== 412; if(isOnline) { // if request succeded, update data @@ -172,7 +187,8 @@ Zotero.Connector = new function() { this.callMethod = function(method, data, callback) { Zotero.HTTP.doPost(CONNECTOR_URI+"connector/"+method, JSON.stringify(data), function(req) { - _checkState(req.status != 0, function() { + _checkState(req.status !== this.EXCEPTION_NOT_AVAILABLE + && req.status !== this.EXCEPTION_INCOMPATIBLE_VERSION, function() { if(!callback) return; if(Zotero.Connector.EXCEPTION_CODES.indexOf(req.status) !== -1) { diff --git a/chrome/content/zotero/xpcom/connector/connector_debug.js b/chrome/content/zotero/xpcom/connector/connector_debug.js new file mode 100644 index 000000000..6b35a98f4 --- /dev/null +++ b/chrome/content/zotero/xpcom/connector/connector_debug.js @@ -0,0 +1,86 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2009 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + http://zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + ***** END LICENSE BLOCK ***** +*/ + +Zotero.Connector_Debug = new function() { + /** + * Call a callback depending upon whether debug output is being stored + */ + this.storing = function(callback) { + callback(Zotero.Debug.storing); + } + + /** + * Call a callback with the lines themselves + */ + this.get = function(callback) { + callback(Zotero.Debug.get()); + } + + /** + * Call a callback with the number of lines of output + */ + this.count = function(callback) { + callback(Zotero.Debug.count()); + } + + /** + * Submit data to the sserver + */ + this.submitReport = function(callback) { + var uploadCallback = function (xmlhttp) { + var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + + if (!xmlhttp.responseXML) { + callback(false, 'Invalid response from server'); + return; + } + var reported = xmlhttp.responseXML.getElementsByTagName('reported'); + if (reported.length != 1) { + callback(false, 'The server returned an error. Please try again.'); + return; + } + + var reportID = reported[0].getAttribute('reportID'); + callback(true, reportID); + } + + Zotero.HTTP.doPost("http://www.zotero.org/repo/report?debug=1", output, + function(xmlhttp) { + if (!xmlhttp.responseXML) { + callback(false, 'Invalid response from server'); + return; + } + var reported = xmlhttp.responseXML.getElementsByTagName('reported'); + if (reported.length != 1) { + callback(false, 'The server returned an error. Please try again.'); + return; + } + + var reportID = reported[0].getAttribute('reportID'); + callback(true, reportID); + }, {"Content-Type":"application/octet-stream"}); + } +} \ No newline at end of file diff --git a/chrome/content/zotero/xpcom/server.js b/chrome/content/zotero/xpcom/server.js index c276c4016..98060f6f5 100755 --- a/chrome/content/zotero/xpcom/server.js +++ b/chrome/content/zotero/xpcom/server.js @@ -31,6 +31,7 @@ Zotero.Server = new function() { 300:"Multiple Choices", 400:"Bad Request", 404:"Not Found", + 412:"Precondition Failed", 500:"Internal Server Error", 501:"Method Not Implemented" }; diff --git a/chrome/content/zotero/xpcom/server_connector.js b/chrome/content/zotero/xpcom/server_connector.js index 5b878de2c..6ea90c526 100755 --- a/chrome/content/zotero/xpcom/server_connector.js +++ b/chrome/content/zotero/xpcom/server_connector.js @@ -23,6 +23,8 @@ ***** END LICENSE BLOCK ***** */ +const CONNECTOR_SERVER_API_VERSION = 1; + Zotero.Server.Connector = function() {}; Zotero.Server.Connector._waitingForSelection = {}; Zotero.Server.Connector.Data = {}; @@ -227,6 +229,10 @@ Zotero.Server.Connector.GetData.prototype = { * @param {Function} sendResponseCallback function to send HTTP response */ "init":function(data, sendResponseCallback) { + if(data.apiVersion !== CONNECTOR_SERVER_API_VERSION) { + sendResponseCallback(412); + } + // Translator data var responseData = {"preferences":{}, "translators":[]}; diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index 9171b8db7..d3b976dec 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -122,7 +122,7 @@ Zotero.Translate.Sandbox = { */ "getOption":function(translate, option) { if(typeof option !== "string") { - throw("Translate: getOption: option must be a string"); + throw(new Error("getOption: option must be a string")); return; } @@ -149,7 +149,7 @@ Zotero.Translate.Sandbox = { } if(typeof type !== "string") { - throw("Translate: loadTranslator: type must be a string"); + throw(new Error("loadTranslator: type must be a string")); return; } @@ -158,7 +158,7 @@ Zotero.Translate.Sandbox = { translation._parentTranslator = translate; if(translation instanceof Zotero.Translate.Export && !(translation instanceof Zotero.Translate.Export)) { - throw("Translate: only export translators may call other export translators"); + throw(new Error("Only export translators may call other export translators")); } /** @@ -207,7 +207,7 @@ Zotero.Translate.Sandbox = { safeTranslator.setTranslator = function(arg) { var success = translation.setTranslator(arg); if(!success) { - throw "Translator "+translate.translator[0].translatorID+" attempted to call invalid translatorID "+arg; + throw new Error("Translator "+translate.translator[0].translatorID+" attempted to call invalid translatorID "+arg); } }; safeTranslator.getTranslators = function() { return translation.getTranslators() }; @@ -226,7 +226,7 @@ Zotero.Translate.Sandbox = { if(callback) translate.incrementAsyncProcesses(); var haveTranslatorFunction = function(translator) { translation.translator[0] = translator; - if(!Zotero._loadTranslator(translator)) throw "Translator could not be loaded"; + if(!Zotero._loadTranslator(translator)) throw new Error("Translator could not be loaded"); if(Zotero.isFx) { // do same origin check @@ -243,8 +243,8 @@ Zotero.Translate.Sandbox = { try { secMan.checkSameOriginURI(outerSandboxURI, innerSandboxURI, false); } catch(e) { - throw "Translate: getTranslatorObject() may not be called from web or search "+ - "translators to web or search translators from different origins."; + throw new Error("getTranslatorObject() may not be called from web or search "+ + "translators to web or search translators from different origins."); } } @@ -262,8 +262,8 @@ Zotero.Translate.Sandbox = { return translation._sandboxManager.sandbox; } else { if(Zotero.isConnector && !callback) { - throw "Translate: Translator must accept a callback to getTranslatorObject() to "+ - "operate in this translation environment."; + throw new Error("Translator must accept a callback to getTranslatorObject() to "+ + "operate in this translation environment."); } Zotero.Translators.get(translation.translator[0], haveTranslatorFunction); @@ -319,7 +319,7 @@ Zotero.Translate.Sandbox = { */ "selectItems":function(translate, items, callback) { if(Zotero.Utilities.isEmpty(items)) { - throw "Translate: translator called select items with no items"; + throw new Error("Translator called select items with no items"); } if(translate._selectedItems) { @@ -423,7 +423,7 @@ Zotero.Translate.Sandbox = { } if(!item.title) { - throw "No title specified for item"; + throw new Error("No title specified for item"); } // create short title @@ -520,7 +520,7 @@ Zotero.Translate.Sandbox = { */ "nextCollection":function(translate) { if(!translate.translator[0].configOptions.getCollections) { - throw("Translate: getCollections configure option not set; cannot retrieve collection"); + throw(new Error("getCollections configure option not set; cannot retrieve collection")); } return translate._itemGetter.nextCollection(); @@ -594,7 +594,7 @@ Zotero.Translate.Base.prototype = { */ "setTranslator":function(translator) { if(!translator) { - throw new Error("Zotero.Translate: no translator specified"); + throw new Error("No translator specified"); } this.translator = null; @@ -604,7 +604,7 @@ Zotero.Translate.Base.prototype = { if(translator.translatorID) { this.translator = [translator]; } else { - throw("No translatorID specified"); + throw(new Error("No translatorID specified")); } } else { this.translator = [translator]; @@ -748,7 +748,7 @@ Zotero.Translate.Base.prototype = { */ "getTranslators":function(getAllTranslators) { // do not allow simultaneous instances of getTranslators - if(this._currentState == "detect") throw "Translate: getTranslators: detection is already running"; + if(this._currentState == "detect") throw new Error("getTranslators: detection is already running"); this._currentState = "detect"; this._getAllTranslators = getAllTranslators; this._getTranslatorsGetPotentialTranslators(); @@ -832,7 +832,7 @@ Zotero.Translate.Base.prototype = { this._currentState = "translate"; if(!this.translator || !this.translator.length) { - throw("Translate: Failed: no translator specified"); + throw new Error("Failed: no translator specified"); } this._libraryID = libraryID; @@ -1300,6 +1300,7 @@ Zotero.Translate.Web.prototype._translateRPCComplete = function(obj, failureCode for(var i in obj.items) { this._runHandler("itemDone", null, obj.items[i]); } + this.newItems = obj.items; this.complete(true); } } @@ -1551,7 +1552,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = function() { var io = this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this.translator[0].configOptions["dataMode"]); this.__defineGetter__("string", function() { return io.string; }); } else if(!Zotero.Translate.IO.Write) { - throw "Translate: Writing to files is not supported in this build of Zotero."; + throw new Error("Writing to files is not supported in this build of Zotero."); } else { this._io = new Zotero.Translate.IO.Write(this.location, this.translator[0].configOptions["dataMode"], @@ -1687,7 +1688,7 @@ Zotero.Translate.IO = { var dp = Components.classes["@mozilla.org/xmlextras/domparser;1"] .createInstance(Components.interfaces.nsIDOMParser); } catch(e) { - throw "DOMParser not supported"; + throw new Error("DOMParser not supported"); } } @@ -1698,7 +1699,7 @@ Zotero.Translate.IO = { } if(nodes.getElementsByTagName("parsererror").length) { - throw("DOMParser error: loading data into data store failed"); + throw new Error("DOMParser error: loading data into data store failed"); } return nodes; @@ -1945,7 +1946,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = { type = type.toLowerCase(); if(!containerTypes[type]) { - throw "Invalid container type in Zotero.RDF.newContainer"; + throw new Error("Invalid container type in Zotero.RDF.newContainer"); } var about = this._getResource(about); @@ -2016,7 +2017,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = { "getResourceURI":function(resource) { if(typeof(resource) == "string") return resource; if(resource.uri) return resource.uri; - if(resource.toNT == undefined) throw "Zotero.RDF: getResourceURI called on invalid resource"; + if(resource.toNT == undefined) throw new Error("Zotero.RDF: getResourceURI called on invalid resource"); return resource.toNT(); },