Remove connector proxy code
Observing requests, auto-redirecting and learning proxies no longer relevant on this codebase (and interferes with Scaffold).
This commit is contained in:
parent
da21c9c47b
commit
7a062a7493
1 changed files with 0 additions and 521 deletions
|
@ -41,9 +41,6 @@ Zotero.Proxies = new function() {
|
|||
*/
|
||||
this.init = Zotero.Promise.coroutine(function* () {
|
||||
if(!this.proxies) {
|
||||
var me = this;
|
||||
Zotero.MIMETypeHandler.addObserver(function(ch) { me.observe(ch) });
|
||||
|
||||
var rows = yield Zotero.DB.queryAsync("SELECT * FROM proxies");
|
||||
Zotero.Proxies.proxies = yield Zotero.Promise.all(
|
||||
rows.map(row => this.newProxyFromRow(row))
|
||||
|
@ -81,201 +78,6 @@ Zotero.Proxies = new function() {
|
|||
});
|
||||
|
||||
|
||||
/**
|
||||
* Observe method to capture page loads and determine if they're going through an EZProxy.
|
||||
*
|
||||
* @param {nsIChannel} channel
|
||||
*/
|
||||
this.observe = Zotero.Promise.coroutine(function* (channel) {
|
||||
// try to detect a proxy
|
||||
channel.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
var url = channel.URI.spec;
|
||||
|
||||
try {
|
||||
var { browser, window } = _getBrowserAndWindow(channel);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
if (!browser) {
|
||||
Zotero.debug("Couldn't get browser from channel", 2);
|
||||
}
|
||||
|
||||
// see if there is a proxy we already know
|
||||
var m = false;
|
||||
var proxy;
|
||||
for (proxy of Zotero.Proxies.proxies) {
|
||||
if(proxy.proxyID && proxy.regexp && proxy.multiHost) {
|
||||
m = proxy.regexp.exec(url);
|
||||
if(m) break;
|
||||
}
|
||||
}
|
||||
|
||||
if(m) {
|
||||
var host = m[proxy.parameters.indexOf("%h")+1];
|
||||
// add this host if we know a proxy
|
||||
if(proxy.autoAssociate // if autoAssociate is on
|
||||
&& channel.responseStatus < 400 // and query was successful
|
||||
&& !Zotero.Proxies.hosts[host] // and host is not saved
|
||||
&& proxy.hosts.indexOf(host) === -1
|
||||
&& !_isBlacklisted(host) // and host is not blacklisted
|
||||
) {
|
||||
proxy.hosts.push(host);
|
||||
yield proxy.save(true);
|
||||
|
||||
if (!browser) return;
|
||||
_showNotification(
|
||||
browser,
|
||||
window,
|
||||
Zotero.getString('proxies.notification.associated.label', [host, channel.URI.hostPort]),
|
||||
[
|
||||
{
|
||||
label: "proxies.notification.settings.button",
|
||||
callback: () => _prefsOpenCallback(window)
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!browser) return;
|
||||
|
||||
// otherwise, try to detect a proxy
|
||||
var proxy = false;
|
||||
for(var detectorName in Zotero.Proxies.Detectors) {
|
||||
var detector = Zotero.Proxies.Detectors[detectorName];
|
||||
try {
|
||||
proxy = detector(channel);
|
||||
} catch(e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
|
||||
if(!proxy) continue;
|
||||
Zotero.debug("Proxies: Detected "+detectorName+" proxy "+proxy.scheme+
|
||||
(proxy.multiHost ? " (multi-host)" : " for "+proxy.hosts[0]));
|
||||
|
||||
var savedTransparent = false;
|
||||
if(Zotero.Proxies.autoRecognize) {
|
||||
// Ask to save only if automatic proxy recognition is on
|
||||
savedTransparent = _showNotification(
|
||||
browser,
|
||||
window,
|
||||
Zotero.getString('proxies.notification.recognized.label', [proxy.hosts[0], channel.URI.hostPort]),
|
||||
[{ label: "proxies.notification.enable.button", callback: function() { _showDialog(proxy.hosts[0], channel.URI.hostPort, proxy); } }]);
|
||||
}
|
||||
|
||||
yield proxy.save();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// try to get an applicable proxy
|
||||
var docShell = browser.docShell;
|
||||
if (!docShell) {
|
||||
Zotero.logError("Couldn't get docshell");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!docShell || !docShell.allowMetaRedirects) return;
|
||||
|
||||
// check that proxy redirection is actually enabled
|
||||
if(!Zotero.Proxies.transparent) return;
|
||||
|
||||
var proxied = Zotero.Proxies.properToProxy(url, true);
|
||||
if(!proxied) return;
|
||||
|
||||
if(Zotero.Proxies.disableByDomain) {
|
||||
var now = new Date();
|
||||
|
||||
// IP update interval is every 15 minutes
|
||||
if((now - Zotero.Proxies.lastIPCheck) > 900000) {
|
||||
Zotero.Proxies.DNS.getHostnames().then(function (hosts) {
|
||||
// if domains necessitate disabling, disable them
|
||||
Zotero.Proxies.disabledByDomain = false;
|
||||
for (var host of hosts) {
|
||||
Zotero.Proxies.disabledByDomain = host.toLowerCase().indexOf(Zotero.Proxies.disableByDomain) != -1;
|
||||
if (Zotero.Proxies.disabledByDomain) return;
|
||||
}
|
||||
_maybeRedirect(channel, browser, window, proxied);
|
||||
}, function(e) {
|
||||
_maybeRedirect(channel, browser, window, proxied);
|
||||
});
|
||||
Zotero.Proxies.lastIPCheck = now;
|
||||
return;
|
||||
}
|
||||
|
||||
if(Zotero.Proxies.disabledByDomain) return;
|
||||
}
|
||||
|
||||
_maybeRedirect(channel, browser, window, proxied);
|
||||
});
|
||||
|
||||
function _maybeRedirect(channel, browser, window, proxied) {
|
||||
channel.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
var proxiedURI = Services.io.newURI(proxied, null, null);
|
||||
if(channel.referrer) {
|
||||
// If the referrer is a proxiable host, we already have access (e.g., we're
|
||||
// on-campus) and shouldn't redirect
|
||||
if(Zotero.Proxies.properToProxy(channel.referrer.spec, true)) {
|
||||
Zotero.debug("Proxies: skipping redirect; referrer was proxiable");
|
||||
return;
|
||||
}
|
||||
// If the referrer is the same host as we're about to redirect to, we shouldn't
|
||||
// or we risk a loop
|
||||
if(channel.referrer.host == proxiedURI.host) {
|
||||
Zotero.debug("Proxies: skipping redirect; redirect URI and referrer have same host");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(channel.originalURI) {
|
||||
// If the original URI was a proxied host, we also shouldn't redirect, since any
|
||||
// links handed out by the proxy should already be proxied
|
||||
if(Zotero.Proxies.proxyToProper(channel.originalURI.spec, true)) {
|
||||
Zotero.debug("Proxies: skipping redirect; original URI was proxied");
|
||||
return;
|
||||
}
|
||||
// Finally, if the original URI is the same as the host we're about to redirect
|
||||
// to, then we also risk a loop
|
||||
if(channel.originalURI.host == proxiedURI.host) {
|
||||
Zotero.debug("Proxies: skipping redirect; redirect URI and original URI have same host");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure that the top two domains (e.g. gmu.edu in foo.bar.gmu.edu) of the
|
||||
// channel and the site to which we're redirecting don't match, to prevent loops.
|
||||
const top2DomainsRe = /[^\.]+\.[^\.]+$/;
|
||||
top21 = top2DomainsRe.exec(channel.URI.host);
|
||||
top22 = top2DomainsRe.exec(proxiedURI.host);
|
||||
if(!top21 || !top22 || top21[0] == top22[0]) {
|
||||
Zotero.debug("Proxies: skipping redirect; redirect URI and URI have same top 2 domains");
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, redirect. Note that we save the URI we're redirecting from as the
|
||||
// referrer, since we can't make a proper redirect
|
||||
if(Zotero.Proxies.showRedirectNotification) {
|
||||
_showNotification(
|
||||
browser,
|
||||
window,
|
||||
Zotero.getString('proxies.notification.redirected.label', [channel.URI.hostPort, proxiedURI.hostPort]),
|
||||
[
|
||||
{
|
||||
label: "general.dontShowAgain",
|
||||
callback: () => _disableRedirectNotification()
|
||||
},
|
||||
{
|
||||
label: "proxies.notification.settings.button",
|
||||
callback: () => _prefsOpenCallback(window)
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
browser.loadURIWithFlags(proxied, 0, channel.URI, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -425,145 +227,6 @@ Zotero.Proxies = new function() {
|
|||
}
|
||||
return urlToProxy;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 = [
|
||||
/edu$/,
|
||||
/google\.com$/,
|
||||
/wikipedia\.org$/,
|
||||
/^[^.]*$/,
|
||||
/doubleclick\.net$/
|
||||
];
|
||||
/**
|
||||
* Regular expression patterns of hosts that should always be proxied, regardless of whether
|
||||
* they're on the blacklist
|
||||
* @const
|
||||
*/
|
||||
const hostWhitelist = [
|
||||
/^scholar\.google\.com$/,
|
||||
/^muse\.jhu\.edu$/
|
||||
]
|
||||
|
||||
for (let blackPattern of hostBlacklist) {
|
||||
if(blackPattern.test(host)) {
|
||||
for (let whitePattern of 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.
|
||||
*/
|
||||
var _showDialog = Zotero.Promise.coroutine(function* (proxiedHost, proxyHost, proxy) {
|
||||
// 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.autoRecognize = false;
|
||||
Zotero.Prefs.set("proxies.autoRecognize", false);
|
||||
}
|
||||
|
||||
if(io.add) {
|
||||
yield proxy.erase();
|
||||
yield proxy.save(true);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get browser and window from a channel
|
||||
* @return {Object} Object containing the content browser as 'browser' and a ChromeWindow as 'window'
|
||||
*/
|
||||
function _getBrowserAndWindow(channel) {
|
||||
let outerWindowID = channel.loadInfo.outerWindowID;
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator);
|
||||
let outerContentWin = wm.getOuterWindowWithId(outerWindowID);
|
||||
if (!outerContentWin) {
|
||||
return { browser: null, window: null };
|
||||
}
|
||||
var browser = outerContentWin.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
|
||||
return {
|
||||
browser,
|
||||
window: browser.ownerDocument.defaultView
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a proxy-related notification
|
||||
* @param {Browser} browser
|
||||
* @param {Window} window
|
||||
* @param {String} label - notification text
|
||||
* @param {Object[]} buttons - Array of objects with 'label' (for getString()) and 'callback'
|
||||
*/
|
||||
function _showNotification(browser, window, label, buttons) {
|
||||
// Get localized button labels
|
||||
buttons = buttons.map(function(button) {
|
||||
return {
|
||||
label: Zotero.getString(button.label),
|
||||
callback: button.callback
|
||||
}
|
||||
});
|
||||
|
||||
var listener = function() {
|
||||
var nb = window.gBrowser.getNotificationBox();
|
||||
nb.appendNotification(label,
|
||||
'zotero-proxy', 'chrome://browser/skin/Info.png', nb.PRIORITY_WARNING_MEDIUM,
|
||||
buttons);
|
||||
browser.removeEventListener("pageshow", listener, false);
|
||||
}
|
||||
|
||||
browser.addEventListener("pageshow", listener, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables proxy redirection notification
|
||||
*/
|
||||
function _disableRedirectNotification() {
|
||||
Zotero.Proxies.showRedirectNotification = false;
|
||||
Zotero.Prefs.set("proxies.showRedirectNotification",false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens preferences window
|
||||
*/
|
||||
function _prefsOpenCallback(window) {
|
||||
window.openDialog('chrome://zotero/content/preferences/preferences.xul',
|
||||
'zotero-prefs',
|
||||
'chrome,titlebar,toolbar,'
|
||||
+ Zotero.Prefs.get('browser.preferences.instantApply', true) ? 'dialog=no' : 'modal',
|
||||
{"pane":"zotero-prefpane-proxies"}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -864,190 +527,6 @@ Zotero.Proxy.prototype.loadHosts = Zotero.Promise.coroutine(function* () {
|
|||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// 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 = Services.io.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 (proxy of Zotero.Proxies.proxies) {
|
||||
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 = Services.io.newChannelFromURI(toProxy);
|
||||
newChannel.originalURI = channel.originalURI ? channel.originalURI : channel.URI;
|
||||
newChannel.QueryInterface(Components.interfaces.nsIRequest).loadFlags = newChannel.loadFlags;
|
||||
Zotero.debug("Proxies: Identified putative port-by-port EZProxy link from "+fromProxy.hostPort+" to "+toProxy.hostPort);
|
||||
|
||||
new Zotero.Proxies.Detectors.EZProxy.Observer(newChannel);
|
||||
newChannel.asyncOpen(new Zotero.Proxies.Detectors.EZProxy.DummyStreamListener(), null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now try to catch redirects
|
||||
if(channel.responseStatus != 302) return false;
|
||||
try {
|
||||
if(channel.getResponseHeader("Server") != "EZproxy") return false;
|
||||
var proxiedURI = Services.io.newURI(channel.getResponseHeader("Location"), null, null);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
return Zotero.Proxies.Detectors.EZProxy.learn(channel.URI, proxiedURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Learn about a mapping from an EZProxy to a normal proxy
|
||||
* @param {nsIURI} loginURI The URL of the login page
|
||||
* @param {nsIURI} proxiedURI The URI of the page
|
||||
* @return {Zotero.Proxy | false}
|
||||
*/
|
||||
Zotero.Proxies.Detectors.EZProxy.learn = function(loginURI, proxiedURI) {
|
||||
// look for query
|
||||
var m = /\?(?:.+&)?(url|qurl)=([^&]+)/i.exec(loginURI.path);
|
||||
if(!m) return false;
|
||||
|
||||
// Ignore if we already know about it
|
||||
if(Zotero.Proxies.proxyToProper(proxiedURI.spec, true)) return false;
|
||||
|
||||
// Found URL
|
||||
var properURL = (m[1].toLowerCase() == "qurl" ? unescape(m[2]) : m[2]);
|
||||
var properURI = Services.io.newURI(properURL, null, null);
|
||||
|
||||
var proxy = false;
|
||||
if(loginURI.host == proxiedURI.host && [loginURI.port, 80, 443, -1].indexOf(proxiedURI.port) == -1) {
|
||||
// Proxy by port
|
||||
proxy = new Zotero.Proxy();
|
||||
proxy.multiHost = false;
|
||||
proxy.scheme = proxiedURI.scheme+"://"+proxiedURI.hostPort+"/%p";
|
||||
proxy.hosts = [properURI.hostPort];
|
||||
} else if(proxiedURI.host != loginURI.host && proxiedURI.hostPort.indexOf(properURI.host) != -1) {
|
||||
// Proxy by host
|
||||
proxy = new Zotero.Proxy();
|
||||
proxy.multiHost = proxy.autoAssociate = true;
|
||||
proxy.scheme = proxiedURI.scheme+"://"+proxiedURI.hostPort.replace(properURI.host, "%h")+"/%p";
|
||||
proxy.hosts = [properURI.hostPort];
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Do-nothing stream listener
|
||||
* @private
|
||||
*/
|
||||
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) {}
|
||||
|
||||
/**
|
||||
* @class Observer to clear cookies on an HTTP request, then remove itself
|
||||
* @private
|
||||
*/
|
||||
Zotero.Proxies.Detectors.EZProxy.Observer = function(newChannel) {
|
||||
this.channel = newChannel;
|
||||
Services.obs.addObserver(this, "http-on-modify-request", false);
|
||||
Services.obs.addObserver(this, "http-on-examine-response", false);
|
||||
}
|
||||
Zotero.Proxies.Detectors.EZProxy.Observer.prototype.observe = Zotero.Promise.coroutine(function* (aSubject, aTopic, aData) {
|
||||
if (aSubject == this.channel) {
|
||||
if(aTopic === "http-on-modify-request") {
|
||||
try {
|
||||
aSubject.QueryInterface(Components.interfaces.nsIHttpChannel).setRequestHeader("Cookie", "", false);
|
||||
} catch(e) {
|
||||
Zotero.logError(e);
|
||||
} finally {
|
||||
Services.obs.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
} else if(aTopic === "http-on-examine-response") {
|
||||
try {
|
||||
// Make sure this is a redirect involving an EZProxy
|
||||
if(aSubject.responseStatus !== 302) return;
|
||||
try {
|
||||
if(aSubject.getResponseHeader("Server") !== "EZproxy") return;
|
||||
var loginURL = aSubject.getResponseHeader("Location");
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
var proxy = Zotero.Proxies.Detectors.EZProxy.learn(Services.io.newURI(loginURL, null, null), aSubject.URI);
|
||||
if(proxy) {
|
||||
Zotero.debug("Proxies: Proxy-by-port EZProxy "+aSubject.URI.hostPort+" corresponds to "+proxy.hosts[0]);
|
||||
yield proxy.save();
|
||||
}
|
||||
} catch(e) {
|
||||
Zotero.logError(e);
|
||||
} finally {
|
||||
Services.obs.removeObserver(this, "http-on-examine-response");
|
||||
aSubject.cancel(0x80004004 /*NS_ERROR_ABORT*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
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
|
||||
* @param {nsIChannel} channel
|
||||
* @type Boolean|Zotero.Proxy
|
||||
*/
|
||||
Zotero.Proxies.Detectors.Juniper = function(channel) {
|
||||
const juniperRe = /^(https?:\/\/[^\/:]+(?:\:[0-9]+)?)\/(.*),DanaInfo=([^+,]*)([^+]*)(?:\+(.*))?$/;
|
||||
try {
|
||||
var url = channel.URI.spec;
|
||||
var m = juniperRe.exec(url);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
if(!m) return false;
|
||||
|
||||
var proxy = new Zotero.Proxy();
|
||||
proxy.multiHost = true;
|
||||
proxy.autoAssociate = false;
|
||||
proxy.scheme = m[1]+"/%d"+",DanaInfo=%h%a+%f";
|
||||
proxy.hosts = [m[3]];
|
||||
return proxy;
|
||||
}
|
||||
|
||||
Zotero.Proxies.DNS = new function() {
|
||||
this.getHostnames = function() {
|
||||
if (!Zotero.isWin && !Zotero.isMac && !Zotero.isLinux) return Zotero.Promise.resolve([]);
|
||||
|
|
Loading…
Reference in a new issue