Proxy system overhaul

- Only one preference for recognizing proxies for transparent redirection
- Blacklists sites and http://%h/%p
- Fixes to EZProxy

This will clear all existing proxies from Zotero
This commit is contained in:
Simon Kornblith 2009-03-23 19:55:57 +00:00
parent 5aae6bc9ce
commit 9ca461c59b
9 changed files with 251 additions and 175 deletions

View File

@ -24,7 +24,7 @@ var openURLServerField;
var openURLVersionMenu; var openURLVersionMenu;
var proxies; var proxies;
var charsets; var charsets;
var _io; var _io = {};
function init() function init()
{ {
@ -47,14 +47,16 @@ function init()
charsetMap[Zotero.Prefs.get("import.charset")] ? charsetMap[Zotero.Prefs.get("import.charset")] ?
charsetMap[Zotero.Prefs.get("import.charset")] : charsetMap["auto"]; charsetMap[Zotero.Prefs.get("import.charset")] : charsetMap["auto"];
_io = window.arguments[0]; if(window.arguments) {
_io = window.arguments[0];
if (_io.pane) {
var pane = document.getElementById(_io.pane); if(_io.pane) {
document.getElementById('zotero-prefs').showPane(pane); var pane = document.getElementById(_io.pane);
// Quick hack to support install prompt from PDF recognize option document.getElementById('zotero-prefs').showPane(pane);
if (_io.action && _io.action == 'pdftools-install') { // Quick hack to support install prompt from PDF recognize option
checkPDFToolsDownloadVersion(); if (_io.action && _io.action == 'pdftools-install') {
checkPDFToolsDownloadVersion();
}
} }
} }
} }
@ -1313,7 +1315,13 @@ function deleteProxy() {
*/ */
function refreshProxyList() { function refreshProxyList() {
// get and sort proxies // get and sort proxies
proxies = Zotero.Proxies.get(); proxies = Zotero.Proxies.proxies.slice();
for(var i=0; i<proxies.length; i++) {
if(!proxies[i].proxyID) {
proxies.splice(i, 1);
i--;
}
}
proxies = proxies.sort(function(a, b) { proxies = proxies.sort(function(a, b) {
if(a.multiHost) { if(a.multiHost) {
if(b.multiHost) { if(b.multiHost) {
@ -1362,7 +1370,6 @@ function refreshProxyList() {
document.getElementById('proxyTree').currentIndex = -1; document.getElementById('proxyTree').currentIndex = -1;
document.getElementById('proxyTree-delete').disabled = true; document.getElementById('proxyTree-delete').disabled = true;
document.getElementById('zotero-proxies-autoRecognize').checked = Zotero.Prefs.get("proxies.autoRecognize");
document.getElementById('zotero-proxies-transparent').checked = Zotero.Prefs.get("proxies.transparent"); document.getElementById('zotero-proxies-transparent').checked = Zotero.Prefs.get("proxies.transparent");
} }
@ -1370,16 +1377,10 @@ function refreshProxyList() {
* Updates proxy autoRecognize and transparent settings based on checkboxes * Updates proxy autoRecognize and transparent settings based on checkboxes
*/ */
function updateProxyPrefs() { 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 oldTransparent = Zotero.Prefs.get("proxies.transparent");
var newTransparent = document.getElementById('zotero-proxies-transparent').checked; 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.Prefs.set("proxies.transparent", newTransparent);
Zotero.Proxies.init() Zotero.Proxies.init()

View File

@ -535,13 +535,16 @@ To add a new preference:
<prefpane id="zotero-prefpane-proxies" <prefpane id="zotero-prefpane-proxies"
label="&zotero.preferences.prefpane.proxies;" label="&zotero.preferences.prefpane.proxies;"
image="chrome://zotero/skin/prefs-proxies.png"> image="chrome://zotero/skin/prefs-proxies.png">
<groupbox> <description width="45em" style="font-size: 12px">
<command id="zotero-proxies-update" oncommand="updateProxyPrefs()"/> &zotero.preferences.proxies.desc_before_link;
<checkbox id="zotero-proxies-autoRecognize" label="&zotero.preferences.proxies.autoRecognize;" <label class="text-link" href="http://www.zotero.org/support/proxies"
command="zotero-proxies-update"/> value="&zotero.preferences.proxies.desc_link;"/>
<checkbox id="zotero-proxies-transparent" label="&zotero.preferences.proxies.transparent;" &zotero.preferences.proxies.desc_after_link;
command="zotero-proxies-update"/> </description>
</groupbox>
<command id="zotero-proxies-update" oncommand="updateProxyPrefs()"/>
<checkbox id="zotero-proxies-transparent" label="&zotero.preferences.proxies.transparent;"
command="zotero-proxies-update"/>
<groupbox flex="1"> <groupbox flex="1">
<caption label="&zotero.preferences.proxies.configured;"/> <caption label="&zotero.preferences.proxies.configured;"/>

View File

@ -111,17 +111,18 @@ var Zotero_ProxyEditor = new function() {
var hasErrors = proxy.validate(); var hasErrors = proxy.validate();
if(hasErrors) { if(hasErrors) {
error = hasErrors.shift();
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService); .getService(Components.interfaces.nsIPromptService);
promptService.alert( promptService.alert(
window, window, Zotero.getString("proxies.error"),
Zotero.getString("proxies.error"), Zotero.getString("proxies.error." + error, hasErrors)
Zotero.getString("proxies.error." + hasErrors)
); );
if(window.arguments && window.arguments[0]) proxy.revert(); if(window.arguments && window.arguments[0]) proxy.revert();
return false; return false;
} }
proxy.save(); proxy.save(true);
return true; return true;
} }

View File

@ -16,10 +16,6 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
Utilities based in part on code taken from Piggy Bank 2.1.1 (BSD-licensed)
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
@ -27,15 +23,17 @@
/** /**
* A singleton to handle URL rewriting proxies * A singleton to handle URL rewriting proxies
* @namespace * @namespace
* @property transparent {Boolean} Whether transparent proxy functionality is enabled
* @property proxies {Zotero.Proxy[]} All loaded proxies
* @property hosts {Zotero.Proxy{}} Object mapping hosts to proxies
*/ */
Zotero.Proxies = new function() { Zotero.Proxies = new function() {
var on = false; this.proxies = false;
var proxies = false; this.transparent = false;
var hosts; this.hosts = {};
var ioService = Components.classes["@mozilla.org/network/io-service;1"] var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService); .getService(Components.interfaces.nsIIOService);
var autoRecognize = false;
var transparent = false;
var lastRecognizedURI = false; var lastRecognizedURI = false;
var lastButton = false; var lastButton = false;
@ -43,15 +41,21 @@ Zotero.Proxies = new function() {
* Initializes http-on-examine-response observer to intercept page loads and gets preferences * Initializes http-on-examine-response observer to intercept page loads and gets preferences
*/ */
this.init = function() { this.init = function() {
if(!on) { if(!this.proxies) {
var me = this; var me = this;
Zotero.MIMETypeHandler.addObserver(function(ch) { me.observe(ch) }); Zotero.MIMETypeHandler.addObserver(function(ch) { me.observe(ch) });
this.get();
on = true; var rows = Zotero.DB.query("SELECT * FROM proxies");
Zotero.Proxies.proxies = [new Zotero.Proxy(row) for each(row in rows)];
for each(var proxy in Zotero.Proxies.proxies) {
for each(var host in proxy.hosts) {
Zotero.Proxies.hosts[host] = proxy;
}
}
} }
autoRecognize = Zotero.Prefs.get("proxies.autoRecognize"); Zotero.Proxies.transparent = Zotero.Prefs.get("proxies.transparent");
transparent = Zotero.Prefs.get("proxies.transparent");
} }
/** /**
@ -69,23 +73,22 @@ Zotero.Proxies = new function() {
// see if there is a proxy we already know // see if there is a proxy we already know
var m = false; var m = false;
var proxy; var proxy;
for each(proxy in proxies) { for each(proxy in Zotero.Proxies.proxies) {
if(proxy.regexp && proxy.multiHost) { if(proxy.proxyID && proxy.regexp && proxy.multiHost) {
m = proxy.regexp.exec(url); m = proxy.regexp.exec(url);
if(m) break; if(m) break;
} }
} }
if(m) { if(m) {
var host = m[proxy.parameters.indexOf("%h")+1];
// add this host if we know a proxy // add this host if we know a proxy
if(proxy.autoAssociate) { if(proxy.autoAssociate && !Zotero.Proxies.hosts[host] && proxy.hosts.indexOf(host) == -1 && !_isBlacklisted(host)) {
var host = m[proxy.parameters.indexOf("%h")+1]; // if no saved host and host is not blacklisted, auto associate
if(proxy.hosts.indexOf(host) == -1) { proxy.hosts.push(host);
proxy.hosts.push(host); proxy.save(true);
proxy.save();
}
} }
} else if(autoRecognize) { } else {
// otherwise, try to detect a proxy // otherwise, try to detect a proxy
var proxy = false; var proxy = false;
for each(var detector in Zotero.Proxies.Detectors) { for each(var detector in Zotero.Proxies.Detectors) {
@ -95,78 +98,50 @@ Zotero.Proxies = new function() {
Components.utils.reportError(e); Components.utils.reportError(e);
} }
if (!proxy) { if(!proxy) continue;
continue; var transparent = _showDialog(proxy.hosts[0], channel.URI.hostPort);
} proxy.save(transparent);
// if transparent is turned off, just save the proxy
if(!transparent) {
proxy.save();
break;
}
// 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(io.add) proxy.save();
if(io.disable) {
transparent = false;
Zotero.Prefs.set("proxies.transparent", false);
}
break; break;
} }
} }
// try to get an applicable proxy // try to get an applicable proxy
if(transparent) { var webNav = null;
var webNav = null; try {
try { webNav = channel.notificationCallbacks.QueryInterface(Components.interfaces.nsIWebNavigation);
webNav = channel.notificationCallbacks.QueryInterface(Components.interfaces.nsIWebNavigation); } catch(e) {}
} catch(e) {}
if(webNav) {
if(webNav) { var proxied = Zotero.Proxies.properToProxy(url, true);
var proxied = this.properToProxy(url, true); if(proxied) {
if(proxied) { channel.QueryInterface(Components.interfaces.nsIHttpChannel);
channel.QueryInterface(Components.interfaces.nsIHttpChannel); // If the referrer is a proxiable host, we already have access
// If the referrer is a proxiable host, we already have access // (e.g., we're on-campus) and shouldn't redirect
// (e.g., we're on-campus) and shouldn't redirect if (channel.referrer) {
if (channel.referrer) { if (Zotero.Proxies.properToProxy(channel.referrer.spec, true)) {
if (this.properToProxy(channel.referrer.spec, true)) { return;
return;
}
} }
webNav.loadURI(proxied, 0, channel.URI, null, null);
} }
webNav.loadURI(proxied, 0, channel.URI, null, null);
} }
} }
} }
/**
* Gets all proxy objects
* @type Zotero.Proxy[]
*/
this.get = function() {
if(!proxies) {
var rows = Zotero.DB.query("SELECT * FROM proxies");
proxies = [new Zotero.Proxy(row) for each(row in rows)];
this.refreshHostMap();
}
return proxies;
}
/** /**
* Removes a proxy object from the list of proxy objects * 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 * @returns {Boolean} True if the proxy was in the list, false if it was not
*/ */
this.remove = function(proxy) { this.remove = function(proxy) {
var index = proxies.indexOf(proxy); var index = Zotero.Proxies.proxies.indexOf(proxy);
if(index == -1) return false; if(index == -1) return false;
proxies.splice(index, 1); // remove proxy from proxy list
this.refreshHostMap(); Zotero.Proxies.proxies.splice(index, 1);
// remove hosts from host list
for(var host in Zotero.Proxies.hosts) {
if(Zotero.Proxies.hosts[host] == proxy) {
delete Zotero.Proxies.hosts[host];
}
}
return true; return true;
} }
@ -174,10 +149,14 @@ Zotero.Proxies = new function() {
* Inserts a proxy into the host map; necessary when proxies are added * Inserts a proxy into the host map; necessary when proxies are added
*/ */
this.save = function(proxy) { this.save = function(proxy) {
proxies.push(proxy); // add to list of proxies
for each(var host in proxy.hosts) { if(Zotero.Proxies.proxies.indexOf(proxy) == -1) Zotero.Proxies.proxies.push(proxy);
if(!hosts[host]) {
hosts[host] = proxy; // if there is a proxy ID (i.e., if this is a persisting, transparent proxy), add to host
// list to do reverse mapping
if(proxy.proxyID) {
for each(var host in proxy.hosts) {
Zotero.Proxies.hosts[host] = proxy;
} }
} }
} }
@ -185,19 +164,22 @@ Zotero.Proxies = new function() {
/** /**
* Refreshes host map; necessary when proxies are changed or deleted * Refreshes host map; necessary when proxies are changed or deleted
*/ */
this.refreshHostMap = function() { this.refreshHostMap = function(proxy) {
hosts = {}; // if there is no proxyID, then return immediately, since there is no need to update
for each(var proxy in proxies) { if(!proxy.proxyID) return;
for each(var host in proxy.hosts) {
if(!hosts[host]) { // delete hosts that point to this proxy if they no longer exist
hosts[host] = proxy; for(var host in Zotero.Proxies.hosts) {
} if(Zotero.Proxies.hosts[host] == proxy && proxy.hosts.indexOf(host) == -1) {
delete Zotero.Proxies.hosts[host];
} }
} }
// add new hosts for this proxy
Zotero.Proxies.save(proxy);
} }
/** /**
* Returns a page's proper URL from a proxied URL * Returns a page's proper URL from a proxied URL. Uses both transparent and opaque proxies.
* @param {String} url * @param {String} url
* @param {Boolean} onlyReturnIfProxied Controls behavior if the given URL is not proxied. If * @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 * it is false or unspecified, unproxied URLs are returned verbatim. If it is true, the
@ -205,7 +187,7 @@ Zotero.Proxies = new function() {
* @type String * @type String
*/ */
this.proxyToProper = function(url, onlyReturnIfProxied) { this.proxyToProper = function(url, onlyReturnIfProxied) {
for each(var proxy in proxies) { for each(var proxy in Zotero.Proxies.proxies) {
if(proxy.regexp) { if(proxy.regexp) {
var m = proxy.regexp.exec(url); var m = proxy.regexp.exec(url);
if(m) { if(m) {
@ -219,7 +201,7 @@ Zotero.Proxies = new function() {
} }
/** /**
* Returns a page's proxied URL from the proper URL * Returns a page's proxied URL from the proper URL. Uses only transparent proxies.
* @param {String} url * @param {String} url
* @param {Boolean} onlyReturnIfProxied Controls behavior if the given URL is not proxied. If * @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 * it is false or unspecified, unproxied URLs are returned verbatim. If it is true, the
@ -228,13 +210,78 @@ Zotero.Proxies = new function() {
*/ */
this.properToProxy = function(url, onlyReturnIfProxied) { this.properToProxy = function(url, onlyReturnIfProxied) {
var uri = ioService.newURI(url, null, null); var uri = ioService.newURI(url, null, null);
if(hosts[uri.hostPort]) { if(Zotero.Proxies.hosts[uri.hostPort] && Zotero.Proxies.hosts[uri.hostPort].proxyID) {
var toProxy = hosts[uri.hostPort].toProxy(uri); var toProxy = Zotero.Proxies.hosts[uri.hostPort].toProxy(uri);
Zotero.debug("Zotero.Proxies.properToProxy: "+url+" to "+toProxy); Zotero.debug("Zotero.Proxies.properToProxy: "+url+" to "+toProxy);
return toProxy; return toProxy;
} }
return (onlyReturnIfProxied ? false : url); return (onlyReturnIfProxied ? false : url);
} }
/**
* Determines whether a host is blacklisted, i.e., whether we should refuse to save transparent
* proxy entries for this host. This is necessary because EZProxy offers to proxy all Google and
* Wikipedia subdomains, but in practice, this would get really annoying.
*
* @type Boolean
* @private
*/
function _isBlacklisted(host) {
/**
* Regular expression patterns of hosts never to proxy
* @const
*/
const hostBlacklist = [
/google\.com$/,
/wikipedia\.org$/
];
/**
* Regular expression patterns of hosts that should always be proxied, regardless of whether
* they're on the blacklist
* @const
*/
const hostWhitelist = [
/^scholar\.google\.com$/
]
for each(var blackPattern in hostBlacklist) {
if(blackPattern.test(host)) {
for each(var whitePattern in hostWhitelist) {
if(whitePattern.test(host)) {
return false;
}
}
return true;
}
}
return false;
}
/**
* If transparent is enabled, shows a dialog asking user whether to add a proxy to the
* transparent proxy list.
*
* @param {String} proxiedHost The host that would be redirected through the proxy.
* @param {String} proxyHost The host through which the given site would be redirected.
* @returns {Boolean} True if proxy should be added; false if it should not be.
*/
function _showDialog(proxiedHost, proxyHost) {
if(!Zotero.Proxies.transparent) return false;
// ask user whether to add this proxy
var io = {site:proxiedHost, proxy:proxyHost};
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);
// disable transparent if checkbox checked
if(io.disable) {
Zotero.Proxies.transparent = false;
Zotero.Prefs.set("proxies.transparent", false);
}
return io.add;
}
} }
/** /**
@ -260,7 +307,7 @@ const Zotero_Proxy_schemeParameters = {
"%p":"(.*?)", // path "%p":"(.*?)", // path
"%d":"(.*?)", // directory "%d":"(.*?)", // directory
"%f":"(.*?)", // filename "%f":"(.*?)", // filename
"%a":"(.*?)" // filename "%a":"(.*?)" // anything
}; };
/** /**
@ -275,13 +322,13 @@ const Zotero_Proxy_schemeParameterRegexps = {
"%a":/([^%])%a/ "%a":/([^%])%a/
}; };
const Zotero_Proxy_metaRegexp = /[-[\]{}()*+?.\\^$|,#\s]/g;
/** /**
* Compiles the regular expression against which we match URLs to determine if this proxy is in use * Compiles the regular expression against which we match URLs to determine if this proxy is in use
* and saves it in this.regexp * and saves it in this.regexp
*/ */
Zotero.Proxy.prototype.compileRegexp = function() { Zotero.Proxy.prototype.compileRegexp = function() {
const metaRe = /[-[\]{}()*+?.\\^$|,#\s]/g;
// take host only if flagged as multiHost // take host only if flagged as multiHost
var parametersToCheck = Zotero_Proxy_schemeParameters; var parametersToCheck = Zotero_Proxy_schemeParameters;
if(this.multiHost) parametersToCheck["%h"] = "([a-zA-Z0-9]+\\.[a-zA-Z0-9\.]+)"; if(this.multiHost) parametersToCheck["%h"] = "([a-zA-Z0-9]+\\.[a-zA-Z0-9\.]+)";
@ -309,7 +356,7 @@ Zotero.Proxy.prototype.compileRegexp = function() {
}) })
// now replace with regexp fragment in reverse order // now replace with regexp fragment in reverse order
var re = "^"+this.scheme.replace(metaRe, "\\$&")+"$"; var re = "^"+this.scheme.replace(Zotero_Proxy_metaRegexp, "\\$&")+"$";
for(var i=this.parameters.length-1; i>=0; i--) { for(var i=this.parameters.length-1; i>=0; i--) {
var param = this.parameters[i]; var param = this.parameters[i];
re = re.replace(Zotero_Proxy_schemeParameterRegexps[param], "$1"+parametersToCheck[param]); re = re.replace(Zotero_Proxy_schemeParameterRegexps[param], "$1"+parametersToCheck[param]);
@ -326,19 +373,30 @@ Zotero.Proxy.prototype.compileRegexp = function() {
*/ */
Zotero.Proxy.prototype.validate = function() { Zotero.Proxy.prototype.validate = function() {
if(this.scheme.length < 8 || (this.scheme.substr(0, 7) != "http://" && this.scheme.substr(0, 8) != "https://")) { if(this.scheme.length < 8 || (this.scheme.substr(0, 7) != "http://" && this.scheme.substr(0, 8) != "https://")) {
return "scheme.noHTTP"; return ["scheme.noHTTP"];
} }
if(!this.multiSite && (!this.hosts.length || !this.hosts[0])) { if(!this.multiSite && (!this.hosts.length || !this.hosts[0])) {
return "host.invalid"; return ["host.invalid"];
} else if(this.multiSite && !Zotero_Proxy_schemeParameterRegexps["%h"].test(this.scheme)) { } else if(this.multiSite && !Zotero_Proxy_schemeParameterRegexps["%h"].test(this.scheme)) {
return "scheme.noHost"; return ["scheme.noHost"];
} }
if(!Zotero_Proxy_schemeParameterRegexps["%p"].test(this.scheme) && if(!Zotero_Proxy_schemeParameterRegexps["%p"].test(this.scheme) &&
(!Zotero_Proxy_schemeParameterRegexps["%d"].test(this.scheme) || (!Zotero_Proxy_schemeParameterRegexps["%d"].test(this.scheme) ||
!Zotero_Proxy_schemeParameterRegexps["%f"].test(this.scheme))) { !Zotero_Proxy_schemeParameterRegexps["%f"].test(this.scheme))) {
return "scheme.noPath"; return ["scheme.noPath"];
}
if(this.scheme.substr(0, 10) == "http://%h/" || this.scheme.substr(0, 11) == "https://%h/") {
return ["scheme.invalid"];
}
for each(var host in this.hosts) {
var oldHost = Zotero.Proxies.hosts[host];
if(oldHost && oldHost.proxyID && oldHost != this) {
return ["host.proxyExists", host];
}
} }
return false; return false;
@ -346,45 +404,50 @@ Zotero.Proxy.prototype.validate = function() {
/** /**
* Saves any changes to this proxy * Saves any changes to this proxy
*
* @param {Boolean} transparent True if proxy should be saved as a persisting, transparent proxy
*/ */
Zotero.Proxy.prototype.save = function() { Zotero.Proxy.prototype.save = function(transparent) {
// ensure this proxy is valid // ensure this proxy is valid
Zotero.debug(this); Zotero.debug(this);
var hasErrors = this.validate(); var hasErrors = this.validate();
if(hasErrors) throw "Proxy could not be saved because it is invalid: error "+hasErrors; if(hasErrors) throw "Zotero.Proxy: could not be saved because it is invalid: error "+hasErrors[0];
this.autoAssociate = this.multiHost && this.autoAssociate; this.autoAssociate = this.multiHost && this.autoAssociate;
this.compileRegexp(); this.compileRegexp();
if(this.proxyID) { if(this.proxyID) {
Zotero.Proxies.refreshHostMap(); Zotero.Proxies.refreshHostMap(this);
if(!transparent) throw "Zotero.Proxy: cannot save transparent proxy without transparent param";
} else { } else {
Zotero.Proxies.save(this); Zotero.Proxies.save(this);
} }
try { if(transparent) {
Zotero.DB.beginTransaction(); try {
Zotero.DB.beginTransaction();
if(this.proxyID) {
Zotero.DB.query("UPDATE proxies SET multiHost = ?, autoAssociate = ?, scheme = ? WHERE proxyID = ?", if(this.proxyID) {
[this.multiHost ? 1 : 0, this.autoAssociate ? 1 : 0, this.scheme, this.proxyID]); Zotero.DB.query("UPDATE proxies SET multiHost = ?, autoAssociate = ?, scheme = ? WHERE proxyID = ?",
Zotero.DB.query("DELETE FROM proxyHosts WHERE proxyID = ?", [this.proxyID]); [this.multiHost ? 1 : 0, this.autoAssociate ? 1 : 0, this.scheme, this.proxyID]);
} else { Zotero.DB.query("DELETE FROM proxyHosts WHERE proxyID = ?", [this.proxyID]);
this.proxyID = Zotero.DB.query("INSERT INTO proxies (multiHost, autoAssociate, scheme) VALUES (?, ?, ?)", } else {
[this.multiHost ? 1 : 0, this.autoAssociate ? 1 : 0, this.scheme]) this.proxyID = Zotero.DB.query("INSERT INTO proxies (multiHost, autoAssociate, scheme) VALUES (?, ?, ?)",
[this.multiHost ? 1 : 0, this.autoAssociate ? 1 : 0, this.scheme])
}
this.hosts = this.hosts.sort();
var host;
for(var i in this.hosts) {
host = this.hosts[i] = this.hosts[i].toLowerCase();
Zotero.DB.query("INSERT INTO proxyHosts (proxyID, hostname) VALUES (?, ?)",
[this.proxyID, host]);
}
Zotero.DB.commitTransaction();
} catch(e) {
Zotero.DB.rollbackTransaction();
throw(e);
} }
this.hosts = this.hosts.sort();
var host;
for(var i in this.hosts) {
host = this.hosts[i] = this.hosts[i].toLowerCase();
Zotero.DB.query("INSERT INTO proxyHosts (proxyID, hostname) VALUES (?, ?)",
[this.proxyID, host]);
}
Zotero.DB.commitTransaction();
} catch(e) {
Zotero.DB.rollbackTransaction();
throw(e);
} }
} }
@ -400,17 +463,18 @@ Zotero.Proxy.prototype.revert = function() {
* Deletes this proxy * Deletes this proxy
*/ */
Zotero.Proxy.prototype.erase = function() { Zotero.Proxy.prototype.erase = function() {
if(!this.proxyID) throw "Tried to erase an unsaved proxy";
Zotero.Proxies.remove(this); Zotero.Proxies.remove(this);
try { if(this.proxyID) {
Zotero.DB.beginTransaction(); try {
Zotero.DB.query("DELETE FROM proxyHosts WHERE proxyID = ?", [this.proxyID]); Zotero.DB.beginTransaction();
Zotero.DB.query("DELETE FROM proxies WHERE proxyID = ?", [this.proxyID]); Zotero.DB.query("DELETE FROM proxyHosts WHERE proxyID = ?", [this.proxyID]);
Zotero.DB.commitTransaction(); Zotero.DB.query("DELETE FROM proxies WHERE proxyID = ?", [this.proxyID]);
} catch(e) { Zotero.DB.commitTransaction();
Zotero.DB.rollbackTransaction(); } catch(e) {
throw(e); Zotero.DB.rollbackTransaction();
throw(e);
}
} }
} }
@ -514,7 +578,7 @@ Zotero.Proxies.Detectors.EZProxy = function(channel) {
if(fromProxy && toProxy && fromProxy.host == toProxy.host && fromProxy.port != toProxy.port if(fromProxy && toProxy && fromProxy.host == toProxy.host && fromProxy.port != toProxy.port
&& [80, 443, -1].indexOf(toProxy.port) == -1) { && [80, 443, -1].indexOf(toProxy.port) == -1) {
var proxy; var proxy;
for each(proxy in Zotero.Proxies.get()) { for each(proxy in Zotero.Proxies.proxies) {
if(proxy.regexp) { if(proxy.regexp) {
var m = proxy.regexp.exec(fromProxy.spec); var m = proxy.regexp.exec(fromProxy.spec);
if(m) break; if(m) break;
@ -569,7 +633,7 @@ Zotero.Proxies.Detectors.EZProxy = function(channel) {
proxy.multiHost = false; proxy.multiHost = false;
proxy.scheme = proxiedURI.scheme+"://"+proxiedURI.hostPort+"/%p"; proxy.scheme = proxiedURI.scheme+"://"+proxiedURI.hostPort+"/%p";
proxy.hosts = [properURI.hostPort]; proxy.hosts = [properURI.hostPort];
} else if(proxiedURI.host != channel.URI.host) { } else if(proxiedURI.host != channel.URI.host && proxiedURI.hostPort.indexOf(properURI.host) != -1) {
// Proxy by host // Proxy by host
var proxy = new Zotero.Proxy(); var proxy = new Zotero.Proxy();
proxy.multiHost = proxy.autoAssociate = true; proxy.multiHost = proxy.autoAssociate = true;
@ -628,7 +692,8 @@ Zotero.Proxies.Detectors.Juniper = function(channel) {
if(!m) return false; if(!m) return false;
var proxy = new Zotero.Proxy(); var proxy = new Zotero.Proxy();
proxy.multiHost = proxy.autoAssociate = true; proxy.multiHost = true;
proxy.autoAssociate = false;
proxy.scheme = m[1]+"/%d"+",DanaInfo=%h%a+%f"; proxy.scheme = m[1]+"/%d"+",DanaInfo=%h%a+%f";
proxy.hosts = [m[3]]; proxy.hosts = [m[3]];
return proxy; return proxy;

View File

@ -2194,6 +2194,11 @@ Zotero.Schema = new function(){
Zotero.DB.query("DROP TABLE savedSearchesOld"); Zotero.DB.query("DROP TABLE savedSearchesOld");
Zotero.DB.query("DROP TABLE tagsOld"); Zotero.DB.query("DROP TABLE tagsOld");
} }
if (i==50) {
Zotero.DB.query("DELETE FROM proxyHosts");
Zotero.DB.query("DELETE FROM proxies");
}
} }
_updateDBVersion('userdata', toVersion); _updateDBVersion('userdata', toVersion);

View File

@ -87,8 +87,10 @@
<!ENTITY zotero.preferences.prefpane.proxies "Proxies"> <!ENTITY zotero.preferences.prefpane.proxies "Proxies">
<!ENTITY zotero.preferences.proxies.proxyOptions "Proxy Options"> <!ENTITY zotero.preferences.proxies.proxyOptions "Proxy Options">
<!ENTITY zotero.preferences.proxies.autoRecognize "Automatically recognize common URL-rewriting proxy systems"> <!ENTITY zotero.preferences.proxies.desc_before_link "Zotero will transparently redirect requests through saved proxies. See the">
<!ENTITY zotero.preferences.proxies.transparent "Transparently redirect requests through previously used proxies"> <!ENTITY zotero.preferences.proxies.desc_link "proxy documentation">
<!ENTITY zotero.preferences.proxies.desc_after_link "for more information.">
<!ENTITY zotero.preferences.proxies.transparent "Automatically remember proxied resources">
<!ENTITY zotero.preferences.proxies.configured "Configured Proxies"> <!ENTITY zotero.preferences.proxies.configured "Configured Proxies">
<!ENTITY zotero.preferences.proxies.hostname "Hostname"> <!ENTITY zotero.preferences.proxies.hostname "Hostname">
<!ENTITY zotero.preferences.proxies.scheme "Scheme"> <!ENTITY zotero.preferences.proxies.scheme "Scheme">

View File

@ -519,10 +519,10 @@ 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.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.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.error.scheme.noPath = A valid proxy scheme must contain either the path variable (%p) or the directory and filename variables (%d and %f).
proxies.error.host.proxyExists = You have already defined another proxy for the host %1$S.
proxies.error.scheme.invalid = The entered proxy scheme is invalid; it would apply to all hosts.
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.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.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.
recognizePDF.noOCR = PDF does not contain OCRed text. recognizePDF.noOCR = PDF does not contain OCRed text.
recognizePDF.couldNotRead = Could not read text from PDF. recognizePDF.couldNotRead = Could not read text from PDF.

View File

@ -104,7 +104,6 @@ pref("extensions.zotero.sync.storage.maxUploads", 4);
pref("extensions.zotero.sync.storage.deleteDelayDays", 30); pref("extensions.zotero.sync.storage.deleteDelayDays", 30);
// Proxy // Proxy
pref("extensions.zotero.proxies.autoRecognize", true);
pref("extensions.zotero.proxies.transparent", true); pref("extensions.zotero.proxies.transparent", true);
// Data layer purging // Data layer purging

View File

@ -1,4 +1,4 @@
-- 49 -- 50
-- This file creates tables containing user-specific data -- any changes made -- This file creates tables containing user-specific data -- any changes made
-- here must be mirrored in transition steps in schema.js::_migrateSchema() -- here must be mirrored in transition steps in schema.js::_migrateSchema()