diff --git a/extensions/chromium/runet-censorship-bypass/extension/00-init-apis.js b/extensions/chromium/runet-censorship-bypass/extension/00-init-apis.js
index 75bf363..445fd3d 100644
--- a/extensions/chromium/runet-censorship-bypass/extension/00-init-apis.js
+++ b/extensions/chromium/runet-censorship-bypass/extension/00-init-apis.js
@@ -26,6 +26,23 @@ window.utils = {
},
+ getProp(obj, path = this.mandatory()) {
+
+ const props = path.split('.');
+ if (!props.length) {
+ throw new TypeError('Property must be supplied.');
+ }
+ const lastProp = props.pop();
+ for( const prop of props ) {
+ if (!(prop in obj)) {
+ return undefined;
+ }
+ obj = obj[prop];
+ }
+ return obj[lastProp];
+
+ },
+
areSettingsNotControlledFor(details) {
return ['controlled_by_other', 'not_controllable']
diff --git a/extensions/chromium/runet-censorship-bypass/extension/12-api-sync-pac-script-with-pac-provider.js b/extensions/chromium/runet-censorship-bypass/extension/12-api-sync-pac-script-with-pac-provider.js
index 50ebbc4..fefc98a 100644
--- a/extensions/chromium/runet-censorship-bypass/extension/12-api-sync-pac-script-with-pac-provider.js
+++ b/extensions/chromium/runet-censorship-bypass/extension/12-api-sync-pac-script-with-pac-provider.js
@@ -415,7 +415,7 @@
desc: 'Основной PAC-скрипт от автора расширения.' +
' Блокировка определятся по доменному имени или IP адресу.' +
' Работает на switch-ах.
' +
- ' Страница проекта.',
+ ' Страница проекта.',
/*
Don't use in system configs! Because Windows does poor caching.
diff --git a/extensions/chromium/runet-censorship-bypass/extension/13-pac-kitchen.js b/extensions/chromium/runet-censorship-bypass/extension/13-pac-kitchen.js
new file mode 100644
index 0000000..bfa2f49
--- /dev/null
+++ b/extensions/chromium/runet-censorship-bypass/extension/13-pac-kitchen.js
@@ -0,0 +1,252 @@
+'use strict';
+
+{ // Private namespace starts.
+
+ const kitchenStorageKey = 'pac-kitchen-kept-mods';
+ const kitchenStartsMark = '\n\n//%#@@@@@@ PAC_KITCHEN_STARTS @@@@@@#%';
+
+ const configs = {
+
+ ifProxyHttpsUrlsOnly: {
+ dflt: false,
+ label: 'проксировать только HTTPS-сайты',
+ desc: 'Проксировать только сайты, доступные по шифрованному протоколу HTTPS. Прокси и провайдер смогут видеть только адреса посещаемых вами ресурсов, но не их содержимое.',
+ index: 0,
+ },
+ ifUseSecureProxiesOnly: {
+ dflt: false,
+ label: 'только шифрованная связь с прокси',
+ desc: 'Шифровать соединение до прокси от провайдера. Провайдер всё же сможет видеть адреса (но не содержимое) посещаемых вами ресурсов из протокола DNS.',
+ index: 1,
+ },
+ ifUsePacScriptProxies: {
+ dflt: true,
+ label: 'использовать прокси PAC-скрипта',
+ desc: 'Использовать прокси от авторов PAC-скрипта.',
+ index: 2,
+ },
+ ifUseLocalTor: {
+ dflt: false,
+ label: 'использовать свой локальный TOR',
+ desc: 'Установите TOR на свой компьютер и используйте его как прокси. ВАЖНО',
+ index: 3,
+ },
+ customProxyStringRaw: {
+ dflt: '',
+ label: 'использовать свои прокси',
+ url: 'https://rebrand.ly/ac-own-proxy',
+ index: 4,
+ },
+
+ };
+
+ const getDefaults = function getDefaults() {
+
+ return Object.keys(configs).reduce((acc, key) => {
+
+ acc[key] = configs[key].dflt;
+ return acc;
+
+ }, {});
+
+ };
+
+ const getCurrentConfigs = function getCurrentConfigs() {
+
+ const json = localStorage.getItem(kitchenStorageKey);
+ if (!json) {
+ return null;
+ }
+ return new PacModifiers(JSON.parse(json));
+
+ };
+
+ const getOrderedConfigsForUser = function getOrderedConfigs() {
+
+ const pacMods = getCurrentConfigs() || {};
+ return Object.keys(configs).reduce((arr, key) => {
+
+ const conf = configs[key]
+ arr[conf.index] = conf;
+ conf.value = (key in pacMods) ? pacMods[key] : conf.dflt;
+ conf.key = key;
+ return arr;
+
+ }, []);
+
+ };
+
+ class PacModifiers {
+
+ constructor(mods = {}) {
+
+ const defaults = getDefaults();
+ const ifAllDefaults =
+ Object.keys(defaults)
+ .every(
+ (prop) => !(prop in mods) || Boolean(defaults[prop]) === Boolean(mods[prop])
+ );
+
+ Object.assign(this, defaults, mods);
+ this.ifNoMods = ifAllDefaults ? true : false;
+
+ let customProxyArray = [];
+ if (this.customProxyStringRaw) {
+ customProxyArray = this.customProxyStringRaw
+ .replace(/#.*$/mg, '') // Strip comments.
+ .split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g ).filter( (p) => p.trim() );
+ if (this.ifUseSecureProxiesOnly) {
+ customProxyArray = customProxyArray.filter( (p) => !p.startsWith('HTTP ') );
+ }
+ }
+ if (this.ifUseLocalTor) {
+ customProxyArray.push('SOCKS5 localhost:9050', 'SOCKS5 localhost:9150');
+ }
+
+ if (customProxyArray.length) {
+ this.customProxyArray = customProxyArray;
+ this.filteredCustomsString = customProxyArray.join('; ');
+ } else {
+ if (!this.ifUsePacScriptProxies) {
+ throw new TypeError('Нет ни одного прокси, удовлетворяющего вашим требованиям!');
+ }
+ this.customProxyArray = false;
+ this.filteredCustomsString = '';
+ }
+
+ }
+
+ };
+
+ window.apis.pacKitchen = {
+
+ getConfigs: getOrderedConfigsForUser,
+
+ cook(pacData, pacMods = window.utils.mandatory()) {
+
+ return pacMods.ifNoMods ? pacData : pacData + `${ kitchenStartsMark }
+;+function(global) {
+ "use strict";
+
+ const originalFindProxyForURL = FindProxyForURL;
+ global.FindProxyForURL = function(url, host) {
+ ${function() {
+
+ let res = '';
+ if (pacMods.ifProxyHttpsUrlsOnly) {
+
+ res = `
+ if (!url.startsWith("https")) {
+ return "DIRECT";
+ }
+`;
+ if(
+ !pacMods.ifUseSecureProxiesOnly &&
+ !pacMods.filteredCustomsString &&
+ pacMods.ifUsePacScriptProxies
+ ) {
+ return res + `
+ return originalFindProxyForURL(url, host);`;
+ }
+ }
+
+ return res + `
+ const originalProxyString = originalFindProxyForURL(url, host);
+ let originalProxyArray = originalProxyString.split(/(?:\\s*;\\s*)+/g).filter( (p) => p );
+ if (originalProxyArray.every( (p) => /^DIRECT$/i.test(p) )) {
+ // Directs only or null, no proxies.
+ return originalProxyString;
+ }
+ return ` +
+ function() {
+
+ if (!pacMods.ifUsePacScriptProxies) {
+ return '"' + pacMods.filteredCustomsString + '"';
+ }
+ let filteredOriginalsExp = 'originalProxyString';
+ if (pacMods.ifUseSecureProxiesOnly) {
+ filteredOriginalsExp =
+ 'originalProxyArray.filter( (p) => !p.toUpperCase().startsWith("HTTP ") ).join("; ")';
+ }
+ if ( !pacMods.filteredCustomsString ) {
+ return filteredOriginalsExp;
+ }
+ return '"' + pacMods.filteredCustomsString + '; " + ' + filteredOriginalsExp;
+
+ }() + ' + "; DIRECT";'; // Without DIRECT you will get 'PROXY CONN FAILED' pac-error.
+
+ }()}
+
+ };
+
+}(this);`;
+
+ },
+
+ keepCookedNow(pacMods = window.utils.mandatory(), cb) {
+
+ if (typeof(pacMods) === 'function') {
+ cb = pacMods;
+ const pacMods = getCurrentConfigs();
+ if (!pacMods) {
+ return cb(TypeError('PAC mods were never initialized.'));
+ }
+ } else {
+ try {
+ pacMods = new PacModifiers(pacMods);
+ } catch(e) {
+ return cb(e);
+ }
+ localStorage.setItem(kitchenStorageKey, JSON.stringify(pacMods));
+ }
+ chrome.proxy.settings.get({}, (details) => {
+
+ if (
+ details.levelOfControl === 'controlled_by_this_extension'
+ ) {
+ const pac = window.utils.getProp(details, 'value.pacScript');
+ if (pac && pac.data) {
+ // Delete old kitchen modifications.
+ pac.data = pac.data.replace(
+ new RegExp(kitchenStartsMark + '[\\s\\S]*$', 'g'),
+ ''
+ );
+ return chrome.proxy.settings.set(details, cb);
+ }
+ }
+ return cb(
+ null,
+ null,
+ [new TypeError('PAC-скрипт не обнаружен, но настройки будут активированы при установке PAC-скрипта.')]
+ );
+
+ });
+
+ },
+
+ resetToDefaultsVoid() {
+
+ delete localStorage[kitchenStorageKey];
+ this.keepCookedNow({});
+
+ },
+
+ };
+
+ const originalSet = chrome.proxy.settings.set.bind( chrome.proxy.settings );
+
+ chrome.proxy.settings.set = function(details, cb) {
+
+ const pac = window.utils.getProp(details, 'value.pacScript');
+ if (!(pac && pac.data)) {
+ return originalSet(details, cb);
+ }
+ const pacMods = getCurrentConfigs();
+ if (pacMods) {
+ pac.data = window.apis.pacKitchen.cook( pac.data, pacMods );
+ }
+ originalSet({ value: details.value }, cb);
+
+ };
+
+} // Private namespace ends.
diff --git a/extensions/chromium/runet-censorship-bypass/extension/manifest.json b/extensions/chromium/runet-censorship-bypass/extension/manifest.json
index 8cebd53..8a660a7 100755
--- a/extensions/chromium/runet-censorship-bypass/extension/manifest.json
+++ b/extensions/chromium/runet-censorship-bypass/extension/manifest.json
@@ -1,10 +1,10 @@
{
"manifest_version": 2,
- "name": "__MSG_extName__",
+ "name": "__MSG_extName__ 0.18",
"default_locale": "ru",
"description": "__MSG_extDesc__",
- "version": "0.0.0.17",
+ "version": "0.0.0.18",
"icons": {
"128": "/icons/default-128.png"
},
@@ -26,14 +26,15 @@
"scripts": [
"00-init-apis.js",
"11-api-error-handlers.js",
- "12-api-sync-pac-script-with-pac-provider.js",
+ "13-pac-kitchen.js",
+ "15-api-sync-pac-script-with-pac-provider.js",
"20-api-fixes.js",
"30-block-informer.js",
"40-context-menus.js"
]
},
"browser_action": {
- "default_title": "Этот сайт благословлён 0.17",
+ "default_title": "Этот сайт благословлён 0.18",
"default_popup": "/pages/choose-pac-provider/index.html"
},
"options_ui": {
diff --git a/extensions/chromium/runet-censorship-bypass/extension/pages/choose-pac-provider/index.html b/extensions/chromium/runet-censorship-bypass/extension/pages/choose-pac-provider/index.html
index 65bdc67..81bfe34 100755
--- a/extensions/chromium/runet-censorship-bypass/extension/pages/choose-pac-provider/index.html
+++ b/extensions/chromium/runet-censorship-bypass/extension/pages/choose-pac-provider/index.html
@@ -1,8 +1,7 @@
-
+