Merge branch 'development' into production

This commit is contained in:
Ilya Ig. Petrov 2017-11-11 12:41:40 +05:00
commit d6037e6810
14 changed files with 278 additions and 102 deletions

View File

@ -13,7 +13,7 @@ This repo contains:
3. ~~PAC-scripts performance analyses of scripts generated~~ (doesn't take parse time into account) 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). 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://script.google.com/d/1RlqqfUmYNpEhekySfOqdzJ8L4eV1GsHYDjPD1DexxEW0RcGvuCSQlWa0/edit?usp=sharing [pac-generator]: https://github.com/anticensority/pac-script-generator
## Why I do This ## Why I do This

View File

@ -1 +1 @@
grep -r $@ ./src --exclude-dir=vendor --exclude-dir=node_modules grep -r $@ ./src --exclude-dir=vendor --exclude-dir=node_modules --exclude-dir=dist

View File

@ -43,7 +43,7 @@ const templatePlugin = (context) => through.obj(function(file, encoding, cb) {
}); });
gulp.task('default', ['build']); gulp.task('default', ['build:beta']);
gulp.task('clean', function(cb) { gulp.task('clean', function(cb) {
@ -120,4 +120,4 @@ gulp.task('_cp-beta', ['_cp-common'], function(cb) {
}); });
gulp.task('build:all', ['_cp-mini', '_cp-full', '_cp-beta']); gulp.task('build:all', ['_cp-mini', '_cp-full', '_cp-beta']);
gulp.task('build', ['_cp-full']); gulp.task('build:beta', ['_cp-beta']);

View File

@ -2311,11 +2311,6 @@
"resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz",
"integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=" "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8="
}, },
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@ -2327,6 +2322,11 @@
"strip-ansi": "3.0.1" "strip-ansi": "3.0.1"
} }
}, },
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",

View File

@ -8,8 +8,8 @@
"gulp": "gulp", "gulp": "gulp",
"test": "mocha --recursive ./src/**/test/*", "test": "mocha --recursive ./src/**/test/*",
"subpages": "cd ./src/extension-common/pages/options/ && npm run build && cd -", "subpages": "cd ./src/extension-common/pages/options/ && npm run build && cd -",
"start": "npm run subpages && npm run gulp", "start": "npm run subpages && npm run gulp build:beta",
"beta": "npm run subpages && npm run gulp build:all" "release": "npm run subpages && npm run gulp build:all"
}, },
"author": "Ilya Ig. Petrov", "author": "Ilya Ig. Petrov",
"license": "GPLv3", "license": "GPLv3",

View File

@ -71,6 +71,19 @@
}, },
getOrDie(cb = self.mandatory()) {
return self.chromified((err, ...args) => {
if (err) {
throw err;
}
cb(...args);
});
},
getProp(obj, path = self.mandatory()) { getProp(obj, path = self.mandatory()) {
const props = path.split('.'); const props = path.split('.');
@ -183,12 +196,56 @@
}, },
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,
}
},
}; };
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);
window.apis = { window.apis = {
version: { version: {
ifMini: false, ifMini: false,
build: chrome.runtime.getManifest().version.replace(/\d+\.\d+\./g, ''), build: chrome.runtime.getManifest().version.replace(/\d+\.\d+\./g, ''),
isLeq: (a, b) => compareVersions(a, b) <= 0,
}, },
}; };

View File

