diff --git a/chrome/content/zotero/preferences/preferences.js b/chrome/content/zotero/preferences/preferences.js index d1a085e6db..a2003390b8 100644 --- a/chrome/content/zotero/preferences/preferences.js +++ b/chrome/content/zotero/preferences/preferences.js @@ -1127,6 +1127,16 @@ function refreshProxyList() { */ function updateProxyPrefs() { Zotero.Prefs.set("proxies.autoRecognize", document.getElementById('zotero-proxies-autoRecognize').checked); - Zotero.Prefs.set("proxies.transparent", document.getElementById('zotero-proxies-transparent').checked); + + var oldTransparent = Zotero.Prefs.get("proxies.transparent"); + var newTransparent = document.getElementById('zotero-proxies-transparent').checked; + if(!oldTransparent && newTransparent) { + Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService).alert(window, + Zotero.getString("proxies.enableTransparentWarning.title"), + Zotero.getString("proxies.enableTransparentWarning.description")); + } + Zotero.Prefs.set("proxies.transparent", newTransparent); + Zotero.Proxies.init() } \ No newline at end of file diff --git a/chrome/content/zotero/xpcom/proxy.js b/chrome/content/zotero/xpcom/proxy.js index a7ba4c1155..9abd62973a 100644 --- a/chrome/content/zotero/xpcom/proxy.js +++ b/chrome/content/zotero/xpcom/proxy.js @@ -26,6 +26,7 @@ /** * A singleton to handle URL rewriting proxies + * @namespace */ Zotero.Proxies = new function() { var on = false; @@ -38,6 +39,9 @@ Zotero.Proxies = new function() { var lastRecognizedURI = false; var lastButton = false; + /** + * Initializes http-on-examine-response observer to intercept page loads and gets preferences + */ this.init = function() { if(!on) { var observerService = Components.classes["@mozilla.org/observer-service;1"] @@ -52,7 +56,11 @@ Zotero.Proxies = new function() { } /** - * Observe method to capture page loads + * Observe method to capture page loads and determine if they're going through an EZProxy. + * At the moment, also clears Content-Disposition header on requests for EndNote files so we + * can capture them instead of letting them get saved as attachments + * + * @param {nsIChannel} channel */ this.observe = function(channel) { channel.QueryInterface(Components.interfaces.nsIHttpChannel); @@ -106,28 +114,21 @@ Zotero.Proxies = new function() { Components.utils.reportError(e); } - if(proxy) { - var checkState = {value:false}; - var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService); + if(!transparent) { + // if transparent is turned off, just save the proxy + proxy.save(); + } else if(proxy) { + // otherwise, make sure we want it + var io = {site:proxy.hosts[0], proxy:channel.URI.hostPort}; var window = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator) .getMostRecentWindow("navigator:browser"); + window.openDialog('chrome://zotero/content/proxy.xul', '', 'chrome,modal', io); - if(!lastRecognizedURI || !channel.originalURI || !channel.originalURI.equals(lastRecognizedURI)) { - lastButton = ps.confirmEx(window, - Zotero.getString("proxies.recognized"), - Zotero.getString("proxies.recognized.message"), - ((proxies.length ? 0 : ps.BUTTON_DELAY_ENABLE) + ps.BUTTON_POS_0 * ps.BUTTON_TITLE_OK + - ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL + ps.BUTTON_POS_1_DEFAULT), - null, null, null, Zotero.getString("proxies.recognized.disable"), checkState); - lastRecognizedURI = channel.originalURI ? channel.originalURI : channel.URI; - } - - if(lastButton == 0) proxy.save(); - if(checkState.value) { - autoRecognize = false; - Zotero.Prefs.set("proxies.autoRecognize", false); + if(io.add) proxy.save(); + if(io.disable) { + transparent = false; + Zotero.Prefs.set("proxies.transparent", false); } break; @@ -154,6 +155,7 @@ Zotero.Proxies = new function() { /** * Gets all proxy objects + * @type Zotero.Proxy[] */ this.get = function() { if(!proxies) { @@ -166,6 +168,7 @@ Zotero.Proxies = new function() { /** * Removes a proxy object from the list of proxy objects + * @returns {Boolean} True if the proxy was in the list, false if it was not */ this.remove = function(proxy) { var index = proxies.indexOf(proxy); @@ -176,7 +179,7 @@ Zotero.Proxies = new function() { } /** - * Saves a proxy object not previously in the proxy list + * Inserts a proxy into the host map; necessary when proxies are added */ this.save = function(proxy) { proxies.push(proxy); @@ -185,11 +188,10 @@ Zotero.Proxies = new function() { hosts[host] = proxy; } } - return proxy; } /** - * Refreshes host map; necessary when proxies are added, changed, or deleted + * Refreshes host map; necessary when proxies are changed or deleted */ this.refreshHostMap = function() { hosts = {}; @@ -203,7 +205,12 @@ Zotero.Proxies = new function() { } /** - * Returns a page's proper url, adjusting for proxying + * Returns a page's proper URL from a proxied URL + * @param {String} url + * @param {Boolean} onlyReturnIfProxied Controls behavior if the given URL is not proxied. If + * it is false or unspecified, unproxied URLs are returned verbatim. If it is true, the + * function will return "false" if the given URL is unproxied. + * @type String */ this.proxyToProper = function(url, onlyReturnIfProxied) { for each(var proxy in proxies) { @@ -220,7 +227,12 @@ Zotero.Proxies = new function() { } /** - * Returns a page's proxied url from the proper url + * Returns a page's proxied URL from the proper URL + * @param {String} url + * @param {Boolean} onlyReturnIfProxied Controls behavior if the given URL is not proxied. If + * it is false or unspecified, unproxied URLs are returned verbatim. If it is true, the + * function will return "false" if the given URL is unproxied. + * @type String */ this.properToProxy = function(url, onlyReturnIfProxied) { var uri = ioService.newURI(url, null, null); @@ -234,9 +246,10 @@ Zotero.Proxies = new function() { } /** - * A class to handle individual proxy servers - * + * Creates a Zotero.Proxy object from a DB row + * * @constructor + * @class Represents an individual proxy server */ Zotero.Proxy = function(row) { if(row) { @@ -247,21 +260,32 @@ Zotero.Proxy = function(row) { } } +/** + * Regexps to match the URL contents corresponding to proxy scheme parameters + * @const + */ const Zotero_Proxy_schemeParameters = { "%p":"(.*?)", // path "%d":"(.*?)", // directory "%f":"(.*?)", // filename "%a":"(.*?)" // filename }; + +/** + * Regexps to match proxy scheme parameters in the proxy scheme URL + * @const + */ const Zotero_Proxy_schemeParameterRegexps = { "%p":/([^%])%p/, "%d":/([^%])%d/, "%f":/([^%])%f/, "%h":/([^%])%h/, "%a":/([^%])%a/ -} +}; + /** - * Compiles the regular expression against which we match URLs for this proxy + * Compiles the regular expression against which we match URLs to determine if this proxy is in use + * and saves it in this.regexp */ Zotero.Proxy.prototype.compileRegexp = function() { const metaRe = /[-[\]{}()*+?.\\^$|,#\s]/g; @@ -304,6 +328,9 @@ Zotero.Proxy.prototype.compileRegexp = function() { /** * Ensures that the proxy scheme and host settings are valid for this proxy type + * + * @returns {String|Boolean} An error type if a validation error occurred, or "false" if there was + * no error. */ Zotero.Proxy.prototype.validate = function() { if(this.scheme.length < 8 || (this.scheme.substr(0, 7) != "http://" && this.scheme.substr(0, 8) != "https://")) { @@ -399,6 +426,7 @@ Zotero.Proxy.prototype.erase = function() { * Converts a proxied URL to an unproxied URL using this proxy * * @param m {Array} The match from running this proxy's regexp against a URL spec + * @type String */ Zotero.Proxy.prototype.toProper = function(m) { if(this.multiHost) { @@ -423,6 +451,7 @@ Zotero.Proxy.prototype.toProper = function(m) { * Converts an unproxied URL to a proxied URL using this proxy * * @param {nsIURI} uri The nsIURI corresponding to the unproxied URL + * @type String */ Zotero.Proxy.prototype.toProxy = function(uri) { proxyURL = this.scheme; @@ -448,6 +477,7 @@ Zotero.Proxy.prototype.toProxy = function(uri) { /** * Loads a proxy object from a DB row + * @private */ Zotero.Proxy.prototype._loadFromRow = function(row) { this.proxyID = row.proxyID; @@ -458,10 +488,16 @@ Zotero.Proxy.prototype._loadFromRow = function(row) { this.compileRegexp(); } +/** + * Detectors for various proxy systems + * @namespace + */ Zotero.Proxies.Detectors = new Object(); /** * Detector for OCLC EZProxy + * @param {nsIChannel} channel + * @type Boolean|Zotero.Proxy */ Zotero.Proxies.Detectors.EZProxy = function(channel) { const ezProxyRe = /\?(?:.+&)?(url|qurl)=([^&]+)/i; @@ -556,7 +592,8 @@ Zotero.Proxies.Detectors.EZProxy.obs = Components.classes["@mozilla.org/observer .getService(Components.interfaces.nsIObserverService); /** - * Do-nothing stream listener + * @class Do-nothing stream listener + * @private */ Zotero.Proxies.Detectors.EZProxy.DummyStreamListener = function() {} Zotero.Proxies.Detectors.EZProxy.DummyStreamListener.prototype.onDataAvailable = function(request, @@ -565,7 +602,8 @@ Zotero.Proxies.Detectors.EZProxy.DummyStreamListener.prototype.onStartRequest = Zotero.Proxies.Detectors.EZProxy.DummyStreamListener.prototype.onStopRequest = function(request, context, status) {} /** - * Observer to clear cookies on an HTTP request, then remove itself + * @class Observer to clear cookies on an HTTP request, then remove itself + * @private */ Zotero.Proxies.Detectors.EZProxy.Observer = function(newChannel) { this.channel = newChannel; @@ -584,6 +622,8 @@ Zotero.Proxies.Detectors.EZProxy.Observer.prototype.QueryInterface = function(aI /** * Detector for Juniper Networks WebVPN + * @param {nsIChannel} channel + * @type Boolean|Zotero.Proxy */ Zotero.Proxies.Detectors.Juniper = function(channel) { const juniperRe = /^(https?:\/\/[^\/:]+(?:\:[0-9]+)?)\/(.*),DanaInfo=([^+,]*)([^+]*)(?:\+(.*))?$/; diff --git a/chrome/locale/en-US/zotero/zotero.dtd b/chrome/locale/en-US/zotero/zotero.dtd index 0fe423dc1d..c5cd815b04 100644 --- a/chrome/locale/en-US/zotero/zotero.dtd +++ b/chrome/locale/en-US/zotero/zotero.dtd @@ -154,4 +154,10 @@ - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index 79353ebe0e..054d15954c 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -505,6 +505,7 @@ proxies.error.scheme.noHTTP = Valid proxy schemes must start with "http://" or proxies.error.host.invalid = You must enter a full hostname for the site served by this proxy (e.g., jstor.org). proxies.error.scheme.noHost = A multi-site proxy scheme must contain the host variable (%h). proxies.error.scheme.noPath = A valid proxy scheme must contain either the path variable (%p) or the directory and filename variables (%d and %f). -proxies.recognized = Proxy Recognized -proxies.recognized.message = Would you like Zotero to store information about this proxy server to enable saving of references accessed through it?\n\nWARNING: Only click "OK" below if you have accessed this site through your library or another institution you trust. -proxies.recognized.disable = Disable automatic recognition of proxy systems \ No newline at end of file +proxies.recognized.message = Adding this proxy will allow Zotero to recognize items from its pages and will automatically redirect future requests to %1$S through %2$S. +proxies.recognized.add = Add Proxy +proxies.enableTransparentWarning.title = Warning +proxies.enableTransparentWarning.description = Please ensure that the proxies listed below belong to a library, school, or other institution with which you are affiliated. A malicious proxy could pose a security risk when transparent redirection is enabled. \ No newline at end of file diff --git a/chrome/skin/default/zotero/zotero.css b/chrome/skin/default/zotero/zotero.css index d253792792..49222acf81 100644 --- a/chrome/skin/default/zotero/zotero.css +++ b/chrome/skin/default/zotero/zotero.css @@ -205,4 +205,10 @@ zoteromergepane { .zotero-scrape-popup-collection { list-style-image: url('chrome://zotero/skin/treesource-collection.png'); +} + +.zotero-warning { + font-weight: bold; + font-size: 1.25em; + margin-bottom: 1em; } \ No newline at end of file diff --git a/defaults/preferences/zotero.js b/defaults/preferences/zotero.js index e1669216cd..6d16414090 100644 --- a/defaults/preferences/zotero.js +++ b/defaults/preferences/zotero.js @@ -89,4 +89,4 @@ pref("extensions.zotero.sync.server.compressData", true); // Proxy pref("extensions.zotero.proxies.autoRecognize", true); -pref("extensions.zotero.proxies.transparent", false); \ No newline at end of file +pref("extensions.zotero.proxies.transparent", true); \ No newline at end of file