2015-03-26 07:11:08 +00:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
|
|
|
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
|
|
|
Cu.import('resource://gre/modules/Services.jsm');
|
|
|
|
|
2015-09-15 18:19:45 +00:00
|
|
|
var DEBUG = false;
|
2015-03-26 07:11:08 +00:00
|
|
|
|
|
|
|
if (DEBUG) {
|
|
|
|
debug = function (s) { dump("-*- PACGenerator: " + s + "\n"); };
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
debug = function (s) {};
|
|
|
|
}
|
|
|
|
|
|
|
|
const PACGENERATOR_CONTRACTID = "@mozilla.org/pac-generator;1";
|
|
|
|
const PACGENERATOR_CID = Components.ID("{788507c4-eb5f-4de8-b19b-e0d531974e8a}");
|
|
|
|
|
|
|
|
//
|
|
|
|
// RFC 2396 section 3.2.2:
|
|
|
|
//
|
|
|
|
// host = hostname | IPv4address
|
|
|
|
// hostname = *( domainlabel "." ) toplabel [ "." ]
|
|
|
|
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
|
|
|
// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
|
|
|
|
// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
|
|
|
|
//
|
|
|
|
const HOST_REGEX =
|
|
|
|
new RegExp("^(?:" +
|
|
|
|
// *( domainlabel "." )
|
|
|
|
"(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
|
|
|
|
// toplabel
|
|
|
|
"[a-z](?:[a-z0-9-]*[a-z0-9])?" +
|
|
|
|
"|" +
|
|
|
|
// IPv4 address
|
|
|
|
"\\d+\\.\\d+\\.\\d+\\.\\d+" +
|
|
|
|
")$",
|
|
|
|
"i");
|
|
|
|
|
|
|
|
function PACGenerator() {
|
|
|
|
debug("Starting PAC Generator service.");
|
|
|
|
}
|
|
|
|
|
|
|
|
PACGenerator.prototype = {
|
|
|
|
|
|
|
|
classID : PACGENERATOR_CID,
|
|
|
|
|
|
|
|
QueryInterface : XPCOMUtils.generateQI([Ci.nsIPACGenerator]),
|
|
|
|
|
|
|
|
classInfo : XPCOMUtils.generateCI({classID: PACGENERATOR_CID,
|
|
|
|
contractID: PACGENERATOR_CONTRACTID,
|
|
|
|
classDescription: "PACGenerator",
|
|
|
|
interfaces: [Ci.nsIPACGenerator]}),
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Validate the the host.
|
|
|
|
*/
|
|
|
|
isValidHost: function isValidHost(host) {
|
|
|
|
if (!HOST_REGEX.test(host)) {
|
|
|
|
debug("Unexpected host: '" + host + "'");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a PAC string based on proxy settings in the preference.
|
|
|
|
* Only effective when the network.proxy.pac_generator preference is true.
|
|
|
|
*/
|
|
|
|
generate: function generate() {
|
|
|
|
let enabled, host, port, proxy;
|
|
|
|
|
|
|
|
try {
|
|
|
|
enabled = Services.prefs.getBoolPref("network.proxy.pac_generator");
|
|
|
|
} catch (ex) {}
|
|
|
|
if (!enabled) {
|
|
|
|
debug("PAC Generator disabled.");
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
let pac = "data:text/plain,function FindProxyForURL(url, host) { ";
|
|
|
|
|
|
|
|
// Direct connection for localhost.
|
|
|
|
pac += "if (shExpMatch(host, 'localhost') || " +
|
|
|
|
"shExpMatch(host, '127.0.0.1')) {" +
|
|
|
|
" return 'DIRECT'; } ";
|
|
|
|
|
|
|
|
// Rules for browsing proxy.
|
|
|
|
try {
|
|
|
|
enabled = Services.prefs.getBoolPref("network.proxy.browsing.enabled");
|
|
|
|
host = Services.prefs.getCharPref("network.proxy.browsing.host");
|
|
|
|
port = Services.prefs.getIntPref("network.proxy.browsing.port");
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
if (enabled && host && this.isValidHost(host)) {
|
|
|
|
proxy = host + ":" + ((port && port !== 0) ? port : 8080);
|
|
|
|
let appOrigins;
|
|
|
|
try {
|
|
|
|
appOrigins = Services.prefs.getCharPref("network.proxy.browsing.app_origins");
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
pac += "var origins ='" + appOrigins +
|
|
|
|
"'.split(/[ ,]+/).filter(Boolean); " +
|
|
|
|
"if ((origins.indexOf('*') > -1 || origins.indexOf(myAppOrigin()) > -1)" +
|
|
|
|
" && isInBrowser()) { return 'PROXY " + proxy + "'; } ";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rules for system proxy.
|
|
|
|
let share;
|
|
|
|
try {
|
|
|
|
share = Services.prefs.getBoolPref("network.proxy.share_proxy_settings");
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
if (share) {
|
|
|
|
// Add rules for all protocols.
|
|
|
|
try {
|
|
|
|
host = Services.prefs.getCharPref("network.proxy.http");
|
|
|
|
port = Services.prefs.getIntPref("network.proxy.http_port");
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
if (host && this.isValidHost(host)) {
|
|
|
|
proxy = host + ":" + ((port && port !== 0) ? port : 8080);
|
|
|
|
pac += "return 'PROXY " + proxy + "'; "
|
|
|
|
} else {
|
|
|
|
pac += "return 'DIRECT'; ";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Add rules for specific protocols.
|
|
|
|
const proxyTypes = [
|
|
|
|
{"scheme": "http:", "pref": "http"},
|
|
|
|
{"scheme": "https:", "pref": "ssl"},
|
|
|
|
{"scheme": "ftp:", "pref": "ftp"}
|
|
|
|
];
|
|
|
|
for (let i = 0; i < proxyTypes.length; i++) {
|
|
|
|
try {
|
|
|
|
host = Services.prefs.getCharPref("network.proxy." +
|
|
|
|
proxyTypes[i]["pref"]);
|
|
|
|
port = Services.prefs.getIntPref("network.proxy." +
|
|
|
|
proxyTypes[i]["pref"] + "_port");
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
if (host && this.isValidHost(host)) {
|
|
|
|
proxy = host + ":" + (port === 0 ? 8080 : port);
|
|
|
|
pac += "if (url.substring(0, " + (proxyTypes[i]["scheme"]).length +
|
|
|
|
") == '" + proxyTypes[i]["scheme"] + "') { return 'PROXY " +
|
|
|
|
proxy + "'; } ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pac += "return 'DIRECT'; ";
|
|
|
|
}
|
|
|
|
|
|
|
|
pac += "}";
|
|
|
|
|
|
|
|
debug("PAC: " + pac);
|
|
|
|
|
|
|
|
return pac;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PACGenerator]);
|