diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js index 0b0796cc2..a7ab63212 100644 --- a/chrome/content/zotero/xpcom/attachments.js +++ b/chrome/content/zotero/xpcom/attachments.js @@ -200,7 +200,7 @@ Zotero.Attachments = new function(){ function importFromURL(url, sourceItemID, forceTitle, forceFileBaseName, parentCollectionIDs, - mimeType, libraryID, callback) { + mimeType, libraryID, callback, cookieSandbox) { Zotero.debug('Importing attachment from URL'); if (sourceItemID && parentCollectionIDs) { @@ -222,6 +222,7 @@ Zotero.Attachments = new function(){ // Save using a hidden browser var nativeHandlerImport = function () { var browser = Zotero.Browser.createHiddenBrowser(); + if(cookieSandbox) cookieSandbox.attachToBrowser(browser); var imported = false; var onpageshow = function() { // ignore spurious about:blank loads @@ -263,6 +264,7 @@ Zotero.Attachments = new function(){ .classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] .createInstance(nsIWBP); wbp.persistFlags = nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(wbp); var encodingFlags = false; Zotero.DB.beginTransaction(); @@ -396,7 +398,7 @@ Zotero.Attachments = new function(){ else { Zotero.MIME.getMIMETypeFromURL(url, function (mimeType, hasNativeHandler) { process(mimeType, hasNativeHandler); - }); + }, cookieSandbox); } } diff --git a/chrome/content/zotero/xpcom/connector/translate_item.js b/chrome/content/zotero/xpcom/connector/translate_item.js index febac63e2..e24c65caa 100644 --- a/chrome/content/zotero/xpcom/connector/translate_item.js +++ b/chrome/content/zotero/xpcom/connector/translate_item.js @@ -1,7 +1,7 @@ /* ***** BEGIN LICENSE BLOCK ***** - Copyright © 2009 Center for History and New Media + Copyright © 2012 Center for History and New Media George Mason University, Fairfax, Virginia, USA http://zotero.org @@ -23,10 +23,15 @@ ***** END LICENSE BLOCK ***** */ -Zotero.Translate.ItemSaver = function(libraryID, attachmentMode, forceTagType) { +Zotero.Translate.ItemSaver = function(libraryID, attachmentMode, forceTagType, document, + cookieSandbox) { this.newItems = []; - this._timeoutID = null; + + if(document) { + this._uri = document.location.toString(); + this._cookie = document.cookie; + } } Zotero.Translate.ItemSaver.ATTACHMENT_MODE_IGNORE = 0; @@ -40,7 +45,13 @@ Zotero.Translate.ItemSaver.prototype = { "saveItems":function(items, callback) { var me = this; // first try to save items via connector - Zotero.Connector.callMethod("saveItems", {"items":items}, function(success, status) { + var payload = {"items":items}; + if(this._uri && this._cookie) { + payload.uri = this._uri; + payload.cookie = this._cookie; + } + + Zotero.Connector.callMethod("saveItems", payload, function(success, status) { if(success !== false) { Zotero.debug("Translate: Save via Standalone succeeded"); callback(true, items); diff --git a/chrome/content/zotero/xpcom/cookieSandbox.js b/chrome/content/zotero/xpcom/cookieSandbox.js index 6682ff93c..2f68f1853 100755 --- a/chrome/content/zotero/xpcom/cookieSandbox.js +++ b/chrome/content/zotero/xpcom/cookieSandbox.js @@ -27,16 +27,12 @@ * Manage cookies in a sandboxed fashion * * @constructor - * @param {browser} browser Hidden browser object + * @param {browser} [browser] Hidden browser object * @param {String|nsIURI} uri URI of page to manage cookies for (cookies for domains that are not * subdomains of this URI are ignored) * @param {String} cookieData Cookies with which to initiate the sandbox */ Zotero.CookieSandbox = function(browser, uri, cookieData) { - this._webNav = browser.webNavigation; - this._browser = browser; - this._watchedBrowsers = [browser]; - this._watchedXHRs = []; this._observerService = Components.classes["@mozilla.org/observer-service;1"]. getService(Components.interfaces.nsIObserverService); @@ -58,30 +54,13 @@ Zotero.CookieSandbox = function(browser, uri, cookieData) { } } - // register with observer - Zotero.CookieSandbox.Observer.register(this); + if(browser) { + this.attachToBrowser(browser); + } + Zotero.CookieSandbox.Observer.register(); } Zotero.CookieSandbox.prototype = { - /** - * Check whether we track a browser for this document - */ - "isDocumentTracked":function(doc) { - var i = this._watchedBrowsers.length; - while(i--) { - var browser = this._watchedBrowsers[i]; - if(doc == browser.contentDocument) return true; - } - return false; - }, - - /** - * Check whether we track an XHR for this document - */ - "isXHRTracked":function(xhr) { - return this._watchedXHRs.indexOf(xhr) !== -1; - }, - /** * Adds cookies to this CookieSandbox based on a cookie header * @param {String} cookieString; @@ -108,27 +87,19 @@ Zotero.CookieSandbox.prototype = { }, /** - * Attach CookieSandbox to a specific XMLHttpRequest - * @param {XMLHttpRequest} xhr + * Attach CookieSandbox to a specific browser + * @param {Browser} browser */ "attachToBrowser":function(browser) { - this._watchedBrowsers.push(browser); + Zotero.CookieSandbox.Observer.trackedBrowsers.set(browser, this); }, /** * Attach CookieSandbox to a specific XMLHttpRequest - * @param {XMLHttpRequest} xhr + * @param {nsIInterfaceRequestor} ir */ - "attachToXHR": function(xhr) { - this._watchedXHRs.push(xhr); - }, - - /** - * Destroys this CookieSandbox (intended to be executed when the browser is destroyed) - */ - "destroy": function() { - // unregister with observer - Zotero.CookieSandbox.Observer.unregister(this); + "attachToInterfaceRequestor": function(ir) { + Zotero.CookieSandbox.Observer.trackedInterfaceRequestors.set(ir.QueryInterface(Components.interfaces.nsIInterfaceRequestor), this); } } @@ -144,36 +115,21 @@ Zotero.CookieSandbox.Observer = new function() { var observerService = Components.classes["@mozilla.org/observer-service;1"]. getService(Components.interfaces.nsIObserverService), - observing = false, - cookieSandboxes = []; + observing = false; + + this.trackedBrowsers = new WeakMap(); + this.trackedInterfaceRequestors = new WeakMap(); /** * Registers cookie manager and observer, if necessary */ this.register = function(CookieSandbox) { - cookieSandboxes.push(CookieSandbox); - if(!observing) { Zotero.debug("CookieSandbox: Registering observers"); for each(var topic in observeredTopics) observerService.addObserver(this, topic, false); observing = true; } - } - - /** - * Unregisters cookie manager and observer - */ - this.unregister = function(CookieSandbox) { - // remove cookie manager from list - cookieSandboxes.splice(cookieSandboxes.indexOf(CookieSandbox), 1); - - // remove observer if this is the last and this is not translation-server - if(cookieSandboxes.length === 0 && !Zotero.isServer) { - Zotero.debug("CookieSandbox: Unregistering observers"); - for each(var topic in observeredTopics) observerService.removeObserver(this, topic); - observing = false; - } - } + }; /** * Implements nsIObserver to watch for new cookies and to add sandboxed cookies @@ -185,50 +141,48 @@ Zotero.CookieSandbox.Observer = new function() { } channel.QueryInterface(Components.interfaces.nsIHttpChannel); - var trackedBy, tested, doc, xhr, + var trackedBy, tested, browser, callbacks, channelURI = channel.URI.spec, notificationCallbacks = channel.notificationCallbacks; - // try the document - try { - doc = notificationCallbacks.getInterface(Components.interfaces.nsIDOMWindow).top.document; - } catch(e) {} - if(doc) { + // try the notification callbacks + trackedBy = this.trackedInterfaceRequestors.get(notificationCallbacks); + if(trackedBy) { tested = true; - for(var i=0, n=cookieSandboxes.length; i<n; i++) { - if(cookieSandboxes[i].isDocumentTracked(doc)) { - trackedBy = cookieSandboxes[i]; - } - } } else { - // try the document for the load group + // try the browser try { - doc = channel.loadGroup.notificationCallbacks.getInterface(Components.interfaces.nsIDOMWindow).top.document; + browser = notificationCallbacks.getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell).chromeEventHandler; } catch(e) {} - if(doc) { + if(browser) { tested = true; - for(var i=0, n=cookieSandboxes.length; i<n; i++) { - if(cookieSandboxes[i].isDocumentTracked(doc)) { - trackedBy = cookieSandboxes[i]; - } - } + trackedBy = this.trackedBrowsers.get(browser); } else { - // try getting as an XHR + // try the document for the load group try { - xhr = notificationCallbacks.QueryInterface(Components.interfaces.nsIXMLHttpRequest); + browser = channel.loadGroup.notificationCallbacks.getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell).chromeEventHandler; } catch(e) {} - if(xhr) { + if(browser) { tested = true; - for(var i=0, n=cookieSandboxes.length; i<n; i++) { - if(cookieSandboxes[i].isXHRTracked(xhr)) { - trackedBy = cookieSandboxes[i]; - } + trackedBy = this.trackedBrowsers.get(browser); + } else { + // try getting as an XHR or nsIWBP + try { + notificationCallbacks.QueryInterface(Components.interfaces.nsIXMLHttpRequest); + tested = true; + } catch(e) {} + if(!tested) { + try { + notificationCallbacks.QueryInterface(Components.interfaces.nsIWebBrowserPersist); + tested = true; + } catch(e) {} } } } } - // isTracked is now either true, false, or null // trackedBy => we should manage cookies for this request // tested && !trackedBy => we should not manage cookies for this request // !tested && !trackedBy => this request is of a type we couldn't match to this request. @@ -256,7 +210,6 @@ Zotero.CookieSandbox.Observer = new function() { } // add cookies to be sent to this domain - Zotero.debug(trackedBy.cookieString); channel.setRequestHeader("Cookie", trackedBy.cookieString, false); Zotero.debug("CookieSandbox: Added cookies for request to "+channelURI, 5); } else if(topic == "http-on-examine-response") { @@ -276,7 +229,6 @@ Zotero.CookieSandbox.Observer = new function() { } // put new cookies into our sandbox - Zotero.debug(cookieHeader); if(cookieHeader) trackedBy.addCookiesFromHeader(cookieHeader); Zotero.debug("CookieSandbox: Slurped cookies from "+channelURI, 5); diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index 42ff2d2b5..c1ae6612d 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -52,7 +52,7 @@ Zotero.HTTP = new function() { _stateChange(xmlhttp, onDone, responseCharset); }; - if(cookieSandbox) cookieSandbox.attachToXHR(xmlhttp); + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp); xmlhttp.send(null); return xmlhttp; @@ -131,7 +131,7 @@ Zotero.HTTP = new function() { _stateChange(xmlhttp, onDone, responseCharset); }; - if(cookieSandbox) cookieSandbox.attachToXHR(xmlhttp); + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp); xmlhttp.send(body); return xmlhttp; @@ -143,9 +143,10 @@ Zotero.HTTP = new function() { * @param {String} url URL to request * @param {Function} onDone Callback to be executed upon request completion * @param {Object} requestHeaders HTTP headers to include with request + * @param {Zotero.CookieSandbox} [cookieSandbox] Cookie sandbox object * @return {Boolean} True if the request was sent, or false if the browser is offline */ - this.doHead = function(url, onDone, requestHeaders) { + this.doHead = function(url, onDone, requestHeaders, cookieSandbox) { if (url instanceof Components.interfaces.nsIURI) { // Don't display password in console var disp = url.clone(); @@ -190,6 +191,7 @@ Zotero.HTTP = new function() { _stateChange(xmlhttp, onDone); }; + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp); xmlhttp.send(null); return xmlhttp; diff --git a/chrome/content/zotero/xpcom/mime.js b/chrome/content/zotero/xpcom/mime.js index f499c377b..87866fe09 100644 --- a/chrome/content/zotero/xpcom/mime.js +++ b/chrome/content/zotero/xpcom/mime.js @@ -280,7 +280,7 @@ Zotero.MIME = new function(){ } - this.getMIMETypeFromURL = function (url, callback) { + this.getMIMETypeFromURL = function (url, callback, cookieSandbox) { Zotero.HTTP.doHead(url, function(xmlhttp) { if (xmlhttp.status != 200 && xmlhttp.status != 204) { Zotero.debug("Attachment HEAD request returned with status code " @@ -308,7 +308,7 @@ Zotero.MIME = new function(){ var hasNativeHandler = Zotero.MIME.hasNativeHandler(mimeType, ext) callback(mimeType, hasNativeHandler); - }); + }, undefined, cookieSandbox); } diff --git a/chrome/content/zotero/xpcom/server_connector.js b/chrome/content/zotero/xpcom/server_connector.js index 7caa1b617..d259249d0 100755 --- a/chrome/content/zotero/xpcom/server_connector.js +++ b/chrome/content/zotero/xpcom/server_connector.js @@ -156,7 +156,6 @@ Zotero.Server.Connector.Detect.prototype = { } this.sendResponse(200, "application/json", JSON.stringify(jsons)); - this._translate.cookieSandbox.destroy(); Zotero.Browser.deleteHiddenBrowser(this._browser); } } @@ -225,7 +224,6 @@ Zotero.Server.Connector.SavePage.prototype = { "_translatorsAvailable":function(translate, translators) { // make sure translatorsAvailable succeded if(!translators.length) { - me._translate.cookieSandbox.destroy(); Zotero.Browser.deleteHiddenBrowser(this._browser); this.sendResponse(500); return; @@ -251,7 +249,6 @@ Zotero.Server.Connector.SavePage.prototype = { jsonItems.push(jsonItem); }); translate.setHandler("done", function(obj, item) { - me._translate.cookieSandbox.destroy(); Zotero.Browser.deleteHiddenBrowser(me._browser); if(jsonItems.length || me.selectedItems === false) { me.sendResponse(201, "application/json", JSON.stringify({"items":jsonItems})); @@ -296,9 +293,12 @@ Zotero.Server.Connector.SaveItem.prototype = { var collection = zp.getSelectedCollection(); } catch(e) {} + var cookieSandbox = data["uri"] && data["cookie"] ? new Zotero.CookieSandbox(null, data["uri"], + data["cookie"]) : null; + // save items var itemSaver = new Zotero.Translate.ItemSaver(libraryID, - Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD, 1); + Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD, 1, undefined, cookieSandbox); itemSaver.saveItems(data.items, function(returnValue, data) { if(returnValue) { try { @@ -390,8 +390,6 @@ Zotero.Server.Connector.SaveSnapshot.prototype = { // remove browser Zotero.Browser.deleteHiddenBrowser(browser); - // destroy cookieSandbox - cookieSandbox.destroy(); sendResponseCallback(201); } catch(e) { sendResponseCallback(500); diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index 8e2ee7993..8716d4f48 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -1433,7 +1433,8 @@ Zotero.Translate.Web.prototype._getParameters = function() { return [this.docume */ Zotero.Translate.Web.prototype._prepareTranslation = function() { this._itemSaver = new Zotero.Translate.ItemSaver(this._libraryID, - Zotero.Translate.ItemSaver[(this._saveAttachments ? "ATTACHMENT_MODE_DOWNLOAD" : "ATTACHMENT_MODE_IGNORE")], 1); + Zotero.Translate.ItemSaver[(this._saveAttachments ? "ATTACHMENT_MODE_DOWNLOAD" : "ATTACHMENT_MODE_IGNORE")], 1, + this.document, this._cookieSandbox); this.newItems = []; } @@ -1548,7 +1549,7 @@ Zotero.Translate.Import.prototype.setString = function(string) { Zotero.Translate.Import.prototype.complete = function(returnValue, error) { if(this._io) { this._progress = null; - this._io.close(); + this._io.close(false); } // call super @@ -1728,7 +1729,7 @@ Zotero.Translate.Export.prototype.setDisplayOptions = function(displayOptions) { Zotero.Translate.Export.prototype.complete = function(returnValue, error) { if(this._io) { this._progress = null; - this._io.close(); + this._io.close(true); if(this._io instanceof Zotero.Translate.IO.String) { this.string = this._io.string; } @@ -2064,7 +2065,13 @@ Zotero.Translate.IO.String.prototype = { } }, - "close":function() {} + "close":function(serialize) { + // if we are writing in RDF data mode and no string is set, serialize current RDF to the + // string + if(serialize && Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1 && this.string === "") { + this.string = this.RDF.serialize(); + } + } } /****** RDF DATA MODE ******/ diff --git a/chrome/content/zotero/xpcom/translation/translate_item.js b/chrome/content/zotero/xpcom/translation/translate_item.js index 2def6c55d..daf0b5a12 100644 --- a/chrome/content/zotero/xpcom/translation/translate_item.js +++ b/chrome/content/zotero/xpcom/translation/translate_item.js @@ -1,7 +1,7 @@ /* ***** BEGIN LICENSE BLOCK ***** - Copyright © 2009 Center for History and New Media + Copyright © 2012 Center for History and New Media George Mason University, Fairfax, Virginia, USA http://zotero.org @@ -23,7 +23,8 @@ ***** END LICENSE BLOCK ***** */ -Zotero.Translate.ItemSaver = function(libraryID, attachmentMode, forceTagType) { +Zotero.Translate.ItemSaver = function(libraryID, attachmentMode, forceTagType, document, + cookieSandbox) { // initialize constants this.newItems = []; this.newCollections = []; @@ -65,6 +66,7 @@ Zotero.Translate.ItemSaver = function(libraryID, attachmentMode, forceTagType) { // force tag types if requested this._forceTagType = forceTagType; + this._cookieSandbox = cookieSandbox; }; Zotero.Translate.ItemSaver.ATTACHMENT_MODE_IGNORE = 0; @@ -346,7 +348,9 @@ Zotero.Translate.ItemSaver.prototype = { var fileBaseName = Zotero.Attachments.getFileBaseNameFromItem(parentID); try { - Zotero.Attachments.importFromURL(attachment.url, parentID, title, fileBaseName); + Zotero.debug('Importing attachment from URL'); + Zotero.Attachments.importFromURL(attachment.url, parentID, title, + fileBaseName, null, mimeType, this._libraryID, null, this._cookieSandbox); } catch(e) { Zotero.debug("Translate: Error adding attachment "+attachment.url, 2); } diff --git a/resource/schema/repotime.txt b/resource/schema/repotime.txt index e54aade7f..1a2ff2586 100644 --- a/resource/schema/repotime.txt +++ b/resource/schema/repotime.txt @@ -1 +1 @@ -2012-01-31 04:00:00 +2012-02-10 23:24:58 diff --git a/translators b/translators index 3daf3bdf2..94bcbbcdc 160000 --- a/translators +++ b/translators @@ -1 +1 @@ -Subproject commit 3daf3bdf2ce13d7e1a329f5648f18937d8251dee +Subproject commit 94bcbbcdc6c4db94391db64dd4b7270e12401e13