did the survey, modified extension

This commit is contained in:
Ilya Ig. Petrov 2015-11-28 01:47:27 +05:00
parent 6c134cd48f
commit 2bc2412689
31 changed files with 78008 additions and 21 deletions

1
.gitignore vendored Executable file
View File

@ -0,0 +1 @@
node_modules

1
Benchmark/.gitignore vendored Executable file
View File

@ -0,0 +1 @@
bin

File diff suppressed because it is too large Load Diff

9523
Benchmark/Inputs/blocked-ips.txt Executable file

File diff suppressed because it is too large Load Diff

10000
Benchmark/Inputs/missed.txt Executable file

File diff suppressed because it is too large Load Diff

47
Benchmark/Output.txt Executable file
View File

@ -0,0 +1,47 @@
blocked-hosts-reversed-binary.js: 371 bytes, 3633268 ns, Missed: 331 bytes, 959025 ns
blocked-hosts-switch.js: 35 bytes, 861416 ns, Missed: 54 bytes, 1009980 ns
blocked-hosts-binary.js: 355 bytes, 3741660 ns, Missed: 315 bytes, 1101475 ns
blocked-hosts-plain-switch.js: 368 bytes, 4595046 ns, Missed: 327 bytes, 1181185 ns
blocked-ips-indexOf.js: 30 bytes, 4744851 ns, Missed: 50 bytes, 949647 ns
blocked-ips-switch.js: 30 bytes, 1324520 ns, Missed: 50 bytes, 954300 ns
blocked-ips-binary.js: 30 bytes, 3528872 ns, Missed: 50 bytes, 955016 ns
======================
blocked-hosts-reversed-binary.js: 60 bytes, 3810837 ns, Missed: 71 bytes, 971006 ns
blocked-hosts-switch.js: 90 bytes, 881944 ns, Missed: 54 bytes, 987749 ns
blocked-hosts-binary.js: 352 bytes, 3715816 ns, Missed: 311 bytes, 1015559 ns
blocked-hosts-plain-switch.js: 367 bytes, 5108743 ns, Missed: 322 bytes, 1057506 ns
blocked-ips-switch.js: 32 bytes, 1331517 ns, Missed: 48 bytes, 952596 ns
blocked-ips-indexOf.js: 36 bytes, 4863773 ns, Missed: 50 bytes, 956231 ns
blocked-ips-binary.js: 33 bytes, 3724425 ns, Missed: 52 bytes, 958463 ns
======================
blocked-hosts-plain-switch.js: 367 bytes, 3895654 ns, Missed: 218 bytes, 590817 ns
blocked-hosts-binary.js: 351 bytes, 4559283 ns, Missed: 207 bytes, 595531 ns
blocked-hosts-reversed-binary.js: 367 bytes, 3757800 ns, Missed: 96 bytes, 607930 ns
blocked-hosts-switch.js: 85 bytes, 909670 ns, Missed: 82 bytes, 665152 ns
blocked-ips-switch.js: 34 bytes, 1326365 ns, Missed: 72 bytes, 583463 ns
blocked-ips-binary.js: 36 bytes, 3567749 ns, Missed: 77 bytes, 583504 ns
blocked-ips-indexOf.js: 37 bytes, 4794414 ns, Missed: 77 bytes, 584845 ns
======================
blocked-hosts-binary.js: 355 bytes, 3669894 ns, Missed: 207 bytes, 593995 ns
blocked-hosts-plain-switch.js: 363 bytes, 3977687 ns, Missed: 223 bytes, 594579 ns
blocked-hosts-switch.js: 89 bytes, 874404 ns, Missed: 81 bytes, 608442 ns
blocked-hosts-reversed-binary.js: 54 bytes, 3706841 ns, Missed: 96 bytes, 622309 ns
blocked-ips-indexOf.js: 35 bytes, 4839284 ns, Missed: 78 bytes, 587725 ns
blocked-ips-switch.js: 43 bytes, 1346437 ns, Missed: 77 bytes, 599972 ns
blocked-ips-binary.js: 33 bytes, 3651593 ns, Missed: 80 bytes, 621814 ns
======================
blocked-hosts-binary.js: 352 bytes, 3711255 ns, Missed: 207 bytes, 590903 ns
blocked-hosts-switch.js: 91 bytes, 863216 ns, Missed: 77 bytes, 592086 ns
blocked-hosts-reversed-binary.js: 371 bytes, 3690426 ns, Missed: 99 bytes, 595659 ns
blocked-hosts-plain-switch.js: 367 bytes, 3933146 ns, Missed: 218 bytes, 618715 ns
blocked-ips-indexOf.js: 34 bytes, 4861233 ns, Missed: 77 bytes, 592716 ns
blocked-ips-switch.js: 30 bytes, 1339607 ns, Missed: 84 bytes, 595159 ns
blocked-ips-binary.js: 31 bytes, 3552007 ns, Missed: 76 bytes, 603872 ns
======================
blocked-hosts-binary-trie.js: 364 bytes, 27134555ns, Missed: 218 bytes, 725467 ns

