Better support for proxy-by-port EZProxies (like the GMU EZProxy). When we see a link or redirect from (e.g.) mutex.gmu.edu:3793 to mutex.gmu.edu:3618, we now make a background request to the latter site with no cookies in order to get the EZProxy log-in screen. From the log-in screen, we can find the real URL of the latter site.

This commit is contained in:
Simon Kornblith 2008-07-29 05:08:26 +00:00
parent 17c3d1cc34
commit 79d759fd8d

View File

@ -35,6 +35,8 @@ Zotero.Proxies = new function() {
.getService(Components.interfaces.nsIIOService);
var autoRecognize = false;
var transparent = false;
var lastRecognizedURI = false;
var lastButton = false;
this.init = function() {
if(!on) {
@ -76,20 +78,23 @@ Zotero.Proxies = new function() {
var url = channel.URI.spec;
// see if there is a proxy we already know
var m = false;
var proxy;
for each(proxy in proxies) {
if(proxy.regexp && proxy.autoAssociate) {
var m = proxy.regexp.exec(url);
if(proxy.regexp && proxy.multiHost) {
m = proxy.regexp.exec(url);
if(m) break;
}
}
if(m) {
// add this host if we know a proxy
var host = m[proxy.parameters.indexOf("%h")+1];
if(proxy.hosts.indexOf(host) == -1) {
proxy.hosts.push(host);
proxy.save();
if(proxy.autoAssociate) {
var host = m[proxy.parameters.indexOf("%h")+1];
if(proxy.hosts.indexOf(host) == -1) {
proxy.hosts.push(host);
proxy.save();
}
}
} else if(autoRecognize) {
// otherwise, try to detect a proxy
@ -109,14 +114,17 @@ Zotero.Proxies = new function() {
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
var button = 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);
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(button == 0) proxy.save();
if(lastButton == 0) proxy.save();
if(checkState.value) {
autoRecognize = false;
Zotero.Prefs.set("proxies.autoRecognize", false);
@ -457,53 +465,122 @@ Zotero.Proxies.Detectors = new Object();
*/
Zotero.Proxies.Detectors.EZProxy = function(channel) {
const ezProxyRe = /\?(?:.+&)?(url|qurl)=([^&]+)/i;
try {
if(channel.getResponseHeader("Server") != "EZproxy" || channel.responseStatus != "302") {
return false;
// Try to catch links from one proxy-by-port site to another
if([80, 443, -1].indexOf(channel.URI.port) == -1) {
// Two options here: we could have a redirect from an EZProxy site to another, or a link
// If it's a redirect, we'll have to catch the Location: header
var toProxy = false;
var fromProxy = false;
if([301, 302, 303].indexOf(channel.responseStatus) !== -1) {
try {
toProxy = Zotero.Proxies.Detectors.EZProxy.ios.newURI(
channel.getResponseHeader("Location"), null, null);
fromProxy = channel.URI;
} catch(e) {}
} else {
toProxy = channel.URI;
fromProxy = channel.referrer;
}
if(fromProxy && toProxy && fromProxy.host == toProxy.host && fromProxy.port != toProxy.port
&& [80, 443, -1].indexOf(toProxy.port) == -1) {
var proxy;
for each(proxy in Zotero.Proxies.get()) {
if(proxy.regexp) {
var m = proxy.regexp.exec(fromProxy.spec);
if(m) break;
}
}
if(m) {
// Make sure caught proxy is not multi-host and that we don't have this new proxy already
if(proxy.multiHost || Zotero.Proxies.proxyToProper(toProxy.spec, true)) return false;
// Create a new nsIObserver and nsIChannel to figure out real URL (by failing to
// send cookies, so we get back to the login page)
var newChannel = Zotero.Proxies.Detectors.EZProxy.ios.newChannelFromURI(toProxy);
newChannel.originalURI = channel.originalURI ? channel.originalURI : channel.URI;
newChannel.QueryInterface(Components.interfaces.nsIRequest).loadFlags = newChannel.loadFlags |
Components.interfaces.nsIHttpChannel.LOAD_DOCUMENT_URI;
Zotero.Proxies.Detectors.EZProxy.obs.addObserver(
new Zotero.Proxies.Detectors.EZProxy.Observer(newChannel),
"http-on-modify-request", false);
newChannel.asyncOpen(new Zotero.Proxies.Detectors.EZProxy.DummyStreamListener(), null);
return false;
}
}
}
// Now try to catch redirects
try {
if(channel.getResponseHeader("Server") != "EZproxy") return false;
} catch(e) {
return false
}
// We should be able to scrape the URL out of this
// Get the new URL
if(channel.responseStatus != 302) return false;
var proxiedURL = channel.getResponseHeader("Location");
if(!proxiedURL) return false;
var proxiedURI = Zotero.Proxies.Detectors.EZProxy.ios.newURI(proxiedURL, null, null);
// look for query
var m = ezProxyRe.exec(channel.URI.spec);
if(!m) return false;
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
// Ignore if we already know about it
if(Zotero.Proxies.proxyToProper(proxiedURI.spec, true)) return false;
// Found URL
var properURL = m[2];
if(m[1].toLowerCase() == "qurl") properURL = unescape(properURL);
var properURI = ioService.newURI(properURL, null, null);
if(!properURI) return false;
var properURL = (m[1].toLowerCase() == "qurl" ? unescape(m[2]) : m[2]);
var properURI = Zotero.Proxies.Detectors.EZProxy.ios.newURI(properURL, null, null);
// Get the new URL
var newURL = channel.getResponseHeader("Location");
if(!newURL) return false;
// Ignore if we already know about it
if(Zotero.Proxies.proxyToProper(newURL, true)) return false;
// parse into nsIURI
var newURI = ioService.newURI(newURL, null, null);
if(!newURI) return false;
if(channel.URI.host == newURI.host && [channel.URI.port, 80, 443, -1].indexOf(newURI.port) == -1) {
// Old style per-port
if(channel.URI.host == proxiedURI.host && [channel.URI.port, 80, 443, -1].indexOf(proxiedURI.port) == -1) {
// Proxy by port
var proxy = new Zotero.Proxy();
proxy.multiHost = false;
proxy.scheme = newURI.scheme+"://"+newURI.hostPort+"/%p";
proxy.scheme = proxiedURI.scheme+"://"+proxiedURI.hostPort+"/%p";
proxy.hosts = [properURI.hostPort];
} else if(newURI.host != channel.URI.host) {
// New style rewriting
} else if(proxiedURI.host != channel.URI.host) {
// Proxy by host
var proxy = new Zotero.Proxy();
proxy.multiHost = proxy.autoAssociate = true;
proxy.scheme = newURI.scheme+"://"+newURI.hostPort.replace(properURI.host, "%h")+"/%p";
proxy.scheme = proxiedURI.scheme+"://"+proxiedURI.hostPort.replace(properURI.host, "%h")+"/%p";
proxy.hosts = [properURI.hostPort];
}
return proxy;
}
Zotero.Proxies.Detectors.EZProxy.ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
Zotero.Proxies.Detectors.EZProxy.obs = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
/**
* Do-nothing stream listener
*/
Zotero.Proxies.Detectors.EZProxy.DummyStreamListener = function() {}
Zotero.Proxies.Detectors.EZProxy.DummyStreamListener.prototype.onDataAvailable = function(request,
context, inputStream, offset, count) {}
Zotero.Proxies.Detectors.EZProxy.DummyStreamListener.prototype.onStartRequest = function(request, context) {}
Zotero.Proxies.Detectors.EZProxy.DummyStreamListener.prototype.onStopRequest = function(request, context, status) {}
/**
* Observer to clear cookies on an HTTP request, then remove itself
*/
Zotero.Proxies.Detectors.EZProxy.Observer = function(newChannel) {
this.channel = newChannel;
}
Zotero.Proxies.Detectors.EZProxy.Observer.prototype.observe = function(aSubject, aTopic, aData) {
if (aSubject == this.channel) {
aSubject.QueryInterface(Components.interfaces.nsIHttpChannel).setRequestHeader("Cookie", "", false);
Zotero.Proxies.Detectors.EZProxy.obs.removeObserver(this, "http-on-modify-request");
}
}
Zotero.Proxies.Detectors.EZProxy.Observer.prototype.QueryInterface = function(aIID) {
if (aIID.equals(Components.interfaces.nsISupports) ||
aIID.equals(Components.interfaces.nsIObserver)) return this;
throw Components.results.NS_NOINTERFACE;
}
/**
* Detector for Juniper Networks WebVPN
@ -519,7 +596,7 @@ Zotero.Proxies.Detectors.Juniper = function(channel) {
if(!m) return false;
var proxy = new Zotero.Proxy();
proxy.multiHost = true;
proxy.multiHost = proxy.autoAssociate = true;
proxy.scheme = m[1]+"/%d"+",DanaInfo=%h%a+%f";
proxy.hosts = [m[3]];
return proxy;