-
Notifications
You must be signed in to change notification settings - Fork 83
/
code.js
106 lines (91 loc) · 2.29 KB
/
code.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Author: iBug <ibug.io>
// Source: https://github.com/iBug/pac
// Time: @@TIME@@
var proxy = __PROXY__;
var direct = "DIRECT";
function belongsToSubnet(host, list) {
var ip = convert_addr(host) >>> 0;
if (list.length === 0 || ip < list[0][0])
return false;
// Binary search
var x = 0, y = list.length, middle;
while (y - x > 1) {
middle = Math.floor((x + y) / 2);
if (list[middle][0] <= ip)
x = middle;
else
y = middle;
}
// Match
var masked = ip & list[x][1];
return (masked ^ list[x][0]) === 0;
}
function hasMatchedPattern(text, patterns) {
for (var i = 0; i < patterns.length; i++) {
if (shExpMatch(text, patterns[i]))
return true;
}
return false;
}
function checkDomainType(host) {
// Check if a domain is blacklisted or whitelisted
var segments = host.split(".").reverse();
var ptr = DOMAINS;
var type = DOMAINS["@"];
for (var i = 0; i < segments.length; i++) {
var segment = segments[i];
ptr = ptr[segment];
if (ptr === undefined)
break;
if (typeof ptr === "number")
return ptr;
if (ptr["@"] !== undefined)
type = ptr["@"];
}
return type;
}
function hasWhitelistedPattern(url) {
return hasMatchedPattern(url, WHITEPAT);
}
function hasBlacklistedPattern(url) {
return hasMatchedPattern(url, BLACKPAT);
}
function isChina(host) {
return belongsToSubnet(host, CHINA);
}
function isLan(host) {
return belongsToSubnet(host, LAN);
}
function FindProxyForURL(url, host) {
if (hasWhitelistedPattern(url)) {
return direct;
}
if (hasBlacklistedPattern(url)) {
return proxy;
}
var domainType = checkDomainType(host);
if (domainType === 0) {
return proxy;
} else if (domainType === 1) {
return direct;
}
// Fallback to IP whitelist
var remote = dnsResolve(host);
if (!remote || remote.indexOf(":") !== -1) {
// resolution failed or is IPv6 addr
return proxy;
}
if (isLan(remote) || isChina(remote)) {
return direct;
}
return proxy;
}
var LAN = [
[0x00000000, 0xFFFFFFFF], // 0.0.0.0/32
[0x0A000000, 0xFF000000], // 10.0.0.0/8
[0x64400000, 0xFFC00000], // 100.64.0.0/10
[0x7F000000, 0xFF000000], // 127.0.0.0/8
[0xA9FE0000, 0xFFFF0000], // 169.254.0.0/16
[0xAC100000, 0xFFF00000], // 172.16.0.0/12
[0xC0A80000, 0xFFFF0000] // 192.168.0.0/16
];