119
Benchmark/Program.cs Normal file
View File

@ -0,0 +1,119 @@
using System;
using System.IO;
using PacProxyUsage;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
public class Program
{
public static string RunTest(string hostsFile, string pacName, bool ifMissing = false) {
using(StreamReader hostsReader = new StreamReader(hostsFile))
{
string pacUri = "http://localhost:8080/"+pacName+"?"+new Random().Next();
GC.Collect();
long memBefore = GC.GetTotalMemory(true);
var myTimer = new QueryPerfCounter();
myTimer.Start();
int iterations = 0;
string host;
while( (host = hostsReader.ReadLine()) != null )
{
string uri = Proxy.GetProxyForUrlUsingPac( "http://"+host, pacUri );
if (ifMissing && uri != null || !ifMissing && uri == null)
Console.WriteLine("DIRECT !" + host + "!");
//else Console.WriteLine("PROXY !" + uri + "!"); // For DEBUG.
++iterations;
}
myTimer.Stop();
// Calculate time per iteration in nanoseconds
double duration = myTimer.Duration(iterations);
long memAfter = GC.GetTotalMemory(false);
long memUsage = memAfter - memBefore;
double memPerAddr = memUsage / (double) iterations;
var resultNs = Convert.ToInt32(duration).ToString();
var resultBytes = Convert.ToInt32(memPerAddr).ToString();
return string.Format( "{0} bytes, {1} ns", resultBytes, resultNs );
}
}
public static void Main(string[] args)
{
if (args.Length != 1 || !Directory.Exists(args[0]))
{
Console.WriteLine("Arguments: PACs-dir.\nPac scripts must be served from the root of localhost:8080.");
return;
}
bool ifAppend = true;
using (StreamWriter resultsWriter = new StreamWriter("Output.txt", ifAppend))
{
resultsWriter.WriteLine("======================");
var pacsPath = args[0];
string [] pacs = Directory.GetFiles(pacsPath);
foreach(string pacPath in pacs)
{
string pacName = Path.GetFileName(pacPath);
Regex r = new Regex(@"^(\w+-\w+)", RegexOptions.IgnoreCase);
Match m = r.Match(pacName);
var prefix = m.Groups[1].ToString();
var hostsFile = "./Inputs/"+prefix + ".txt";
var missedFile = "./Inputs/missed.txt";
var results = pacName+":\t"+RunTest(hostsFile, pacName) + ", Missed: "+RunTest(missedFile, pacName, true);
Console.WriteLine(results);
resultsWriter.WriteLine(results);
}
}
}
}
public class QueryPerfCounter
{
[DllImport("KERNEL32")]
private static extern bool QueryPerformanceCounter(
out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceFrequency(out long lpFrequency);
private long start;
private long stop;
private long frequency;
Decimal multiplier = new Decimal(1.0e9);
public QueryPerfCounter()
{
if (QueryPerformanceFrequency(out frequency) == false)
{
// Frequency not supported
throw new Exception();
}
}
public void Start()
{
QueryPerformanceCounter(out start);
}
public void Stop()
{
QueryPerformanceCounter(out stop);
}
public double Duration(int iterations)
{
return ((((double)(stop - start)* (double) multiplier) / (double) frequency)/iterations);
}
}

46
Benchmark/Proxy.cs Executable file
View File

@ -0,0 +1,46 @@
using System;
namespace PacProxyUsage
{
/// <summary>
/// Summary description for Proxy.
/// </summary>
public class Proxy
{
public Proxy()
{
}
/// <summary>
/// Return proxy for requested Url
/// </summary>
/// <param name="sUrl">url</param>
/// <param name="sPacUri">Uri to PAC file</param>
/// <returns>proxy info</returns>
public static string GetProxyForUrlUsingPac ( string DestinationUrl, string PacUri ){
IntPtr WinHttpSession = Win32Api.WinHttpOpen("User", Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, IntPtr.Zero, IntPtr.Zero, 0);
Win32Api.WINHTTP_AUTOPROXY_OPTIONS ProxyOptions = new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
Win32Api.WINHTTP_PROXY_INFO ProxyInfo = new Win32Api.WINHTTP_PROXY_INFO();
ProxyOptions.fAutoLoginIfChallenged = true;
ProxyOptions.dwFlags = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP | Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
ProxyOptions.lpszAutoConfigUrl = PacUri;
// Get Proxy
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl( WinHttpSession, DestinationUrl, ref ProxyOptions, ref ProxyInfo );
Win32Api.WinHttpCloseHandle(WinHttpSession);
if ( IsSuccess ){
return ProxyInfo.lpszProxy;
}else {
Console.WriteLine("Error: {0}", Win32Api.GetLastError() );
return null;
}
}
}
}

204
Benchmark/Win32Api.cs Executable file
View File

@ -0,0 +1,204 @@
using System;
using System.Runtime.InteropServices;
namespace PacProxyUsage
{
/// <summary>
/// Summary description for Win32Api.
/// </summary>
public class Win32Api
{
#region AutoProxy Constants
/// <summary>
/// Applies only when setting proxy information
/// </summary>
public const int WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
/// <summary>
/// Internet accessed through a direct connection
/// </summary>
public const int WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
/// <summary>
/// Internet accessed using a proxy
/// </summary>
public const int WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3;
/// <summary>
/// Attempt to automatically discover the URL of the
/// PAC file using both DHCP and DNS queries to the local network.
/// </summary>
public const int WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001;
/// <summary>
/// Download the PAC file from the URL in the WINHTTP_AUTOPROXY_OPTIONS structure.
/// </summary>
public const int WINHTTP_AUTOPROXY_CONFIG_URL = 0x00000002;
/// <summary>
/// Executes the Web Proxy Auto-Discovery (WPAD) protocol in-process instead of
/// delegating to an out-of-process WinHTTP AutoProxy Service, if available.
/// This flag must be combined with one of the other flags
/// </summary>
public const int WINHTTP_AUTOPROXY_RUN_INPROCESS = 0x00010000;
/// <summary>
/// By default, WinHTTP is configured to fall back to auto-discover a proxy
/// in-process. If this fallback behavior is undesirable in the event that
/// an out-of-process discovery fails, it can be disabled using this flag.
/// </summary>
public const int WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = 0x00020000;
/// <summary>
/// Use DHCP to locate the proxy auto-configuration file.
/// </summary>
public const int WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001;
/// <summary>
/// Use DNS to attempt to locate the proxy auto-configuration file at a
/// well-known location on the domain of the local computer
/// </summary>
public const int WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002;
#endregion
#region Proxy Structures
/// <summary>
/// The structure is used to indicate to the WinHttpGetProxyForURL
/// function whether to specify the URL of the Proxy Auto-Configuration
/// (PAC) file or to automatically locate the URL with DHCP or DNS
/// queries to the network
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct WINHTTP_AUTOPROXY_OPTIONS {
/// <summary>
/// Mechanisms should be used to obtain the PAC file
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public int dwFlags;
/// <summary>
/// If dwflags includes the WINHTTP_AUTOPROXY_AUTO_DETECT flag,
/// then dwAutoDetectFlags specifies what protocols are to be
/// used to locate the PAC file. If both the DHCP and DNS auto
/// detect flags are specified, then DHCP is used first;
/// if no PAC URL is discovered using DHCP, then DNS is used.
/// If dwflags does not include the WINHTTP_AUTOPROXY_AUTO_DETECT
/// flag, then dwAutoDetectFlags must be zero.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public int dwAutoDetectFlags;
/// <summary>
/// If dwflags includes the WINHTTP_AUTOPROXY_CONFIG_URL flag, the
/// lpszAutoConfigUrl must point to a null-terminated Unicode string
/// that contains the URL of the proxy auto-configuration (PAC) file.
/// If dwflags does not include the WINHTTP_AUTOPROXY_CONFIG_URL flag,
/// then lpszAutoConfigUrl must be NULL.
/// </summary>
public string lpszAutoConfigUrl;
/// <summary>
/// Reserved for future use; must be NULL.
/// </summary>
public IntPtr lpvReserved;
/// <summary>
/// Reserved for future use; must be zero.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public int dwReserved;
/// <summary>
/// Specifies whether the client's domain credentials should be automatically
/// sent in response to an NTLM or Negotiate Authentication challenge when
/// WinHTTP requests the PAC file.
/// If this flag is TRUE, credentials should automatically be sent in response
/// to an authentication challenge. If this flag is FALSE and authentication
/// is required to download the PAC file, the WinHttpGetProxyForUrl fails.
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool fAutoLoginIfChallenged;
}
/// <summary>
/// The structure contains the session or default proxy configuration.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct WINHTTP_PROXY_INFO {
/// <summary>
/// Unsigned long integer value that contains the access type
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public int dwAccessType;
/// <summary>
/// Pointer to a string value that contains the proxy server list
/// </summary>
public string lpszProxy;
/// <summary>
/// Pointer to a string value that contains the proxy bypass list
/// </summary>
public string lpszProxyBypass;
}
#endregion
#region WinHttp
/// <summary>
/// This function implements the Web Proxy Auto-Discovery (WPAD) protocol
/// for automatically configuring the proxy settings for an HTTP request.
/// The WPAD protocol downloads a Proxy Auto-Configuration (PAC) file,
/// which is a script that identifies the proxy server to use for a given
/// target URL. PAC files are typically deployed by the IT department within
/// a corporate network environment. The URL of the PAC file can either be
/// specified explicitly or WinHttpGetProxyForUrl can be instructed to
/// automatically discover the location of the PAC file on the local network.
/// </summary>
/// <param name="hSession">The WinHTTP session handle returned by the WinHttpOpen function</param>
/// <param name="lpcwszUrl">A pointer to a null-terminated Unicode string that contains the
/// URL of the HTTP request that the application is preparing to send.</param>
/// <param name="pAutoProxyOptions">A pointer to a WINHTTP_AUTOPROXY_OPTIONS structure that
/// specifies the auto-proxy options to use.</param>
/// <param name="pProxyInfo">A pointer to a WINHTTP_PROXY_INFO structure that receives the
/// proxy setting. This structure is then applied to the request handle using the
/// WINHTTP_OPTION_PROXY option.</param>
/// <returns></returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpGetProxyForUrl(
IntPtr hSession,
string lpcwszUrl,
ref WINHTTP_AUTOPROXY_OPTIONS pAutoProxyOptions,
ref WINHTTP_PROXY_INFO pProxyInfo);
/// <summary>
/// The function initializes, for an application, the use of WinHTTP
/// functions and returns a WinHTTP-session handle
/// </summary>
/// <param name="pwszUserAgent">A pointer to a string variable that contains the name of the
/// application or entity calling the WinHTTP functions.</param>
/// <param name="dwAccessType">Type of access required. This can be one of the following values</param>
/// <param name="pwszProxyName"> A pointer to a string variable that contains the name of the
/// proxy server to use when proxy access is specified by setting dwAccessType to
/// WINHTTP_ACCESS_TYPE_NAMED_PROXY. The WinHTTP functions recognize only CERN type proxies for HTTP.
/// If dwAccessType is not set to WINHTTP_ACCESS_TYPE_NAMED_PROXY, this parameter must be set
/// to WINHTTP_NO_PROXY_NAME</param>
/// <param name="pwszProxyBypass">A pointer to a string variable that contains an optional list
/// of host names or IP addresses, or both, that should not be routed through the proxy when
/// dwAccessType is set to WINHTTP_ACCESS_TYPE_NAMED_PROXY. The list can contain wildcard characters.
/// Do not use an empty string, because the WinHttpOpen function uses it as the proxy bypass list.
/// If this parameter specifies the "&lt;local&gt;" macro as the only entry, this function bypasses
/// any host name that does not contain a period. If dwAccessType is not set to WINHTTP_ACCESS_TYPE_NAMED_PROXY,
/// this parameter must be set to WINHTTP_NO_PROXY_BYPASS.</param>
/// <param name="dwFlags">Unsigned long integer value that contains the flags that indicate various options
/// affecting the behavior of this function</param>
/// <returns>Returns a valid session handle if successful, or NULL otherwise</returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern IntPtr WinHttpOpen(
string pwszUserAgent,
int dwAccessType,
IntPtr pwszProxyName,
IntPtr pwszProxyBypass,
int dwFlags
);
/// <summary>
/// The function closes a single HINTERNET handle
/// </summary>
/// <param name="hInternet">Valid HINTERNET handle to be closed.</param>
/// <returns>Returns TRUE if the handle is successfully closed, or FALSE otherwise</returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpCloseHandle(IntPtr hInternet);
#endregion
[DllImport("kernel32.dll")]
public static extern int GetLastError();
}
}

