From 0998b15facfb38e23e8ac536d2b9532c56c9b1a5 Mon Sep 17 00:00:00 2001 From: Aurimas Vinckevicius Date: Mon, 28 Jul 2014 15:39:07 -0500 Subject: [PATCH] Improved cookie handling when translating from connectors * Accept detailed cookie information (including host, path, secureOnly, and hostOnly) from connectors so we can send correct cookies when fetching pages from different hosts. This way we also don't have to worry about exposing cookies to different hosts. * Don't drop cookies that we receive from other hosts. Some pages (e.g. PDF URLs) result in redirects to other hosts (and even domains) that then set cookies, which are required to retrieve the PDF. (e.g. Cell Press stores PDFs on ScienceDirect, but their PDF links initially point to cell.com). * Send detailed cookies where possible. Currently that's only for Chrome/Opera and Firefox in Connector mode. Does not seem to be possible in Safari. --- .../zotero/xpcom/connector/connector.js | 53 ++++- .../zotero/xpcom/connector/translate_item.js | 3 +- chrome/content/zotero/xpcom/cookieSandbox.js | 218 +++++++++++++++--- .../content/zotero/xpcom/server_connector.js | 6 +- 4 files changed, 250 insertions(+), 30 deletions(-) diff --git a/chrome/content/zotero/xpcom/connector/connector.js b/chrome/content/zotero/xpcom/connector/connector.js index 4b0cf8de86..31a85857cc 100644 --- a/chrome/content/zotero/xpcom/connector/connector.js +++ b/chrome/content/zotero/xpcom/connector/connector.js @@ -136,7 +136,7 @@ Zotero.Connector = new function() { * @param {Object} data RPC data. See documentation above. * @param {Function} callback Function to be called when requests complete. */ - this.callMethod = function(method, data, callback) { + this.callMethod = function(method, data, callback, tab) { // Don't bother trying if not online in bookmarklet if(Zotero.isBookmarklet && this.isOnline === false) { callback(false, 0); @@ -204,6 +204,57 @@ Zotero.Connector = new function() { "X-Zotero-Connector-API-Version":CONNECTOR_API_VERSION }); } + }, + + /** + * Adds detailed cookies to the data before sending "saveItems" request to + * the server/Standalone + * + * @param {Object} data RPC data. See documentation above. + * @param {Function} callback Function to be called when requests complete. + */ + this.setCookiesThenSaveItems = function(data, callback, tab) { + if(Zotero.isFx && !Zotero.isBookmarklet && data.uri) { + var host = Services.ios.newURI(data.uri, null, null).host; + var cookieEnum = Services.cookies.getCookiesFromHost(host); + var cookieHeader = ''; + while(cookieEnum.hasMoreElements()) { + var cookie = cookieEnum.getNext().QueryInterface(Components.interfaces.nsICookie2); + cookieHeader += '\n' + cookie.name + '=' + cookie.value + + ';Domain=' + cookie.host + + (cookie.path ? ';Path=' + cookie.path : '') + + (!cookie.isDomain ? ';hostOnly' : '') //not a legit flag, but we have to use it internally + + (cookie.isSecure ? ';secure' : ''); + } + + if(cookieHeader) { + data.detailedCookies = cookieHeader.substr(1); + } + + this.callMethod("saveItems", data, callback, tab); + return; + } else if(Zotero.isChrome && !Zotero.isBookmarklet) { + var self = this; + chrome.cookies.getAll({url: tab.url}, function(cookies) { + var cookieHeader = ''; + for(var i=0, n=cookies.length; i=0; i--) { + cookieHost = '.' + hostParts[i] + cookieHost; + if(this._cookies[cookieHost]) { + found = this._getCookiesForPath(cookies, this._cookies[cookieHost], pathParts, secure, i==0) || found; + } + } + + //Zotero.debug("CookieSandbox: returning cookies:"); + //Zotero.debug(cookies); + + return found ? cookies : null; + }, + + "_getCookiesForPath": function(cookies, cookiePaths, pathParts, secure, isHost) { + var found = false; + var path = ''; + for(var i=0, n=pathParts.length; i