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 @@  - + Выбор провайдера PAC - @@ -130,16 +155,25 @@
Обновлялись: ...
- Загрузка... + Загрузка... +
+
+ +

Я ❤️ уведомления:
-