10
Benchmark/project.json Normal file
View File

@ -0,0 +1,10 @@
{
"version": "0.1-alpha",
"authors": ["ilyaigpetrov"],
"description": "A wonderful library that does nice stuff",
"code": ["**/*.cs"],
"frameworks": {
"dnx451": { }
}
}

14
Benchmark/project.lock.json Executable file
View File

@ -0,0 +1,14 @@
{
"locked": false,
"version": 2,
"targets": {
"DNX,Version=v4.5.1": {},
"DNX,Version=v4.5.1/win7-x86": {},
"DNX,Version=v4.5.1/win7-x64": {}
},
"libraries": {},
"projectFileDependencyGroups": {
"": [],
"DNX,Version=v4.5.1": []
}
}

3
Extensions/Chrome/README.md Executable file
View File

@ -0,0 +1,3 @@
# antizapret-chrome-extension
РосКомНадзор заблокировал очередной сайт?

View File

@ -0,0 +1,788 @@
'use strict';
var Antizapret = {
csvMirrors: [
'https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv',
'http://sourceforge.net/p/z-i/code-0/HEAD/tree/dump.csv?format=raw',
'https://www.assembla.com/spaces/z-i/git/source/master/dump.csv?_format=raw'
],
lastUpdate: new Date(0),
updatePeriodInMinutes: 7*60,
rescheduleUpdate: function(period) {
var checkNewBlocked = 'Check for new blocked sites';
var period = period || this.updatePeriodInMinutes;
chrome.alarms.clearAll( (ifWasCleared) => {
chrome.alarms.create(checkNewBlocked, {
delayInMinutes: period
});
chrome.alarms.onAlarm.addListener( alarm => {
if (alarm.name === checkNewBlocked)
this.checkForUpdate();
});
});
},
checkForUpdates: function(url, cb) {
if (!url)
return this._useTheMirrorsLuke(this.checkForUpdates, url, cb);
var req = new XMLHttpRequest();
var ifAsync = true;
req.open('HEAD', url, ifAsync);
req.onload = event => {
if (req.status === 404)
return cb(req.status);
var date = Date.parse(req.getResponseHeader('Date'));
if (date > this.lastUpdate)
return this.update(url, cb);
return cb(null);
};
req.send(null);
},
update: function(url, cb) {
if (!url)
return this._useTheMirrorsLuke(this.update, url, cb);
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.onload = event => {
this.lastUpdate = Date.now();
this.applyCsv( req.responseText );
this.rescheduleUpdate();
return cb(null, req.responseText);
};
req.send(null);
},
applyCsv: function(csv) {
var pac = generatePac(csv);
console.log(pac);
var config = {
mode: "pac_script",
pacScript: {
data: pac
}
};
chrome.proxy.settings.set(
{value: config, scope: 'regular'}, function() {}
);
},
_useTheMirrorsLuke: function(method, url, cb) {
if (!cb)
if (typeof url === 'function') {
cb = url;
url = undefined;
} else cb = () => {};
var it;
if (typeof url === 'string')
it = [url][Symbol.iterator]();
else
it = url || this.csvMirrors[Symbol.iterator]();
var self = this;
function cbb(err, res) {
var cur = it.next();
if (cur.done || !err)
return cb(err, res);
method.call(self, cur.value, cbb);
}
var url = it.next().value;
return method.call(this, url, cbb);
}
};
chrome.runtime.onInstalled.addListener( details => {
switch(details.reason) {
case 'install':
case 'update':
Antizapret.checkForUpdates()
}
});
chrome.browserAction.onClicked.addListener( tab => Antizapret.checkForUpdates() );
//==============GENERATE-PACS.JS============================
function generatePac(input) {
var columnsSep = ';';
var valuesSep = /\s*\|\s*/g;
var ips = [], hosts = [], urls = [], orgs = [], date, reason;
var lines = input.trim().split(/\r?\n/g).slice(1);
lines.forEach( function(line) {
var values = line.split( columnsSep );
var newIps = values.shift().split( valuesSep );
var newHosts = values.shift().split( valuesSep ).map( punycode.toASCII ).map( function(h) { return h.replace(/\.+$/g); } );
var newUrls = values.shift().split( valuesSep );
var newOrgs = values.shift().split( valuesSep );
var newDate = values.pop();
var newReason = values.join(';');
ips.push.apply(ips, newIps);
hosts.push.apply(hosts, newHosts);
});
function toHash(arr) {
var res = {};
arr.forEach( function(el) { res[el] = true; } );
return res;
}
var ipsHash = toHash(ips);
var hostsHash = toHash(hosts);
// Remove duplicates and sort.
var ips = Object.keys(ipsHash).sort();
var hosts = Object.keys(hostsHash).sort();
function FindProxyForURL(url, host) {
// ProstoVPN.AntiZapret PAC-ip File
// Generated on Sun Nov 22 10:12:29 MSK 2015
// The whole PAC script is reevaluated on each call of this function.
host = host.replace(/\.+$/).toLowerCase(); // E.g. WinHTTP may be nasty.
// HTTPS proxy is a HTTP proxy over SSL. It is NOT CONNECT proxy!
// Supported only in Chrome and Firefox.
// http://www.chromium.org/developers/design-documents/secure-web-proxy
// This is to bypass FULL DPI
var isIE = /*@cc_on!@*/!1;
var viaProxy = isIE
? 'PROXY proxy.antizapret.prostovpn.org:3128; DIRECT'
: 'HTTPS proxy.antizapret.prostovpn.org:3143; PROXY proxy.antizapret.prostovpn.org:3128; DIRECT';
return IFPROXY() ? viaProxy : 'DIRECT';
}
var pacTemplate = FindProxyForURL.toString();
function stringifyCall() {
var fun = arguments[0];
var args = [].slice.call( arguments, 1 )
.map( function(a) { return typeof a !== 'string' ? JSON.stringify(a) : a; } ).join(', ');
return '('+fun+')('+args+')';
}
// REVERSED HOSTS SWITCH
function populateTrie(trie, doms) {
var dom = doms.pop();
if (!doms.length || doms.length === 1 && doms[0] === 'www') {
trie[''] = trie[''] || [];
trie[''].push( dom )
return trie;
}
if (trie[''] && trie[''].indexOf(dom) !== -1) // Subdomain of a blocked domain.
return trie;
trie[dom] = trie[dom] || {};
populateTrie( trie[dom], doms );
return trie;
}
var trie = {};
hosts.forEach( function(host) {
var doms = host.replace(/\.+$/).split('.');
populateTrie(trie, doms);
});
function trieToSwitch(trie, indent) {
var _indent = indent || '';
var indent = _indent + ' ';
var keys = Object.keys(trie).sort();
if (!trie[''] && keys.length === 1) {
var key = keys[0];
return _indent + 'if (doms.pop() === "'+key+'")\n'+ trieToSwitch(trie[key], indent);
}
var cases = '';
if (trie['']) {
var values = trie[''].sort();
if (values.length === 1 && keys.length === 1)
return _indent + 'return doms.pop() === "'+values[0]+'";\n';
cases =
values.filter( function(v) { return v; } ).map( function(val) { return indent +'case "'+val+'":\n'; } ).join('') + indent +' return true;\n';
delete trie[''];
keys = Object.keys(trie).sort();
}
cases += keys.filter( function(k) { return k; } ).map(
function(key) {
var tmp = trieToSwitch( trie[key], indent+' ');
if (!/^\s*return/.test(tmp))
tmp += indent+' break;\n';
return indent +'case "'+key+'":\n' +tmp;
}).join('');
return ''
+ _indent +'switch( doms.pop() ) {\n'
+ cases
+ _indent +'}\n';
}
function ifProxyByTrie(host) {
var doms = host.replace(/\.+$/).split('.');
"{SWITCH}"
return false;
}
var ifProxyByTrieStr = ifProxyByTrie.toString().replace('"{SWITCH}"', trieToSwitch(trie, ' '));
return pacTemplate
.replace( 'IFPROXY()', stringifyCall(ifProxyByTrieStr, 'host') );
}
//==============PUNYCODE====================================
/*! https://mths.be/punycode v1.3.2 by @mathias */
;(function(root) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports &&
!exports.nodeType && exports;
var freeModule = typeof module == 'object' && module &&
!module.nodeType && module;
var freeGlobal = typeof global == 'object' && global;
if (
freeGlobal.global === freeGlobal ||
freeGlobal.window === freeGlobal ||
freeGlobal.self === freeGlobal
) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw new RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
var result = [];
while (length--) {
result[length] = fn(array[length]);
}
return result;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings or email
* addresses.
* @private
* @param {String} domain The domain name or email address.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
var parts = string.split('@');
var result = '';
if (parts.length > 1) {
// In email addresses, only the domain name should be punycoded. Leave
// the local part (i.e. everything up to `@`) intact.
result = parts[0] + '@';
string = parts[1];
}
// Avoid `split(regex)` for IE8 compatibility. See #17.
string = string.replace(regexSeparators, '\x2E');
var labels = string.split('.');
var encoded = map(labels, fn).join('.');
return result + encoded;
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* https://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
/** Cached calculation results */
baseMinusT;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
// Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode symbols (e.g. a domain name label) to a
* Punycode string of ASCII-only symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT;
// Convert the input in UCS-2 to Unicode
input = ucs2decode(input);
// Cache the length
inputLength = input.length;
// Initialize the state
n = initialN;
delta = 0;
bias = initialBias;
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base; /* no condition */; k += base) {
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name or an email address
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
* it doesn't matter if you call it on a string that has already been
* converted to Unicode.
* @memberOf punycode
* @param {String} input The Punycoded domain name or email address to
* convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(input) {
return mapDomain(input, function(string) {
return regexPunycode.test(string)
? decode(string.slice(4).toLowerCase())
: string;
});
}
/**
* Converts a Unicode string representing a domain name or an email address to
* Punycode. Only the non-ASCII parts of the domain name will be converted,
* i.e. it doesn't matter if you call it with a domain that's already in
* ASCII.
* @memberOf punycode
* @param {String} input The domain name or email address to convert, as a
* Unicode string.
* @returns {String} The Punycode representation of the given domain name or
* email address.
*/
function toASCII(input) {
return mapDomain(input, function(string) {
return regexNonASCII.test(string)
? 'xn--' + encode(string)
: string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.3.2',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define('punycode', function() {
return punycode;
});
} else if (freeExports && freeModule) {
if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = punycode;
} else { // in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else { // in Rhino or a web browser
root.punycode = punycode;
}
}(this));

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Антизапрет",
"description": "РосКомНадзор заблокировал очередной сайт? Ты не нарушаешь закон! Ты не ребёнок!",
"description": "Безопасный Интернет от РосКомНадзор.",
"version": "0.1",
"browser_action": {
@ -10,7 +10,13 @@
"default_title": "Обсуждай на https://reddit.com/r/ru"
},
"permissions": [
"proxy"
"proxy",
"storage",
"alarms",
"http://*/",
"https://*/",
"ftp://*/"
],
"icons": { "16": "unlock.ico",
"128": "unlock.png" },

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