@ -12,6 +12,57 @@
const ifIncontinence = 'if-incontinence'; const ifIncontinence = 'if-incontinence';
const modsKey = 'mods'; 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! const getDefaultConfigs = () => ({// Configs user may mutate them and we don't care!
ifProxyHttpsUrlsOnly: { ifProxyHttpsUrlsOnly: {
@ -94,13 +145,13 @@
}; };
const getCurrentConfigs = function getCurrentConfigs() { const getCurrentConfigs = function getCurrentConfigs(ifRaw = false) {
const oldMods = kitchenState(modsKey); const oldMods = kitchenState(modsKey);
/*if (oldMods) { if (ifRaw) {
// No migration! // No migration!
return oldMods; return oldMods;
}*/ }
// Client may expect mods.included and mods.excluded! // Client may expect mods.included and mods.excluded!
// On first install they are not defined. // On first install they are not defined.
@ -143,10 +194,12 @@
.every((dProp) => { .every((dProp) => {
const ifDflt = ( 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; const ifMods = configs[dProp].ifDfltMods; // If default value implies PAC-script modification.
return ifDflt ? !ifMods : ifMods; return ifDflt ? !ifMods : ifMods;
}); });
@ -159,9 +212,9 @@
if (self.customProxyStringRaw) { if (self.customProxyStringRaw) {
customProxyArray = self.customProxyStringRaw customProxyArray = self.customProxyStringRaw
.replace(/#.*$/mg, '') // Strip comments. .replace(/#.*$/mg, '') // Strip comments.
.split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g ) .split( /(?:\s*(?:;\r?\n)+\s*)+/g )
.map( (p) => p.trim() ) .map( (p) => p.trim() )
.filter( (p) => p && /\s+/g.test(p) ); .filter( (p) => p && /\s+/g.test(p) ); // At least one space is required.
if (self.ifUseSecureProxiesOnly) { if (self.ifUseSecureProxiesOnly) {
customProxyArray = customProxyArray.filter( (pStr) => /^HTTPS\s/.test(pStr) ); customProxyArray = customProxyArray.filter( (pStr) => /^HTTPS\s/.test(pStr) );
} }
@ -171,6 +224,38 @@
customProxyArray.push(...self.torPoints); 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 = ''; self.filteredCustomsString = '';
if (customProxyArray.length) { if (customProxyArray.length) {
self.customProxyArray = customProxyArray; self.customProxyArray = customProxyArray;
@ -225,6 +310,7 @@
window.apis.pacKitchen = { window.apis.pacKitchen = {
getPacMods: getCurrentConfigs, getPacMods: getCurrentConfigs,
getPacModsRaw: () => getCurrentConfigs(true),
getOrderedConfigs: getOrderedConfigsForUser, getOrderedConfigs: getOrderedConfigsForUser,
cook(pacData, pacMods = mandatory()) { cook(pacData, pacMods = mandatory()) {
@ -382,12 +468,12 @@ ${ pacMods.filteredCustomsString
details details
? resolve(details) ? resolve(details)
: chrome.proxy.settings.get({}, timeouted(resolve) ) : chrome.proxy.settings.get({}, timeouted(resolve) ),
).then( (details) => { ).then((details) => {
if ( if (
details.levelOfControl === 'controlled_by_this_extension' details && details.levelOfControl === 'controlled_by_this_extension'
) { ) {
const pac = window.utils.getProp(details, 'value.pacScript'); const pac = window.utils.getProp(details, 'value.pacScript');
if (pac && pac.data) { if (pac && pac.data) {
@ -448,9 +534,14 @@ ${ pacMods.filteredCustomsString
return cb(null, res, ...accWarns); return cb(null, res, ...accWarns);
} }
const newHosts = (pacMods.customProxyArray || []).map( (ps) => ps.split(/\s+/)[1] ); 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.concat(moreWarns) )); window.utils.fireRequest(
'ip-to-host-replace-all',
newHosts,
(err, res, ...moreWarns) =>
cb(err, res, ...accWarns, ...moreWarns),
);
} },
); );
}, },

View File

@ -190,20 +190,6 @@
Version: 0.17 Version: 0.17
*/ */
pacUrls: ${JSON.stringify(anticensorityPacUrls, null, 2)}, 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: { onlyOwnSites: {
label: 'Только свои сайты и свои прокси', label: 'Только свои сайты и свои прокси',
@ -525,7 +511,7 @@
Better on each launch then on each pull. Better on each launch then on each pull.
*/ */
await new Promise((resolve) => { await new Promise(async (resolve) => {
const ifUpdating = antiCensorRu.version !== oldStorage.version; const ifUpdating = antiCensorRu.version !== oldStorage.version;
if (!ifUpdating) { if (!ifUpdating) {
@ -538,21 +524,28 @@
} }
// UPDATE & MIGRATION // 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 = 'Антицензорити';
}
}
antiCensorRu.pushToStorageAsync(() => { const ifUpdatedCb = () => antiCensorRu.pushToStorageAsync(() => {
console.log('Extension updated.'); console.log('Extension updated.');
resolve(); resolve();
}); });
console.log('Updating from', oldStorage.version, 'to', antiCensorRu.version);
if (window.apis.version.isLeq(oldStorage.version, '0.0.1.5')) {
// Change semicolons to semicolons followed by newlines in proxy string (raw).
const migrateProxies = (oldStr) => oldStr.replace(/;\\r?\\n?/g, ';\\n');
const modsMutated = window.apis.pacKitchen.getPacModsRaw();
modsMutated['customProxyStringRaw'] = migrateProxies(modsMutated['customProxyStringRaw']);
await new Promise(
(resolve) => window.apis.pacKitchen.keepCookedNowAsync(modsMutated, resolve),
);
}
ifUpdatedCb();
}); });
if (antiCensorRu.getPacProvider()) { if (antiCensorRu.getPacProvider()) {

View File

@ -2274,15 +2274,6 @@
"xtend": "4.0.1" "xtend": "4.0.1"
} }
}, },
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
},
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@ -2294,6 +2285,15 @@
"strip-ansi": "3.0.1" "strip-ansi": "3.0.1"
} }
}, },
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
},
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",

View File

@ -79,7 +79,8 @@ export default function getApp(theState) {
headers: new Headers(headers), headers: new Headers(headers),
}; };
//const ghUrl = `https://api.github.com/repos/anticensority/chromium-extension/issues/10/comments${query}`; // 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/for-testing/issues/1/comments${query}`;
const [error, comments, etag] = await fetch( const [error, comments, etag] = await fetch(

View File

@ -55,7 +55,14 @@ export default function getModList(theState) {
const child = ifMayHaveChild && this.state.checks[index] const child = ifMayHaveChild && this.state.checks[index]
&& createElement( && createElement(
props.childrenOfMod[conf.key], 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 return (<InfoLi

View File

@ -64,7 +64,7 @@ export default function getProxyEditor(theState) {
{ {
text-align: center; text-align: center;
} }
table.editor tr.proxyRow input[name="hostname"] { table.editor tr.proxyRow input[name="crededHostname"] {
padding: 0; padding: 0;
} }
@ -158,8 +158,14 @@ export default function getProxyEditor(theState) {
return true; return true;
}; };
const splitBySemi = (proxyString) => proxyString.replace(/#.*$/mg, '').trim().split(/\s*;\s*/g).filter((s) => s); const splitBySemi = (proxyString) => proxyString
const joinBySemi = (strs) => strs.join(';\n') + ';'; .replace(/#.*$/mg, '')
.trim()
.split(/\s*;\r?\n\s*/g)
.map((s) => s.trim())
.filter((s) => s);
const joinBySemi = (strs) => strs.join(';\n');
const normalizeProxyString = (str) => joinBySemi(splitBySemi(str)); const normalizeProxyString = (str) => joinBySemi(splitBySemi(str));
const PROXY_TYPE_LABEL_PAIRS = [['PROXY', 'PROXY/HTTP'],['HTTPS'],['SOCKS4'],['SOCKS5'],['SOCKS']]; const PROXY_TYPE_LABEL_PAIRS = [['PROXY', 'PROXY/HTTP'],['HTTPS'],['SOCKS4'],['SOCKS5'],['SOCKS']];
@ -217,11 +223,11 @@ export default function getProxyEditor(theState) {
}, {}); }, {});
const type = that.state.selectedNewType; const type = that.state.selectedNewType;
const hostname = elements.newHostname; const crededHostname = elements.newHostname;
const port = elements.newPort; const port = elements.newPort;
const newValue = `${that.props.proxyStringRaw}; ${type} ${hostname}:${port}` const newValue = `${that.props.proxyStringRaw};\n${type} ${crededHostname}:${port}`
.trim().replace(/(\s*;\s*)+/, '; '); .trim().replace(/(\s*;\n\s*)+/, ';\n');
that.props.setProxyStringRaw(true, newValue); that.props.setProxyStringRaw(true, newValue);
} }
@ -322,10 +328,17 @@ export default function getProxyEditor(theState) {
</tr> </tr>
{/* ADD NEW PROXY ENDS. */} {/* ADD NEW PROXY ENDS. */}
{ {
splitBySemi(this.props.proxyStringRaw).map((proxyAsString, index) => { splitBySemi(this.props.proxyStringRaw).map((proxyAsStringRaw, index) => {
const proxyAsString = proxyAsStringRaw.trim();
const {
type,
creds,
hostname,
port,
} = theState.utils.parseProxyScheme(proxyAsString);
const [type, addr] = proxyAsString.trim().split(/\s+/);
const [hostname, port] = addr.split(':');
return ( return (
<tr class={scopedCss.proxyRow}> <tr class={scopedCss.proxyRow}>
<td> <td>
@ -335,7 +348,7 @@ export default function getProxyEditor(theState) {
>X</button> >X</button>
</td> </td>
<td>{type}</td> <td>{type}</td>
<td><input value={hostname} name="hostname" readonly/></td> <td><input value={`${creds && `${creds}@`}${hostname}`} name="crededHostname" readonly/></td>
<td>{port}</td> <td>{port}</td>
<td> <td>
<button type="button" disabled={props.ifInputsDisabled} <button type="button" disabled={props.ifInputsDisabled}
@ -350,6 +363,7 @@ export default function getProxyEditor(theState) {
} }
</tbody> </tbody>
</table> </table>
<a href="https://rebrand.ly/ac-protected-proxy">Запароленные прокси?</a>
</form> </form>
); );
} }
@ -390,28 +404,34 @@ export default function getProxyEditor(theState) {
const errors = splitBySemi(this.state.stashedExports) const errors = splitBySemi(this.state.stashedExports)
.map((proxyAsString) => { .map((proxyAsString) => {
const [rawType, addr, ...rest] = proxyAsString.split(/\s+/); const {
if (rest && rest.length) { type,
return new Error( creds,
`"${rest.join(', ')}" кажется мне лишним. Вы забыли ";"?` hostname,
); port,
} username,
password,
} = theState.utils.parseProxyScheme(proxyAsString);
const crededAddr = `${creds ? `${creds}@` : ''}${hostname}:${port}`;
const knownTypes = PROXY_TYPE_LABEL_PAIRS.map(([type, label]) => type); const knownTypes = PROXY_TYPE_LABEL_PAIRS.map(([type, label]) => type);
if( !knownTypes.includes(rawType.toUpperCase()) ) { if( !knownTypes.includes(type.toUpperCase()) ) {
return new Error( return new Error(
`Неверный тип ${rawType}. Известные типы: ${knownTypes.join(', ')}.` `Неверный тип ${type}. Известные типы: ${knownTypes.join(', ')}.`
); );
} }
if (!(addr && /^[^:]+:\d+$/.test(addr))) { if (!(crededAddr && /^(?:.+@)?[^:]+:\d+$/.test(crededAddr))) {
return new Error( return new Error(
`Адрес прокси "${addr || ''}" не соответствует формату "омен_или_IP>:<порт_из_цифр>".` `Адрес прокси "${crededAddr || ''}" не соответствует формату "<опц_логин>:<опц_пароль>@омен_или_IP>:<порт_из_цифр>".`
); );
} }
const [hostname, rawPort] = addr.split(':'); if (password && !username) {
const port = parseInt(rawPort); return new Error('Вашему пользователю не хватает имени?');
if (port < 0 || port > 65535) { }
const portInt = parseInt(port);
if (portInt < 0 || portInt > 65535) {
return new Error( return new Error(
`Порт "${rawPort}" должен быть целым числом от 0 до 65535.` `Порт "${port}" должен быть целым числом от 0 до 65535.`
); );
} }
return false; return false;
@ -495,7 +515,7 @@ PROXY foobar.com:8080; # Not HTTP!`.trim()}
value={ value={
this.state.stashedExports !== false this.state.stashedExports !== false
? this.state.stashedExports ? this.state.stashedExports
: (this.props.proxyStringRaw || '').replace(/\s*;\s*/g, ';\n') : (this.props.proxyStringRaw || '').replace(/\s*;\n\s*/g, ';\n')
} }
/></td> /></td>
</tr> </tr>
@ -514,10 +534,12 @@ PROXY foobar.com:8080; # Not HTTP!`.trim()}
return proxyStringRaw return proxyStringRaw
.replace(/#.*$/mg, '') // Strip comments. .replace(/#.*$/mg, '') // Strip comments.
.replace(/[^\S\r\n]*DIRECT[^\S\r\n]*/g, '') // Remove DIRECT from old versions. .replace(/[^\S\r\n]*DIRECT[^\S\r\n]*/g, '') // Remove DIRECT from old versions.
/*
.split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g ) .split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g )
.map( (p) => p.trim() ) .map( (p) => p.trim() )
.filter((p) => p) .filter((p) => p)
.join(';\n'); .join(';\n');
*/
}; };

View File

@ -59,7 +59,7 @@
if (err) { if (err) {
// E.g., no tab with such id happens. // E.g., no tab with such id happens.
// Because requestDetails may be stale. // Because requestDetails may be stale.
console.log('Notifier error ignored:', err); console.log('Notifier error ignored (this is normal, it happens):', err);
return cb(); return cb();
} }
const ifTitleSetAlready = /\n/.test(title); const ifTitleSetAlready = /\n/.test(title);

View File

@ -1,30 +1,32 @@
'use strict'; 'use strict';
const commonContext = { const pacUrls = [
version: '1.5', // GitHub.io (anticensority), cached:
anticensorityPacUrls: [
// 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', '\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): // GitHub repo (anticensority), cached:
'\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', '\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',
// First official, shortened, not cached:
'https://rebrand.ly/ac-chrome-anticensority-pac',
// Old, deprecated: // Old, deprecated:
'https://anticensorship-russia.tk/generated-pac-scripts/anticensority.pac', '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',
] const commonContext = {
version: '1.6',
anticensorityPacUrls: [
...pacUrls,
],
}; };
exports.contexts = {}; exports.contexts = {};
const extra_permissions = ', "webRequest", "webRequestBlocking", "webNavigation"';
exports.contexts.full = Object.assign({}, commonContext, { exports.contexts.full = Object.assign({}, commonContext, {
versionSuffix: '', versionSuffix: '',
nameSuffixEn: '', nameSuffixEn: '',
nameSuffixRu: '', nameSuffixRu: '',
extra_permissions: ', "webRequest", "webNavigation"', extra_permissions,
persistent: '', persistent: '',
scripts_2x: ', "20-ip-to-host-api.js"', scripts_2x: ', "20-ip-to-host-api.js"',
scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"', scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"',
@ -41,12 +43,15 @@ exports.contexts.mini = Object.assign({}, commonContext, {
}); });
exports.contexts.beta = Object.assign({}, commonContext, { exports.contexts.beta = Object.assign({}, commonContext, {
anticensorityPacUrls: ['https://rebrand.ly/ac-beta-pac'], anticensorityPacUrls: [
version: '1.5', // 'https://rebrand.ly/ac-beta-pac',
...pacUrls,
],
version: '1.6',
versionSuffix: '', versionSuffix: '',
nameSuffixEn: ' FOR TESTING', nameSuffixEn: ' FOR TESTING',
nameSuffixRu: ' ДЛЯ ТЕСТОВ', nameSuffixRu: ' ДЛЯ ТЕСТОВ',
extra_permissions: ', "webRequest", "webNavigation"', extra_permissions,
persistent: '', persistent: '',
scripts_2x: ', "20-ip-to-host-api.js"', scripts_2x: ', "20-ip-to-host-api.js"',
scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"', scripts_8x: ', "80-error-menu.js", "83-last-errors.js", "85-block-informer.js"',