mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2025-04-20 09:12:02 +03:00
Compare commits
No commits in common. "development" and "1.5" have entirely different histories.
developmen
...
1.5
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
|
@ -1,12 +0,0 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # ilyaigpetrov
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective:
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: https://github.com/anticensority/runet-censorship-bypass/wiki/Поддержать
|
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
78
README.md
Normal file → Executable file
78
README.md
Normal file → Executable file
|
@ -1,71 +1,35 @@
|
|||
If you __unstar__, please, [leave us a note](https://github.com/anticensority/runet-censorship-bypass/issues) why you do so.
|
||||
# [Maintainer Needed! Нужен разработчик!](https://github.com/anticensorship-russia/chromium-extension/issues/2)
|
||||
|
||||
[d1]: https://img.shields.io/badge/Поддержать-❤-green.svg
|
||||
[d2]: https://github.com/anticensority/runet-censorship-bypass/wiki/Поддержать
|
||||
Also, if you __unstar__, please, [leave us a note](https://github.com/anticensorship-russia/chromium-extension/issues) why you do so.
|
||||
|
||||
[![Поддержать][d1]][d2]
|
||||
[](#backers)
|
||||
[](#sponsors)
|
||||
# Russian Anti-Censorship on PAC-Scripts
|
||||
|
||||
# Russian Anticensorship on PAC-Scripts
|
||||
This repo contains:
|
||||
|
||||
This repo contains an extension for Chromium and FireFox that helps to bypass censorship in Russia: [WebStore](https://chrome.google.com/webstore/detail/npgcnondjocldhldegnakemclmfkngch)
|
||||
| [Sources](./extensions/chromium/runet-censorship-bypass).
|
||||
This extension uses pac scripts, one of which (anticensority) is generated by this [pac-generator].
|
||||
1. Chrome Extension to bypass censorship in Russia:
|
||||
[WebStore](https://chrome.google.com/webstore/detail/npgcnondjocldhldegnakemclmfkngch)
|
||||
| [Sources](https://github.com/ilyaigpetrov/anti-censorship-russia/tree/master/extensions/chromium/minimalistic-pac-setter)
|
||||
2. Proof of concept PAC-script generator based on https://github.com/zapret-info/z-i
|
||||
3. ~~PAC-scripts performance analyses of scripts generated~~ (doesn't take parse time into account)
|
||||
4. Based on the research of step 3 [the final PAC-generator][pac-generator] was written as a Google App Script in JavaScript which is triggered every two hours to generate and publish PAC-script on Google Drive (don't use direct URL without extension, please, URL will be periodically changed to counter abuse).
|
||||
|
||||
[pac-generator]: https://github.com/anticensority/pac-script-generator
|
||||
|
||||
## Install / Установка
|
||||
|
||||
1. [Chrome Web Store](https://chrome.google.com/webstore/detail/обход-блокировок-рунета/npgcnondjocldhldegnakemclmfkngch)
|
||||
2. [Chrome Web Store (MINI)](https://chrome.google.com/webstore/detail/обход-блокировок-рунета-м/gnknjnebjldmkpmlhjipalimhjofpgho)
|
||||
3. [Microsoft Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/обход-блокировок-рунета/ajgpnodjpffiagcfmifildjpoaeiobfh)
|
||||
4. [Microsoft Edge Add-ons (MINI)](https://microsoftedge.microsoft.com/addons/detail/обход-блокировок-рунета-м/cjppllmpmkpjfchbaoebeneghcbmlibj)
|
||||
5. [FireFox Add-ons](https://addons.mozilla.org/ru/firefox/addon/обход-блокировок-рунета/).
|
||||
6. Opera: сначала [установщик расширений из WebStore](https://addons.opera.com/ru/extensions/details/install-chrome-extensions/) (от команды Opera), затем см. пункты 1 и 2 выше.
|
||||
7. Пакеты для автономной (offline) установки / Packages for offline installation: https://github.com/anticensority/runet-censorship-bypass/releases.
|
||||
|
||||
Из-за блокировок адресов Google расширение может не устанавливаться из WebStore. Подробности и способы установки см. https://github.com/anticensority/runet-censorship-bypass/wiki/Автономная-установка-расширения.
|
||||
[pac-generator]: https://script.google.com/d/1RlqqfUmYNpEhekySfOqdzJ8L4eV1GsHYDjPD1DexxEW0RcGvuCSQlWa0/edit?usp=sharing
|
||||
|
||||
## Why I do This
|
||||
|
||||
See [my arguments against censorship (ru)](https://github.com/anticensority/runet-censorship-bypass/wiki/Почему-мы-это-делаем%3F-Аргументы-против-цензуры).
|
||||
I believe __information mustn't be blocked based on political or other subjective views__.
|
||||
|
||||
Looking at how Russian government [distorts TV](https://therussianreader.wordpress.com/2015/11/22/russian-truckers-strike-dagestan/) and blocks [critics of Putin](https://www.reuters.com/article/us-russia-internet-idUSBREA2C21L20140313),
|
||||
My maxim is _"Your freedom ends when it starts to confine the freedom of others"_.
|
||||
|
||||
See [my other arguments against censorship (ru)](https://gist.github.com/ilyaigpetrov/9452b93ef3d7dd3d8cc2)
|
||||
|
||||
Looking at how Russian government [distorts TV](https://therussianreader.wordpress.com/2015/11/22/russian-truckers-strike-dagestan/) and blocks [critics of Putin](http://www.reuters.com/article/2014/03/13/us-russia-internet-idUSBREA2C21L20140313),
|
||||
I decided to write an anti-censorship extension for Chromium before they strike me first.
|
||||
|
||||
## How it Works
|
||||
|
||||
0. PAC script is a JavaScript file, triggered on every URL request, which tells the browser which proxy to use if any for this particular URL.
|
||||
1. The Chrome Extension sets the PAC-script in browser settings and keeps it synced with the PAC script on the server. It offers Antizapret (hosted on a dedicated server) or Anticensority (hosted on GitHub) built-in PAC scripts for the user choice.
|
||||
2. On every request the PAC script checks if the host is blocked or if its IP is blocked.
|
||||
3. If an address is blocked, the PAC script returns the proxy server to the browser. The Antizapret PAC script uses its own proxy servers and the Anticensority PAC-script uses local Tor.
|
||||
0. PAC script is a JavaScript file, triggered on every URL request, which says browser which proxy to use if any for this particular URL.
|
||||
1. The Chrome Extension sets PAC script in browser settings and keeps it synced with PAC script on the server (offering Antizapret (hosted on a dedicated server) or Anticensority (hosted on GitHub + CloudFlare)).
|
||||
2. On every request PAC script checks if host is blocked or if its IP is blocked.
|
||||
3. If address is blocked PAC script returns proxy server to the browser, both Antizapret and Anticensority use Antizapret proxy servers.
|
||||
4. PAC scripts on servers are updated periodically from https://github.com/zapret-info/z-i.
|
||||
|
||||
## Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute.
|
||||
<a href="https://github.com/anticensority/runet-censorship-bypass/graphs/contributors"><img src="https://opencollective.com/anticensority/contributors.svg?width=890&button=false?force" /></a>
|
||||
|
||||
|
||||
## Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/anticensority#backer)]
|
||||
|
||||
<a href="https://opencollective.com/anticensority#backers" target="_blank"><img src="https://opencollective.com/anticensority/backers.svg?width=890"></a>
|
||||
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/anticensority#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/anticensority/sponsor/0/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/1/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/2/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/3/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/4/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/5/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/6/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/7/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/8/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/anticensority/sponsor/9/website" target="_blank"><img src="https://opencollective.com/anticensority/sponsor/9/avatar.svg"></a>
|
||||
|
|
|
@ -1,33 +1,30 @@
|
|||
# Install
|
||||
# Dev
|
||||
|
||||
Tested on:
|
||||
Linting JS: `npm run lint`
|
||||
|
||||
NodeJS: v16.1.0.
|
||||
NPM: 7.11.2.
|
||||
OS: Linux Mint 20 Xfce Edition.
|
||||
# О расширении
|
||||
|
||||
```
|
||||
npm install
|
||||
cd src/extension-common/pages/options/
|
||||
npm install
|
||||
cd -
|
||||
Обход интернет-цензуры в России пока что не является преступлением.
|
||||
|
||||
# For debugging:
|
||||
npm start
|
||||
# Use your build/extension-beta
|
||||
Расширение позволяет обходить блокировки РосКомНадзора, давая вам доступ
|
||||
к библиотекам, энциклопедиям, сайтам оппозиционеров, а также к неповинным
|
||||
сайтам, случайно заблокированным в силу разных причин.
|
||||
|
||||
# For production:
|
||||
npm start
|
||||
# Use your build/extension-full or build/extension-mini
|
||||
```
|
||||
Проксирует только заблокированные сайты, оставляя нетронутыми все остальные.
|
||||
|
||||
# For Reviewers
|
||||
Устанавливает PAC-скрипт, работающий через сервера anticenz.org и antizapret.prostovpn.org.
|
||||
|
||||
See ./src/extension-common/FOR_REVIEWERS.md.
|
||||
Обновляет PAC-скрипт каждые 4 часа, что составляет примерно 7MB трафика в сутки.
|
||||
Также расширение постоянно потребляет ~15MB памяти для информирования о блокировках через иконку.
|
||||
|
||||
# Release Instructions
|
||||
Синяя лента – кампания фонда EFF в защиту свобод слова, прессы и союзов.
|
||||
|
||||
1. `npm run release`
|
||||
2. `vim src/templates-data.js` and bump version.
|
||||
3. Commit bumped version.
|
||||
4. Merge development to production (usually after deployment and testing and many patches).
|
||||
Если расширение не работает: https://git.io/vgDDj
|
||||
|
||||
Антицензура на Реддите: https://www.reddit.com/r/anticensorship_russia
|
||||
Группа в G+: https://goo.gl/Lh0Cjh
|
||||
История изменений: https://github.com/ilyaigpetrov/anti-censorship-russia/releases
|
||||
|
||||
# Дополнительно
|
||||
|
||||
Иконка синей ленты: http://www.iconsdb.com/icon-sets/cardboard-blue-icons/ribbon-12-icon.html
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# О расширении
|
||||
|
||||
Обход интернет-цензуры в России пока что не является преступлением.
|
||||
|
||||
Расширение позволяет обходить блокировки РосКомНадзора, давая вам доступ
|
||||
к библиотекам, энциклопедиям, сайтам оппозиционеров, а также к неповинным
|
||||
сайтам, случайно заблокированным в силу разных причин.
|
||||
|
||||
Проксирует только заблокированные сайты, оставляя нетронутыми все остальные.
|
||||
|
||||
Устанавливает PAC-скрипт, работающий через сервера anticenz.org и antizapret.prostovpn.org.
|
||||
|
||||
Обновляет PAC-скрипт каждые 4 часа, что составляет примерно 7MB трафика в сутки.
|
||||
Также расширение постоянно потребляет ~15MB памяти для информирования о блокировках через иконку.
|
||||
|
||||
Синяя лента – кампания фонда EFF в защиту свобод слова, прессы и союзов.
|
||||
|
||||
Если расширение не работает: https://git.io/vgDDj
|
||||
|
||||
Антицензура на Реддите: https://www.reddit.com/r/anticensorship_russia
|
||||
История изменений: https://github.com/anticensority/runet-censorship-bypass/releases
|
||||
|
||||
# Дополнительно
|
||||
|
||||
Иконка синей ленты: http://www.iconsdb.com/icon-sets/cardboard-blue-icons/ribbon-12-icon.html
|
|
@ -1 +1 @@
|
|||
grep -r "$@" ./*.js ./src --exclude-dir=vendor --exclude-dir=node_modules --exclude-dir=dist
|
||||
grep -r $@ ./src --exclude-dir=vendor --exclude-dir=node_modules
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const gulp = require('gulp');
|
||||
const del = require('del');
|
||||
const through = require('through2');
|
||||
const PluginError = require('plugin-error');
|
||||
const PluginError = require('gulp-util').PluginError;
|
||||
const changed = require('gulp-changed');
|
||||
|
||||
const PluginName = 'Template literals';
|
||||
|
@ -29,7 +29,7 @@ const templatePlugin = (context) => through.obj(function(file, encoding, cb) {
|
|||
|
||||
}, { keys: [], values: [] });
|
||||
try {
|
||||
file.contents = Buffer.from(
|
||||
file.contents = new Buffer(
|
||||
(new Function(...keys, 'return `' + String(file.contents) + '`;'))(...values)
|
||||
);
|
||||
} catch(e) {
|
||||
|
@ -43,65 +43,81 @@ const templatePlugin = (context) => through.obj(function(file, encoding, cb) {
|
|||
|
||||
});
|
||||
|
||||
gulp.task('default', ['build']);
|
||||
|
||||
const clean = function(cb) {
|
||||
gulp.task('clean', function(cb) {
|
||||
|
||||
del.sync('./build');
|
||||
//return del.sync('./build');
|
||||
return cb();
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
const contexts = require('./src/templates-data').contexts;
|
||||
|
||||
const excFolder = (name) => [`!./src/**/${name}`, `!./src/**/${name}/**/*`];
|
||||
const excluded = [ ...excFolder('test') , ...excFolder('node_modules'), ...excFolder('src') ];
|
||||
const commonWoTests = ['./src/extension-common/**/*', ...excluded];
|
||||
|
||||
const miniDst = './build/extension-mini';
|
||||
const fullDst = './build/extension-full';
|
||||
const betaDst = './build/extension-beta';
|
||||
const firefoxDst = './build/extension-firefox';
|
||||
|
||||
const commonSrc = './src/extension-common/**/*';;
|
||||
const miniSrc = './src/extension-mini/**/*';
|
||||
const fullSrc = './src/extension-full/**/*';
|
||||
const firefoxSrc = './src/extension-firefox/**/*';
|
||||
gulp.task('_cp-common', ['clean'], function(cb) {
|
||||
|
||||
const joinSrc = (...args) => [...args, ...excluded];
|
||||
let fins = 0;
|
||||
const intheend = () => {
|
||||
if (++fins === 2) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
const copyMini = function(cb) {
|
||||
gulp.src(commonWoTests)
|
||||
//.pipe(changed(miniDst))
|
||||
.pipe(templatePlugin(contexts.mini))
|
||||
.pipe(gulp.dest(miniDst))
|
||||
.on('end', intheend);
|
||||
|
||||
gulp.src(joinSrc(commonSrc, miniSrc))
|
||||
gulp.src(commonWoTests)
|
||||
//.pipe(changed(fullDst))
|
||||
.pipe(templatePlugin(contexts.full))
|
||||
.pipe(gulp.dest(fullDst))
|
||||
.on('end', intheend);
|
||||
|
||||
gulp.src(commonWoTests)
|
||||
//.pipe(changed(fullDst))
|
||||
.pipe(templatePlugin(contexts.beta))
|
||||
.pipe(gulp.dest(betaDst))
|
||||
.on('end', intheend);
|
||||
});
|
||||
|
||||
gulp.task('_cp-mini', ['_cp-common'], function(cb) {
|
||||
|
||||
gulp.src(['./src/extension-mini/**/*', ...excluded])
|
||||
//.pipe(changed(miniDst))
|
||||
.pipe(templatePlugin(contexts.mini))
|
||||
.pipe(gulp.dest(miniDst))
|
||||
.on('end', cb);
|
||||
};
|
||||
});
|
||||
|
||||
const copyFull = function(cb) {
|
||||
gulp.task('_cp-full', ['_cp-common'], function(cb) {
|
||||
|
||||
gulp.src(joinSrc(commonSrc, fullSrc))
|
||||
gulp.src(['./src/extension-full/**/*', ...excluded])
|
||||
//.pipe(changed(fullDst))
|
||||
.pipe(templatePlugin(contexts.full))
|
||||
.pipe(gulp.dest(fullDst))
|
||||
.on('end', cb);
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
const copyBeta = function(cb) {
|
||||
gulp.task('_cp-beta', ['_cp-common'], function(cb) {
|
||||
|
||||
gulp.src(joinSrc(commonSrc, fullSrc))
|
||||
gulp.src(['./src/extension-full/**/*', ...excluded])
|
||||
//.pipe(changed(fullDst))
|
||||
.pipe(templatePlugin(contexts.beta))
|
||||
.pipe(gulp.dest(betaDst))
|
||||
.on('end', cb);
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
const buildAll = gulp.series(clean, gulp.parallel(copyMini, copyFull, copyBeta));
|
||||
const buildBeta = copyBeta;
|
||||
|
||||
module.exports = {
|
||||
default: buildAll,
|
||||
buildAll,
|
||||
buildBeta,
|
||||
};
|
||||
gulp.task('build:all', ['_cp-mini', '_cp-full', '_cp-beta']);
|
||||
gulp.task('build', ['_cp-full']);
|
||||
|
|
11452
extensions/chromium/runet-censorship-bypass/package-lock.json
generated
11452
extensions/chromium/runet-censorship-bypass/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -3,29 +3,27 @@
|
|||
"version": "0.0.19",
|
||||
"description": "Development tools for chromium extension",
|
||||
"scripts": {
|
||||
"postinstall": "node --use_strict -e \"const fs = require('fs'), path = 'node_modules/_project-root'; fs.unlink(path, ()=> fs.symlinkSync('..', path, 'dir'));\"",
|
||||
"lint": "eslint ./src/**/*.js --ignore-pattern vendor",
|
||||
"gulp": "gulp",
|
||||
"test": "mocha --recursive ./src/**/test/*",
|
||||
"subpages": "cd ./src/extension-common/pages/options/ && npm run build && cd -",
|
||||
"subpages:dev": "cd ./src/extension-common/pages/options/ && npm run build:dev:nocomp && cd -",
|
||||
"start": "npm run release",
|
||||
"release": "npm run subpages && npx gulp -- buildAll"
|
||||
"start": "npm run subpages && npm run gulp",
|
||||
"beta": "npm run subpages && npm run gulp build:all"
|
||||
},
|
||||
"author": "Ilya Ig. Petrov",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"chai": "^4.3.0",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"gulp-changed": "^4.0.2",
|
||||
"mocha": "^8.2.1",
|
||||
"sinon-chrome": "^3.0.1",
|
||||
"symlink-to": "^0.0.4"
|
||||
"chai": "^3.5.0",
|
||||
"eslint": "^3.15.0",
|
||||
"eslint-config-google": "^0.7.1",
|
||||
"gulp-changed": "^3.1.0",
|
||||
"mocha": "^3.3.0",
|
||||
"sinon-chrome": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"del": "^6.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"plugin-error": "^1.0.1",
|
||||
"through2": "^4.0.2"
|
||||
"del": "^2.2.2",
|
||||
"gulp": "^3.9.1",
|
||||
"through2": "^2.0.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
console.log('Extension started.');
|
||||
|
||||
{
|
||||
|
||||
const IF_DEBUG = true;
|
||||
|
@ -41,18 +39,15 @@ console.log('Extension started.');
|
|||
|
||||
},
|
||||
|
||||
lastError: undefined,
|
||||
|
||||
checkChromeError() {
|
||||
|
||||
// Chrome API calls your cb in a context different from the point of API
|
||||
// method invokation.
|
||||
const err = chrome.runtime.lastError || chrome.extension.lastError || self.lastError;
|
||||
const err = chrome.runtime.lastError || chrome.extension.lastError;
|
||||
if (!err) {
|
||||
return;
|
||||
}
|
||||
console.warn('API returned error:', err);
|
||||
delete self.lastError;
|
||||
return new Error(err.message); // Add stack.
|
||||
|
||||
},
|
||||
|
@ -76,19 +71,6 @@ console.log('Extension started.');
|
|||
|
||||
},
|
||||
|
||||
getOrDie(cb = self.mandatory()) {
|
||||
|
||||
return self.chromified((err, ...args) => {
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
cb(...args);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
getProp(obj, path = self.mandatory()) {
|
||||
|
||||
const props = path.split('.');
|
||||
|
@ -158,32 +140,6 @@ console.log('Extension started.');
|
|||
|
||||
},
|
||||
|
||||
promisedLocalStorage: {
|
||||
get(key) {
|
||||
return new Promise((resolve) => (
|
||||
chrome.storage.local.get(
|
||||
key,
|
||||
window.utils.getOrDie((storage) => resolve(key ? storage[key] : storage)),
|
||||
)
|
||||
));
|
||||
},
|
||||
set(items) {
|
||||
return new Promise((resolve) => (
|
||||
chrome.storage.local.set(items, resolve)
|
||||
));
|
||||
},
|
||||
remove(keys) {
|
||||
return new Promise((resolve) => (
|
||||
chrome.storage.local.remove(keys, resolve)
|
||||
));
|
||||
},
|
||||
clear() {
|
||||
return new Promise((resolve) => (
|
||||
chrome.storage.local.clear(resolve)
|
||||
));
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Possible values for levelOfControl:
|
||||
*
|
||||
|
@ -212,7 +168,7 @@ console.log('Extension started.');
|
|||
|
||||
searchSettingsForUrl(niddle) {
|
||||
|
||||
return 'chrome://settings/?search=' + (chrome.i18n.getMessage(niddle) || niddle);
|
||||
return 'chrome://settings/search#' + (chrome.i18n.getMessage(niddle) || niddle);
|
||||
|
||||
},
|
||||
|
||||
|
@ -220,86 +176,19 @@ console.log('Extension started.');
|
|||
|
||||
return chrome.i18n.getMessage('noControl') +
|
||||
` <a href="${ this.searchSettingsForUrl('proxy') }">
|
||||
${ chrome.i18n.getMessage('WhichQ') }
|
||||
${ chrome.i18n.getMessage('which') }
|
||||
</a>`;
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
parseProxyScheme(proxyAsStringRaw) {
|
||||
|
||||
const proxyAsString = proxyAsStringRaw.trim();
|
||||
const [type] = proxyAsString.split(/\s+/);
|
||||
/*
|
||||
if (!/^[a-zA-Z0-9]+$/.test(type)) {
|
||||
throw new Error(`${type} is not a proxy type!`);
|
||||
}
|
||||
JS has no code blocks in RE, seems safe to omit this check.
|
||||
*/
|
||||
const typeRe = new RegExp(`^${type}\\s+`, 'g');
|
||||
const crededAddr = proxyAsString.replace(typeRe, '');
|
||||
|
||||
let parts;
|
||||
parts = crededAddr.split('@');
|
||||
let [creds, addr] = [parts.slice(0, -1).join('@'), parts[parts.length - 1]];
|
||||
|
||||
const [hostname, port] = addr.split(':');
|
||||
|
||||
parts = creds.split(':')
|
||||
const username = parts[0];
|
||||
const password = parts.slice(1).join(':');
|
||||
|
||||
return {
|
||||
type,
|
||||
username,
|
||||
password,
|
||||
hostname,
|
||||
port,
|
||||
creds,
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
openAndFocus(url) {
|
||||
|
||||
chrome.tabs.create(
|
||||
{url: url},
|
||||
(tab) => chrome.windows.update(tab.windowId, {focused: true})
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
const max = 2**16;
|
||||
const versionToArray = (v) => [ ...v.split('.'), 0, 0, 0].slice(0,4);
|
||||
const versionToInt = (v) => versionToArray(v)
|
||||
.reverse()
|
||||
.reduce((acc, vv, i) => acc + parseInt(vv)*(max**i), 0);
|
||||
|
||||
const compareVersions = (a, b) => versionToInt(a) - versionToInt(b);
|
||||
|
||||
const ifFirefox = navigator.userAgent.toLowerCase().includes('firefox');
|
||||
|
||||
let give;
|
||||
const promise = !ifFirefox ? Promise.resolve() : new Promise((resolve) => {
|
||||
give = resolve;
|
||||
});
|
||||
|
||||
window.apis = {
|
||||
consent: {
|
||||
promise,
|
||||
give,
|
||||
},
|
||||
platform: {
|
||||
ifFirefox,
|
||||
},
|
||||
version: {
|
||||
ifMini: false,
|
||||
build: chrome.runtime.getManifest().version.replace(/\d+\.\d+\./g, ''),
|
||||
|
||||
isLeq: (a, b) => compareVersions(a, b) <= 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
const errorJsonReplacer = function errorJsonReplacer(key, value) {
|
||||
|
||||
// fooWindow.ErrorEvent !== barWindow.ErrorEvent
|
||||
if (value === window) {
|
||||
return; // STUPID, because other window object may be passed.
|
||||
}
|
||||
if (!( value && value.constructor
|
||||
&& ['Error', 'Event'].some(
|
||||
(suff) => value.constructor.name.endsWith(suff)
|
||||
|
@ -53,6 +50,15 @@
|
|||
|
||||
};
|
||||
|
||||
const openAndFocus = function openAndFocus(url) {
|
||||
|
||||
chrome.tabs.create(
|
||||
{url: url},
|
||||
(tab) => chrome.windows.update(tab.windowId, {focused: true})
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
const ifPrefix = 'if-on-';
|
||||
const extName = chrome.runtime.getManifest().name;
|
||||
const extVersion = window.apis.version.build;
|
||||
|
@ -66,12 +72,10 @@
|
|||
const errors = err ? {[type]: err} : this.idToError;
|
||||
const json = JSON.stringify(errors, errorJsonReplacer, 0);
|
||||
|
||||
window.utils.openAndFocus(
|
||||
'https://anticensority.github.io/error/?json=' + encodeURIComponent(json) +
|
||||
openAndFocus(
|
||||
'http://rebrand.ly/ac-error/?json=' + encodeURIComponent(json) +
|
||||
(type ? '&type=' + encodeURIComponent(type) : '') +
|
||||
'&version=' + chrome.runtime.getManifest().version +
|
||||
'&useragent=' + encodeURIComponent(navigator.userAgent) +
|
||||
'&platform=' + encodeURIComponent(navigator.platform),
|
||||
'&version=' + chrome.runtime.getManifest().version
|
||||
);
|
||||
|
||||
},
|
||||
|
@ -110,22 +114,20 @@
|
|||
|
||||
isControllable(details) {
|
||||
|
||||
if (details) {
|
||||
this.ifControllable = window.utils.areSettingsControllableFor(details);
|
||||
this.ifControllable = window.utils.areSettingsControllableFor(details);
|
||||
|
||||
if (this.ifControllable) {
|
||||
this.ifControlled = window.utils.areSettingsControlledFor(details);
|
||||
} else {
|
||||
this.ifControlled = false;
|
||||
}
|
||||
if (this.ifControllable) {
|
||||
this.ifControlled = window.utils.areSettingsControlledFor(details);
|
||||
} else {
|
||||
this.ifControlled = false;
|
||||
}
|
||||
|
||||
if (this.ifControlled) {
|
||||
chrome.browserAction.setIcon( {path: './icons/default-128.png'} );
|
||||
} else {
|
||||
chrome.browserAction.setIcon({
|
||||
path: './icons/default-grayscale-128.png',
|
||||
});
|
||||
}
|
||||
if (this.ifControlled) {
|
||||
chrome.browserAction.setIcon( {path: './icons/default-128.png'} );
|
||||
} else {
|
||||
chrome.browserAction.setIcon({
|
||||
path: './icons/default-grayscale-128.png',
|
||||
});
|
||||
}
|
||||
|
||||
return this.ifControllable;
|
||||
|
@ -134,9 +136,7 @@
|
|||
|
||||
isControlled(details) {
|
||||
|
||||
if (details) {
|
||||
this.isControllable(details);
|
||||
}
|
||||
this.isControllable(details);
|
||||
return this.ifControlled;
|
||||
|
||||
},
|
||||
|
@ -148,9 +148,7 @@
|
|||
timeouted(
|
||||
(details) => {
|
||||
|
||||
if (details) {
|
||||
this.isControllable(details);
|
||||
}
|
||||
this.isControllable(details);
|
||||
cb();
|
||||
|
||||
}
|
||||
|
@ -177,15 +175,16 @@
|
|||
const message = errOrMessage.message || errOrMessage.toString();
|
||||
chrome.notifications.create(
|
||||
id,
|
||||
Object.assign({
|
||||
{
|
||||
title: title,
|
||||
message: message,
|
||||
contextMessage: context,
|
||||
requireInteraction: ifSticky,
|
||||
type: 'basic',
|
||||
iconUrl: './icons/' + icon,
|
||||
appIconMaskUrl: './icons/default-mask-128.png',
|
||||
isClickable: true,
|
||||
}, window.apis.platform.ifFirefox ? {} : { requireInteraction: ifSticky }),
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
|
@ -233,7 +232,7 @@
|
|||
|
||||
chrome.notifications.clear(notId);
|
||||
if(notId === 'no-control') {
|
||||
return window.utils.openAndFocus(
|
||||
return openAndFocus(
|
||||
window.utils.messages.searchSettingsForUrl('proxy')
|
||||
);
|
||||
}
|
||||
|
@ -243,7 +242,7 @@
|
|||
|
||||
handlers.installListenersOn(window, 'BG');
|
||||
|
||||
(chrome.proxy.onProxyError || chrome.proxy.onError).addListener( timeouted( (details) => {
|
||||
chrome.proxy.onProxyError.addListener( timeouted( (details) => {
|
||||
|
||||
if (!handlers.ifControlled) {
|
||||
return;
|
||||
|
@ -254,11 +253,7 @@
|
|||
error: "net::ERR_PAC_SCRIPT_FAILED",
|
||||
fatal: false,
|
||||
*/
|
||||
const ifConFail = [
|
||||
'net::ERR_TUNNEL_CONNECTION_FAILED',
|
||||
'net::ERR_PROXY_CONNECTION_FAILED',
|
||||
].includes(details.error);
|
||||
|
||||
const ifConFail = details.error === 'net::ERR_PROXY_CONNECTION_FAILED';
|
||||
if (ifConFail) {
|
||||
// Happens if you return neither prixies nor "DIRECT".
|
||||
// Ignore it.
|
||||
|
@ -267,7 +262,7 @@
|
|||
console.warn('PAC ERROR', details);
|
||||
// TOOD: add "view pac script at this line" button.
|
||||
handlers.mayNotify('pac-error', 'Ошибка PAC!',
|
||||
(details.error || details.message /* Firefox */) + '\n' + details.details,
|
||||
details.error + '\n' + details.details,
|
||||
{icon: 'pac-error-128.png'}
|
||||
);
|
||||
|
||||
|
@ -275,14 +270,14 @@
|
|||
|
||||
chrome.proxy.settings.onChange.addListener( timeouted( (details) => {
|
||||
|
||||
console.log('Proxy settings changed:', details.levelOfControl);
|
||||
console.log('Proxy settings changed.', details);
|
||||
const noCon = 'no-control';
|
||||
const ifWasControllable = handlers.ifControllable;
|
||||
if ( !handlers.isControllable(details) && ifWasControllable ) {
|
||||
handlers.mayNotify(
|
||||
noCon,
|
||||
chrome.i18n.getMessage('noControl'),
|
||||
chrome.i18n.getMessage('WhichQ'),
|
||||
chrome.i18n.getMessage('which'),
|
||||
{icon: 'no-control-128.png', ifSticky: false}
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
);
|
||||
}
|
||||
|
||||
console.log('GETed with success:', url.substr(0, 100), Date.now() - start);
|
||||
console.log('GETed with success:', url, Date.now() - start);
|
||||
textCb();
|
||||
|
||||
},
|
||||
|
@ -78,31 +78,6 @@
|
|||
|
||||
},
|
||||
|
||||
head(url, cb = mandatory()) {
|
||||
|
||||
const start = Date.now();
|
||||
fetch(url, {cache: 'no-store', method: 'HEAD'}).then(
|
||||
(res) => {
|
||||
|
||||
const status = res.status;
|
||||
if ( !( status >= 200 && status < 300 || status === 304 ) ) {
|
||||
return cb(
|
||||
errorsLib.clarify(
|
||||
res,
|
||||
'Получен ответ с неудачным HTTP-кодом ' + status + '.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
console.log('HEADed with success:', url, Date.now() - start);
|
||||
cb();
|
||||
|
||||
},
|
||||
errorsLib.clarifyThen(checkCon, cb)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
if (window.apis.platform.ifFirefox) {
|
||||
|
||||
const prefix = 'firefox-only';
|
||||
|
||||
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 blob = new Blob([pac.data], { type : 'application/x-ns-proxy-autoconfig' });
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
originalSet({
|
||||
value: {
|
||||
proxyType: 'autoConfig',
|
||||
autoConfigUrl: blobUrl,
|
||||
},
|
||||
}, window.utils.chromified( async (err) => {
|
||||
if (err) {
|
||||
window.utils.lastError = err;
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
await window.utils.promisedLocalStorage.set({ [`${prefix}-pac-data`]: pac.data });
|
||||
cb();
|
||||
}));
|
||||
};
|
||||
|
||||
const originalGet = chrome.proxy.settings.get.bind( chrome.proxy.settings );
|
||||
chrome.proxy.settings.get = function(details, cb) {
|
||||
originalGet(details, window.utils.chromified(async (err, originalDetails) => {
|
||||
if (err) {
|
||||
window.utils.lastError = err;
|
||||
cb(originalDetails);
|
||||
return;
|
||||
}
|
||||
let pacData = await window.utils.promisedLocalStorage.get(`${prefix}-pac-data`);
|
||||
if (!pacData || !Object.keys(pacData).length) {
|
||||
cb(originalDetails);
|
||||
return;
|
||||
}
|
||||
cb(Object.assign(
|
||||
originalDetails,
|
||||
{
|
||||
value: {
|
||||
mode: 'pac_script',
|
||||
pacScript: {
|
||||
data: pacData,
|
||||
},
|
||||
},
|
||||
}
|
||||
));
|
||||
}));
|
||||
};
|
||||
|
||||
const originalClear = chrome.proxy.settings.clear.bind( chrome.proxy.settings );
|
||||
chrome.proxy.settings.clear = async function(details, cb) {
|
||||
await window.utils.promisedLocalStorage.remove(`${prefix}-pac-data`);
|
||||
originalClear(details, cb);
|
||||
};
|
||||
}
|
|
@ -12,57 +12,6 @@
|
|||
const ifIncontinence = 'if-incontinence';
|
||||
const modsKey = 'mods';
|
||||
|
||||
let proxyHostToCredsList = {};
|
||||
const ifAuthSupported = chrome.webRequest && chrome.webRequest.onAuthRequired && !window.apis.version.ifMini;
|
||||
if (ifAuthSupported) {
|
||||
|
||||
const requestIdToTries = {};
|
||||
|
||||
chrome.webRequest.onAuthRequired.addListener(
|
||||
(details) => {
|
||||
|
||||
if (!details.isProxy) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const proxyHost = `${details.challenger.host}:${details.challenger.port}`;
|
||||
const credsList = proxyHostToCredsList[proxyHost];
|
||||
if (!credsList) {
|
||||
return {}; // No creds found for this proxy.
|
||||
}
|
||||
const requestId = details.requestId;
|
||||
const tries = requestIdToTries[requestId] || 0;
|
||||
if (tries > credsList.length) {
|
||||
return {}; // All creds for this proxy were tried already.
|
||||
}
|
||||
requestIdToTries[requestId] = tries + 1;
|
||||
return {
|
||||
authCredentials: credsList[tries],
|
||||
};
|
||||
|
||||
},
|
||||
{urls: ['<all_urls>']},
|
||||
['blocking'],
|
||||
);
|
||||
|
||||
const forgetRequestId = (details) => {
|
||||
|
||||
delete requestIdToTries[details.requestId];
|
||||
|
||||
};
|
||||
|
||||
chrome.webRequest.onCompleted.addListener(
|
||||
forgetRequestId,
|
||||
{urls: ['<all_urls>']},
|
||||
);
|
||||
|
||||
chrome.webRequest.onErrorOccurred.addListener(
|
||||
forgetRequestId,
|
||||
{urls: ['<all_urls>']},
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
const getDefaultConfigs = () => ({// Configs user may mutate them and we don't care!
|
||||
|
||||
ifProxyHttpsUrlsOnly: {
|
||||
|
@ -79,7 +28,7 @@
|
|||
},
|
||||
ifProhibitDns: {
|
||||
dflt: false,
|
||||
label: 'запретить определение по IP/DNS',
|
||||
label: 'запретить опредление по IP/DNS',
|
||||
desc: 'Пытается запретить скрипту использовать DNS, без которого определение блокировки по IP работать не будет (т.е. будет разблокироваться меньше сайтов). Используйте, чтобы получить прирост в производительности или если вам кажется, что мы проксируем слишком много сайтов. Запрет действует только для скрипта, браузер и др.программы продолжат использование DNS.',
|
||||
order: 2,
|
||||
},
|
||||
|
@ -101,19 +50,12 @@
|
|||
dflt: false,
|
||||
category: 'ownProxies',
|
||||
label: 'использовать СВОЙ локальный Tor',
|
||||
desc: 'Установите <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Расширение-и-TOR">Tor</a> на свой компьютер и используйте его как прокси-сервер. <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Расширение-и-TOR#важно">ВАЖНО</a>.',
|
||||
desc: 'Установите <a href="https://rebrand.ly/ac-tor">Tor</a> на свой компьютер и используйте его как прокси-сервер. <a href="https://rebrand.ly/ac-tor">ВАЖНО</a>',
|
||||
order: 5,
|
||||
},
|
||||
ifUseLocalWarp: {
|
||||
dflt: false,
|
||||
category: 'ownProxies',
|
||||
label: 'использовать WARP как прокси',
|
||||
desc: 'Использовать СВОЙ локальный CloudFlare WARP (<a href="https://one.one.one.one">https://one.one.one.one</a>) в качестве прокси.',
|
||||
order: 5.5,
|
||||
},
|
||||
exceptions: {
|
||||
dflt: null,
|
||||
category: 'exceptions',
|
||||
dflt: null,
|
||||
},
|
||||
ifMindExceptions: {
|
||||
dflt: true,
|
||||
|
@ -122,31 +64,13 @@
|
|||
desc: 'Учитывать сайты, добавленные вручную. Только для своих прокси-серверов! Без своих прокси работать не будет.',
|
||||
order: 6,
|
||||
},
|
||||
whitelist: {
|
||||
dflt: [],
|
||||
category: 'exceptions',
|
||||
},
|
||||
ifMindWhitelist: {
|
||||
dflt: false,
|
||||
category: 'exceptions',
|
||||
label: 'Ограничиться только <a href="../exceptions/index.html">белым списком</a>',
|
||||
desc: 'Разрешить расширению работать только с адресами из белого списка.',
|
||||
order: 6.5,
|
||||
},
|
||||
customProxyStringRaw: {
|
||||
dflt: '',
|
||||
category: 'ownProxies',
|
||||
label: 'использовать СВОИ прокси',
|
||||
url: 'https://github.com/anticensority/runet-censorship-bypass/wiki/Свои-прокси-в-расширении',
|
||||
url: 'https://rebrand.ly/ac-own-proxy',
|
||||
order: 7,
|
||||
},
|
||||
ifUseOwnProxiesOnlyForOwnSites: {
|
||||
dflt: false,
|
||||
category: 'ownProxies',
|
||||
label: 'СВОИ прокси только для СВОИХ сайтов',
|
||||
desc: 'Не использовать СВОИ прокси для всех сайтов из PAC-скрипта, а только для добавленных вручную исключений.',
|
||||
order: 7.5,
|
||||
},
|
||||
ifProxyMoreDomains: {
|
||||
ifDisabled: true,
|
||||
dflt: false,
|
||||
|
@ -155,14 +79,6 @@
|
|||
desc: 'Проксировать особые домены. Необходима поддержка со стороны СВОИХ прокси.',
|
||||
order: 8,
|
||||
},
|
||||
replaceDirectWith: {
|
||||
ifDisabled: true,
|
||||
dflt: false,
|
||||
category: 'ownProxies',
|
||||
label: 'подменять DIRECT на',
|
||||
desc: 'Использовать в PAC-скрипте указанную строку для запросов напрямую (вместо директивы DIRECT). Данная строка не проверяется на требования к шифрованию связи до прокси! Строка должна соответствовать формату возвращаемого значения PAC-скрипта, который подобен <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Свои-прокси-в-расширении#формат">формату своих прокси</a>.',
|
||||
order: 9,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
@ -175,15 +91,16 @@
|
|||
return acc;
|
||||
|
||||
}, {});
|
||||
|
||||
};
|
||||
|
||||
const getCurrentConfigs = function getCurrentConfigs(ifRaw = false) {
|
||||
const getCurrentConfigs = function getCurrentConfigs() {
|
||||
|
||||
const oldMods = kitchenState(modsKey);
|
||||
if (ifRaw) {
|
||||
/*if (oldMods) {
|
||||
// No migration!
|
||||
return oldMods;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Client may expect mods.included and mods.excluded!
|
||||
// On first install they are not defined.
|
||||
|
@ -226,73 +143,34 @@
|
|||
.every((dProp) => {
|
||||
|
||||
const ifDflt = (
|
||||
!(
|
||||
dProp in mods &&
|
||||
Boolean(configs[dProp].dflt) !== Boolean(mods[dProp])
|
||||
)
|
||||
!(dProp in mods) ||
|
||||
Boolean(configs[dProp].dflt) === Boolean(mods[dProp])
|
||||
);
|
||||
const ifMods = configs[dProp].ifDfltMods; // If default value implies PAC-script modification.
|
||||
const ifMods = configs[dProp].ifDfltMods;
|
||||
return ifDflt ? !ifMods : ifMods;
|
||||
|
||||
});
|
||||
|
||||
const self = {};
|
||||
const gdft = getDefaults();
|
||||
Object.assign(self, gdft, mods);
|
||||
Object.assign(self, getDefaults(), mods);
|
||||
self.ifNoMods = ifNoMods;
|
||||
|
||||
let customProxyArray = [];
|
||||
if (self.customProxyStringRaw) {
|
||||
customProxyArray = self.customProxyStringRaw
|
||||
.replace(/#.*$/mg, '') // Strip comments.
|
||||
.split( /(?:\s*(?:;\r?\n)+\s*)+/g )
|
||||
.split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g )
|
||||
.map( (p) => p.trim() )
|
||||
.filter( (p) => p && /\s+/g.test(p) ); // At least one space is required.
|
||||
.filter( (p) => p && /\s+/g.test(p) );
|
||||
if (self.ifUseSecureProxiesOnly) {
|
||||
customProxyArray = customProxyArray.filter( (pStr) => /^HTTPS\s/.test(pStr) );
|
||||
}
|
||||
}
|
||||
if (self.ifUseLocalWarp) {
|
||||
self.warpPoints = ['SOCKS5 localhost:40000', 'HTTPS localhost:40000'];
|
||||
customProxyArray.push(...self.warpPoints);
|
||||
}
|
||||
if (self.ifUseLocalTor) {
|
||||
self.torPoints = ['SOCKS5 localhost:9150', 'SOCKS5 localhost:9050'];
|
||||
customProxyArray.push(...self.torPoints);
|
||||
}
|
||||
|
||||
// Hanlde protected proxies in customProxyArray.
|
||||
const protectedProxies = [];
|
||||
customProxyArray = customProxyArray.map((proxyScheme) => {
|
||||
|
||||
if (proxyScheme.includes('@')) {
|
||||
|
||||
const proxy = window.utils.parseProxyScheme(proxyScheme);
|
||||
protectedProxies.push(proxy);
|
||||
return `${proxy.type} ${proxy.hostname}:${proxy.port}`;
|
||||
|
||||
}
|
||||
return proxyScheme;
|
||||
|
||||
});
|
||||
|
||||
if (!ifAuthSupported && protectedProxies.length) {
|
||||
return [new Error('Запароленные прокси не поддерживаются в данной версии/платформе!')];
|
||||
}
|
||||
|
||||
proxyHostToCredsList = {};
|
||||
protectedProxies.forEach(({ hostname, port, username, password }) => {
|
||||
|
||||
proxyHostToCredsList[`${hostname}:${port}`] =
|
||||
proxyHostToCredsList[`${hostname}:${port}`] || [];
|
||||
const tries = proxyHostToCredsList[`${hostname}:${port}`];
|
||||
tries.push({
|
||||
username: username || '',
|
||||
password: password || '',
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
self.filteredCustomsString = '';
|
||||
if (customProxyArray.length) {
|
||||
self.customProxyArray = customProxyArray;
|
||||
|
@ -320,8 +198,7 @@
|
|||
self.included = [];
|
||||
self.excluded = [];
|
||||
for(const host of Object.keys(self.exceptions)) {
|
||||
const ifProxy = self.exceptions[host] || false;
|
||||
if (ifProxy) {
|
||||
if (self.exceptions[host]) {
|
||||
self.included.push(host);
|
||||
} else {
|
||||
self.excluded.push(host);
|
||||
|
@ -330,9 +207,9 @@
|
|||
['included', 'excluded'].forEach((who) => {
|
||||
|
||||
self[who] = self[who]
|
||||
.map( (domain) => domain.split('').reverse() )
|
||||
.map( (s) => s.split('').reverse() )
|
||||
.sort()
|
||||
.map( (rDomain) => rDomain.reverse().join('') );
|
||||
.map( (a) => a.reverse().join('') );
|
||||
|
||||
});
|
||||
if (self.included.length && !self.filteredCustomsString) {
|
||||
|
@ -348,50 +225,29 @@
|
|||
window.apis.pacKitchen = {
|
||||
|
||||
getPacMods: getCurrentConfigs,
|
||||
getPacModsRaw: () => getCurrentConfigs(true),
|
||||
getOrderedConfigs: getOrderedConfigsForUser,
|
||||
|
||||
cook(pacData, pacMods = mandatory()) {
|
||||
|
||||
pacData = pacData.replace(
|
||||
new RegExp(kitchenStartsMark + '[\\s\\S]*$', 'g'),
|
||||
''
|
||||
);
|
||||
/a/.test('a'); // GC RegExp.input and friends.
|
||||
|
||||
return pacMods.ifNoMods ? pacData : pacData + `${ kitchenStartsMark }
|
||||
/******/
|
||||
/******/;(function(global) {
|
||||
/******/;+function(global) {
|
||||
/******/ "use strict";
|
||||
/******/
|
||||
/******/ const originalFindProxyForURL = FindProxyForURL;
|
||||
/******/ let tmp = function(url, host) {
|
||||
/******/ const dotHost = '.' + host;
|
||||
/******/ global.FindProxyForURL = function(url, host) {
|
||||
/******/
|
||||
${
|
||||
function() {
|
||||
let generatedPac = `
|
||||
/******/ if (${pacMods.ifMindWhitelist && pacMods.whitelist.length}) {
|
||||
/******/ const ifWhitelisted =
|
||||
/******/ ${JSON.stringify(pacMods.whitelist)}.some((whiteHost) => {
|
||||
/******/ const ifWild = whiteHost.startsWith('*');
|
||||
/******/ if (ifWild) {
|
||||
/******/ return dotHost.endsWith(whiteHost.substr(1));
|
||||
/******/ }
|
||||
/******/ return host === whiteHost;
|
||||
/******/ })
|
||||
/******/ if (!ifWhitelisted) {
|
||||
/******/ return 'DIRECT';
|
||||
/******/ }
|
||||
/******/ }`;
|
||||
|
||||
generatedPac += pacMods.ifProhibitDns ? `
|
||||
let res = pacMods.ifProhibitDns ? `
|
||||
/******/
|
||||
/******/ global.dnsResolve = function(host) { return null; };
|
||||
/******/
|
||||
/******/` : '';
|
||||
if (pacMods.ifProxyHttpsUrlsOnly) {
|
||||
|
||||
generatedPac += `
|
||||
res += `
|
||||
/******/
|
||||
/******/ if (!url.startsWith("https")) {
|
||||
/******/ return "DIRECT";
|
||||
|
@ -401,7 +257,7 @@
|
|||
}
|
||||
if (pacMods.ifUseLocalTor) {
|
||||
|
||||
generatedPac += `
|
||||
res += `
|
||||
/******/
|
||||
/******/ if (host.endsWith(".onion")) {
|
||||
/******/ return "${pacMods.torPoints.join('; ')}";
|
||||
|
@ -409,25 +265,25 @@
|
|||
/******/
|
||||
/******/ `;
|
||||
}
|
||||
generatedPac += `
|
||||
res += `
|
||||
/******/
|
||||
/******/ const directIfAllowed = ${pacMods.ifProxyOrDie ? '""/* Not allowed. */' : '"DIRECT"'};
|
||||
/******/ const directIfAllowed = ${pacMods.ifProxyOrDie ? '""/* Not allowed. */' : '"; DIRECT"'};
|
||||
/******/`;
|
||||
if (pacMods.filteredCustomsString) {
|
||||
generatedPac += `
|
||||
res += `
|
||||
/******/
|
||||
/******/ const filteredCustomProxies = "${pacMods.filteredCustomsString}";
|
||||
/******/ const filteredCustomProxies = "; ${pacMods.filteredCustomsString}";
|
||||
/******/`;
|
||||
}
|
||||
|
||||
const ifIncluded = pacMods.included && pacMods.included.length;
|
||||
const ifExcluded = pacMods.excluded && pacMods.excluded.length;
|
||||
const ifManualExceptions = ifIncluded || ifExcluded;
|
||||
let finalExceptions = {};
|
||||
const finalExceptions = {};
|
||||
if (pacMods.ifProxyMoreDomains) {
|
||||
finalExceptions = pacMods.moreDomains.reduce((acc, tld) => {
|
||||
pacMods.moreDomains.reduce((acc, tld) => {
|
||||
|
||||
acc['*.' + tld] = true;
|
||||
acc[tld] = true;
|
||||
return acc;
|
||||
|
||||
}, finalExceptions);
|
||||
|
@ -438,33 +294,21 @@
|
|||
const ifExceptions = Object.keys(finalExceptions).length;
|
||||
|
||||
if (ifExceptions) {
|
||||
generatedPac += `
|
||||
res += `
|
||||
/******/
|
||||
/******/ /* EXCEPTIONS START */
|
||||
// TODO: handle wildcards.
|
||||
/******/ const isHostInDomain = (domain, ifWild) => {
|
||||
if (ifWild) {
|
||||
return dotHost.endsWith(domain.substr(1));
|
||||
}
|
||||
return domain === host;
|
||||
}
|
||||
/******/ const domainReducer = (maxWeight, [domain, ifProxy]) => {
|
||||
/******/ const dotHost = '.' + host;
|
||||
/******/ const isHostInDomain = (domain) => dotHost.endsWith('.' + domain);
|
||||
/******/ const domainReducer = (maxWeight, [domain, ifIncluded]) => {
|
||||
/******/
|
||||
const ifWild = domain.startsWith('*.');
|
||||
/******/ if (!isHostInDomain(domain, ifWild)) {
|
||||
/******/ if (!isHostInDomain(domain)) {
|
||||
/******/ return maxWeight;
|
||||
/******/ }
|
||||
let len = domain.length;
|
||||
if (ifWild) {
|
||||
len = len === 0 ? len : (len - 2)*2 - 1;
|
||||
} else {
|
||||
len = len*2;
|
||||
}
|
||||
/******/ const newWeightAbs = len;
|
||||
/******/ const newWeightAbs = domain.length;
|
||||
/******/ if (newWeightAbs < Math.abs(maxWeight)) {
|
||||
/******/ return maxWeight;
|
||||
/******/ }
|
||||
/******/ return newWeightAbs*(ifProxy ? 1 : -1);
|
||||
/******/ return newWeightAbs*(ifIncluded ? 1 : -1);
|
||||
/******/
|
||||
/******/ };
|
||||
/******/
|
||||
|
@ -476,30 +320,27 @@
|
|||
/******/ }
|
||||
/******/ // Always proxy it!
|
||||
${ pacMods.filteredCustomsString
|
||||
? `/******/ return filteredCustomProxies + "; " + directIfAllowed;`
|
||||
? `/******/ return filteredCustomProxies + directIfAllowed;`
|
||||
: '/******/ /* No custom proxies -- continue. */'
|
||||
}
|
||||
/******/ }
|
||||
/******/ /* EXCEPTIONS END */
|
||||
`;
|
||||
}
|
||||
generatedPac += `
|
||||
res += `
|
||||
/******/ const pacScriptProxies = originalFindProxyForURL(url, host)${
|
||||
/******/ pacMods.ifProxyOrDie
|
||||
? '.replace(/DIRECT/g, "")'
|
||||
: ' + "; " + directIfAllowed'
|
||||
/******/ pacMods.ifProxyOrDie ? '.replace(/DIRECT/g, "")' : ' + directIfAllowed'
|
||||
};`;
|
||||
if(
|
||||
!pacMods.ifUseSecureProxiesOnly &&
|
||||
!pacMods.filteredCustomsString &&
|
||||
pacMods.ifUsePacScriptProxies
|
||||
) {
|
||||
return generatedPac + `
|
||||
/******/ return [pacScriptProxies, directIfAllowed]
|
||||
.filter((p) => p).join("; ") || "DIRECT";`;
|
||||
return res + `
|
||||
/******/ return pacScriptProxies + directIfAllowed;`;
|
||||
}
|
||||
|
||||
return generatedPac + `
|
||||
return res + `
|
||||
/******/ let pacProxyArray = pacScriptProxies.split(/(?:\\s*;\\s*)+/g).filter( (p) => p );
|
||||
/******/ const ifNoProxies = pacProxyArray${pacMods.ifProxyOrDie ? '.length === 0' : '.every( (p) => /^DIRECT$/i.test(p) )'};
|
||||
/******/ if (ifNoProxies) {
|
||||
|
@ -507,10 +348,6 @@ ${ pacMods.filteredCustomsString
|
|||
/******/ return "DIRECT";
|
||||
/******/ }
|
||||
/******/ return ` +
|
||||
((pacMods.filteredCustomsString && !pacMods.ifUseOwnProxiesOnlyForOwnSites)
|
||||
? 'filteredCustomProxies + "; " + '
|
||||
: ''
|
||||
) +
|
||||
function() {
|
||||
|
||||
if (!pacMods.ifUsePacScriptProxies) {
|
||||
|
@ -521,57 +358,16 @@ ${ pacMods.filteredCustomsString
|
|||
filteredPacExp =
|
||||
'pacProxyArray.filter( (pStr) => /^HTTPS\\s/.test(pStr) ).join("; ")';
|
||||
}
|
||||
return filteredPacExp + ' + "; " + ';
|
||||
return filteredPacExp + ' + ';
|
||||
|
||||
}() + 'directIfAllowed;'; // Without DIRECT you will get 'PROXY CONN FAILED' pac-error.
|
||||
}() + `${pacMods.filteredCustomsString ? 'filteredCustomProxies + ' : ''}directIfAllowed;`; // Without DIRECT you will get 'PROXY CONN FAILED' pac-error.
|
||||
|
||||
}()
|
||||
}
|
||||
|
||||
/******/ };
|
||||
${
|
||||
!pacMods.replaceDirectWith
|
||||
? ''
|
||||
: `
|
||||
/******/ const oldTmp = tmp;
|
||||
/******/ tmp = function(url, host) {
|
||||
/******/ const ip = dnsResolve(host);
|
||||
/******/ if (ip) {
|
||||
/******/ const ipInt = convert_addr(ip);
|
||||
/******/ if([
|
||||
/******/ /* Reserved networks: https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4 */
|
||||
/******/ [-16777216, 0 ], // ['0.0.0.0' , '255.0.0.0' ],
|
||||
/******/ [-16777216, 167772160 ], // ['10.0.0.0' , '255.0.0.0' ],
|
||||
/******/ [-4194304, 1681915904 ], // ['100.64.0.0' , '255.192.0.0'],
|
||||
/******/ [-16777216, 2130706432 ], // ['127.0.0.0' , '255.0.0.0' ],
|
||||
/******/ [-65536, -1442971648], // ['169.254.0.0', '255.255.0.0'],
|
||||
/******/ [-1048576, -1408237568], // ['172.16.0.0', '255.240.0.0'],
|
||||
/******/ [-256, -1073741824], // ['192.0.0.0' , '255.255.255.0'],
|
||||
/******/ [-256, -1073741312], // ['192.0.2.0' , '255.255.255.0'],
|
||||
/******/ [-256, -1067949312], // ['192.88.99.0' , '255.255.255.0'],
|
||||
/******/ [-65536, -1062731776], // ['192.168.0.0', '255.255.0.0'],
|
||||
/******/ [-131072, -971898880 ], // ['198.18.0.0', '255.254.0.0'],
|
||||
/******/ [-256, -969710592 ], // ['198.51.100.0', '255.255.255.0'],
|
||||
/******/ [-256, -889163520 ], // ['203.0.113.0', '255.255.255.0'],
|
||||
/******/ [-268435456, -536870912 ], // ['224.0.0.0', '240.0.0.0'],
|
||||
/******/ [-268435456, -268435456 ], // ['240.0.0.0', '240.0.0.0'],
|
||||
/******/ [-1, -1 ], // ['255.255.255.255' , '255.255.255.255'],
|
||||
/******/ ].some(([netMask, maskedNet]) => (ipInt & netMask) === maskedNet)
|
||||
/******/ ) {
|
||||
/******/ return "DIRECT";
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ return oldTmp.call(this, url, host).replace(/(;|^)\\s*DIRECT\\s*(?=;|$)/g, "$1${pacMods.replaceDirectWith}");
|
||||
/******/ };
|
||||
`
|
||||
}
|
||||
/******/ if (global) {
|
||||
/******/ global.FindProxyForURL = tmp;
|
||||
/******/ } else {
|
||||
/******/ FindProxyForURL = tmp;
|
||||
/******/ }
|
||||
};
|
||||
|
||||
/*****/})(this);`;
|
||||
}(this);`;
|
||||
|
||||
},
|
||||
|
||||
|
@ -586,15 +382,21 @@ ${
|
|||
|
||||
details
|
||||
? resolve(details)
|
||||
: chrome.proxy.settings.get({}, timeouted(resolve) ),
|
||||
: chrome.proxy.settings.get({}, timeouted(resolve) )
|
||||
|
||||
).then((details) => {
|
||||
).then( (details) => {
|
||||
|
||||
if (
|
||||
details && details.levelOfControl === 'controlled_by_this_extension'
|
||||
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'),
|
||||
''
|
||||
);
|
||||
/a/.test('a'); // GC RegExp.input and friends.
|
||||
return chrome.proxy.settings.set(details, chromified(cb));
|
||||
}
|
||||
}
|
||||
|
@ -611,7 +413,7 @@ ${
|
|||
checkIncontinence(details) {
|
||||
|
||||
if ( kitchenState(ifIncontinence) ) {
|
||||
this.setNowAsync(details, (err) => { if (err) { throw err; } }); // TODO: suppress?
|
||||
this.setNowAsync(details, () => {/* Swallow. */});
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -646,14 +448,9 @@ ${
|
|||
return cb(null, res, ...accWarns);
|
||||
}
|
||||
const newHosts = (pacMods.customProxyArray || []).map( (ps) => ps.split(/\s+/)[1] );
|
||||
window.utils.fireRequest(
|
||||
'ip-to-host-replace-all',
|
||||
newHosts,
|
||||
(err, res, ...moreWarns) =>
|
||||
cb(err, res, ...accWarns, ...moreWarns),
|
||||
);
|
||||
window.utils.fireRequest('ip-to-host-replace-all', newHosts, (err, res, ...moreWarns) => cb( err, res, ...accWarns.concat(moreWarns) ));
|
||||
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
|
@ -673,21 +470,27 @@ ${
|
|||
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, window.utils.timeouted(cb));
|
||||
return originalSet(details, cb);
|
||||
}
|
||||
const pacMods = getCurrentConfigs();
|
||||
pac.data = pacKitchen.cook( pac.data, pacMods );
|
||||
originalSet({value: details.value}, window.utils.chromified((err) => {
|
||||
originalSet({value: details.value}, (/* No args. */) => {
|
||||
|
||||
if (!err) {
|
||||
kitchenState(ifIncontinence, null);
|
||||
}
|
||||
window.utils.lastError = err;
|
||||
kitchenState(ifIncontinence, null);
|
||||
cb && cb();
|
||||
|
||||
}));
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
pacKitchen.checkIncontinence();
|
||||
chrome.proxy.settings.onChange.addListener(
|
||||
timeouted(
|
||||
pacKitchen.checkIncontinence.bind(pacKitchen)
|
||||
)
|
||||
);
|
||||
|
||||
} // Private namespace ends.
|
||||
|
|
|
@ -19,25 +19,14 @@
|
|||
|
||||
*/
|
||||
|
||||
/*
|
||||
Due to History
|
||||
|
||||
- *Async suffix usually means that function requires a cb.
|
||||
It may not be related to async (returning a Promise).
|
||||
This naming is confusing and should be reconsidered.
|
||||
*/
|
||||
|
||||
{ // Private namespace starts.
|
||||
|
||||
const ifRu = chrome.i18n.getMessage('@@ui_locale').startsWith('ru');
|
||||
console.log('Russian?', ifRu);
|
||||
const mandatory = window.utils.mandatory;
|
||||
const throwIfError = window.utils.throwIfError;
|
||||
const chromified = window.utils.chromified;
|
||||
const timeouted = window.utils.timeouted;
|
||||
|
||||
const clarifyThen = window.apis.errorsLib.clarifyThen;
|
||||
const clarify = window.apis.errorsLib.clarify;
|
||||
const Warning = window.apis.errorsLib.Warning;
|
||||
|
||||
const httpLib = window.apis.httpLib;
|
||||
|
@ -60,70 +49,8 @@
|
|||
|
||||
};
|
||||
|
||||
const tryPromiseSeveralTimesAsync = (createPromise, timeoutsInSec) =>
|
||||
createPromise().then(
|
||||
(res) => Promise.resolve(res),
|
||||
(err) => {
|
||||
console.log('Promise failed, are there any retries?');
|
||||
const outSec = timeoutsInSec.shift();
|
||||
if (outSec === undefined) {
|
||||
console.log('No retries left.');
|
||||
return Promise.reject(err);
|
||||
}
|
||||
console.log('Retrying in', outSec, 'sec');
|
||||
/*
|
||||
const alarmName = 'try-promise=several-times-async';
|
||||
const res = new Promise((resolve) => {
|
||||
chrome.alarms.onAlarm.addListener((alarmInfo) => {
|
||||
if (alarmInfo.name === alarmName) {
|
||||
console.log('Time to retry.');
|
||||
resolve(tryPromiseSeveralTimesAsync(createPromise, timeoutsInSec));
|
||||
}
|
||||
});
|
||||
});
|
||||
chrome.alarms.create(alarmName, { delayInMinutes: outSec/60 });
|
||||
return res;
|
||||
*/
|
||||
return new Promise((resolve) =>
|
||||
window.setTimeout(() => resolve(tryPromiseSeveralTimesAsync(createPromise, timeoutsInSec)), outSec*1000),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const doWithoutProxyAsync = (createPromise) => new Promise((resolve, reject) => {
|
||||
console.log('Doing without proxy...');
|
||||
chrome.proxy.settings.get({}, chromified((getErr, settings) => {
|
||||
if (getErr) {
|
||||
reject(getErr);
|
||||
return;
|
||||
}
|
||||
const ifWeAreInControl = window.utils.areSettingsControlledFor(settings);
|
||||
if (!ifWeAreInControl) {
|
||||
resolve(createPromise());
|
||||
return;
|
||||
}
|
||||
delete settings.levelOfControl;
|
||||
const setProxyAsync = () => new Promise((setResolve, setReject) => {
|
||||
|
||||
console.log('Restoring chrome proxy settings...');
|
||||
chrome.proxy.settings.set(
|
||||
settings,
|
||||
chromified((err) => err ? setReject(err) : setResolve()),
|
||||
);
|
||||
});
|
||||
console.log('Clearing chrome proxy settings...');
|
||||
chrome.proxy.settings.clear({}, chromified((clearErr) => {
|
||||
if (clearErr) {
|
||||
reject(clearErr);
|
||||
return;
|
||||
}
|
||||
createPromise().then((actionResult) => setProxyAsync().then(() => resolve(actionResult)), reject);
|
||||
}));
|
||||
}));
|
||||
});
|
||||
|
||||
const setPacAsync = function setPacAsync(
|
||||
pacData = mandatory(), cb = throwIfError,
|
||||
pacData = mandatory(), cb = throwIfError
|
||||
) {
|
||||
|
||||
const config = {
|
||||
|
@ -134,16 +61,9 @@
|
|||
},
|
||||
};
|
||||
console.log('Setting chrome proxy settings...');
|
||||
chrome.proxy.settings.set( { value: config }, chromified((err) => {
|
||||
chrome.proxy.settings.set( {value: config}, chromified((err) => {
|
||||
|
||||
if (err) {
|
||||
if (err.message === 'proxy.settings requires private browsing permission.') {
|
||||
clarifyThen(
|
||||
chrome.i18n.getMessage('AllowExtensionToRunInPrivateWindows'),
|
||||
cb,
|
||||
)(err);
|
||||
return;
|
||||
}
|
||||
return cb(err);
|
||||
}
|
||||
handlers.updateControlState( () => {
|
||||
|
@ -152,16 +72,17 @@
|
|||
|
||||
console.warn('Failed, other extension is in control.');
|
||||
return cb(
|
||||
new Error( window.utils.messages.whichExtensionHtml() ),
|
||||
new Error( window.utils.messages.whichExtensionHtml() )
|
||||
);
|
||||
|
||||
}
|
||||
console.log('Successfuly set PAC in proxy settings.');
|
||||
console.log('Successfuly set PAC in proxy settings..');
|
||||
cb();
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
};
|
||||
|
||||
const updatePacProxyIps = function updatePacProxyIps(
|
||||
|
@ -170,86 +91,75 @@
|
|||
|
||||
cb = asyncLogGroup(
|
||||
'Getting IPs for PAC hosts...',
|
||||
cb,
|
||||
cb
|
||||
);
|
||||
window.utils.fireRequest('ip-to-host-update-all', cb);
|
||||
|
||||
};
|
||||
|
||||
const setPacScriptFromProviderAsync = function setPacScriptFromProviderAsync(
|
||||
provider, lastModifiedStr, ifUnattended = mandatory(), cb = throwIfError,
|
||||
provider, lastModifiedStr = mandatory(), cb = throwIfError
|
||||
) {
|
||||
|
||||
const pacUrl = provider.pacUrls[0];
|
||||
cb = asyncLogGroup(
|
||||
'Getting PAC script from provider...', pacUrl,
|
||||
cb,
|
||||
cb
|
||||
);
|
||||
|
||||
const warnings = [];
|
||||
const originalCb = cb;
|
||||
cb = (err, res, ...warns) => originalCb(err, res, ...warns, ...warnings);
|
||||
const addWarning = (wText) => { warnings.push(new Warning(wText)) };
|
||||
httpLib.ifModifiedSince(pacUrl, lastModifiedStr, (err, newLastModifiedStr) => {
|
||||
|
||||
if (provider.distinctKey === 'Anticensority') {
|
||||
|
||||
const pacMods = window.apis.pacKitchen.getPacMods();
|
||||
if (!pacMods.filteredCustomsString) {
|
||||
addWarning(
|
||||
ifRu
|
||||
? \`
|
||||
Не найдено СВОИХ прокси. Этот PAC-скрипт
|
||||
работает только со <a href="https://git.io/ac-own-proxy">СВОИМИ прокси</a>
|
||||
(по умолчанию будет использоваться локальный <a href="https://git.io/ac-tor">Tor</a>).
|
||||
\`
|
||||
: \`
|
||||
Couldn't find OWN proxies. This PAC-script
|
||||
works only with <a href="https://git.io/ac-own-proxy">OWN proxies</a>
|
||||
(by default local <a href="https://git.io/ac-tor">Tor</a> will be used).
|
||||
\`,
|
||||
);
|
||||
if (!newLastModifiedStr) {
|
||||
const res = {lastModified: lastModifiedStr};
|
||||
const ifWasEverModified = lastModifiedStr !== new Date(0).toUTCString();
|
||||
if (ifWasEverModified) {
|
||||
return cb(
|
||||
null, res,
|
||||
new Warning(
|
||||
'Ваш PAC-скрипт не нуждается в обновлении. Его дата: ' +
|
||||
lastModifiedStr
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
doWithoutProxyAsync(
|
||||
// Employ all urls, the latter are fallbacks for the former.
|
||||
() => {
|
||||
const tryAllUrlsAsync = () => provider.pacUrls.reduce(
|
||||
(promise, url) => promise.catch(
|
||||
() => new Promise(
|
||||
(resolve, reject) => httpLib.get(
|
||||
url,
|
||||
(newErr, pacData) =>
|
||||
newErr ? reject(newErr) : resolve(pacData),
|
||||
),
|
||||
),
|
||||
),
|
||||
Promise.reject(),
|
||||
);
|
||||
return (ifUnattended
|
||||
? tryPromiseSeveralTimesAsync(tryAllUrlsAsync, [20, 40, 60])
|
||||
: tryAllUrlsAsync()
|
||||
).catch(
|
||||
(err) => Promise.reject(clarify(
|
||||
const pacDataPromise = provider.pacUrls.reduce(
|
||||
(promise, url) => promise.catch(
|
||||
() => new Promise(
|
||||
(resolve, reject) => httpLib.get(
|
||||
url,
|
||||
(newErr, pacData) => newErr ? reject(newErr) : resolve(pacData)
|
||||
)
|
||||
)
|
||||
),
|
||||
Promise.reject()
|
||||
);
|
||||
|
||||
pacDataPromise.then(
|
||||
|
||||
(pacData) => {
|
||||
|
||||
setPacAsync(
|
||||
pacData,
|
||||
(err, res) => cb(
|
||||
err,
|
||||
chrome.i18n.getMessage('FailedToDownloadPacScriptFromAddresses') + ': [ '
|
||||
+ provider.pacUrls.join(' , ') + ' ].',
|
||||
)),
|
||||
);
|
||||
},
|
||||
).then(
|
||||
(pacData) => {
|
||||
setPacAsync(
|
||||
pacData,
|
||||
(err, res) => cb(
|
||||
err,
|
||||
Object.assign(res || {}, {lastModified: lastModifiedStr}),
|
||||
),
|
||||
);
|
||||
},
|
||||
cb,
|
||||
);
|
||||
Object.assign(res || {}, {lastModified: newLastModifiedStr})
|
||||
)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
clarifyThen(
|
||||
'Не удалось скачать PAC-скрипт с адресов: [ '
|
||||
+ provider.pacUrls.join(' , ') + ' ].',
|
||||
cb
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
window.apis.antiCensorRu = {
|
||||
|
@ -258,45 +168,20 @@
|
|||
|
||||
pacProviders: {
|
||||
Антизапрет: {
|
||||
// Distinct keys are needed if you want to check if a given
|
||||
// provider is this or that (distinct it from others).
|
||||
distinctKey: 'Antizapret',
|
||||
label: chrome.i18n.getMessage('Antizapret'),
|
||||
desc: ifRu
|
||||
? \`Основной PAC-скрипт от автора проекта «Антизапрет».
|
||||
Охватывет меньше сайтов.
|
||||
Блокировка определяется по доменному имени и при необходимости по IP.
|
||||
<br/> <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/PAC-скрипты:-различия">Сравнение PAC-скриптов</a>.
|
||||
\`
|
||||
: \`The main PAC-script from the author of project "Antizapret"\.
|
||||
Covers fewer sites.
|
||||
Block is detected based on a domain name and, if necessary, on an IP.
|
||||
<br/> <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/PAC-скрипты:-различия">Comparison of PAC-scripts (ru)</a>.
|
||||
\`,
|
||||
label: 'Антизапрет',
|
||||
desc: \`Альтернативный PAC-скрипт от стороннего разработчика.
|
||||
Работает быстрее, но охватывает меньше сайтов.
|
||||
Блокировка определяется по доменному имени,
|
||||
<br/> <a href="https://antizapret.prostovpn.org">Страница проекта</a>.\`,
|
||||
order: 0,
|
||||
pacUrls: [
|
||||
'https://e.cen.rodeo:8443/proxy.pac',
|
||||
'https://antizapret.prostovpn.org:8443/proxy.pac',
|
||||
'https://antizapret.prostovpn.org:18443/proxy.pac',
|
||||
'https://antizapret.prostovpn.org/proxy.pac',
|
||||
],
|
||||
pacUrls: ['https://antizapret.prostovpn.org/proxy.pac'],
|
||||
},
|
||||
Антицензорити: {
|
||||
distinctKey: 'Anticensority',
|
||||
label: chrome.i18n.getMessage('Anticensority'),
|
||||
desc: ifRu
|
||||
? \`Альтернативный PAC-скрипт от автора расширения.
|
||||
Охватывает больше сайтов.
|
||||
Блокировка определятся по доменному имени или IP адресу.
|
||||
Подходит для провайдеров, блокирующих все сайты на одном IP.
|
||||
<br/> <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/PAC-скрипты:-различия">Сравнение PAC-скриптов</a>.
|
||||
\`
|
||||
: \`Alternative PAC-script from the author of this extension.
|
||||
Covers more sites.
|
||||
Block is detected based on a domain name and on an IP address.
|
||||
Better fits providers that block all sites on one IP.
|
||||
<br/> <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/PAC-скрипты:-различия">Comparison of PAC-scripts (ru)</a>.
|
||||
\`,
|
||||
label: 'Антицензорити',
|
||||
desc: \`Основной PAC-скрипт от автора расширения.
|
||||
Работает медленней, но охватывает больше сайтов.
|
||||
Блокировка определятся по доменному имени или IP адресу.<br/>
|
||||
<a href="https://rebrand.ly/ac-anticensority">Страница проекта</a>.\`,
|
||||
order: 1,
|
||||
|
||||
/*
|
||||
|
@ -305,17 +190,28 @@
|
|||
Version: 0.17
|
||||
*/
|
||||
pacUrls: ${JSON.stringify(anticensorityPacUrls, null, 2)},
|
||||
/*[
|
||||
// First official, shortened:
|
||||
'https://rebrand.ly/ac-chrome-anticensority-pac',
|
||||
// Second official, Cloud Flare with caching:
|
||||
'https://anticensority.tk/generated-pac-scripts/anticensority.pac',
|
||||
// GitHub.io (anticensority):
|
||||
'\x68\x74\x74\x70\x73\x3a\x2f\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2e\x67\x69\x74\x68\x75\x62\x2e\x69\x6f\x2f\x67\x65\x6e\x65\x72\x61\x74\x65\x64\x2d\x70\x61\x63\x2d\x73\x63\x72\x69\x70\x74\x73\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2e\x70\x61\x63',
|
||||
// GitHub repo (anticensority):
|
||||
'\x68\x74\x74\x70\x73\x3a\x2f\x2f\x72\x61\x77\x2e\x67\x69\x74\x68\x75\x62\x75\x73\x65\x72\x63\x6f\x6e\x74\x65\x6e\x74\x2e\x63\x6f\x6d\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2f\x67\x65\x6e\x65\x72\x61\x74\x65\x64\x2d\x70\x61\x63\x2d\x73\x63\x72\x69\x70\x74\x73\x2f\x6d\x61\x73\x74\x65\x72\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2e\x70\x61\x63',
|
||||
// Old, deprecated:
|
||||
'https://anticensorship-russia.tk/generated-pac-scripts/anticensority.pac',
|
||||
// Google Drive (0.17, anticensority):
|
||||
'\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x72\x69\x76\x65\x2e\x67\x6f\x6f\x67\x6c\x65\x2e\x63\x6f\x6d\x2f\x75\x63\x3f\x65\x78\x70\x6f\x72\x74\x3d\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x26\x69\x64\x3d\x30\x42\x32\x6d\x68\x42\x67\x46\x6e\x66\x34\x70\x45\x4c\x56\x6c\x47\x4e\x54\x42\x45\x4d\x58\x4e\x6d\x52\x58\x63',
|
||||
],*/
|
||||
},
|
||||
onlyOwnSites: {
|
||||
distinctKey: 'onlyOwnSites',
|
||||
label: chrome.i18n.getMessage('Only_own_sites_and_only_own_proxies'),
|
||||
desc: ifRu
|
||||
? 'Проксируются только добавленные вручную адреса через СВОИ вручную добавленные прокси или через локальный Tor.'
|
||||
: 'Only added manually urls are proxied via your OWN manually added proxies or via Tor.',
|
||||
label: 'Только свои сайты и свои прокси',
|
||||
desc: 'Проксируются только добавленные вручную сайты через СВОИ вручную добавленные прокси или через локальный Tor.',
|
||||
order: 99,
|
||||
pacUrls: [
|
||||
'data:application/x-ns-proxy-autoconfig,' + escape('function FindProxyForURL(){ return "DIRECT"; }'),
|
||||
],
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -325,18 +221,12 @@
|
|||
|
||||
},
|
||||
|
||||
_currentPacProviderKey: 'Антизапрет',
|
||||
_currentPacProviderKey: 'Антицензорити',
|
||||
|
||||
/* Is it the first time extension installed?
|
||||
Do something, e.g. initiate PAC sync.
|
||||
*/
|
||||
ifFirstInstall: false,
|
||||
/* We have .lastPacUpdateStamp and ._currentPacProviderLastModified.
|
||||
LastModified is received from a server, we kind of don't trust it,
|
||||
just use it for cache and maybe show to the user.
|
||||
UpdateStamp is got from client and we base our timers on it,
|
||||
malicious server can't interfere with it.
|
||||
*/
|
||||
lastPacUpdateStamp: 0,
|
||||
|
||||
setTitle() {
|
||||
|
@ -344,12 +234,12 @@
|
|||
const upDate = new Date(this.lastPacUpdateStamp).toLocaleString('ru-RU')
|
||||
.replace(/:\\d+$/, '').replace(/\\.\\d{4}/, '');
|
||||
chrome.browserAction.setTitle({
|
||||
title: \`\${chrome.i18n.getMessage('Updated')} \${upDate} | \${chrome.i18n.getMessage('Version')} \${window.apis.version.build}\`,
|
||||
title: \`Обновлялись \${upDate} | Версия \${window.apis.version.build}\`,
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
_currentPacProviderLastModified: 0,
|
||||
_currentPacProviderLastModified: 0, // Not initialized.
|
||||
|
||||
getLastModifiedForKey(key = mandatory()) {
|
||||
|
||||
|
@ -382,7 +272,7 @@
|
|||
|
||||
setCurrentPacProviderKey(
|
||||
newKey = mandatory(),
|
||||
lastModified = new Date().toUTCString(),
|
||||
lastModified = new Date().toUTCString()
|
||||
) {
|
||||
|
||||
this.mustBeKey(newKey);
|
||||
|
@ -419,28 +309,27 @@
|
|||
}
|
||||
}
|
||||
|
||||
chrome.storage.local.remove(
|
||||
'antiCensorRu',
|
||||
chrome.storage.local.clear(
|
||||
() => chrome.storage.local.set(
|
||||
{ antiCensorRu: onlySettable },
|
||||
chromified(cb),
|
||||
),
|
||||
onlySettable,
|
||||
chromified(cb)
|
||||
)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
syncWithPacProviderAsync(opts = {}, cb = throwIfError) {
|
||||
const optsDefaults = Object.freeze({ key: this.getCurrentPacProviderKey(), ifUnattended: false });
|
||||
if( typeof(opts) === 'function' ) {
|
||||
cb = opts;
|
||||
opts = {};
|
||||
syncWithPacProviderAsync(
|
||||
key = this.currentPacProvierKey, cb = throwIfError) {
|
||||
|
||||
if( typeof(key) === 'function' ) {
|
||||
cb = key;
|
||||
key = this.getCurrentPacProviderKey();
|
||||
}
|
||||
let { key, ifUnattended } = { ...optsDefaults, ...opts };
|
||||
cb = asyncLogGroup('Syncing with PAC provider ' + key + '...', cb);
|
||||
|
||||
if (key === null) {
|
||||
// No pac provider set.
|
||||
return clarifyThen(chrome.i18n.getMessage('ChoosePacProviderFirstD'), cb);
|
||||
return clarifyThen('Сперва выберите PAC-провайдера.', cb);
|
||||
}
|
||||
|
||||
const pacProvider = this.getPacProvider(key);
|
||||
|
@ -449,7 +338,6 @@
|
|||
(resolve, reject) => setPacScriptFromProviderAsync(
|
||||
pacProvider,
|
||||
this.getLastModifiedForKey(key),
|
||||
ifUnattended,
|
||||
(err, res, ...warns) => {
|
||||
|
||||
if (!err) {
|
||||
|
@ -466,37 +354,24 @@
|
|||
)
|
||||
);
|
||||
|
||||
const updateIpsAsync = () => new Promise(
|
||||
const ipsErrorPromise = new Promise(
|
||||
(resolve, reject) => updatePacProxyIps(
|
||||
(err, res, ...warns) => {
|
||||
if (err) {
|
||||
reject([err, ...warns]);
|
||||
return;
|
||||
}
|
||||
resolve([err, res, ...warns]);
|
||||
},
|
||||
),
|
||||
resolve
|
||||
)
|
||||
);
|
||||
|
||||
const ipsPromise = !ifUnattended
|
||||
? updateIpsAsync()
|
||||
: tryPromiseSeveralTimesAsync(updateIpsAsync, [20, 40, 60]);
|
||||
Promise.all([pacSetPromise, ipsErrorPromise]).then(
|
||||
([[pacErr, pacRes, ...pacWarns], ipsErr]) => {
|
||||
|
||||
Promise.all([pacSetPromise, ipsPromise]).then(
|
||||
([[pacErr, pacRes, ...pacWarns], [ipsErr, ipsRes, ...ipsWarns]]) => {
|
||||
|
||||
if (pacErr) {
|
||||
if (pacErr && ipsErr) {
|
||||
return cb(pacErr, pacRes);
|
||||
}
|
||||
const warns = pacWarns;
|
||||
if (ipsErr) {
|
||||
warns.push(ipsErr);
|
||||
}
|
||||
if (ipsWarns.length) {
|
||||
warns.push(...ipsWarns);
|
||||
}
|
||||
this.pushToStorageAsync(
|
||||
(pushErr) => cb(pacErr || pushErr, null, ...warns),
|
||||
(pushErr) => cb(pacErr || pushErr, null, ...warns)
|
||||
);
|
||||
|
||||
},
|
||||
|
@ -523,7 +398,7 @@
|
|||
|
||||
console.log(
|
||||
'Next PAC update is scheduled on',
|
||||
new Date(nextUpdateMoment).toLocaleString('ru-RU'),
|
||||
new Date(nextUpdateMoment).toLocaleString('ru-RU')
|
||||
);
|
||||
|
||||
chrome.alarms.create(
|
||||
|
@ -546,7 +421,7 @@
|
|||
throw new Error('Key must be defined.');
|
||||
}
|
||||
if (this.currentProviderKey !== key) {
|
||||
return this.syncWithPacProviderAsync({ key }, cb);
|
||||
return this.syncWithPacProviderAsync(key, cb);
|
||||
}
|
||||
console.log(key + ' already installed.');
|
||||
cb();
|
||||
|
@ -566,11 +441,11 @@
|
|||
}
|
||||
this.setCurrentPacProviderKey(null);
|
||||
this.pushToStorageAsync(
|
||||
() => handlers.updateControlState(cb),
|
||||
() => handlers.updateControlState(cb)
|
||||
);
|
||||
|
||||
}),
|
||||
),
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
},
|
||||
|
@ -578,25 +453,12 @@
|
|||
};
|
||||
|
||||
// ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
|
||||
(async () => {
|
||||
let ifConsentGiven = await window.utils.promisedLocalStorage.get('ifConsentGiven');
|
||||
if (!ifConsentGiven) {
|
||||
window.utils.openAndFocus('/pages/consent/index.html');
|
||||
await window.apis.consent.promise;
|
||||
ifConsentGiven = true
|
||||
await window.utils.promisedLocalStorage.set({ ifConsentGiven });
|
||||
chrome.storage.local.get(null, chromified( async (err, oldStorage) => {
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
let oldAntiCensorRu = await window.utils.promisedLocalStorage.get('antiCensorRu') || {};
|
||||
|
||||
const otherKeys = [
|
||||
'pac-kitchen-if-incontinence',
|
||||
'pac-kitchen-mods',
|
||||
'ip-to-host',
|
||||
'handlers-pac-error',
|
||||
'handlers-ext-error',
|
||||
'handlers-no-control',
|
||||
];
|
||||
/*
|
||||
Event handlers that ALWAYS work (even if installation is not done
|
||||
or failed).
|
||||
|
@ -611,9 +473,9 @@
|
|||
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
|
||||
console.log(
|
||||
'Periodic PAC update triggered:',
|
||||
new Date().toLocaleString('ru-RU'),
|
||||
new Date().toLocaleString('ru-RU')
|
||||
);
|
||||
antiCensorRu.syncWithPacProviderAsync({ ifUnattended: true }, () => { /* Swallow. */ });
|
||||
antiCensorRu.syncWithPacProviderAsync(() => {/* swallow */});
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -630,29 +492,28 @@
|
|||
console.log('Keep cooked...');
|
||||
await new Promise((resolve) => window.apis.pacKitchen.keepCookedNowAsync(resolve));
|
||||
|
||||
//console.log('Storage on init:', oldAntiCensorRu);
|
||||
antiCensorRu.ifFirstInstall = Object.keys(oldAntiCensorRu).length === 0;
|
||||
console.log('Storage on init:', oldStorage);
|
||||
antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0;
|
||||
|
||||
if (antiCensorRu.ifFirstInstall) {
|
||||
// INSTALL
|
||||
console.log('Installing...');
|
||||
handlers.switch('on', 'ext-error');
|
||||
chrome.runtime.openOptionsPage();
|
||||
return;
|
||||
return chrome.runtime.openOptionsPage();
|
||||
}
|
||||
|
||||
// LAUNCH, RELOAD, UPDATE
|
||||
// Use old or migrate to default.
|
||||
antiCensorRu._currentPacProviderKey =
|
||||
oldAntiCensorRu._currentPacProviderKey || null;
|
||||
oldStorage._currentPacProviderKey || null;
|
||||
antiCensorRu.lastPacUpdateStamp =
|
||||
oldAntiCensorRu.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
|
||||
oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
|
||||
antiCensorRu._currentPacProviderLastModified =
|
||||
oldAntiCensorRu._currentPacProviderLastModified
|
||||
oldStorage._currentPacProviderLastModified
|
||||
|| antiCensorRu._currentPacProviderLastModified;
|
||||
console.log(
|
||||
'Last PAC update was on',
|
||||
new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU'),
|
||||
new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU')
|
||||
);
|
||||
|
||||
|
||||
|
@ -664,45 +525,34 @@
|
|||
Better on each launch then on each pull.
|
||||
*/
|
||||
|
||||
await new Promise(async (resolve) => {
|
||||
await new Promise((resolve) => {
|
||||
|
||||
const ifUpdating = antiCensorRu.version !== oldAntiCensorRu.version;
|
||||
const ifUpdating = antiCensorRu.version !== oldStorage.version;
|
||||
if (!ifUpdating) {
|
||||
|
||||
// LAUNCH, RELOAD, ENABLE
|
||||
antiCensorRu.pacProviders = oldAntiCensorRu.pacProviders;
|
||||
antiCensorRu.pacProviders = oldStorage.pacProviders;
|
||||
console.log('Extension launched, reloaded or enabled.');
|
||||
return resolve();
|
||||
|
||||
}
|
||||
|
||||
// UPDATE & MIGRATION
|
||||
console.log('Updating from ', oldStorage.version, 'to', antiCensorRu.version);
|
||||
const key = antiCensorRu._currentPacProviderKey;
|
||||
if (oldStorage.version === ' 0.0.1.2') {
|
||||
if (key !== null && key !== 'onlyOwnSites') {
|
||||
antiCensorRu._currentPacProviderKey = 'Антицензорити';
|
||||
}
|
||||
}
|
||||
|
||||
const ifUpdatedCb = () => antiCensorRu.pushToStorageAsync(() => {
|
||||
antiCensorRu.pushToStorageAsync(() => {
|
||||
|
||||
console.log('Extension updated.');
|
||||
resolve();
|
||||
|
||||
});
|
||||
|
||||
console.log('Updating from', oldAntiCensorRu.version, 'to', antiCensorRu.version);
|
||||
try {
|
||||
if (window.apis.version.isLeq(oldAntiCensorRu.version, '0.0.1.62')) {
|
||||
window.apis.antiCensorRu.pacProviders['Антизапрет'].pacUrls = [
|
||||
'https://e.cen.rodeo:8443/proxy.pac',
|
||||
'https://antizapret.prostovpn.org:8443/proxy.pac',
|
||||
'https://antizapret.prostovpn.org:18443/proxy.pac',
|
||||
'https://antizapret.prostovpn.org/proxy.pac',
|
||||
];
|
||||
console.log('Successfully updated to 0.0.1.63.');
|
||||
}
|
||||
} catch (e) {
|
||||
// Log update error.
|
||||
console.log('UPDATE ERROR:');
|
||||
console.error(e);
|
||||
}
|
||||
ifUpdatedCb();
|
||||
|
||||
});
|
||||
|
||||
if (antiCensorRu.getPacProvider()) {
|
||||
|
@ -725,6 +575,6 @@
|
|||
* Add storage.lastPacUpdateStamp.
|
||||
**/
|
||||
|
||||
})();
|
||||
}));
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
order: 0,
|
||||
},
|
||||
|
||||
googleCache: {
|
||||
hostTracker: {
|
||||
title: 'Из кэша Google',
|
||||
getUrl: (blockedUrl) => 'http://webcache.googleusercontent.com/search?q=cache:' + blockedUrl,
|
||||
order: 1,
|
||||
|
@ -27,19 +27,19 @@
|
|||
|
||||
otherUnblock: {
|
||||
title: 'Разблокировать по-другому',
|
||||
getUrl: (blockedUrl) => ('https://anticensority.github.io/unblock#' + blockedUrl),
|
||||
getUrl: (blockedUrl) => ('https://rebrand.ly/ac-unblock#' + blockedUrl),
|
||||
order: 3,
|
||||
},
|
||||
|
||||
antizapretInfo: {
|
||||
title: 'Сайт в реестре блокировок?',
|
||||
getUrl: (blockedUrl) => 'https://reestr.rublacklist.net/?q=' + new URL(blockedUrl).hostname,
|
||||
getUrl: (blockedUrl) => 'https://antizapret.info/index.php?search=' + new URL(blockedUrl).hostname,
|
||||
order: 4,
|
||||
},
|
||||
|
||||
support: {
|
||||
title: 'Документация / Помощь / Поддержка',
|
||||
getUrl: (blockedUrl) => 'https://github.com/anticensority/runet-censorship-bypass/wiki',
|
||||
getUrl: (blockedUrl) => 'https://rebrand.ly/ac-wiki',
|
||||
order: 99,
|
||||
},
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
# For Reviewers
|
||||
|
||||
## Prerequirements
|
||||
|
||||
* You need a globally installed `gulp-cli@3.0.0`.
|
||||
See https://gulpjs.com/docs/en/getting-started/quick-start#install-the-gulp-command-line-utility.
|
||||
* Node v21.7.3
|
||||
* NPM 10.5.0
|
||||
|
||||
## Steps
|
||||
|
||||
Steps to reproduce the same zip:
|
||||
```
|
||||
npm ci
|
||||
cd src/extension-common/pages/options/
|
||||
npm ci
|
||||
cd -
|
||||
npm start
|
||||
# See ./build/extension-full
|
||||
cd ./build/extension-full
|
||||
zip -r runet-censorship-bypass-full.zip ./*
|
||||
```
|
||||
|
||||
## Minified Files
|
||||
|
||||
### Ace Editor
|
||||
|
||||
https://ace.c9.io -> https://github.com/ajaxorg/ace -> Building Ace -> "The ace-builds repository endeavours to maintain the latest build" -> https://github.com/ajaxorg/ace-builds/ -> Select tag of 1.2.5, open https://github.com/ajaxorg/ace-builds/tree/v1.2.5/src-min and download the files you want to check.
|
||||
|
||||
|
||||
```
|
||||
mkdir downloaded
|
||||
cd downloaded
|
||||
wget https://raw.githubusercontent.com/ajaxorg/ace-builds/v1.2.5/src-min/ace.js
|
||||
wget https://raw.githubusercontent.com/ajaxorg/ace-builds/v1.2.5/src-min/ext-searchbox.js
|
||||
wget https://raw.githubusercontent.com/ajaxorg/ace-builds/v1.2.5/src-min/mode-javascript.js
|
||||
wget https://raw.githubusercontent.com/ajaxorg/ace-builds/v1.2.5/src-min/worker-javascript.js
|
||||
|
||||
downloaded$ for i in ./*; do md5sum "$i"; done
|
||||
2b9a1157bb3ba711a0402b6751d9ac71 ./ace.js
|
||||
1f73efaff2853571af0e701c5e9a15ee ./ext-searchbox.js
|
||||
e5eebd85c4e66667c28f124e6a07e3ed ./mode-javascript.js
|
||||
f0d1342102d16ab7abe319b2683d10ea ./worker-javascript.js
|
||||
```
|
||||
|
||||
## PAC-Script AntiZapret
|
||||
|
||||
https://antizapret.prostovpn.org/proxy.pac (old) and https://e.cen.rodeo:8443/proxy.pac (new) are generated by https://bitbucket.org/anticensority/antizapret-pac-generator-light/, reviewers may find justifications related to this PAC-script in that repo.
|
|
@ -0,0 +1 @@
|
|||
Files of this directory must be copied into final build without modifications.
|
|
@ -3,7 +3,7 @@
|
|||
"message": "Runet Censorship Bypass${nameSuffixEn}"
|
||||
},
|
||||
"extDesc": {
|
||||
"message": "Circumvent Russian Internet Censorship: https://git.io/ac-wiki"
|
||||
"message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki"
|
||||
},
|
||||
"proxy": {
|
||||
"message": "proxy"
|
||||
|
@ -11,133 +11,7 @@
|
|||
"noControl": {
|
||||
"message": "Other extension controls proxy!"
|
||||
},
|
||||
"WhichQ": {
|
||||
"which": {
|
||||
"message": "Which?"
|
||||
},
|
||||
"update": {
|
||||
"message": "update"
|
||||
},
|
||||
"UpdatingDDD": {
|
||||
"message": "Updating..."
|
||||
},
|
||||
"UpdatedD": {
|
||||
"message": "Updated."
|
||||
},
|
||||
"DisablingDDD": {
|
||||
"message": "Disabling..."
|
||||
},
|
||||
"DisabledD": {
|
||||
"message": "Disabled."
|
||||
},
|
||||
"InstallingDDD": {
|
||||
"message": "Installing..."
|
||||
},
|
||||
"PacScriptWasInstalledD": {
|
||||
"message": "PAC-script was installed."
|
||||
},
|
||||
"Version": {
|
||||
"message": "Version"
|
||||
},
|
||||
"FullVersion": {
|
||||
"message": "Full version"
|
||||
},
|
||||
"VersionForSlowMachines": {
|
||||
"message": "Version for slow machines"
|
||||
},
|
||||
"FailedToDownloadPacScriptFromAddresses": {
|
||||
"message": "Failed to download PAC-script from addresses"
|
||||
},
|
||||
"ChoosePacProviderFirstD": {
|
||||
"message": "Choose PAC-provider first."
|
||||
},
|
||||
"ProblemsQ": {
|
||||
"message": "Problems?"
|
||||
},
|
||||
"Finish": {
|
||||
"message": "OK"
|
||||
},
|
||||
"Disable": {
|
||||
"message": "Disable"
|
||||
},
|
||||
"Only_own_sites_and_only_own_proxies": {
|
||||
"message": "Only own sites and only own proxies"
|
||||
},
|
||||
"Antizapret": {
|
||||
"message": "Antizapret"
|
||||
},
|
||||
"Anticensority": {
|
||||
"message": "Anticensority"
|
||||
},
|
||||
"PAC_script": {
|
||||
"message": "PAC-script"
|
||||
},
|
||||
"Exceptions": {
|
||||
"message": "Exceptions"
|
||||
},
|
||||
"Own_proxies": {
|
||||
"message": "Own proxies"
|
||||
},
|
||||
"Modifiers": {
|
||||
"message": "Modifiers"
|
||||
},
|
||||
"Notifications": {
|
||||
"message": "Notifications"
|
||||
},
|
||||
"Error": {
|
||||
"message": "Error"
|
||||
},
|
||||
"Non_critical_error": {
|
||||
"message": "Non-critical error. Don't worry: it works"
|
||||
},
|
||||
"Donate": {
|
||||
"message": "Donate"
|
||||
},
|
||||
"Updated": {
|
||||
"message": "Updated"
|
||||
},
|
||||
"ago": {
|
||||
"message": "ago"
|
||||
},
|
||||
"never": {
|
||||
"message": "never"
|
||||
},
|
||||
"ms": {
|
||||
"message": "ms"
|
||||
},
|
||||
"s": {
|
||||
"message": "s"
|
||||
},
|
||||
"min": {
|
||||
"message": "min"
|
||||
},
|
||||
"h": {
|
||||
"message": "h"
|
||||
},
|
||||
"d": {
|
||||
"message": "d"
|
||||
},
|
||||
"w": {
|
||||
"message": "w"
|
||||
},
|
||||
"m": {
|
||||
"message": "m"
|
||||
},
|
||||
"ProxyTheDomainNameBelowQ": {
|
||||
"message": "Proxy the domain name below?"
|
||||
},
|
||||
"auto": {
|
||||
"message": "auto"
|
||||
},
|
||||
"yes": {
|
||||
"message": "yes"
|
||||
},
|
||||
"no": {
|
||||
"message": "no"
|
||||
},
|
||||
"noOwnProxiesError": {
|
||||
"message": "Proxying of OWN sites is possible only via OWN proxies. No own proxies found that satisfy your requirements."
|
||||
},
|
||||
"AllowExtensionToRunInPrivateWindows": {
|
||||
"message": "For the extension to work it is required to allow it to run in private windows, see <a href='https://github.com/anticensority/runet-censorship-bypass/wiki/Как-разрешить-запуск-расширения-в-приватных-окнах-|-How-to-allow-extension-to-run-in-private-windows'>a HOWTO</a>."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"message": "Обход блокировок Рунета${nameSuffixRu}"
|
||||
},
|
||||
"extDesc": {
|
||||
"message": "Обход интернет-цензуры в России: https://git.io/ac-wiki"
|
||||
"message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki"
|
||||
},
|
||||
"proxy": {
|
||||
"message": "прокси"
|
||||
|
@ -11,133 +11,7 @@
|
|||
"noControl": {
|
||||
"message": "Другое расширение контролирует настройки прокси!"
|
||||
},
|
||||
"WhichQ": {
|
||||
"which": {
|
||||
"message": "Какое?"
|
||||
},
|
||||
"update": {
|
||||
"message": "обновить"
|
||||
},
|
||||
"UpdatingDDD": {
|
||||
"message": "Обновляем..."
|
||||
},
|
||||
"UpdatedD": {
|
||||
"message": "Обновлено."
|
||||
},
|
||||
"DisablingDDD": {
|
||||
"message": "Отключение..."
|
||||
},
|
||||
"DisabledD": {
|
||||
"message": "Отключено."
|
||||
},
|
||||
"InstallingDDD": {
|
||||
"message": "Установка..."
|
||||
},
|
||||
"PacScriptWasInstalledD": {
|
||||
"message": "PAC-скрипт установлен."
|
||||
},
|
||||
"Version": {
|
||||
"message": "Версия"
|
||||
},
|
||||
"FullVersion": {
|
||||
"message": "Полная версия"
|
||||
},
|
||||
"VersionForSlowMachines": {
|
||||
"message": "Версия для слабых машин"
|
||||
},
|
||||
"FailedToDownloadPacScriptFromAddresses": {
|
||||
"message": "Не удалось скачать PAC-скрипт с адресов"
|
||||
},
|
||||
"ChoosePacProviderFirstD": {
|
||||
"message": "Сперва выберите PAC-провайдера."
|
||||
},
|
||||
"ProblemsQ": {
|
||||
"message": "Проблемы?"
|
||||
},
|
||||
"Finish": {
|
||||
"message": "Готово"
|
||||
},
|
||||
"Disable": {
|
||||
"message": "Отключить"
|
||||
},
|
||||
"Only_own_sites_and_only_own_proxies": {
|
||||
"message": "Только свои сайты и свои прокси"
|
||||
},
|
||||
"Antizapret": {
|
||||
"message": "Антизапрет"
|
||||
},
|
||||
"Anticensority": {
|
||||
"message": "Антицензорити"
|
||||
},
|
||||
"PAC_script": {
|
||||
"message": "PAC-скрипт"
|
||||
},
|
||||
"Exceptions": {
|
||||
"message": "Исключения"
|
||||
},
|
||||
"Own_proxies": {
|
||||
"message": "Свои прокси"
|
||||
},
|
||||
"Modifiers": {
|
||||
"message": "Модификаторы"
|
||||
},
|
||||
"Notifications": {
|
||||
"message": "Уведомления"
|
||||
},
|
||||
"Error": {
|
||||
"message": "Ошибка"
|
||||
},
|
||||
"Non_critical_error": {
|
||||
"message": "Некритичная ошибка. Всё хорошо, продолжаем работу"
|
||||
},
|
||||
"Donate": {
|
||||
"message": "Поддержать"
|
||||
},
|
||||
"Updated": {
|
||||
"message": "Обновлялись"
|
||||
},
|
||||
"ago": {
|
||||
"message": "назад"
|
||||
},
|
||||
"never": {
|
||||
"message": "никогда"
|
||||
},
|
||||
"ms": {
|
||||
"message": "мс"
|
||||
},
|
||||
"s": {
|
||||
"message": "с"
|
||||
},
|
||||
"min": {
|
||||
"message": "мин"
|
||||
},
|
||||
"h": {
|
||||
"message": "ч"
|
||||
},
|
||||
"d": {
|
||||
"message": "дн"
|
||||
},
|
||||
"w": {
|
||||
"message": " недель"
|
||||
},
|
||||
"m": {
|
||||
"message": " месяцев"
|
||||
},
|
||||
"ProxyTheDomainNameBelowQ": {
|
||||
"message": "Проксировать указанное доменное имя?"
|
||||
},
|
||||
"auto": {
|
||||
"message": "авто"
|
||||
},
|
||||
"yes": {
|
||||
"message": "да"
|
||||
},
|
||||
"no": {
|
||||
"message": "нет"
|
||||
},
|
||||
"noOwnProxiesError": {
|
||||
"message": "Проксировать СВОИ сайты можно только при наличии СВОИХ прокси. Нет своих прокси, удовлетворяющих вашим требованиям."
|
||||
},
|
||||
"AllowExtensionToRunInPrivateWindows": {
|
||||
"message": "Для работы расширения необходимо разрешить запуск в приватных окнах, см. <a href='https://github.com/anticensority/runet-censorship-bypass/wiki/Как-разрешить-запуск-расширения-в-приватных-окнах-|-How-to-allow-extension-to-run-in-private-windows'>инструкции</a>."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
"description": "__MSG_extDesc__",
|
||||
"version": "0.0.${version}",
|
||||
"icons": {
|
||||
"128": "icons/default-128.png"
|
||||
"128": "/icons/default-128.png"
|
||||
},
|
||||
"author": "anticensority+owners@googlegroups.com",
|
||||
"author": "ilyaigpetrov@gmail.com",
|
||||
"homepage_url": "https://github.com/anticensorship-russia/chromium-extension",
|
||||
|
||||
"permissions": [
|
||||
"proxy"
|
||||
, "alarms"
|
||||
, "storage"
|
||||
, "unlimitedStorage"
|
||||
, "<all_urls>"
|
||||
, "tabs"
|
||||
, "contextMenus"
|
||||
|
@ -22,21 +22,14 @@
|
|||
${extra_permissions}
|
||||
],
|
||||
"minimum_chrome_version": "55.0.0.0",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"strict_min_version": "91.1.0"
|
||||
}
|
||||
},
|
||||
|
||||
"background": {
|
||||
${persistent}
|
||||
"scripts": [
|
||||
"00-init-apis.js"
|
||||
${scripts_0x}
|
||||
, "11-error-handlers-api.js"
|
||||
, "12-errors-lib.js"
|
||||
, "13-http-lib.js"
|
||||
, "15-firefox-proxy-settings.js"
|
||||
${scripts_2x}
|
||||
, "35-pac-kitchen-api.js"
|
||||
, "37-sync-pac-script-with-pac-provider-api.js"
|
||||
|
@ -45,7 +38,6 @@
|
|||
, "75-context-menus.js"
|
||||
]
|
||||
},
|
||||
|
||||
"browser_action": {
|
||||
"default_title": "Этот сайт благословлён | Версия ${version + versionSuffix}",
|
||||
"default_popup": "/pages/options/index.html"
|
||||
|
@ -54,5 +46,4 @@
|
|||
"page": "/pages/options/index.html",
|
||||
"chrome_style": false
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="icon" type="image/x-icon" href="./ribbon-128.ico">
|
||||
<meta charset="utf-8">
|
||||
<title>Согласие на сбор данных / Data Collection Consent</title>
|
||||
<style>
|
||||
p, ol { font-size: 16px }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="margin: 0 auto; max-width: 35rem; text-align: justify; font-family: sans-serif">
|
||||
<img src="./ribbon-128.png">
|
||||
<h1>Согласие на сбор данных / Data Collection Consent</h1>
|
||||
<p>
|
||||
Этот документ написан на двух языках. Английский предпочтительней.
|
||||
</p>
|
||||
<p>
|
||||
This document is written in two languages. English is preferable.
|
||||
</p>
|
||||
<p>
|
||||
Привет! На связи команда разработчиков браузерного расширения «Обход блокировок Рунета».
|
||||
Вы либо только что установили расширение, либо только что обновились до новой версии.
|
||||
По новым правилам мы <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Зачем-нам-согласие-со-сбором-данных%3F">должны</a>
|
||||
получить от вас согласие на сбор ваших данных и передачу их
|
||||
третьим лицам.
|
||||
</p>
|
||||
<p>
|
||||
Hi! It's "Runet Censorship Bypass" browser extension developers team.
|
||||
You have just installed the extension or just updated to a new version.
|
||||
According to the new requirements we <a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Зачем-нам-согласие-со-сбором-данных%3F">have to</a> get your consent before collecting your data and
|
||||
sharing it with 3rd parties.
|
||||
</p>
|
||||
<p>
|
||||
Сообщаем вам, что после первого запуска расширения и при дальнейшем его использовании
|
||||
настроенные в нём PAC-скрипты и прокси-сервера могут собирать или уже* собирают
|
||||
некоторые ваши данные. Какие именно, зависит от выбранного вами поставщика этих ресурсов,
|
||||
так что рекомендуем ознакомиться с их соответствующей политикой конфиденциальности (Privacy
|
||||
Policy).
|
||||
<br>
|
||||
* Если вы установили и пользовалсись расширением уже некоторое время. Этого экрана согласия не
|
||||
было в старых версиях.
|
||||
</p>
|
||||
<p>
|
||||
We inform you that starting from the first launch of the extension and on further usage chosen
|
||||
PAC-scripts and proxy-servers may collect or are already* collecting some of your data. Which
|
||||
exactly depends on the chosen provider of these resources so we recommend you to get
|
||||
acquainted with their corresponding Privacy Policy.
|
||||
<br>
|
||||
* If you have installed and have been using the extension for some time already. This consent
|
||||
screen wasn't shown in the old versions.
|
||||
</p>
|
||||
<p>
|
||||
При первом запуске и по умолчанию будут использоваться PAC-скрипт и встроенные в него
|
||||
прокси-сервера, предоставляемые <a href="https://antizapret.prostovpn.org:8443">проектом
|
||||
"АнтиЗапрет"</a>, — политику конфиденциальности этого решения см. в
|
||||
<a href="https://antizapret.prostovpn.org:8443/faq.html">FAQ</a> под заголовком "Какие данные
|
||||
собирает сервис и каким образом они используются?".
|
||||
</p>
|
||||
<p>
|
||||
On the first launch and by default the PAC-script and its built-in proxy-servers provided by
|
||||
<a href="https://antizapret.prostovpn.org:8443">project "AntiZapret" (RU)</a> will be used, —
|
||||
see its Privacy Policy in
|
||||
<a href="https://antizapret.prostovpn.org:8443/faq.html">the FAQ (RU)</a> under the title
|
||||
"Какие данные собирает сервис и каким образом они используются?". Its translation to EN is
|
||||
present in the Privacy Policy of the extension.
|
||||
</p>
|
||||
<p>
|
||||
Политику конфиденциальности самого расширения см.
|
||||
<a
|
||||
href="https://github.com/anticensority/runet-censorship-bypass/wiki/Privacy-Policy-|-Политика-конфиденциальности"
|
||||
>здесь (EN)</a>.
|
||||
</p>
|
||||
<p>
|
||||
See the Privacy Policy of this extension
|
||||
<a
|
||||
href="https://github.com/anticensority/runet-censorship-bypass/wiki/Privacy-Policy-|-Политика-конфиденциальности"
|
||||
>here</a>.
|
||||
</p>
|
||||
<p>
|
||||
В расширении представлены кнопки / There are these buttons in the extension:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
"Через Google Translate" / "Via Google Translate"
|
||||
</li><li>
|
||||
"Из кэша Google" / "From Google Cache"
|
||||
</li><li>
|
||||
"Из архива archive.org" / "From archive.org archive"
|
||||
</li><li>
|
||||
"Разблокировать по-другому" / "Unblock another way"
|
||||
</li><li>
|
||||
"Сайт в реестре блокировок?" / "Is site in the registry of blockings?"
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Все эти кнопки передают URL-адрес текущей вкладки в соответствующие службы. /
|
||||
All these buttons share URL-address of the current tab with corresponding services.
|
||||
</p>
|
||||
<button id="agreeBtn">Разрешаю собирать заявленные данные / Allow claimed data collection
|
||||
</button>
|
||||
<button id="rejectBtn">Нет, удалите расширение / No, delete this extension
|
||||
</button>
|
||||
</div>
|
||||
<script src="./index.js"></script>
|
||||
<script src="../lib/keep-links-clickable.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
||||
backgroundPage.apis.errorHandlers.installListenersOn(
|
||||
window, 'CONSENT', () => {
|
||||
agreeBtn.onclick = () => {
|
||||
backgroundPage.apis.consent.give();
|
||||
window.close();
|
||||
}
|
||||
rejectBtn.onclick = () =>
|
||||
chrome.management.uninstallSelf();
|
||||
},
|
||||
),
|
||||
);
|
Binary file not shown.
Before Width: | Height: | Size: 66 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
|
@ -1,62 +1,60 @@
|
|||
'use strict';
|
||||
|
||||
chrome.runtime.getBackgroundPage((bgWin) => {
|
||||
const setStatusTo = (msg) => document.getElementById('status').innerHTML = msg;
|
||||
|
||||
const setStatusTo = (msg) => document.getElementById('status').innerHTML = msg;
|
||||
const red = (text) => '<span style="color: red">' + text + '</span>';
|
||||
|
||||
const red = (text) => '<span style="color: red">' + text + '</span>';
|
||||
const editor = window.ace.edit('editor');
|
||||
editor.getSession().setOptions({
|
||||
mode: 'ace/mode/javascript',
|
||||
useSoftTabs: true,
|
||||
});
|
||||
|
||||
chrome.proxy.settings.onChange.addListener(
|
||||
(details) => setStatusTo(red( details.levelOfControl + '!') )
|
||||
);
|
||||
|
||||
function _read() {
|
||||
|
||||
chrome.proxy.settings.get({}, (details) => {
|
||||
|
||||
let control = details.levelOfControl;
|
||||
if (control.startsWith('controlled_by_other')) {
|
||||
control = red(control);
|
||||
}
|
||||
setStatusTo(control);
|
||||
console.log(details);
|
||||
const pac = details.value.pacScript;
|
||||
const data = pac && pac.data || 'PAC скрипт не установлен.';
|
||||
editor.setValue( data );
|
||||
|
||||
const editor = window.ace.edit('editor');
|
||||
editor.getSession().setOptions({
|
||||
mode: 'ace/mode/javascript',
|
||||
useSoftTabs: true,
|
||||
});
|
||||
|
||||
bgWin.chrome.proxy.settings.onChange.addListener(
|
||||
(details) => setStatusTo(red( details.levelOfControl + '!') )
|
||||
);
|
||||
}
|
||||
|
||||
function _read() {
|
||||
document.querySelector('#read-button').onclick = _read;
|
||||
|
||||
bgWin.chrome.proxy.settings.get({}, (details) => {
|
||||
|
||||
let control = details.levelOfControl;
|
||||
if (control.startsWith('controlled_by_other')) {
|
||||
control = red(control);
|
||||
}
|
||||
setStatusTo(control);
|
||||
const pac = details.value.pacScript;
|
||||
const data = pac && pac.data || 'PAC скрипт не установлен.';
|
||||
editor.setValue( data );
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
document.querySelector('#read-button').onclick = _read;
|
||||
|
||||
document.querySelector('#save-button').onclick = () => {
|
||||
|
||||
const config = {
|
||||
mode: 'pac_script',
|
||||
pacScript: {
|
||||
mandatory: false,
|
||||
data: editor.getValue(),
|
||||
},
|
||||
};
|
||||
bgWin.chrome.proxy.settings.set( {value: config}, () => alert('Saved!') );
|
||||
document.querySelector('#save-button').onclick = () => {
|
||||
|
||||
const config = {
|
||||
mode: 'pac_script',
|
||||
pacScript: {
|
||||
mandatory: false,
|
||||
data: editor.getValue(),
|
||||
},
|
||||
};
|
||||
chrome.proxy.settings.set( {value: config}, () => alert('Saved!') );
|
||||
|
||||
document.querySelector('#clear-button').onclick = () => {
|
||||
};
|
||||
|
||||
bgWin.chrome.proxy.settings.clear({}, () => {
|
||||
document.querySelector('#clear-button').onclick = () => {
|
||||
|
||||
alert('Cleared! Reading...');
|
||||
_read();
|
||||
chrome.proxy.settings.clear({}, () => {
|
||||
|
||||
});
|
||||
alert('Cleared! Reading...');
|
||||
_read();
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
})
|
||||
|
|
|
@ -17,9 +17,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
|||
# Сначала идёт список проксируемых сайтов,
|
||||
# затем ==== на отдельной строке,
|
||||
# затем исключённые сайты.
|
||||
# После ещё одной строки с ==== идёт белый список.
|
||||
# Сортировка — с конца строки.
|
||||
# Адреса со звёздочками поддерживаются: *.kasparov.ru, например.
|
||||
|
||||
# ПРОКСИРОВАТЬ:
|
||||
|
||||
|
@ -28,16 +26,7 @@ ${(mods.included || []).join('\n')}
|
|||
===============================
|
||||
# НЕ ПРОКСИРОВАТЬ:
|
||||
|
||||
${(mods.excluded || []).join('\n')}
|
||||
|
||||
|
||||
===============================
|
||||
# БЕЛЫЙ СПИСОК
|
||||
# Разрешить расширению работать только с этими адресами:
|
||||
|
||||
${(mods.whitelist || []).join('\n')}
|
||||
|
||||
`.trim();
|
||||
${(mods.excluded || []).join('\n')}`;
|
||||
|
||||
status.innerText = 'Успешно загружено!';
|
||||
|
||||
|
@ -46,7 +35,7 @@ ${(mods.whitelist || []).join('\n')}
|
|||
|
||||
saveBtn.onclick = function() {
|
||||
|
||||
let [proxyList, dontProxyList, whitelist] = editor.value
|
||||
let [proxyList, dontProxyList] = editor.value
|
||||
.trim()
|
||||
.replace(/#.*/g, '')
|
||||
.split(/=+/g)
|
||||
|
@ -56,14 +45,12 @@ ${(mods.whitelist || []).join('\n')}
|
|||
.filter((host) => host)
|
||||
)
|
||||
dontProxyList = dontProxyList || [];
|
||||
whitelist = whitelist || [];
|
||||
|
||||
const exceptions = {};
|
||||
proxyList.forEach((host) => (exceptions[host] = true));
|
||||
dontProxyList.forEach((host) => (exceptions[host] = false));
|
||||
const mods = backgroundPage.apis.pacKitchen.getPacMods();
|
||||
mods.exceptions = exceptions;
|
||||
mods.whitelist = whitelist;
|
||||
backgroundPage.apis.pacKitchen.keepCookedNowAsync(mods, (err) => {
|
||||
if (!err) {
|
||||
status.innerText = 'Успешно сохранено!';
|
||||
|
|
|
@ -16,7 +16,7 @@ Use only if really required because of performance penalty.
|
|||
const location = ln.href;
|
||||
ln.onclick = function() {
|
||||
|
||||
chrome.tabs.create({active: this.dataset.inBg === "false", url: location});
|
||||
chrome.tabs.create({active: !this.dataset.inBg, url: location});
|
||||
return false;
|
||||
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html style="visibility: hidden; will-change: contents, visibility">
|
||||
<html style="display: none; will-change: contents, display">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Настройки</title>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,27 +1,25 @@
|
|||
{
|
||||
"name": "options-page-builder",
|
||||
"name": "hello-react",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "GPLv3",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-plugin-dynamic-import-webpack": "^1.1.0",
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-loader": "^7.0.0",
|
||||
"babel-plugin-dynamic-import-webpack": "^1.0.1",
|
||||
"babel-preset-flow": "^6.23.0",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"concat-stream": "^1.6.2",
|
||||
"concat-stream": "^1.6.0",
|
||||
"csjs-inject": "^1.0.1",
|
||||
"flow-bin": "^0.45.0",
|
||||
"gulp": "^4.0.2",
|
||||
"inferno": "~3.2.0",
|
||||
"inferno-component": "^3.10.1",
|
||||
"inferno-create-element": "^3.10.1",
|
||||
"webpack": "^5.82.0",
|
||||
"webpack-cli": "^5.0.2"
|
||||
"inferno-component": "^3.1.2",
|
||||
"inferno-create-element": "^3.1.2",
|
||||
"webpack": "^2.5.1"
|
||||
},
|
||||
"scripts": {
|
||||
"check": "flow status",
|
||||
"build:prod": "webpack --node-env=\"'production'\" --env=prod",
|
||||
"build:prod": "webpack --define process.env.NODE_ENV=\"'production'\" --env=prod",
|
||||
"build:dev:nocomp": "NODE_ENV=development webpack --define process.env.NODE_ENV=\"'development'\" --env=dev",
|
||||
"build:dev": "NODE_ENV=development webpack --debug --define process.env.NODE_ENV=\"'development'\" --output-pathinfo --env=dev",
|
||||
"gulp": "cd .. && npm run gulp",
|
||||
|
@ -29,6 +27,6 @@
|
|||
"start": "cd .. && npm start"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-plugin-inferno": "^3.5.1"
|
||||
"babel-plugin-inferno": "^3.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,12 @@ export default function getApp(theState) {
|
|||
constructor(props) {
|
||||
|
||||
super(props);
|
||||
|
||||
const sanitizedUrl = theState.flags.ifOpenedUnsafely ? { hash: '', search: '' } : window.location;
|
||||
const hashParams = new URLSearchParams(sanitizedUrl.hash.substr(1));
|
||||
const searchParams = new URLSearchParams(sanitizedUrl.search.substr(1));
|
||||
const hash = window.location.hash.substr(1);
|
||||
const hashParams = new URLSearchParams(hash);
|
||||
this.state = {
|
||||
status: 'Загрузка...',
|
||||
ifInputsDisabled: false,
|
||||
hashParams,
|
||||
searchParams,
|
||||
hashParams: hashParams,
|
||||
};
|
||||
|
||||
this.setStatusTo = this.setStatusTo.bind(this);
|
||||
|
@ -50,10 +47,7 @@ export default function getApp(theState) {
|
|||
|
||||
this.setStatusTo(
|
||||
<ol style="list-style-type: initial;">
|
||||
{newsArr
|
||||
.map(([title, url]) => (<li><a href={url}>{title}</a></li>))
|
||||
.reverse() // News order.
|
||||
}
|
||||
{newsArr.map(([title, url]) => (<li><a href={url}>{title}</a></li>))}
|
||||
</ol>
|
||||
);
|
||||
|
||||
|
@ -65,16 +59,16 @@ export default function getApp(theState) {
|
|||
const uiComEtag = 'ui-last-comments-etag';
|
||||
const uiLastNewsArr = 'ui-last-news-arr';
|
||||
|
||||
const statusFromUrl = this.state.searchParams.get('status');
|
||||
if (statusFromUrl) {
|
||||
return this.setStatusTo(statusFromUrl);
|
||||
const statusFromHash = this.state.hashParams.get('status');
|
||||
if (statusFromHash) {
|
||||
return this.setStatusTo(statusFromHash);
|
||||
}
|
||||
|
||||
const comDate = localStorage[uiComDate];
|
||||
const query = comDate ? `?since=${comDate}` : '';
|
||||
const oldEtag = localStorage[uiComEtag];
|
||||
const headers = {
|
||||
'User-Agent': 'https://github.com/anticensority/runet-censorship-bypass',
|
||||
'User-Agent': 'anticensorship-russia',
|
||||
};
|
||||
if (oldEtag) {
|
||||
Object.assign(headers, {
|
||||
|
@ -85,9 +79,8 @@ export default function getApp(theState) {
|
|||
headers: new Headers(headers),
|
||||
};
|
||||
|
||||
// I comment and uncomment this variable manually before release or build:
|
||||
const ghUrl = `https://api.github.com/repos/anticensority/chromium-extension/issues/10/comments${query}`;
|
||||
// const ghUrl = `https://api.github.com/repos/anticensority/for-testing/issues/1/comments${query}`;
|
||||
//const ghUrl = `https://api.github.com/repos/anticensority/chromium-extension/issues/10/comments${query}`;
|
||||
const ghUrl = `https://api.github.com/repos/anticensority/for-testing/issues/1/comments${query}`;
|
||||
|
||||
const [error, comments, etag] = await fetch(
|
||||
ghUrl,
|
||||
|
@ -230,10 +223,7 @@ export default function getApp(theState) {
|
|||
this.setStatusTo(
|
||||
(<span>
|
||||
<span style="color:red">
|
||||
{err
|
||||
? <span><span class="emoji">🔥</span> {chrome.i18n.getMessage('Error')}!</span>
|
||||
: `${chrome.i18n.getMessage('Non_critical_error')}.`
|
||||
}
|
||||
{err ? <span><span class="emoji">🔥</span> Ошибка!</span> : 'Некритичная oшибка.'}
|
||||
</span>
|
||||
<br/>
|
||||
<span style="font-size: 0.9em; color: darkred" dangerouslySetInnerHTML={{__html: messageHtml}}></span>
|
||||
|
@ -266,6 +256,7 @@ export default function getApp(theState) {
|
|||
this.setStatusTo(beforeStatus);
|
||||
this.switchInputs('off');
|
||||
operation((err, res, ...warns) => {
|
||||
|
||||
warns = warns.filter( (w) => w );
|
||||
if (err || warns.length) {
|
||||
this.showErrors(err, ...warns);
|
||||
|
|
|
@ -4,7 +4,7 @@ export default function getApplyMods(theState) {
|
|||
|
||||
const resetMods = function resetMods(props) {
|
||||
|
||||
const ifSure = props.bgWindow.confirm('Сбросить все модификаторы и ИСКЛЮЧЕНИЯ?');
|
||||
const ifSure = props.bgWindow.confirm('Сбросиь все модификаторы и ИСКЛЮЧЕНИЯ?');
|
||||
if (!ifSure) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -75,18 +75,13 @@ export default function getExcEditor(theState) {
|
|||
constructor(props) {
|
||||
|
||||
super(props);
|
||||
const trimmedInputValueOrSpace =
|
||||
props.currentTab &&
|
||||
props.currentTab.url &&
|
||||
!props.currentTab.url.startsWith('chrome')
|
||||
? '*.' + (new URL(props.currentTab.url).hostname.replace(/^www\./g, ''))
|
||||
: '';
|
||||
|
||||
const pacMods = props.apis.pacKitchen.getPacMods();
|
||||
this.state = {
|
||||
trimmedInputValueOrSpace,
|
||||
trimmedInputValueOrSpace:
|
||||
props.currentTab && !props.currentTab.url.startsWith('chrome') ? new URL(props.currentTab.url).hostname : '',
|
||||
sortedListOfOptions: this.modsToOpts(pacMods),
|
||||
hostToIfHidden: {},
|
||||
isHostHidden: {}
|
||||
};
|
||||
this.handleRadioClick = this.handleRadioClick.bind(this);
|
||||
this.handleInputOrClick = this.handleInputOrClick.bind(this);
|
||||
|
@ -96,11 +91,11 @@ export default function getExcEditor(theState) {
|
|||
hideAllOptions() {
|
||||
|
||||
this.setState({
|
||||
hostToIfHidden: this.state.sortedListOfOptions.reduce(
|
||||
(hostToIfHidden, [excHost]) => {
|
||||
isHostHidden: this.state.sortedListOfOptions.reduce(
|
||||
(isHostHidden, [excHost]) => {
|
||||
|
||||
hostToIfHidden[excHost] = true;
|
||||
return hostToIfHidden;
|
||||
isHostHidden[excHost] = true;
|
||||
return isHostHidden;
|
||||
|
||||
},
|
||||
{}),
|
||||
|
@ -110,7 +105,7 @@ export default function getExcEditor(theState) {
|
|||
|
||||
isHostValid(host) {
|
||||
|
||||
const ValidHostnameRegex = /^(?:\*\.)?(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
|
||||
const ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
|
||||
if(!ValidHostnameRegex.test(host)) {
|
||||
this.props.funs.showErrors(new TypeError('Должно быть только доменное имя, без протокола, порта и пути. Попробуйте ещё раз.'));
|
||||
return false;
|
||||
|
@ -142,7 +137,7 @@ export default function getExcEditor(theState) {
|
|||
case 'this-no':
|
||||
if (ifYesClicked && !pacMods.filteredCustomsString) {
|
||||
this.props.funs.showErrors( new TypeError(
|
||||
chrome.i18n.getMessage('noOwnProxiesError'),
|
||||
'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси. Нет своих прокси, удовлетворяющих вашим требованиям.'
|
||||
));
|
||||
return false;
|
||||
}
|
||||
|
@ -210,9 +205,7 @@ export default function getExcEditor(theState) {
|
|||
const ifInit = !event;
|
||||
const currentHost = ifTriangleClicked ? '' : (trimmedInput || (ifInit ? '' : ' '));
|
||||
setInputValue(currentHost);
|
||||
this.setState({
|
||||
trimmedInputValueOrSpace: currentHost,
|
||||
});
|
||||
this.setState({trimmedInputValueOrSpace: currentHost});
|
||||
|
||||
// Episode 2.
|
||||
|
||||
|
@ -281,7 +274,7 @@ export default function getExcEditor(theState) {
|
|||
})();
|
||||
|
||||
this.setState({
|
||||
hostToIfHidden: hidden,
|
||||
isHostHidden: hidden,
|
||||
sortedListOfOptions: options,
|
||||
});
|
||||
|
||||
|
@ -300,10 +293,10 @@ export default function getExcEditor(theState) {
|
|||
|
||||
return (
|
||||
<section style="padding-bottom: 1em;">
|
||||
<div>{chrome.i18n.getMessage('ProxyTheDomainNameBelowQ')}</div>
|
||||
<div>Проксировать указанный сайт?</div>
|
||||
<div id="exc-address-container">
|
||||
<div id="exc-address" class={inputProxyingState !== undefined ? ( inputProxyingState === true ? scopedCss.ifYes : scopedCss.ifNo ) : ''}>
|
||||
<input placeholder="*.navalny.com" list="exc-list" id="exc-editor"
|
||||
<span>*.</span><input placeholder="navalny.com" list="exc-list" id="exc-editor"
|
||||
value={this.state.trimmedInputValueOrSpace}
|
||||
ref={(inputNode) => { this.rawInput = inputNode; }}
|
||||
onKeyDown={this.handleKeyDown.bind(this)}
|
||||
|
@ -323,10 +316,9 @@ export default function getExcEditor(theState) {
|
|||
|
||||
// 1. Option's value may be changed to hide it from the tooltip.
|
||||
// 2. Space is used in matching so even an empty input (replaced with space) has tooltip with prompts.
|
||||
const ifProxy = excState;
|
||||
return <option
|
||||
value={ this.state.hostToIfHidden[excHost] ? '\n' : excHost + ' ' }
|
||||
label={ ifProxy === true ? labelIfProxied : (ifProxy === false ? labelIfNotProxied : labelIfAuto) }/>
|
||||
value={ this.state.isHostHidden[excHost] ? '\n' : excHost + ' ' }
|
||||
label={ excState === true ? labelIfProxied : (excState === false ? labelIfNotProxied : labelIfAuto) }/>
|
||||
|
||||
})
|
||||
}
|
||||
|
@ -335,19 +327,19 @@ export default function getExcEditor(theState) {
|
|||
<li><input id="this-auto" type="radio" checked name="if-proxy-this-site" onClick={this.handleRadioClick}/>{' '}
|
||||
<label for="this-auto">{/*<span class="emoji">🔄(looks fat)</span>*/}<svg
|
||||
class="icon"
|
||||
style="position: relative; top: 0.15em;"><use xlink:href="#iconLoopRound"></use></svg> {chrome.i18n.getMessage('auto')}</label>
|
||||
style="position: relative; top: 0.15em;"><use xlink:href="#iconLoopRound"></use></svg> авто</label>
|
||||
</li>
|
||||
<li>
|
||||
<input id="this-yes" type="radio" name="if-proxy-this-site" checked={inputProxyingState === true} onClick={this.handleRadioClick}/>
|
||||
{' '}<label for="this-yes">
|
||||
<span
|
||||
class="emoji____buggy"
|
||||
>✔</span> {chrome.i18n.getMessage('yes')}
|
||||
>✔</span> да
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<input id="this-no" type="radio" name="if-proxy-this-site" checked={inputProxyingState === false} onClick={this.handleRadioClick}/>
|
||||
{' '}<label for="this-no"><span class="emoji">✘</span> {chrome.i18n.getMessage('no')}</label></li>
|
||||
{' '}<label for="this-no"><span class="emoji">✘</span> нет</label></li>
|
||||
</ol>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -67,7 +67,7 @@ export default function getExceptions(theState) {
|
|||
<InfoLi
|
||||
type="checkbox"
|
||||
conf={{
|
||||
label: '<span>Собирать <a data-in-bg="false" href="../errors-to-exc/index.html">последние ошибки</a> сайтов</span>',
|
||||
label: '<span>Собирать <a href="../errors-to-exc/index.html">последние ошибки</a> сайтов</span>',
|
||||
key: 'lookupLastErrors',
|
||||
desc: 'Собирать последние ошибки в запросах, чтобы вручную добавлять избранные из них в исключения.',
|
||||
}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Inferno from 'inferno';
|
||||
import css from 'csjs-inject';
|
||||
|
||||
export default function getFooter(theState) {
|
||||
export default function getFooter() {
|
||||
|
||||
const scopedCss = css`
|
||||
|
||||
|
@ -17,22 +17,23 @@ export default function getFooter(theState) {
|
|||
|
||||
`;
|
||||
|
||||
return (props) => (
|
||||
<div class="horPadded">
|
||||
<section class={scopedCss.statusRow}>
|
||||
<div class={scopedCss.status} style="will-change: contents">
|
||||
{typeof(props.status) === 'string' ? <div dangerouslySetInnerHTML={{ __html: props.status }}></div> : props.status}
|
||||
</div>
|
||||
</section>
|
||||
return function (props) {
|
||||
|
||||
<footer class={scopedCss.controlRow + ' horFlex nowrap'}>
|
||||
<input type="button" value={chrome.i18n.getMessage('Finish')} disabled={props.ifInputsDisabled} style={{ display: theState.flags.ifInsideEdgeOptionsPage ? 'none' : 'initial' }} onClick={() => window.close()} />
|
||||
<a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Поддержать">{chrome.i18n.getMessage('Donate')}</a>
|
||||
<a data-in-bg="false" href="../troubleshoot/index.html">
|
||||
{chrome.i18n.getMessage('ProblemsQ')}
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div class="horPadded">
|
||||
<section class={scopedCss.statusRow}>
|
||||
<div clss={scopedCss.status} style="will-change: contents">{props.status}</div>
|
||||
</section>
|
||||
|
||||
<footer class={scopedCss.controlRow + ' horFlex nowrap'}>
|
||||
<input type="button" value="Готово" disabled={props.ifInputsDisabled} onClick={() => window.close()} />
|
||||
<a href="../troubleshoot/index.html">
|
||||
Проблемы?
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -25,9 +25,6 @@ export default function getInfoLi() {
|
|||
.infoRow {
|
||||
position: relative;
|
||||
}
|
||||
.infoRow a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.infoRow > input[type="checkbox"] {
|
||||
position: relative;
|
||||
top: -0.08em;
|
||||
|
@ -52,7 +49,7 @@ export default function getInfoLi() {
|
|||
position: absolute;
|
||||
white-space: initial;
|
||||
word-break: initial;
|
||||
/* top: 100%; Commented to get rid of bug when tooltip is placed below InfoLi children fields. */
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 1em;
|
||||
z-index: 1;
|
||||
|
|
|
@ -7,10 +7,8 @@ export default function getLastUpdateDate(theState) {
|
|||
|
||||
componentWillMount() {
|
||||
|
||||
this.onStorageChangedHandler = (changes) => {
|
||||
const ac = changes.antiCensorRu;
|
||||
return ac && ac.newValue && ac.newValue.lastPacUpdateStamp && this.forceUpdate();
|
||||
};
|
||||
this.onStorageChangedHandler = (changes) =>
|
||||
changes.lastPacUpdateStamp.newValue && this.forceUpdate();
|
||||
|
||||
chrome.storage.onChanged.addListener( this.onStorageChangedHandler );
|
||||
|
||||
|
@ -24,17 +22,17 @@ export default function getLastUpdateDate(theState) {
|
|||
|
||||
getDate(antiCensorRu) {
|
||||
|
||||
let dateForUser = chrome.i18n.getMessage('never');
|
||||
let dateForUser = 'никогда';
|
||||
if( antiCensorRu.lastPacUpdateStamp ) {
|
||||
let diff = Date.now() - antiCensorRu.lastPacUpdateStamp;
|
||||
let units = chrome.i18n.getMessage('ms');
|
||||
let units = 'мс';
|
||||
const gauges = [
|
||||
[1000, chrome.i18n.getMessage('s')],
|
||||
[60, chrome.i18n.getMessage('min')],
|
||||
[60, chrome.i18n.getMessage('h')],
|
||||
[24, chrome.i18n.getMessage('d')],
|
||||
[7, chrome.i18n.getMessage('w')],
|
||||
[4, chrome.i18n.getMessage('m')],
|
||||
[1000, 'с'],
|
||||
[60, 'мин'],
|
||||
[60, 'ч'],
|
||||
[24, 'дн'],
|
||||
[7, ' недель'],
|
||||
[4, ' месяцев'],
|
||||
];
|
||||
for(const g of gauges) {
|
||||
const diffy = Math.floor(diff / g[0]);
|
||||
|
@ -43,10 +41,10 @@ export default function getLastUpdateDate(theState) {
|
|||
diff = diffy;
|
||||
units = g[1];
|
||||
}
|
||||
dateForUser = diff + units + ' ' + chrome.i18n.getMessage('ago');
|
||||
dateForUser = diff + units + ' назад';
|
||||
}
|
||||
return {
|
||||
text: `${dateForUser} / ${antiCensorRu.pacUpdatePeriodInMinutes/60}${chrome.i18n.getMessage('h')}`,
|
||||
text: `${dateForUser} / ${antiCensorRu.pacUpdatePeriodInMinutes/60}ч`,
|
||||
title: new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU'),
|
||||
};
|
||||
|
||||
|
@ -55,7 +53,7 @@ export default function getLastUpdateDate(theState) {
|
|||
render(props) {
|
||||
|
||||
const date = this.getDate(props.apis.antiCensorRu);
|
||||
return (<div>{chrome.i18n.getMessage('Updated')}: <span class="updateDate" title={date.title}>{ date.text }</span></div>);
|
||||
return (<div>Обновлялись: <span class="updateDate" title={date.title}>{ date.text }</span></div>);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ export default function getMain(theState) {
|
|||
const Notifications = getNotifications(theState);
|
||||
|
||||
const checksName = 'pacMods';
|
||||
let selection = [0, 0]; // TODO: dirty hack but seems ok.
|
||||
|
||||
return class Main extends Component {
|
||||
|
||||
|
@ -145,43 +144,23 @@ export default function getMain(theState) {
|
|||
return createElement(TabPanel, Object.assign({}, props, {
|
||||
tabs: [
|
||||
{
|
||||
label: chrome.i18n.getMessage('PAC_script'),
|
||||
label: 'PAC-скрипт',
|
||||
content: createElement(PacChooser, props),
|
||||
key: 'pacScript',
|
||||
},
|
||||
{
|
||||
label: chrome.i18n.getMessage('Exceptions'),
|
||||
label: 'Исключения',
|
||||
content: createElement(Exceptions, props),
|
||||
key: 'exceptions',
|
||||
},
|
||||
{
|
||||
label: chrome.i18n.getMessage('Own_proxies'),
|
||||
label: 'Свои прокси',
|
||||
content: createElement(
|
||||
ModList,
|
||||
Object.assign({}, props, {
|
||||
orderedConfigs: this.state.catToOrderedMods['ownProxies'],
|
||||
childrenOfMod: {
|
||||
customProxyStringRaw: ProxyEditor,
|
||||
replaceDirectWith: ({ conf, onNewValue, ifInputsDisabled }) =>
|
||||
(<input
|
||||
style="width: 100%; margin: 0.5em 0"
|
||||
disabled={ifInputsDisabled}
|
||||
value={conf.value || ''}
|
||||
onInput={(event) => {
|
||||
|
||||
const t = event.target;
|
||||
selection = [t.selectionStart, t.selectionEnd];
|
||||
onNewValue(true, t.value);
|
||||
}}
|
||||
ref={(input) => {
|
||||
|
||||
if (input) {
|
||||
input.focus();
|
||||
input.selectionStart = selection[0];
|
||||
input.selectionEnd = selection[1];
|
||||
}
|
||||
}}
|
||||
/>),
|
||||
},
|
||||
name: checksName,
|
||||
}, modsHandlers)
|
||||
|
@ -189,7 +168,7 @@ export default function getMain(theState) {
|
|||
key: 'ownProxies',
|
||||
},
|
||||
{
|
||||
label: chrome.i18n.getMessage('Modifiers'),
|
||||
label: 'Модификаторы',
|
||||
content: createElement(
|
||||
ModList,
|
||||
Object.assign({}, props, {
|
||||
|
@ -204,7 +183,7 @@ export default function getMain(theState) {
|
|||
key: 'applyMods',
|
||||
},
|
||||
{
|
||||
label: chrome.i18n.getMessage('Notifications'),
|
||||
label: 'Уведомления',
|
||||
content: createElement(Notifications, props),
|
||||
key: 'notifications',
|
||||
},
|
||||
|
|
|
@ -55,14 +55,7 @@ export default function getModList(theState) {
|
|||
const child = ifMayHaveChild && this.state.checks[index]
|
||||
&& createElement(
|
||||
props.childrenOfMod[conf.key],
|
||||
Object.assign(
|
||||
{},
|
||||
props,
|
||||
{
|
||||
conf,
|
||||
onNewValue: (ifValid, newValue) => this.handleNewValue(ifValid, confMeta, newValue),
|
||||
},
|
||||
)
|
||||
Object.assign({}, props, {conf, onNewValue: (ifValid, newValue) => this.handleNewValue(ifValid, confMeta, newValue)})
|
||||
);
|
||||
|
||||
return (<InfoLi
|
||||
|
|
|
@ -55,16 +55,16 @@ export default function getPacChooser(theState) {
|
|||
|
||||
constructor(props) {
|
||||
|
||||
super(props);
|
||||
super();
|
||||
this.state = {
|
||||
chosenPacName: 'none',
|
||||
};
|
||||
|
||||
this.updatePac = function updatePac(onSuccess) {
|
||||
props.funs.conduct(
|
||||
chrome.i18n.getMessage('UpdatingDDD'),
|
||||
(cb) => theState.apis.antiCensorRu.syncWithPacProviderAsync(cb),
|
||||
chrome.i18n.getMessage('UpdatedD'),
|
||||
'Обновляем...',
|
||||
(cb) => props.apis.antiCensorRu.syncWithPacProviderAsync(cb),
|
||||
'Обновлено.',
|
||||
onSuccess
|
||||
);
|
||||
};
|
||||
|
@ -75,7 +75,7 @@ export default function getPacChooser(theState) {
|
|||
|
||||
getCurrentProviderId() {
|
||||
|
||||
return theState.apis.antiCensorRu.getCurrentPacProviderKey() || 'none';
|
||||
return this.props.apis.antiCensorRu.getCurrentPacProviderKey() || 'none';
|
||||
|
||||
}
|
||||
|
||||
|
@ -94,24 +94,24 @@ export default function getPacChooser(theState) {
|
|||
const pacKey = event.target.id;
|
||||
if (
|
||||
pacKey === (
|
||||
theState.apis.antiCensorRu.getCurrentPacProviderKey() || 'none'
|
||||
this.props.apis.antiCensorRu.getCurrentPacProviderKey() || 'none'
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (pacKey === 'none') {
|
||||
this.props.funs.conduct(
|
||||
chrome.i18n.getMessage('DisablingDDD'),
|
||||
(cb) => theState.apis.antiCensorRu.clearPacAsync(cb),
|
||||
chrome.i18n.getMessage('DisabledD'),
|
||||
'Отключение...',
|
||||
(cb) => this.props.apis.antiCensorRu.clearPacAsync(cb),
|
||||
'Отключено.',
|
||||
() => this.setState({ chosenPacName: 'none' }),
|
||||
checkChosenProvider
|
||||
);
|
||||
} else {
|
||||
this.props.funs.conduct(
|
||||
chrome.i18n.getMessage('InstallingDDD'),
|
||||
(cb) => theState.apis.antiCensorRu.installPacAsync(pacKey, cb),
|
||||
chrome.i18n.getMessage('PacScriptWasInstalledD'),
|
||||
'Установка...',
|
||||
(cb) => this.props.apis.antiCensorRu.installPacAsync(pacKey, cb),
|
||||
'PAC-скрипт установлен.',
|
||||
checkChosenProvider
|
||||
);
|
||||
}
|
||||
|
@ -124,10 +124,10 @@ export default function getPacChooser(theState) {
|
|||
const iddyToCheck = this.getCurrentProviderId();
|
||||
return (
|
||||
<div>
|
||||
{props.flags.ifInsideOptionsPage && (<header>{chrome.i18n.getMessage('PAC_script')}:</header>)}
|
||||
{props.flags.ifInsideOptionsPage && (<header>PAC-скрипт:</header>)}
|
||||
<ul>
|
||||
{
|
||||
[...theState.apis.antiCensorRu.getSortedEntriesForProviders(), {key: 'none', label: chrome.i18n.getMessage('Disable')}].map((provConf) =>
|
||||
[...props.apis.antiCensorRu.getSortedEntriesForProviders(), {key: 'none', label: 'Отключить'}].map((provConf) =>
|
||||
(<InfoLi
|
||||
onClick={this.radioClickHandler}
|
||||
conf={provConf}
|
||||
|
@ -135,7 +135,7 @@ export default function getPacChooser(theState) {
|
|||
name="pacProvider"
|
||||
checked={iddyToCheck === provConf.key}
|
||||
ifInputsDisabled={props.ifInputsDisabled}
|
||||
nodeAfterLabel={<a href="" class={scopedCss.updateButton} onClick={this.updateClickHandler}>[{chrome.i18n.getMessage('update')}]</a>}
|
||||
nodeAfterLabel={<a href="" class={scopedCss.updateButton} onClick={this.updateClickHandler}>[обновить]</a>}
|
||||
/>)
|
||||
)
|
||||
}
|
||||
|
@ -145,10 +145,10 @@ export default function getPacChooser(theState) {
|
|||
<div class={scopedCss.fullLineHeight}>
|
||||
{
|
||||
props.flags.ifMini
|
||||
? (<a class={scopedCss.otherVersion + ' emoji'} href="https://github.com/anticensority/runet-censorship-bypass/wiki/Различные-версии-расширения"
|
||||
title={chrome.i18n.getMessage("FullVersion")}>🏋</a>)
|
||||
: (<a class={scopedCss.otherVersion + ' emoji'} href="https://github.com/anticensority/runet-censorship-bypass/wiki/Различные-версии-расширения"
|
||||
title={chrome.i18n.getMessage("VersionForSlowMachines")}>🐌</a>)
|
||||
? (<a class={scopedCss.otherVersion + ' emoji'} href="https://rebrand.ly/ac-versions"
|
||||
title="Полная версия">🏋</a>)
|
||||
: (<a class={scopedCss.otherVersion + ' emoji'} href="https://rebrand.ly/ac-versions"
|
||||
title="Версия для слабых машин">🐌</a>)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -159,7 +159,7 @@ export default function getPacChooser(theState) {
|
|||
|
||||
componentDidMount() {
|
||||
|
||||
if (theState.apis.antiCensorRu.ifFirstInstall) {
|
||||
if (this.props.apis.antiCensorRu.ifFirstInstall) {
|
||||
this.updatePac();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ export default function getProxyEditor(theState) {
|
|||
{
|
||||
text-align: center;
|
||||
}
|
||||
table.editor tr.proxyRow input[name="crededHostname"] {
|
||||
table.editor tr.proxyRow input[name="hostname"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -158,14 +158,8 @@ export default function getProxyEditor(theState) {
|
|||
return true;
|
||||
|
||||
};
|
||||
const splitBySemi = (proxyString) => proxyString
|
||||
.replace(/#.*$/mg, '')
|
||||
.trim()
|
||||
.split(/\s*;\r?\n\s*/g)
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s);
|
||||
|
||||
const joinBySemi = (strs) => strs.join(';\n');
|
||||
const splitBySemi = (proxyString) => proxyString.replace(/#.*$/mg, '').trim().split(/\s*;\s*/g).filter((s) => s);
|
||||
const joinBySemi = (strs) => strs.join(';\n') + ';';
|
||||
const normalizeProxyString = (str) => joinBySemi(splitBySemi(str));
|
||||
|
||||
const PROXY_TYPE_LABEL_PAIRS = [['PROXY', 'PROXY/HTTP'],['HTTPS'],['SOCKS4'],['SOCKS5'],['SOCKS']];
|
||||
|
@ -223,11 +217,11 @@ export default function getProxyEditor(theState) {
|
|||
|
||||
}, {});
|
||||
const type = that.state.selectedNewType;
|
||||
const crededHostname = elements.newHostname;
|
||||
const hostname = elements.newHostname;
|
||||
const port = elements.newPort;
|
||||
|
||||
const newValue = `${that.props.proxyStringRaw};\n${type} ${crededHostname}:${port}`
|
||||
.trim().replace(/(\s*;\n\s*)+/, ';\n');
|
||||
const newValue = `${that.props.proxyStringRaw}; ${type} ${hostname}:${port}`
|
||||
.trim().replace(/(\s*;\s*)+/, '; ');
|
||||
that.props.setProxyStringRaw(true, newValue);
|
||||
|
||||
}
|
||||
|
@ -328,17 +322,10 @@ export default function getProxyEditor(theState) {
|
|||
</tr>
|
||||
{/* ADD NEW PROXY ENDS. */}
|
||||
{
|
||||
splitBySemi(this.props.proxyStringRaw).map((proxyAsStringRaw, index) => {
|
||||
|
||||
const proxyAsString = proxyAsStringRaw.trim();
|
||||
|
||||
const {
|
||||
type,
|
||||
creds,
|
||||
hostname,
|
||||
port,
|
||||
} = theState.utils.parseProxyScheme(proxyAsString);
|
||||
splitBySemi(this.props.proxyStringRaw).map((proxyAsString, index) => {
|
||||
|
||||
const [type, addr] = proxyAsString.trim().split(/\s+/);
|
||||
const [hostname, port] = addr.split(':');
|
||||
return (
|
||||
<tr class={scopedCss.proxyRow}>
|
||||
<td>
|
||||
|
@ -348,7 +335,7 @@ export default function getProxyEditor(theState) {
|
|||
>X</button>
|
||||
</td>
|
||||
<td>{type}</td>
|
||||
<td><input value={`${creds && `${creds}@`}${hostname}`} name="crededHostname" readonly/></td>
|
||||
<td><input value={hostname} name="hostname" readonly/></td>
|
||||
<td>{port}</td>
|
||||
<td>
|
||||
<button type="button" disabled={props.ifInputsDisabled}
|
||||
|
@ -363,7 +350,6 @@ export default function getProxyEditor(theState) {
|
|||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="https://github.com/anticensority/runet-censorship-bypass/wiki/Прокси-и-пароль">Запароленные прокси?</a>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
@ -404,34 +390,28 @@ export default function getProxyEditor(theState) {
|
|||
const errors = splitBySemi(this.state.stashedExports)
|
||||
.map((proxyAsString) => {
|
||||
|
||||
const {
|
||||
type,
|
||||
creds,
|
||||
hostname,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
} = theState.utils.parseProxyScheme(proxyAsString);
|
||||
const crededAddr = `${creds ? `${creds}@` : ''}${hostname}:${port}`;
|
||||
|
||||
const [rawType, addr, ...rest] = proxyAsString.split(/\s+/);
|
||||
if (rest && rest.length) {
|
||||
return new Error(
|
||||
`"${rest.join(', ')}" кажется мне лишним. Вы забыли ";"?`
|
||||
);
|
||||
}
|
||||
const knownTypes = PROXY_TYPE_LABEL_PAIRS.map(([type, label]) => type);
|
||||
if( !knownTypes.includes(type.toUpperCase()) ) {
|
||||
if( !knownTypes.includes(rawType.toUpperCase()) ) {
|
||||
return new Error(
|
||||
`Неверный тип ${type}. Известные типы: ${knownTypes.join(', ')}.`
|
||||
`Неверный тип ${rawType}. Известные типы: ${knownTypes.join(', ')}.`
|
||||
);
|
||||
}
|
||||
if (!(crededAddr && /^(?:.+@)?[^:]+:\d+$/.test(crededAddr))) {
|
||||
if (!(addr && /^[^:]+:\d+$/.test(addr))) {
|
||||
return new Error(
|
||||
`Адрес прокси "${crededAddr || ''}" не соответствует формату "<опц_логин>:<опц_пароль>@<домен_или_IP>:<порт_из_цифр>".`
|
||||
`Адрес прокси "${addr || ''}" не соответствует формату "<домен_или_IP>:<порт_из_цифр>".`
|
||||
);
|
||||
}
|
||||
if (password && !username) {
|
||||
return new Error('Вашему пользователю не хватает имени?');
|
||||
}
|
||||
const portInt = parseInt(port);
|
||||
if (portInt < 0 || portInt > 65535) {
|
||||
const [hostname, rawPort] = addr.split(':');
|
||||
const port = parseInt(rawPort);
|
||||
if (port < 0 || port > 65535) {
|
||||
return new Error(
|
||||
`Порт "${port}" должен быть целым числом от 0 до 65535.`
|
||||
`Порт "${rawPort}" должен быть целым числом от 0 до 65535.`
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
@ -515,7 +495,7 @@ PROXY foobar.com:8080; # Not HTTP!`.trim()}
|
|||
value={
|
||||
this.state.stashedExports !== false
|
||||
? this.state.stashedExports
|
||||
: (this.props.proxyStringRaw || '').replace(/\s*;\n\s*/g, ';\n')
|
||||
: (this.props.proxyStringRaw || '').replace(/\s*;\s*/g, ';\n')
|
||||
}
|
||||
/></td>
|
||||
</tr>
|
||||
|
@ -534,12 +514,10 @@ PROXY foobar.com:8080; # Not HTTP!`.trim()}
|
|||
return proxyStringRaw
|
||||
.replace(/#.*$/mg, '') // Strip comments.
|
||||
.replace(/[^\S\r\n]*DIRECT[^\S\r\n]*/g, '') // Remove DIRECT from old versions.
|
||||
/*
|
||||
.split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g )
|
||||
.map( (p) => p.trim() )
|
||||
.filter((p) => p)
|
||||
.join(';\n');
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ export default function getTabPannel({ flags, baseCss }) {
|
|||
.navLabels {
|
||||
background-color: var(--cr-grey-panel);
|
||||
text-align: center;
|
||||
min-width: 25em;
|
||||
min-width: 24em;
|
||||
}
|
||||
.navLabels li label {
|
||||
display: inline-block;
|
||||
|
|
|
@ -4,7 +4,7 @@ export default function append(document, { flags }) {
|
|||
document.querySelector('style').innerHTML = `
|
||||
/* GLOBAL VARIABLES */
|
||||
|
||||
body {
|
||||
:root {
|
||||
--ribbon-color: #4169e1;
|
||||
--blue-bg: dodgerblue;
|
||||
--default-grey: #bfbfbf;
|
||||
|
@ -12,13 +12,13 @@ export default function append(document, { flags }) {
|
|||
--cr-icon-selected: #d7d7d7;
|
||||
--cr-popup-border: #bababa;
|
||||
--cr-grey-panel: #f2f2f2;
|
||||
${ flags.ifInsideOptionsPage ? '' : 'max-width: 24em;' }
|
||||
}
|
||||
|
||||
/* BASE ELEMENTS */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
max-width: 25em;
|
||||
}
|
||||
a, a:visited {
|
||||
color: var(--ribbon-color);
|
||||
|
@ -27,11 +27,9 @@ export default function append(document, { flags }) {
|
|||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/*
|
||||
label {
|
||||
user-select: none;
|
||||
}
|
||||
*/
|
||||
div, section, header, ul, ol {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
|
|
@ -9,13 +9,7 @@ import getApp from './components/App';
|
|||
chrome.runtime.getBackgroundPage( (bgWindow) =>
|
||||
bgWindow.apis.errorHandlers.installListenersOn(
|
||||
window, 'PUP', async() => {
|
||||
/*
|
||||
`Extension context invalidated` error is thrown if `window.closed` is true and call to
|
||||
`window.chrome.i18n` or other `window.chrome` api happens. Use bgWindow.chrome instead.
|
||||
Use winChrome for tab-related calls like winChrome.tabs.getCurrent.
|
||||
*/
|
||||
window.winChrome = window.chrome;
|
||||
window.chrome = bgWindow.chrome;
|
||||
|
||||
let theState;
|
||||
{
|
||||
const apis = bgWindow.apis;
|
||||
|
@ -35,26 +29,15 @@ chrome.runtime.getBackgroundPage( (bgWindow) =>
|
|||
// IF INSIDE OPTIONS TAB
|
||||
|
||||
const currentTab = await new Promise(
|
||||
(resolve) => winChrome.tabs.query(
|
||||
(resolve) => chrome.tabs.query(
|
||||
{active: true, currentWindow: true},
|
||||
([tab]) => resolve(tab),
|
||||
([tab]) => resolve(tab)
|
||||
)
|
||||
);
|
||||
// winChrome.runtime.sendMessage({ currentTab, eventName: 'POPUP_OPENED' });
|
||||
|
||||
theState.flags.ifInsideOptionsPage = !(currentTab && currentTab.url) || /.*:\/\/extensions\/\?options=/g.test(currentTab.url) || currentTab.url.startsWith('about:addons');
|
||||
theState.flags.ifInsideEdgeOptionsPage = theState.flags.ifInsideOptionsPage && currentTab && currentTab.url && currentTab.url.startsWith('edge://');
|
||||
|
||||
theState.flags.ifInsideOptionsPage = !currentTab || currentTab.url.startsWith('chrome://extensions/?options=');
|
||||
theState.currentTab = currentTab;
|
||||
|
||||
// If opened not via popup and not via options modal.
|
||||
// E.g., if opened via copy-pasting an URL into the address bar from somewhere.
|
||||
// If browser is not Chrome (Opera, e.g.) then options page may be opened in a separate tab
|
||||
// and then you will get a false positive.
|
||||
theState.flags.ifOpenedUnsafely = Boolean(await new Promise(
|
||||
(resolve) => winChrome.tabs.getCurrent(resolve),
|
||||
));
|
||||
|
||||
// STATE DEFINED, COMPOSE.
|
||||
|
||||
appendGlobalCss(document, theState);
|
||||
|
@ -66,13 +49,7 @@ chrome.runtime.getBackgroundPage( (bgWindow) =>
|
|||
);
|
||||
// READY TO RENDER
|
||||
|
||||
const show = () => { document.documentElement.style.visibility = 'initial'; };
|
||||
|
||||
if (theState.flags.ifInsideOptionsPage) {
|
||||
show();
|
||||
} else {
|
||||
setTimeout(show, 200); // Mac bug: https://bugs.chromium.org/p/chromium/issues/detail?id=428044
|
||||
}
|
||||
document.documentElement.style.display = 'initial';
|
||||
|
||||
}
|
||||
)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,31 +5,17 @@
|
|||
<title>Устранение проблем</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Устранение проблем</h1>
|
||||
<ol>
|
||||
<li><a data-in-bg="false" href class="view-errors">Детали последних ошибок</a></li>
|
||||
<li><a data-in-bg="false" href class="reset-settings">Сбросить настройки</a></li>
|
||||
<li><a data-in-bg="false" href="https://github.com/anticensority/runet-censorship-bypass/wiki/Если-расширение-не-работает" target="_blank">Файл самопомощи</a></li>
|
||||
<li><a data-in-bg="false" href="https://groups.google.com/g/anticensority">Напишите нам!</a></li>
|
||||
<li><a href id="view-errors">Детали последних ошибок</a></li>
|
||||
<li><a href id="reset-settings">Сбросить настройки</a></li>
|
||||
<li><a href="https://rebrand.ly/ac-support" target="_blank">Файл самопомощи</a></li>
|
||||
<li><a href="https://rebrand.ly/ac-contact">Напишите нам!</a></li>
|
||||
</ol>
|
||||
<h2>Для продвинутых</h2>
|
||||
<ol>
|
||||
<li><a data-in-bg="false" href="https://github.com/anticensority/runet-censorship-bypass/wiki/Как-прочитать-логи%3F-%28для-продвинутых%29">Как прочитать логи?</a></li>
|
||||
<li><a data-in-bg="false" href="../debug/index.html">Отладка PAC-скрипта</a></li>
|
||||
</ol>
|
||||
<hr/>
|
||||
<h1>Troubleshooting</h1>
|
||||
<ol>
|
||||
<li><a data-in-bg="false" href class="view-errors">Details of last errors</a></li>
|
||||
<li><a data-in-bg="false" href class="reset-settings">Reset settings</a></li>
|
||||
<li><a data-in-bg="false" href="https://github.com/anticensority/runet-censorship-bypass/wiki/Если-расширение-не-работает" target="_blank">Troubleshoot guide (ru)</a></li>
|
||||
<li><a data-in-bg="false" href="https://groups.google.com/g/anticensority">Write to us!</a></li>
|
||||
</ol>
|
||||
<h2>Advanced</h2>
|
||||
<ol>
|
||||
<li><a data-in-bg="false" href="https://github.com/anticensority/runet-censorship-bypass/wiki/Как-прочитать-логи%3F-%28для-продвинутых%29">How to read logs?</a></li>
|
||||
<li><a data-in-bg="false" href="../debug/index.html">PAC-script debugging</a></li>
|
||||
<li><a href="https://rebrand.ly/ac-logs">Как прочитать логи?</a></li>
|
||||
<li><a href="../debug/index.html">Отладка PAC-скрипта</a></li>
|
||||
</ol>
|
||||
<script src="./index.js"></script>
|
||||
<script src="../lib/keep-links-clickable.js"></script>
|
||||
|
|
|
@ -4,22 +4,15 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
|||
backgroundPage.apis.errorHandlers.installListenersOn(
|
||||
window, 'TRBL', () => {
|
||||
|
||||
document.querySelectorAll('.reset-settings').forEach((el) => {
|
||||
document.getElementById('reset-settings').onclick = () => {
|
||||
|
||||
el.onclick = () => {
|
||||
backgroundPage.localStorage.clear();
|
||||
chrome.storage.local.clear( () => chrome.runtime.reload() );
|
||||
|
||||
backgroundPage.localStorage.clear();
|
||||
chrome.storage.local.clear( () => chrome.runtime.reload() );
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
document.getElementById('view-errors').onclick = () =>
|
||||
backgroundPage.apis.errorHandlers.viewError('all');
|
||||
|
||||
document.querySelectorAll('.view-errors').forEach((el) => {
|
||||
|
||||
el.onclick = () =>
|
||||
backgroundPage.apis.errorHandlers.viewError('all');
|
||||
});
|
||||
|
||||
},
|
||||
),
|
||||
})
|
||||
);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
const Storage = require('symlink-to/project-root/tools/sinon-storage');
|
||||
const Storage = require('_project-root/tools/sinon-storage');
|
||||
const Chai = require('chai');
|
||||
const Mocha = require('mocha');
|
||||
|
||||
const CachelessRequire = require('symlink-to/project-root/tools/cacheless-require')(module);
|
||||
const CachelessRequire = require('_project-root/tools/cacheless-require')(module);
|
||||
|
||||
Mocha.describe('window.apis.pacKitchen', function () {
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const Chai = require('chai');
|
||||
const Mocha = require('mocha');
|
||||
|
||||
const CachelessRequire = require('symlink-to/project-root/tools/cacheless-require')(module);
|
||||
const CachelessRequire = require('_project-root/tools/cacheless-require')(module);
|
||||
|
||||
Mocha.describe('window.utils', function () {
|
||||
|
||||
|
|
|
@ -69,24 +69,27 @@
|
|||
|
||||
const reinit = function reinit() {
|
||||
|
||||
privates._strToHostObj = [
|
||||
/* Please, don't use proxies directly (without PAC-script). */
|
||||
'n.thenewone.lol',
|
||||
's.thenewone.lol',
|
||||
// antizapret.prostovpn.org:
|
||||
'proxy.antizapret.prostovpn.org',
|
||||
'proxy-ssl.antizapret.prostovpn.org',
|
||||
'proxy-nossl.antizapret.prostovpn.org',
|
||||
'proxy-fbtw-ssl.antizapret.prostovpn.org',
|
||||
].reduce((acc, hostname) => Object.assign(acc, { [hostname]: { host: hostname }}), {
|
||||
// Defaults:
|
||||
localhost: { host: 'localhost' },
|
||||
});
|
||||
|
||||
privates._ipToHostObj = {
|
||||
'127.0.0.1': { host: 'localhost' },
|
||||
'0.0.0.0': { host: 'localhost' },
|
||||
// Defaults.
|
||||
const _antizapret = {
|
||||
/* Don't use directly, please.
|
||||
Encoded to counter abuse. */
|
||||
host: '\x70\x72\x6f\x78\x79\x2e\x61\x6e\x74\x69\x7a\x61\x70\x72\x65\x74\x2e\x70\x72\x6f\x73\x74\x6f\x76\x70\x6e\x2e\x6f\x72\x67',
|
||||
};
|
||||
privates._strToHostObj = {
|
||||
[_antizapret.host]: _antizapret,
|
||||
};
|
||||
|
||||
privates._ipToHostObj = {};
|
||||
for( const ip of [
|
||||
// IPs of Antizapret.
|
||||
'195.123.209.38',
|
||||
'137.74.171.91',
|
||||
'51.15.39.201',
|
||||
'2001:bc8:4700:2300::1:d07',
|
||||
'2a02:27ac::10',
|
||||
] ) {
|
||||
privates._ipToHostObj[ip] = _antizapret;
|
||||
}
|
||||
|
||||
// Persisted.
|
||||
const ipToHost = _state(ip2host);
|
||||
|
@ -112,7 +115,7 @@
|
|||
const getIpsFor = function getIpsFor(host, cb = mandatory()) {
|
||||
|
||||
if (host.trim() === 'localhost') {
|
||||
return cb(null, ['127.0.0.1', '0.0.0.0', '::1']);
|
||||
return cb(null, ['127.0.0.1', '::1']);
|
||||
}
|
||||
const types = [1, 28];
|
||||
const promises = types.map(
|
||||
|
@ -234,11 +237,12 @@
|
|||
getIpsFor(hostStr, (err, ips, ...warns) => {
|
||||
|
||||
console.log('Got IPs + err?:', ips, err);
|
||||
if (err) {
|
||||
if (!err) {
|
||||
resolveIps(ips);
|
||||
} else {
|
||||
reject([err, null, ...warns]);
|
||||
return;
|
||||
}
|
||||
resolveIps(ips);
|
||||
|
||||
});
|
||||
|
||||
}).then(
|
||||
|
@ -260,9 +264,7 @@
|
|||
|
||||
_updateAllAsync(cb = mandatory()) {
|
||||
|
||||
const hostArr = Object.keys(privates._strToHostObj)
|
||||
.filter((hostStr) => hostStr !== 'localhost');
|
||||
|
||||
const hostArr = Object.keys(privates._strToHostObj);
|
||||
console.log('Update all:', hostArr);
|
||||
|
||||
const promises = hostArr.map(
|
||||
|
@ -275,18 +277,29 @@
|
|||
);
|
||||
Promise.all( promises ).then( (cbsRes) => {
|
||||
|
||||
let ipErrors = cbsRes.map( ([err]) => err ).filter( (err) => err );
|
||||
let warns = [];
|
||||
if (ipErrors.length) {
|
||||
warns = [clarify(
|
||||
ipErrors,
|
||||
const errors = cbsRes.map( ([err]) => err ).filter( (err) => err );
|
||||
let newError;
|
||||
const ifAllErrors = cbsRes.length === errors.length;
|
||||
if (errors.length) {
|
||||
if (ifAllErrors) {
|
||||
newError = errors.shift();
|
||||
} else {
|
||||
newError = errors;
|
||||
}
|
||||
newError = clarify(
|
||||
newError,
|
||||
'Не удалось получить один или несколько IP адресов для' +
|
||||
' прокси-серверов. Иконка для уведомления об обходе' +
|
||||
' блокировок может не отображаться.'
|
||||
)];
|
||||
} else {}
|
||||
cb(null, null, ...warns);
|
||||
);
|
||||
if (ifAllErrors) {
|
||||
return cb(newError);
|
||||
}
|
||||
}
|
||||
cb(null, null, newError);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
_replaceAllAsync(hostArr = mandatory(), cb) {
|
||||
|
|
|
@ -2,137 +2,7 @@
|
|||
|
||||
{
|
||||
|
||||
const timeouted = window.utils.timeouted;
|
||||
|
||||
const isProxied = (requestDetails) => false;
|
||||
const isProxySideError = (details) =>
|
||||
/* About !main_frame: Main frame websocket errors are followed by webnavigation errors
|
||||
which chrome-internals code resets the state of the popup.
|
||||
*/
|
||||
details.error === 'net::ERR_TUNNEL_CONNECTION_FAILED' && details.type !== 'main_frame' && isProxied(details) ||
|
||||
details.error === 'NS_ERROR_CONNECTION_REFUSED' && Boolean(details.proxyInfo);
|
||||
|
||||
const urlToA = (url) => new URL(url).host.link(
|
||||
encodeURIComponent(url),
|
||||
);
|
||||
|
||||
const isProxyErrorHandledAsync = async (details) => {
|
||||
|
||||
if (!isProxySideError(details)) {
|
||||
return;
|
||||
}
|
||||
let fromPageHref = '';
|
||||
let toUrlHref = '';
|
||||
let fromPageHtml = '';
|
||||
let youMayReportHtml = '';
|
||||
const initiator = details.initiator !== 'null' && details.initiator;
|
||||
try {
|
||||
if (initiator) {
|
||||
fromPageHref = new URL(initiator).href; // Sanitize: only urls, not other stuff.
|
||||
fromPageHtml = ` со страницы ${urlToA(fromPageHref)}`;
|
||||
}
|
||||
toUrlHref = new URL(details.url).href;
|
||||
youMayReportHtml = ` Вы можете <b>${'сообщить об ошибке'.link(
|
||||
encodeURIComponent(
|
||||
'/pages/report-proxy-error/index.html?' +
|
||||
new URLSearchParams({
|
||||
fromPageHref,
|
||||
requestFailedTo: toUrlHref,
|
||||
}),
|
||||
),
|
||||
)}</b> администратору прокси.`;
|
||||
} catch(e) {
|
||||
/* For malformed urls. */
|
||||
console.log('Error handling malformed URLs:', details);
|
||||
const msg = `Error handling malformed URLs: ${JSON.stringify(details, null, 2)}`;
|
||||
throw new TypeError(msg);
|
||||
}
|
||||
|
||||
// Service workers have tabId = -1, get active tubId for them.
|
||||
const tabId = details.tabId < 0
|
||||
? await new Promise((resolve) => chrome.tabs.query(
|
||||
{ active: true },
|
||||
([tab]) => resolve(tab.id)),
|
||||
)
|
||||
: details.tabId;
|
||||
|
||||
const [oldPopup, oldText, oldColor] = await new Promise((resolve) =>
|
||||
chrome.browserAction.getPopup({ tabId }, (oldPopup) =>
|
||||
chrome.browserAction.getBadgeText({ tabId }, (oldText) =>
|
||||
chrome.browserAction.getBadgeBackgroundColor({ tabId }, (oldColor) => resolve([
|
||||
oldPopup,
|
||||
oldText,
|
||||
oldColor,
|
||||
])),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
const popupPrefix = chrome.runtime.getURL(`/pages/options/index.html?status=<span style="color: red">🔥 Прокси-сервер отказался обслуживать запрос к%20`);
|
||||
if (decodeURIComponent(oldPopup).startsWith(popupPrefix)) {
|
||||
return true;
|
||||
}
|
||||
const popup = `${popupPrefix}${urlToA(details.url)}${fromPageHtml}</span>. Это могло быть намеренно или по ошибке.${youMayReportHtml}#tab=exceptions`;
|
||||
|
||||
chrome.browserAction.setPopup({
|
||||
tabId,
|
||||
popup,
|
||||
});
|
||||
|
||||
chrome.browserAction.setBadgeBackgroundColor({
|
||||
tabId,
|
||||
color: 'red',
|
||||
});
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId,
|
||||
text: '❗',
|
||||
});
|
||||
|
||||
let limit = 5;
|
||||
let ifOnTurn = true;
|
||||
let ifError = false;
|
||||
const flip = () => {
|
||||
|
||||
if (!ifOnTurn && !--limit || ifError) {
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId,
|
||||
text: ifOnTurn ? '❗' : '',
|
||||
}, () => {
|
||||
ifError = chrome.runtime.lastError;
|
||||
});
|
||||
ifOnTurn = !ifOnTurn;
|
||||
};
|
||||
flip();
|
||||
const timer = setInterval(flip, 500);
|
||||
|
||||
const restoringHandler = timeouted((eventDetails) => {
|
||||
|
||||
if(eventDetails && tabId !== ((eventDetails.currentTab || eventDetails).id || eventDetails.tabId)) {
|
||||
return;
|
||||
}
|
||||
clearInterval(timer);
|
||||
|
||||
chrome.browserAction.setPopup({ tabId, popup: oldPopup});
|
||||
chrome.browserAction.setBadgeBackgroundColor({ tabId, color: oldColor});
|
||||
chrome.browserAction.setBadgeText({ tabId, text: oldText});
|
||||
|
||||
chrome.runtime.onMessage.removeListener(restoringHandler);
|
||||
chrome.tabs.onRemoved.removeListener(restoringHandler);
|
||||
chrome.tabs.onReplaced.removeListener(restoringHandler);
|
||||
chrome.webNavigation.onBeforeNavigate.removeListener(restoringHandler);
|
||||
});
|
||||
chrome.runtime.onMessage.addListener(restoringHandler);
|
||||
chrome.tabs.onRemoved.addListener(restoringHandler);
|
||||
chrome.tabs.onReplaced.addListener(restoringHandler); // When does it happen?
|
||||
chrome.webNavigation.onBeforeNavigate.addListener(restoringHandler);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
chrome.webNavigation.onErrorOccurred.addListener(timeouted(async (details) => {
|
||||
chrome.webNavigation.onErrorOccurred.addListener((details) => {
|
||||
|
||||
const tabId = details.tabId;
|
||||
if ( !(details.frameId === 0 && tabId >= 0) ||
|
||||
|
@ -142,16 +12,13 @@
|
|||
].includes(details.error) ) {
|
||||
return;
|
||||
}
|
||||
if (await isProxyErrorHandledAsync(details)) {
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.browserAction.setPopup({
|
||||
tabId,
|
||||
popup: './pages/options/index.html?status=Правый клик по иконке — меню инструментов!#tab=exceptions',
|
||||
popup: './pages/options/index.html#tab=exceptions&status=Правый клик по иконке — меню инструментов!',
|
||||
});
|
||||
|
||||
chrome.browserAction.setBadgeBackgroundColor({
|
||||
window.chrome.browserAction.setBadgeBackgroundColor({
|
||||
tabId,
|
||||
color: '#4285f4',
|
||||
});
|
||||
|
@ -160,10 +27,6 @@
|
|||
text: '●●●',
|
||||
});
|
||||
|
||||
}));
|
||||
});
|
||||
|
||||
chrome.webRequest.onErrorOccurred.addListener(
|
||||
timeouted(isProxyErrorHandledAsync),
|
||||
{urls: ['<all_urls>']},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
to "loading".
|
||||
So if you set a title earlier it may be cleared by browser.
|
||||
It pertains not only to page refesh but to newly opened pages too.
|
||||
Also on loosing title see:
|
||||
https://github.com/ilyaigpetrov/repository-for-chrome-bugs/blob/master/browserAction-title-lost-after-setting/background.js
|
||||
Crazy parallel Chrome.
|
||||
**/
|
||||
|
||||
|
@ -41,7 +43,7 @@
|
|||
|
||||
const setRedBadge = (opts) => {
|
||||
|
||||
chrome.browserAction.setBadgeBackgroundColor({
|
||||
window.chrome.browserAction.setBadgeBackgroundColor({
|
||||
color: '#db4b2f',
|
||||
});
|
||||
chrome.browserAction.setBadgeText(opts);
|
||||
|
@ -57,7 +59,7 @@
|
|||
if (err) {
|
||||
// E.g., no tab with such id happens.
|
||||
// Because requestDetails may be stale.
|
||||
console.log('Notifier error ignored (this is normal, it happens):', err);
|
||||
console.log('Notifier error ignored:', err);
|
||||
return cb();
|
||||
}
|
||||
const ifTitleSetAlready = /\n/.test(title);
|
||||
|
@ -140,23 +142,6 @@
|
|||
if (!host) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
/*
|
||||
If we fetch a resource from a proxy address it is almost never proxied and
|
||||
shouldn't be shown.
|
||||
Think about localhost as a proxy and a user working with a web site on localhost.
|
||||
*/
|
||||
/*
|
||||
Host is constructed from hostname and port. Hostname never contains port,
|
||||
it is an ip or a domain name. See hostname and host
|
||||
in `new URL('https://localhost:8080')`.
|
||||
*/
|
||||
const hostnameFromUrl = new URL(requestDetails.url).hostname;
|
||||
const hostnameFromProxy = new URL(`https://${host}`).hostname;
|
||||
if (hostnameFromUrl === requestDetails.ip || hostnameFromUrl === hostnameFromProxy) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const ifMainFrame = requestDetails.type === 'main_frame';
|
||||
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Сообщить об ошибке прокси-сервера</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
:root {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Сообщить об ошибке прокси-сервера</h1>
|
||||
Перешлите администратору вашего прокси следующее:
|
||||
<fieldset>
|
||||
<pre id="errorInfo"></pre>
|
||||
</fieldset>
|
||||
Вот известные нам электронные адреса для популярных прокси-серверов (кликните по email для открытия шаблона письма):
|
||||
<ol>
|
||||
<li>
|
||||
Только если вы используете <a
|
||||
href="https://antizapret.prostovpn.org">Антизапрет</a>:
|
||||
<a
|
||||
href="mailto:antizapret@prostovpn.org">antizapret@prostovpn.org</a>.
|
||||
</li>
|
||||
</ol>
|
||||
<script src="./index.js"></script>
|
||||
<script src="../lib/keep-links-clickable.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,39 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
chrome.runtime.getBackgroundPage( (bgWindow) =>
|
||||
bgWindow.apis.errorHandlers.installListenersOn(
|
||||
window, 'PRERR', () => {
|
||||
|
||||
const params = new URLSearchParams(location.search.substr(1));
|
||||
const requestFailedTo = params.get('requestFailedTo');
|
||||
const fromPageHref = params.get('fromPageHref') || requestFailedTo;
|
||||
|
||||
const acr = bgWindow.apis.antiCensorRu;
|
||||
const pacKey = acr.getCurrentPacProviderKey();
|
||||
const pacModTime = acr.getLastModifiedForKey(pacKey);
|
||||
|
||||
const errorReport = `
|
||||
Your proxy blocked the following request:
|
||||
* Request was from page: ${fromPageHref}
|
||||
* To address: ${requestFailedTo}
|
||||
* Used PAC-script: ${pacKey}
|
||||
* Its Last-Modified HTTP-header: ${pacModTime}
|
||||
I think it's a mistake! Could you, please, take action to fix it.
|
||||
Thank you!
|
||||
|
||||
Ваш прокси-сервер заблокировал следующий запрос:
|
||||
* Запрос был со страницы: ${fromPageHref}
|
||||
* Адрес запроса: ${requestFailedTo}
|
||||
* Мой PAC-скрипт: ${pacKey}
|
||||
* Его HTTP-заголовок Last-Modified: ${pacModTime}
|
||||
Я думаю, это произошло по ошибке! Пожалуйста, примите действия для её исправления.
|
||||
Спасибо!
|
||||
`.trim();
|
||||
errorInfo.innerText = errorReport;
|
||||
document.querySelectorAll('a[href^="mailto:"]').forEach((a) => {
|
||||
|
||||
a.href = `${a.href}?subject=${encodeURIComponent(new URL(requestFailedTo).hostname)} TUNNEL_CONNECTION_FAILED&body=${encodeURIComponent(errorReport)}`;
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
|
@ -1,30 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
const pacUrls = [
|
||||
// GitHub.io (anticensority), cached:
|
||||
'https://anticensority.github.io/generated-pac-scripts/anticensority.pac',
|
||||
// GitHub repo (anticensority), cached:
|
||||
'https://raw.githubusercontent.com/anticensority/generated-pac-scripts/master/anticensority.pac',
|
||||
];
|
||||
|
||||
const commonContext = {
|
||||
version: '1.66',
|
||||
version: '1.5',
|
||||
anticensorityPacUrls: [
|
||||
...pacUrls,
|
||||
],
|
||||
// First official, shortened:
|
||||
'https://rebrand.ly/ac-chrome-anticensority-pac',
|
||||
// Second official, Cloud Flare with caching:
|
||||
'https://anticensority.tk/generated-pac-scripts/anticensority.pac',
|
||||
// GitHub.io (anticensority):
|
||||
'\x68\x74\x74\x70\x73\x3a\x2f\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2e\x67\x69\x74\x68\x75\x62\x2e\x69\x6f\x2f\x67\x65\x6e\x65\x72\x61\x74\x65\x64\x2d\x70\x61\x63\x2d\x73\x63\x72\x69\x70\x74\x73\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2e\x70\x61\x63',
|
||||
// GitHub repo (anticensority):
|
||||
'\x68\x74\x74\x70\x73\x3a\x2f\x2f\x72\x61\x77\x2e\x67\x69\x74\x68\x75\x62\x75\x73\x65\x72\x63\x6f\x6e\x74\x65\x6e\x74\x2e\x63\x6f\x6d\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2f\x67\x65\x6e\x65\x72\x61\x74\x65\x64\x2d\x70\x61\x63\x2d\x73\x63\x72\x69\x70\x74\x73\x2f\x6d\x61\x73\x74\x65\x72\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x69\x74\x79\x2e\x70\x61\x63',
|
||||
// Old, deprecated:
|
||||
'https://anticensorship-russia.tk/generated-pac-scripts/anticensority.pac',
|
||||
// Google Drive (0.17, anticensority):
|
||||
'\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x72\x69\x76\x65\x2e\x67\x6f\x6f\x67\x6c\x65\x2e\x63\x6f\x6d\x2f\x75\x63\x3f\x65\x78\x70\x6f\x72\x74\x3d\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x26\x69\x64\x3d\x30\x42\x32\x6d\x68\x42\x67\x46\x6e\x66\x34\x70\x45\x4c\x56\x6c\x47\x4e\x54\x42\x45\x4d\x58\x4e\x6d\x52\x58\x63',
|
||||
]
|
||||
};
|
||||
|
||||
exports.contexts = {};
|
||||
|
||||
const extra_permissions = ', "webRequest", "webRequestBlocking", "webNavigation"';
|
||||
|
||||
exports.contexts.full = Object.assign({}, commonContext, {
|
||||
versionSuffix: '',
|
||||
nameSuffixEn: '',
|
||||
nameSuffixRu: '',
|
||||
extra_permissions,
|
||||
extra_permissions: ', "webRequest", "webNavigation"',
|
||||
persistent: '',
|
||||
scripts_0x: '',
|
||||
scripts_2x: ', "20-ip-to-host-api.js"',
|
||||
scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"',
|
||||
});
|
||||
|
@ -35,34 +36,18 @@ exports.contexts.mini = Object.assign({}, commonContext, {
|
|||
nameSuffixRu: ' МИНИ',
|
||||
extra_permissions: '',
|
||||
persistent: '"persistent": false,',
|
||||
scripts_0x: '',
|
||||
scripts_2x: ', "20-for-mini-only.js"',
|
||||
scripts_8x: '',
|
||||
});
|
||||
|
||||
exports.contexts.firefox = Object.assign({}, commonContext, {
|
||||
versionSuffix: '',
|
||||
nameSuffixEn: '',
|
||||
nameSuffixRu: '',
|
||||
extra_permissions,
|
||||
persistent: '',
|
||||
scripts_0x: ', "01-chrome-proxy-settings.js"',
|
||||
scripts_2x: ', "20-ip-to-host-api.js"',
|
||||
scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"',
|
||||
});
|
||||
|
||||
exports.contexts.beta = Object.assign({}, commonContext, {
|
||||
anticensorityPacUrls: [
|
||||
'https://raw.githubusercontent.com/anticensority/for-testing/master/anticensority.pac',
|
||||
'https://anticensority.github.io/for-testing/anticensority.pac',
|
||||
],
|
||||
version: '1.14',
|
||||
anticensorityPacUrls: ['https://rebrand.ly/ac-beta-pac'],
|
||||
version: '1.5',
|
||||
versionSuffix: '',
|
||||
nameSuffixEn: ' FOR TESTING',
|
||||
nameSuffixRu: ' ДЛЯ ТЕСТОВ',
|
||||
extra_permissions,
|
||||
extra_permissions: ', "webRequest", "webNavigation"',
|
||||
persistent: '',
|
||||
scripts_0x: '',
|
||||
scripts_2x: ', "20-ip-to-host-api.js"',
|
||||
scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"',
|
||||
});
|
||||
|
|
1835
extensions/chromium/runet-censorship-bypass/yarn.lock
Normal file
1835
extensions/chromium/runet-censorship-bypass/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
17
package.json
Normal file → Executable file
17
package.json
Normal file → Executable file
|
@ -2,16 +2,17 @@
|
|||
"name": "subjective-good-is-evil",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"postinstall": "opencollective postinstall"
|
||||
"generate": "cd pac-generator && npm start",
|
||||
"prestart": "npm run generate",
|
||||
"start": "npm run bench",
|
||||
"bench": "cd ./pac-performance-analyses/benchmark && dnx run ../../pac-generator/generated-PACs",
|
||||
"test": "rm -r pac-generator/generated-PACs"
|
||||
},
|
||||
"author": "anticensority+owners@googlegroups.com",
|
||||
"author": "ilyaigpetrov",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"opencollective": "^1.0.3"
|
||||
},
|
||||
"collective": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/anticensority"
|
||||
"devDependencies": {
|
||||
"http-server": "^0.8.5"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user