4
README.md Normal file → Executable file
View File

@ -1,2 +1,2 @@
# antizapret-chrome-extension
РосКомНадзор заблокировал очередной сайт? Ты не нарушаешь закон! Ты не ребёнок!
# Антизапрет PAC-скрипт

View File

@ -1,17 +0,0 @@
'use strict';
var config = {
mode: "pac_script",
pacScript: {
url: "http://antizapret.prostovpn.org/proxy.pac"
}
};
chrome.proxy.settings.set(
{value: config, scope: 'regular'},
function() {}
);
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.create( {url: "http://antizapret.prostovpn.org"} )
});

17329
dump.csv Normal file

File diff suppressed because one or more lines are too long

331
generate-PACs.js Normal file
View File

@ -0,0 +1,331 @@
var fs = require('fs');
var input = fs.readFileSync('dump.csv').toString();
var outputDir = 'generated-PACs';
try {
fs.mkdirSync( outputDir );
} catch(e) {
if ( e.code != 'EEXIST' ) throw e;
}
var punycode = require('punycode')
/*
CVS Format:
IP(s);host(s);URL(s);organization(s);reason;yyyy-mm-dd
* multiple values are joind by " | "
* url may have wierd protocol, e.g.: Newcamd525://
*/
var columnsSep = ';';
var valuesSep = /\s*\|\s*/g;
var ips = [], hosts = [], urls = [], orgs = [], date, reason;
for(var line of input.trim().split(/\r?\n/g).slice(1)) {
var values = line.split( columnsSep );
var newIps = values.shift().split( valuesSep );
var newHosts = values.shift().split( valuesSep ).map( punycode.toASCII ).map( host => host.replace(/\.+$/g) );
var newUrls = values.shift().split( valuesSep );
var newOrgs = values.shift().split( valuesSep );
var newDate = values.pop();
var newReason = values.join(';');
ips.push.apply(ips, newIps);
hosts.push.apply(hosts, newHosts);
}
function toHash(arr) {
var res = {};
arr.forEach( el => res[el] = true );
return res;
}
var ipsHash = toHash(ips);
var hostsHash = toHash(hosts);
// Remove duplicates and sort.
var ips = Object.keys(ipsHash).sort();
var hosts = Object.keys(hostsHash).sort();
function FindProxyForURL(url, host) {
// ProstoVPN.AntiZapret PAC-ip File
// Generated on Sun Nov 22 10:12:29 MSK 2015
// The whole PAC script is reevaluated on each call of this function.
host = host.replace(/\.+$/).toLowerCase(); // E.g. WinHTTP may be nasty.
// HTTPS proxy is a HTTP proxy over SSL. It is NOT CONNECT proxy!
// Supported only in Chrome and Firefox.
// http://www.chromium.org/developers/design-documents/secure-web-proxy
// This is to bypass FULL DPI
var isIE = /*@cc_on!@*/!1;
var viaProxy = isIE
? 'PROXY proxy.antizapret.prostovpn.org:3128; DIRECT'
: 'HTTPS proxy.antizapret.prostovpn.org:3143; PROXY proxy.antizapret.prostovpn.org:3128; DIRECT';
return IFPROXY() ? viaProxy : 'DIRECT';
}
var pacTemplate = FindProxyForURL.toString();
function stringifyCall() {
var fun = arguments[0];
var args = [].slice.call( arguments, 1 )
.map( a => typeof a !== 'string' ? JSON.stringify(a) : a ).join(', ');
return '('+fun+')('+args+')';
}
function produceOutput() {
var args = [].slice.call( arguments )
var scriptName = args.shift();
var script = pacTemplate
.replace( 'IFPROXY()', stringifyCall.apply(this, args) );
fs.writeFileSync(outputDir +'/'+ scriptName +'.js', script);
}
// BLOCKED IPS ARRAY
function ifProxyByIp(host, blockedIpsArray) {
// Internet Explorer
if (!Array.prototype.indexOf)
Array.prototype.indexOf = function(obj, start) {
for (var i = (start || 0), j = this.length; i < j; i++)
if (this[i] === obj) return i;
return -1;
}
return blockedIpsArray.indexOf( dnsResolve(host) ) !== -1
}
produceOutput('blocked-ips-indexOf', ifProxyByIp, 'host', ips);
// BLOCKED IPS SWITCH
function ifProxyBySwitch(host) {
switch( dnsResolve(host) ) {
/*{CASES}*/
default:
return false;
}
}
var cases = ips.map( ip => 'case "'+ip+'":' ).join('\n') +'\nreturn true;';
var ifProxySwitchStr = ifProxyBySwitch.toString().replace('/*{CASES}*/', cases);
produceOutput('blocked-ips-switch', ifProxySwitchStr, 'host' );
// BLOCKED IPS BINARY
function ifBinaryFound(target, sortedArray) {
var istart = 0;
var iend = sortedArray.length - 1;
while (istart < iend) {
var imid = istart + Math.floor( (iend - istart)*0.5 );
if (target > sortedArray[imid])
istart = imid + 1;
else
iend = imid;
}
return target === sortedArray[iend];
}
produceOutput('blocked-ips-binary', ifBinaryFound, 'dnsResolve(host)', ips);
// BLOCKED HOSTS BINARY
produceOutput('blocked-hosts-binary', ifBinaryFound, 'host', hosts);
// REVERSED BINARY
var reverse = str => str.split('').reverse().join('');
var reversedHosts = hosts.map( reverse ).sort();
function ifReversedBinaryFound(host, sortedArray) {
target = host.split('').reverse().join('');
var istart = 0;
var iend = sortedArray.length - 1;
while (istart < iend) {
var imid = istart + Math.floor( (iend - istart)*0.5 );
if (target > sortedArray[imid])
istart = imid + 1;
else
iend = imid;
}
return dnsDomainIs( host, sortedArray[iend].split('').reverse().join('') );
}
produceOutput('blocked-hosts-reversed-binary', ifReversedBinaryFound, 'host', reversedHosts);
// REVERSED HOSTS SWITCH
function populateTrie(trie, doms) {
var dom = doms.pop();
if (!doms.length || doms.length === 1 && doms[0] === 'www') {
trie[''] = trie[''] || [];
trie[''].push( dom )
return trie;
}
if (trie[''] && trie[''].indexOf(dom) !== -1) // Subdomain of a blocked domain.
return trie;
trie[dom] = trie[dom] || {};
populateTrie( trie[dom], doms );
return trie;
}
var trie = {};
for(var host of hosts) {
var doms = host.split('.');
populateTrie(trie, doms);
}
function trieToSwitch(trie, indent) {
var _indent = indent || '';
var indent = _indent + ' ';
var keys = Object.keys(trie).sort();
if (!trie[''] && keys.length === 1) {
var key = keys[0];
return _indent + 'if (doms.pop() === "'+key+'")\n'+ trieToSwitch(trie[key], indent);
}
var cases = '';
if (trie['']) {
var values = trie[''].sort();
if (values.length === 1 && keys.length === 1)
return _indent + 'return doms.pop() === "'+values[0]+'";\n';
cases =
values.filter( v => v ).map( val => indent +'case "'+val+'":\n' ).join('') + indent +' return true;\n';
delete trie[''];
keys = Object.keys(trie).sort();
}
cases += keys.filter( k => k ).map(
key => {
var tmp = trieToSwitch( trie[key], indent+' ');
if (!/^\s*return/.test(tmp))
tmp += indent+' break;\n';
return indent +'case "'+key+'":\n' +tmp;
}
).join('');
return ''
+ _indent +'switch( doms.pop() ) {\n'
+ cases
+ _indent +'}\n';
}
function ifProxyByTrie(host) {
//SWITCH
return false;
}
var ifProxyByTrieStr = ifProxyByTrie.toString().replace('//SWITCH', trieToSwitch(trie, ' '));
produceOutput('blocked-hosts-switch', ifProxyByTrieStr, 'host' );
/* REVERSED HOSTS BINARY TRIE
function populateBinTrie(trie, doms) {
var dom = doms.pop();
if (!doms.length || doms.length === 1 && doms[0] === 'www') {
trie[dom] = 'blocked';
return trie;
}
if (trie[dom] === 'blocked') // Subdomain of a blocked domain.
return trie;
trie[dom] = trie[dom] || {};
populateBinTrie( trie[dom], doms );
return trie;
}
var trie = {};
for(var host of hosts) {
var doms = host.split('.');
populateBinTrie(trie, doms);
}
function trie2sorted(trie) {
if (trie === 'blocked')
return trie;
var keys = Object.keys(trie).sort();
return keys.map( key => trie[key] !== 'blocked' ? [ key, trie2sorted( trie[key] ) ] : [key] );
}
var sortedTrie = trie2sorted(trie);
function ifProxyByBinTrie(host, sortedTrie) {
var doms = host.split('.');
function ifBinaryBlocked(sortedTrie) {
var target = doms.pop();
if (!target)
return false;
var istart = 0;
var iend = sortedTrie.length - 1;
while (istart < iend) {
var imid = istart + Math.floor( (iend - istart)*0.5 );
if (target > sortedTrie[imid][0])
istart = imid + 1;
else
iend = imid;
}
if (target !== sortedTrie[iend][0])
return false;
return sortedTrie[iend].length < 2 ? true : ifBinaryBlocked( sortedTrie[iend][1] );
}
return ifBinaryBlocked(sortedTrie)
}
produceOutput('blocked-hosts-binary-trie', ifProxyByBinTrie, 'host', sortedTrie);
*/
// BLOCKED HOSTS PLAIN SWITCH
function ifProxyByPlainSwitch(host) {
function ifBlocked(host) {
switch( host ) {
//CASES
}
return false;
}
var doms = host.split('.');
for( var endi = doms.length; endi >= 0; --endi )
if (ifBlocked( doms.slice( endi ).join('.') ))
return true;
return false;
}
var cases = hosts.map( host => 'case "'+host+'":' ).join('\n') +'\nreturn true;';
var tmp = ifProxyByPlainSwitch.toString().replace('//CASES', cases);
produceOutput('blocked-hosts-plain-switch', tmp, 'host' );

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

20
package.json Executable file
View File

@ -0,0 +1,20 @@
{
"name": "subjective-good-is-evil",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate": "node generate-PACs.js",
"prestart": "npm run generate",
"preserve": "npm run kill",
"serve": "START /B http-server generated-PACs",
"bench": "cd Benchmark && dnx run ../generated-PACs",
"start": "npm run bench",
"kill": "taskkill /F /IM node.exe"
},
"author": "ilyaigpetrov",
"license": "ISC",
"devDependencies": {
"http-server": "^0.8.5"
}
}

32
proxy.pac Executable file

File diff suppressed because one or more lines are too long