@browserless.io/browserless 2.20.2 → 2.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -1
- package/bin/browserless.js +2 -1
- package/build/browserless.js +3 -2
- package/build/browsers/index.d.ts +3 -2
- package/build/browsers/index.js +3 -1
- package/build/routes/chrome/http/content.post.body.json +8 -8
- package/build/routes/chrome/http/pdf.post.body.json +8 -8
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chrome/tests/pdf.spec.js +24 -12
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +8 -8
- package/build/routes/chromium/http/scrape.post.body.json +8 -8
- package/build/routes/chromium/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/tests/pdf.spec.js +24 -12
- package/build/shared/pdf.http.js +10 -5
- package/docker/sdk/Dockerfile +11 -0
- package/extensions/ublock/_locales/ar/messages.json +5 -1
- package/extensions/ublock/_locales/az/messages.json +4 -0
- package/extensions/ublock/_locales/be/messages.json +4 -0
- package/extensions/ublock/_locales/bg/messages.json +4 -0
- package/extensions/ublock/_locales/bn/messages.json +4 -0
- package/extensions/ublock/_locales/br_FR/messages.json +9 -5
- package/extensions/ublock/_locales/bs/messages.json +4 -0
- package/extensions/ublock/_locales/ca/messages.json +5 -1
- package/extensions/ublock/_locales/cs/messages.json +4 -0
- package/extensions/ublock/_locales/cv/messages.json +4 -0
- package/extensions/ublock/_locales/cy/messages.json +4 -0
- package/extensions/ublock/_locales/da/messages.json +4 -0
- package/extensions/ublock/_locales/de/messages.json +4 -0
- package/extensions/ublock/_locales/el/messages.json +8 -4
- package/extensions/ublock/_locales/en/messages.json +4 -0
- package/extensions/ublock/_locales/en_GB/messages.json +4 -0
- package/extensions/ublock/_locales/eo/messages.json +9 -5
- package/extensions/ublock/_locales/es/messages.json +4 -0
- package/extensions/ublock/_locales/et/messages.json +4 -0
- package/extensions/ublock/_locales/eu/messages.json +4 -0
- package/extensions/ublock/_locales/fa/messages.json +4 -0
- package/extensions/ublock/_locales/fi/messages.json +6 -2
- package/extensions/ublock/_locales/fil/messages.json +4 -0
- package/extensions/ublock/_locales/fr/messages.json +4 -0
- package/extensions/ublock/_locales/fy/messages.json +4 -0
- package/extensions/ublock/_locales/gl/messages.json +12 -8
- package/extensions/ublock/_locales/gu/messages.json +4 -0
- package/extensions/ublock/_locales/he/messages.json +4 -0
- package/extensions/ublock/_locales/hi/messages.json +4 -0
- package/extensions/ublock/_locales/hr/messages.json +4 -0
- package/extensions/ublock/_locales/hu/messages.json +68 -64
- package/extensions/ublock/_locales/hy/messages.json +4 -0
- package/extensions/ublock/_locales/id/messages.json +6 -2
- package/extensions/ublock/_locales/it/messages.json +4 -0
- package/extensions/ublock/_locales/ja/messages.json +4 -0
- package/extensions/ublock/_locales/ka/messages.json +4 -0
- package/extensions/ublock/_locales/kk/messages.json +4 -0
- package/extensions/ublock/_locales/kn/messages.json +4 -0
- package/extensions/ublock/_locales/ko/messages.json +4 -0
- package/extensions/ublock/_locales/lt/messages.json +4 -0
- package/extensions/ublock/_locales/lv/messages.json +4 -0
- package/extensions/ublock/_locales/mk/messages.json +4 -0
- package/extensions/ublock/_locales/ml/messages.json +4 -0
- package/extensions/ublock/_locales/mr/messages.json +4 -0
- package/extensions/ublock/_locales/ms/messages.json +4 -0
- package/extensions/ublock/_locales/nb/messages.json +4 -0
- package/extensions/ublock/_locales/nl/messages.json +4 -0
- package/extensions/ublock/_locales/no/messages.json +4 -0
- package/extensions/ublock/_locales/oc/messages.json +4 -0
- package/extensions/ublock/_locales/pa/messages.json +8 -4
- package/extensions/ublock/_locales/pl/messages.json +4 -0
- package/extensions/ublock/_locales/pt_BR/messages.json +4 -0
- package/extensions/ublock/_locales/pt_PT/messages.json +4 -0
- package/extensions/ublock/_locales/ro/messages.json +4 -0
- package/extensions/ublock/_locales/ru/messages.json +4 -0
- package/extensions/ublock/_locales/si/messages.json +4 -0
- package/extensions/ublock/_locales/sk/messages.json +4 -0
- package/extensions/ublock/_locales/sl/messages.json +4 -0
- package/extensions/ublock/_locales/so/messages.json +4 -0
- package/extensions/ublock/_locales/sq/messages.json +4 -0
- package/extensions/ublock/_locales/sr/messages.json +6 -2
- package/extensions/ublock/_locales/sv/messages.json +4 -0
- package/extensions/ublock/_locales/sw/messages.json +4 -0
- package/extensions/ublock/_locales/ta/messages.json +4 -0
- package/extensions/ublock/_locales/te/messages.json +4 -0
- package/extensions/ublock/_locales/th/messages.json +4 -0
- package/extensions/ublock/_locales/tr/messages.json +4 -0
- package/extensions/ublock/_locales/uk/messages.json +4 -0
- package/extensions/ublock/_locales/ur/messages.json +4 -0
- package/extensions/ublock/_locales/vi/messages.json +4 -0
- package/extensions/ublock/_locales/zh_CN/messages.json +4 -0
- package/extensions/ublock/_locales/zh_TW/messages.json +5 -1
- package/extensions/ublock/assets/assets.json +8 -6
- package/extensions/ublock/assets/resources/scriptlets.js +455 -301
- package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +4441 -6643
- package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +401 -307
- package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +34 -29
- package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +682 -709
- package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +2439 -1999
- package/extensions/ublock/assets/ublock/badlists.txt +7 -0
- package/extensions/ublock/assets/ublock/badware.min.txt +992 -552
- package/extensions/ublock/assets/ublock/filters.min.txt +1253 -864
- package/extensions/ublock/assets/ublock/privacy.min.txt +58 -31
- package/extensions/ublock/assets/ublock/quick-fixes.min.txt +118 -126
- package/extensions/ublock/assets/ublock/unbreak.min.txt +129 -109
- package/extensions/ublock/js/background.js +4 -3
- package/extensions/ublock/js/benchmarks.js +29 -29
- package/extensions/ublock/js/codemirror/ubo-static-filtering.js +1 -0
- package/extensions/ublock/js/contextmenu.js +20 -21
- package/extensions/ublock/js/devtools.js +137 -3
- package/extensions/ublock/js/filtering-context.js +98 -43
- package/extensions/ublock/js/logger-ui.js +1 -1
- package/extensions/ublock/js/messaging.js +57 -135
- package/extensions/ublock/js/pagestore.js +44 -31
- package/extensions/ublock/js/redirect-resources.js +14 -4
- package/extensions/ublock/js/scriptlet-filtering.js +4 -1
- package/extensions/ublock/js/static-filtering-parser.js +107 -37
- package/extensions/ublock/js/static-net-filtering.js +514 -250
- package/extensions/ublock/js/storage.js +2 -1
- package/extensions/ublock/js/traffic.js +8 -4
- package/extensions/ublock/js/vapi-background.js +1 -0
- package/extensions/ublock/js/vapi-common.js +1 -0
- package/extensions/ublock/logger-ui.html +2 -3
- package/extensions/ublock/manifest.json +2 -2
- package/extensions/ublock/support.html +1 -0
- package/extensions/ublock/web_accessible_resources/noop-vast2.xml +1 -0
- package/extensions/ublock/web_accessible_resources/noop-vast3.xml +1 -0
- package/extensions/ublock/web_accessible_resources/noop-vast4.xml +1 -0
- package/package.json +17 -17
- package/src/browserless.ts +3 -2
- package/src/browsers/index.ts +2 -0
- package/src/routes/chrome/tests/pdf.spec.ts +24 -12
- package/src/routes/chromium/tests/pdf.spec.ts +24 -12
- package/src/shared/pdf.http.ts +10 -6
- package/static/docs/swagger.json +10 -10
- package/static/docs/swagger.min.json +9 -9
- package/static/function/client.js +9 -9
- package/static/function/index.html +9 -9
- /package/extensions/ublock/web_accessible_resources/{noop-vmap1.0.xml → noop-vmap1.xml} +0 -0
|
@@ -19,28 +19,15 @@
|
|
|
19
19
|
Home: https://github.com/gorhill/uBlock
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'use strict';
|
|
22
|
+
import * as sfp from './static-filtering-parser.js';
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
import { domainFromHostname, hostnameFromNetworkURL } from './uri-utils.js';
|
|
25
|
+
import { dropTask, queueTask } from './tasks.js';
|
|
27
26
|
|
|
28
|
-
import { queueTask, dropTask } from './tasks.js';
|
|
29
27
|
import BidiTrieContainer from './biditrie.js';
|
|
30
|
-
import HNTrieContainer from './hntrie.js';
|
|
31
28
|
import { CompiledListReader } from './static-filtering-io.js';
|
|
32
|
-
import * as sfp from './static-filtering-parser.js';
|
|
33
|
-
|
|
34
|
-
import {
|
|
35
|
-
domainFromHostname,
|
|
36
|
-
hostnameFromNetworkURL,
|
|
37
|
-
} from './uri-utils.js';
|
|
38
|
-
|
|
39
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility
|
|
40
|
-
//
|
|
41
|
-
// This import would be best done dynamically, but since dynamic imports are
|
|
42
|
-
// not supported by older browsers, for now a static import is necessary.
|
|
43
29
|
import { FilteringContext } from './filtering-context.js';
|
|
30
|
+
import HNTrieContainer from './hntrie.js';
|
|
44
31
|
|
|
45
32
|
/******************************************************************************/
|
|
46
33
|
|
|
@@ -56,97 +43,99 @@ const keyvalStore = typeof vAPI !== 'undefined'
|
|
|
56
43
|
|
|
57
44
|
/******************************************************************************/
|
|
58
45
|
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
46
|
+
// 10fedcba9876543210
|
|
47
|
+
// |||||||| | || |
|
|
48
|
+
// |||||||| | || |
|
|
49
|
+
// |||||||| | || |
|
|
50
|
+
// |||||||| | || |
|
|
51
|
+
// |||||||| | || +---- bit 0- 1: block=0, allow=1, block important=2
|
|
52
|
+
// |||||||| | |+------ bit 2: unused
|
|
53
|
+
// |||||||| | +------- bit 3- 4: party [0-3]
|
|
54
|
+
// |||||||| +--------- bit 5- 9: type [0-31]
|
|
55
|
+
// |||||||+-------------- bit 10: headers-based filters
|
|
56
|
+
// ||||||+--------------- bit 11: redirect filters
|
|
57
|
+
// |||||+---------------- bit 12: removeparam filters
|
|
58
|
+
// ||||+----------------- bit 13: csp filters
|
|
59
|
+
// |||+------------------ bit 14: permissions filters
|
|
60
|
+
// ||+------------------- bit 15: uritransform filters
|
|
61
|
+
// |+-------------------- bit 16: replace filters
|
|
62
|
+
// +--------------------- bit 17: urlskip filters
|
|
63
|
+
// TODO: bit 11-17 could be converted into 3-bit value, as these options are not
|
|
76
64
|
// meant to be combined.
|
|
77
65
|
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
const BLOCK_REALM = 0b00000000000000000;
|
|
84
|
-
const ALLOW_REALM = 0b00000000000000001;
|
|
85
|
-
const IMPORTANT_REALM = 0b00000000000000010;
|
|
66
|
+
const BLOCK_REALM = 0b0000_0000_0000_0000_0000;
|
|
67
|
+
const ALLOW_REALM = 0b0000_0000_0000_0000_0001;
|
|
68
|
+
const IMPORTANT_REALM = 0b0000_0000_0000_0000_0010;
|
|
69
|
+
const BLOCKALLOW_REALM = BLOCK_REALM | ALLOW_REALM | IMPORTANT_REALM;
|
|
86
70
|
const BLOCKIMPORTANT_REALM = BLOCK_REALM | IMPORTANT_REALM;
|
|
87
|
-
const ANYPARTY_REALM =
|
|
88
|
-
const FIRSTPARTY_REALM =
|
|
89
|
-
const THIRDPARTY_REALM =
|
|
71
|
+
const ANYPARTY_REALM = 0b0000_0000_0000_0000_0000;
|
|
72
|
+
const FIRSTPARTY_REALM = 0b0000_0000_0000_0000_1000;
|
|
73
|
+
const THIRDPARTY_REALM = 0b0000_0000_0000_0001_0000;
|
|
90
74
|
const ALLPARTIES_REALM = FIRSTPARTY_REALM | THIRDPARTY_REALM;
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
75
|
+
const TYPE_REALM = 0b0000_0000_0011_1110_0000;
|
|
76
|
+
const HEADERS_REALM = 0b0000_0000_0100_0000_0000;
|
|
77
|
+
const REDIRECT_REALM = 0b0000_0000_1000_0000_0000;
|
|
78
|
+
const REMOVEPARAM_REALM = 0b0000_0001_0000_0000_0000;
|
|
79
|
+
const CSP_REALM = 0b0000_0010_0000_0000_0000;
|
|
80
|
+
const PERMISSIONS_REALM = 0b0000_0100_0000_0000_0000;
|
|
81
|
+
const URLTRANSFORM_REALM = 0b0000_1000_0000_0000_0000;
|
|
82
|
+
const REPLACE_REALM = 0b0001_0000_0000_0000_0000;
|
|
83
|
+
const URLSKIP_REALM = 0b0010_0000_0000_0000_0000;
|
|
98
84
|
const MODIFY_REALMS = REDIRECT_REALM | CSP_REALM |
|
|
99
85
|
REMOVEPARAM_REALM | PERMISSIONS_REALM |
|
|
100
|
-
URLTRANSFORM_REALM | REPLACE_REALM
|
|
86
|
+
URLTRANSFORM_REALM | REPLACE_REALM |
|
|
87
|
+
URLSKIP_REALM;
|
|
88
|
+
|
|
89
|
+
const TYPE_REALM_OFFSET = 5;
|
|
101
90
|
|
|
102
91
|
const typeNameToTypeValue = {
|
|
103
|
-
'no_type': 0 <<
|
|
104
|
-
'stylesheet': 1 <<
|
|
105
|
-
'image': 2 <<
|
|
106
|
-
'object': 3 <<
|
|
107
|
-
'object_subrequest': 3 <<
|
|
108
|
-
'script': 4 <<
|
|
109
|
-
'fetch': 5 <<
|
|
110
|
-
'xmlhttprequest': 5 <<
|
|
111
|
-
'sub_frame': 6 <<
|
|
112
|
-
'font': 7 <<
|
|
113
|
-
'media': 8 <<
|
|
114
|
-
'websocket': 9 <<
|
|
115
|
-
'beacon': 10 <<
|
|
116
|
-
'ping': 10 <<
|
|
117
|
-
'other': 11 <<
|
|
118
|
-
'popup': 12 <<
|
|
119
|
-
'popunder': 13 <<
|
|
120
|
-
'main_frame': 14 <<
|
|
121
|
-
'generichide': 15 <<
|
|
122
|
-
'specifichide': 16 <<
|
|
123
|
-
'inline-font': 17 <<
|
|
124
|
-
'inline-script': 18 <<
|
|
125
|
-
'cname': 19 <<
|
|
126
|
-
'webrtc': 20 <<
|
|
127
|
-
'unsupported': 21 <<
|
|
92
|
+
'no_type': 0 << TYPE_REALM_OFFSET,
|
|
93
|
+
'stylesheet': 1 << TYPE_REALM_OFFSET,
|
|
94
|
+
'image': 2 << TYPE_REALM_OFFSET,
|
|
95
|
+
'object': 3 << TYPE_REALM_OFFSET,
|
|
96
|
+
'object_subrequest': 3 << TYPE_REALM_OFFSET,
|
|
97
|
+
'script': 4 << TYPE_REALM_OFFSET,
|
|
98
|
+
'fetch': 5 << TYPE_REALM_OFFSET,
|
|
99
|
+
'xmlhttprequest': 5 << TYPE_REALM_OFFSET,
|
|
100
|
+
'sub_frame': 6 << TYPE_REALM_OFFSET,
|
|
101
|
+
'font': 7 << TYPE_REALM_OFFSET,
|
|
102
|
+
'media': 8 << TYPE_REALM_OFFSET,
|
|
103
|
+
'websocket': 9 << TYPE_REALM_OFFSET,
|
|
104
|
+
'beacon': 10 << TYPE_REALM_OFFSET,
|
|
105
|
+
'ping': 10 << TYPE_REALM_OFFSET,
|
|
106
|
+
'other': 11 << TYPE_REALM_OFFSET,
|
|
107
|
+
'popup': 12 << TYPE_REALM_OFFSET, // start of behavioral filtering
|
|
108
|
+
'popunder': 13 << TYPE_REALM_OFFSET,
|
|
109
|
+
'main_frame': 14 << TYPE_REALM_OFFSET, // start of 1p behavioral filtering
|
|
110
|
+
'generichide': 15 << TYPE_REALM_OFFSET,
|
|
111
|
+
'specifichide': 16 << TYPE_REALM_OFFSET,
|
|
112
|
+
'inline-font': 17 << TYPE_REALM_OFFSET,
|
|
113
|
+
'inline-script': 18 << TYPE_REALM_OFFSET,
|
|
114
|
+
'cname': 19 << TYPE_REALM_OFFSET,
|
|
115
|
+
'webrtc': 20 << TYPE_REALM_OFFSET,
|
|
116
|
+
'unsupported': 21 << TYPE_REALM_OFFSET,
|
|
128
117
|
};
|
|
129
118
|
|
|
130
119
|
const otherTypeBitValue = typeNameToTypeValue.other;
|
|
131
120
|
|
|
132
121
|
const bitFromType = type =>
|
|
133
|
-
1 << ((typeNameToTypeValue[type] >>>
|
|
122
|
+
1 << ((typeNameToTypeValue[type] >>> TYPE_REALM_OFFSET) - 1);
|
|
134
123
|
|
|
135
124
|
// All network request types to bitmap
|
|
136
|
-
// bring origin to 0 (from
|
|
125
|
+
// bring origin to 0 (from TYPE_REALM_OFFSET -- see typeNameToTypeValue)
|
|
137
126
|
// left-shift 1 by the above-calculated value
|
|
138
127
|
// subtract 1 to set all type bits
|
|
139
128
|
const allNetworkTypesBits =
|
|
140
|
-
(1 << (otherTypeBitValue >>>
|
|
129
|
+
(1 << (otherTypeBitValue >>> TYPE_REALM_OFFSET)) - 1;
|
|
141
130
|
|
|
142
131
|
const allTypesBits =
|
|
143
132
|
allNetworkTypesBits |
|
|
144
|
-
1 << (typeNameToTypeValue['popup'] >>>
|
|
145
|
-
1 << (typeNameToTypeValue['main_frame'] >>>
|
|
146
|
-
1 << (typeNameToTypeValue['inline-font'] >>>
|
|
147
|
-
1 << (typeNameToTypeValue['inline-script'] >>>
|
|
133
|
+
1 << (typeNameToTypeValue['popup'] >>> TYPE_REALM_OFFSET) - 1 |
|
|
134
|
+
1 << (typeNameToTypeValue['main_frame'] >>> TYPE_REALM_OFFSET) - 1 |
|
|
135
|
+
1 << (typeNameToTypeValue['inline-font'] >>> TYPE_REALM_OFFSET) - 1 |
|
|
136
|
+
1 << (typeNameToTypeValue['inline-script'] >>> TYPE_REALM_OFFSET) - 1;
|
|
148
137
|
const unsupportedTypeBit =
|
|
149
|
-
1 << (typeNameToTypeValue['unsupported'] >>>
|
|
138
|
+
1 << (typeNameToTypeValue['unsupported'] >>> TYPE_REALM_OFFSET) - 1;
|
|
150
139
|
|
|
151
140
|
const typeValueToTypeName = [
|
|
152
141
|
'',
|
|
@@ -199,6 +188,7 @@ const MODIFIER_TYPE_CSP = 4;
|
|
|
199
188
|
const MODIFIER_TYPE_PERMISSIONS = 5;
|
|
200
189
|
const MODIFIER_TYPE_URLTRANSFORM = 6;
|
|
201
190
|
const MODIFIER_TYPE_REPLACE = 7;
|
|
191
|
+
const MODIFIER_TYPE_URLSKIP = 8;
|
|
202
192
|
|
|
203
193
|
const modifierBitsFromType = new Map([
|
|
204
194
|
[ MODIFIER_TYPE_REDIRECT, REDIRECT_REALM ],
|
|
@@ -208,6 +198,7 @@ const modifierBitsFromType = new Map([
|
|
|
208
198
|
[ MODIFIER_TYPE_PERMISSIONS, PERMISSIONS_REALM ],
|
|
209
199
|
[ MODIFIER_TYPE_URLTRANSFORM, URLTRANSFORM_REALM ],
|
|
210
200
|
[ MODIFIER_TYPE_REPLACE, REPLACE_REALM ],
|
|
201
|
+
[ MODIFIER_TYPE_URLSKIP, URLSKIP_REALM ],
|
|
211
202
|
]);
|
|
212
203
|
|
|
213
204
|
const modifierTypeFromName = new Map([
|
|
@@ -218,6 +209,7 @@ const modifierTypeFromName = new Map([
|
|
|
218
209
|
[ 'permissions', MODIFIER_TYPE_PERMISSIONS ],
|
|
219
210
|
[ 'uritransform', MODIFIER_TYPE_URLTRANSFORM ],
|
|
220
211
|
[ 'replace', MODIFIER_TYPE_REPLACE ],
|
|
212
|
+
[ 'urlskip', MODIFIER_TYPE_URLSKIP ],
|
|
221
213
|
]);
|
|
222
214
|
|
|
223
215
|
const modifierNameFromType = new Map([
|
|
@@ -228,22 +220,23 @@ const modifierNameFromType = new Map([
|
|
|
228
220
|
[ MODIFIER_TYPE_PERMISSIONS, 'permissions' ],
|
|
229
221
|
[ MODIFIER_TYPE_URLTRANSFORM, 'uritransform' ],
|
|
230
222
|
[ MODIFIER_TYPE_REPLACE, 'replace' ],
|
|
223
|
+
[ MODIFIER_TYPE_URLSKIP, 'urlskip' ],
|
|
231
224
|
]);
|
|
232
225
|
|
|
233
|
-
//const typeValueFromCatBits = catBits => (catBits >>>
|
|
226
|
+
//const typeValueFromCatBits = catBits => (catBits >>> TYPE_REALM_OFFSET) & 0b11111;
|
|
234
227
|
|
|
235
228
|
const MAX_TOKEN_LENGTH = 7;
|
|
236
229
|
|
|
237
230
|
// Four upper bits of token hash are reserved for built-in predefined
|
|
238
231
|
// token hashes, which should never end up being used when tokenizing
|
|
239
232
|
// any arbitrary string.
|
|
240
|
-
const NO_TOKEN_HASH =
|
|
241
|
-
const DOT_TOKEN_HASH =
|
|
242
|
-
const ANY_TOKEN_HASH =
|
|
243
|
-
const ANY_HTTPS_TOKEN_HASH =
|
|
244
|
-
const ANY_HTTP_TOKEN_HASH =
|
|
245
|
-
const EMPTY_TOKEN_HASH =
|
|
246
|
-
const INVALID_TOKEN_HASH =
|
|
233
|
+
const NO_TOKEN_HASH = 0x5000_0000;
|
|
234
|
+
const DOT_TOKEN_HASH = 0x1000_0000;
|
|
235
|
+
const ANY_TOKEN_HASH = 0x2000_0000;
|
|
236
|
+
const ANY_HTTPS_TOKEN_HASH = 0x3000_0000;
|
|
237
|
+
const ANY_HTTP_TOKEN_HASH = 0x4000_0000;
|
|
238
|
+
const EMPTY_TOKEN_HASH = 0xF000_0000;
|
|
239
|
+
const INVALID_TOKEN_HASH = 0xFFFF_FFFF;
|
|
247
240
|
|
|
248
241
|
/******************************************************************************/
|
|
249
242
|
|
|
@@ -255,6 +248,7 @@ let $requestTypeValue = 0;
|
|
|
255
248
|
let $requestURL = '';
|
|
256
249
|
let $requestURLRaw = '';
|
|
257
250
|
let $requestHostname = '';
|
|
251
|
+
let $requestAddress = '';
|
|
258
252
|
let $docHostname = '';
|
|
259
253
|
let $docDomain = '';
|
|
260
254
|
let $tokenBeg = 0;
|
|
@@ -386,9 +380,9 @@ class LogData {
|
|
|
386
380
|
} else if ( (categoryBits & FIRSTPARTY_REALM) !== 0 ) {
|
|
387
381
|
logData.options.unshift('1p');
|
|
388
382
|
}
|
|
389
|
-
const type = categoryBits &
|
|
383
|
+
const type = categoryBits & TYPE_REALM;
|
|
390
384
|
if ( type !== 0 ) {
|
|
391
|
-
logData.options.unshift(typeValueToTypeName[type >>>
|
|
385
|
+
logData.options.unshift(typeValueToTypeName[type >>> TYPE_REALM_OFFSET]);
|
|
392
386
|
}
|
|
393
387
|
let raw = logData.pattern.join('');
|
|
394
388
|
if (
|
|
@@ -422,6 +416,14 @@ class LogData {
|
|
|
422
416
|
isPureHostname() {
|
|
423
417
|
return this.tokenHash === DOT_TOKEN_HASH;
|
|
424
418
|
}
|
|
419
|
+
|
|
420
|
+
static requote(s) {
|
|
421
|
+
if ( /^(["'`]).+\1$|,/.test(s) === false ) { return s; }
|
|
422
|
+
if ( s.includes("'") === false ) { return `'${s}'`; }
|
|
423
|
+
if ( s.includes('"') === false ) { return `"${s}"`; }
|
|
424
|
+
if ( s.includes('`') === false ) { return `\`${s}\``; }
|
|
425
|
+
return `'${s.replace(/'/g, "\\'")}'`;
|
|
426
|
+
}
|
|
425
427
|
}
|
|
426
428
|
|
|
427
429
|
/******************************************************************************/
|
|
@@ -707,6 +709,8 @@ const dnrAddRuleWarning = (rule, msg) => {
|
|
|
707
709
|
FilterNotType
|
|
708
710
|
FilterStrictParty
|
|
709
711
|
FilterModifier
|
|
712
|
+
FilterOnHeaders
|
|
713
|
+
FilterIPAddress
|
|
710
714
|
|
|
711
715
|
Collection:
|
|
712
716
|
FilterCollection
|
|
@@ -765,7 +769,7 @@ class FilterImportant {
|
|
|
765
769
|
}
|
|
766
770
|
|
|
767
771
|
static dnrFromCompiled(args, rule) {
|
|
768
|
-
rule.priority = (rule.priority ||
|
|
772
|
+
rule.priority = (rule.priority || 0) + 30;
|
|
769
773
|
}
|
|
770
774
|
|
|
771
775
|
static keyFromArgs() {
|
|
@@ -1239,7 +1243,7 @@ class FilterRegex {
|
|
|
1239
1243
|
return [
|
|
1240
1244
|
FilterRegex.fid,
|
|
1241
1245
|
details.pattern,
|
|
1242
|
-
details.
|
|
1246
|
+
details.optionValues.has('match-case') ? 1 : 0,
|
|
1243
1247
|
];
|
|
1244
1248
|
}
|
|
1245
1249
|
|
|
@@ -2080,7 +2084,7 @@ const compileToDomainOpt = (...args) => {
|
|
|
2080
2084
|
|
|
2081
2085
|
class FilterDenyAllow extends FilterToDomainMissSet {
|
|
2082
2086
|
static compile(details) {
|
|
2083
|
-
return super.compile(details.
|
|
2087
|
+
return super.compile(details.optionValues.get('denyallow'), 0b01);
|
|
2084
2088
|
}
|
|
2085
2089
|
|
|
2086
2090
|
static logData(idata, details) {
|
|
@@ -2141,7 +2145,7 @@ class FilterModifier {
|
|
|
2141
2145
|
let opt = modifierNameFromType.get(filterData[idata+2]);
|
|
2142
2146
|
const refs = filterRefs[filterData[idata+3]];
|
|
2143
2147
|
if ( refs.value !== '' ) {
|
|
2144
|
-
opt += `=${refs.value}`;
|
|
2148
|
+
opt += `=${LogData.requote(refs.value)}`;
|
|
2145
2149
|
}
|
|
2146
2150
|
details.options.push(opt);
|
|
2147
2151
|
}
|
|
@@ -2165,7 +2169,7 @@ class FilterModifierResult {
|
|
|
2165
2169
|
this.refs = filterRefs[filterData[imodifierunit+3]];
|
|
2166
2170
|
this.ireportedunit = env.iunit;
|
|
2167
2171
|
this.th = env.th;
|
|
2168
|
-
this.bits = (env.bits & ~
|
|
2172
|
+
this.bits = (env.bits & ~BLOCKALLOW_REALM) | filterData[imodifierunit+1];
|
|
2169
2173
|
}
|
|
2170
2174
|
|
|
2171
2175
|
get result() {
|
|
@@ -2907,7 +2911,7 @@ class FilterStrictParty {
|
|
|
2907
2911
|
|
|
2908
2912
|
static dnrFromCompiled(args, rule) {
|
|
2909
2913
|
const partyness = args[1] === 0 ? 1 : 3;
|
|
2910
|
-
dnrAddRuleError(rule, `
|
|
2914
|
+
dnrAddRuleError(rule, `strict${partyness}p not supported`);
|
|
2911
2915
|
}
|
|
2912
2916
|
|
|
2913
2917
|
static keyFromArgs(args) {
|
|
@@ -2942,12 +2946,12 @@ class FilterOnHeaders {
|
|
|
2942
2946
|
}
|
|
2943
2947
|
|
|
2944
2948
|
static compile(details) {
|
|
2945
|
-
return [ FilterOnHeaders.fid, details.
|
|
2949
|
+
return [ FilterOnHeaders.fid, details.optionValues.get('header') ];
|
|
2946
2950
|
}
|
|
2947
2951
|
|
|
2948
2952
|
static fromCompiled(args) {
|
|
2949
2953
|
return filterDataAlloc(
|
|
2950
|
-
args[0],
|
|
2954
|
+
args[0], // fid
|
|
2951
2955
|
filterRefAdd({
|
|
2952
2956
|
headerOpt: args[1],
|
|
2953
2957
|
$parsed: null,
|
|
@@ -2955,12 +2959,16 @@ class FilterOnHeaders {
|
|
|
2955
2959
|
);
|
|
2956
2960
|
}
|
|
2957
2961
|
|
|
2962
|
+
static dnrFromCompiled(args, rule) {
|
|
2963
|
+
dnrAddRuleError(rule, `header="${args[1]}" not supported`);
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2958
2966
|
static logData(idata, details) {
|
|
2959
2967
|
const irefs = filterData[idata+1];
|
|
2960
2968
|
const headerOpt = filterRefs[irefs].headerOpt;
|
|
2961
2969
|
let opt = 'header';
|
|
2962
2970
|
if ( headerOpt !== '' ) {
|
|
2963
|
-
opt += `=${headerOpt}`;
|
|
2971
|
+
opt += `=${LogData.requote(headerOpt)}`;
|
|
2964
2972
|
}
|
|
2965
2973
|
details.options.push(opt);
|
|
2966
2974
|
}
|
|
@@ -2968,6 +2976,113 @@ class FilterOnHeaders {
|
|
|
2968
2976
|
|
|
2969
2977
|
registerFilterClass(FilterOnHeaders);
|
|
2970
2978
|
|
|
2979
|
+
/******************************************************************************/
|
|
2980
|
+
|
|
2981
|
+
class FilterIPAddress {
|
|
2982
|
+
static TYPE_UNKNOWN = 0;
|
|
2983
|
+
static TYPE_EQUAL = 1;
|
|
2984
|
+
static TYPE_STARTSWITH = 2;
|
|
2985
|
+
static TYPE_LAN = 3;
|
|
2986
|
+
static TYPE_LOOPBACK = 4;
|
|
2987
|
+
static TYPE_RE = 5;
|
|
2988
|
+
static reIPv6IPv4lan = /^::ffff:(7f\w{2}|a\w{2}|a9fe|c0a8):\w+$/;
|
|
2989
|
+
static reIPv6local = /^f[cd]\w{2}:/;
|
|
2990
|
+
|
|
2991
|
+
static match(idata) {
|
|
2992
|
+
const ipaddr = $requestAddress;
|
|
2993
|
+
if ( ipaddr === '' ) { return false; }
|
|
2994
|
+
const details = filterRefs[filterData[idata+1]];
|
|
2995
|
+
switch ( details.$type || this.TYPE_UNKNOWN ) {
|
|
2996
|
+
case this.TYPE_LAN:
|
|
2997
|
+
return this.isLAN(ipaddr);
|
|
2998
|
+
case this.TYPE_LOOPBACK:
|
|
2999
|
+
return this.isLoopback(ipaddr);
|
|
3000
|
+
case this.TYPE_EQUAL:
|
|
3001
|
+
case this.TYPE_STARTSWITH:
|
|
3002
|
+
case this.TYPE_RE:
|
|
3003
|
+
return details.$pattern.test(ipaddr);
|
|
3004
|
+
default:
|
|
3005
|
+
break;
|
|
3006
|
+
}
|
|
3007
|
+
const { pattern } = details;
|
|
3008
|
+
if ( pattern === 'lan' ) {
|
|
3009
|
+
details.$type = this.TYPE_LAN;
|
|
3010
|
+
} else if ( pattern === 'loopback' ) {
|
|
3011
|
+
details.$type = this.TYPE_LOOPBACK;
|
|
3012
|
+
} else if ( pattern.startsWith('/') && pattern.endsWith('/') ) {
|
|
3013
|
+
details.$type = this.TYPE_RE;
|
|
3014
|
+
details.$pattern = new RegExp(pattern.slice(1, -1), 'm');
|
|
3015
|
+
} else if ( pattern.endsWith('*') ) {
|
|
3016
|
+
details.$type = this.TYPE_STARTSWITH;
|
|
3017
|
+
details.$pattern = new RegExp(`^${restrFromPlainPattern(pattern.slice(0, -1))}`, 'm');
|
|
3018
|
+
} else {
|
|
3019
|
+
details.$type = this.TYPE_EQUAL;
|
|
3020
|
+
details.$pattern = new RegExp(`^${restrFromPlainPattern(pattern)}$`, 'm');
|
|
3021
|
+
}
|
|
3022
|
+
return this.match(idata);
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
// https://github.com/uBlockOrigin/uAssets/blob/master/filters/lan-block.txt
|
|
3026
|
+
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
|
3027
|
+
// `ipaddr` is assumed well-formed
|
|
3028
|
+
static isLAN(ipaddr) {
|
|
3029
|
+
const c0 = ipaddr.charCodeAt(0);
|
|
3030
|
+
// ipv4
|
|
3031
|
+
if ( c0 === 0x30 /* 0 */ ) {
|
|
3032
|
+
return ipaddr.startsWith('0.');
|
|
3033
|
+
}
|
|
3034
|
+
if ( c0 === 0x31 /* 1 */ ) {
|
|
3035
|
+
if ( ipaddr.startsWith('10.') ) { return true; }
|
|
3036
|
+
if ( ipaddr.startsWith('127.') ) { return true; }
|
|
3037
|
+
if ( ipaddr.startsWith('169.254.') ) { return true; }
|
|
3038
|
+
if ( ipaddr.startsWith('172.') ) {
|
|
3039
|
+
const v = parseInt(ipaddr.slice(4), 10);
|
|
3040
|
+
return v >= 16 && v <= 31;
|
|
3041
|
+
}
|
|
3042
|
+
return ipaddr.startsWith('192.168.');
|
|
3043
|
+
}
|
|
3044
|
+
// ipv6
|
|
3045
|
+
if ( c0 === 0x3A /* : */ ) {
|
|
3046
|
+
if ( ipaddr.startsWith('::') === false ) { return false; }
|
|
3047
|
+
if ( ipaddr === '::' || ipaddr === '::1' ) { return true; }
|
|
3048
|
+
if ( ipaddr.startsWith('::ffff:') === false ) { return false; }
|
|
3049
|
+
return this.reIPv6IPv4lan.test(ipaddr);
|
|
3050
|
+
}
|
|
3051
|
+
if ( c0 === 0x36 /* 6 */ ) {
|
|
3052
|
+
return ipaddr.startsWith('64:ff9b:');
|
|
3053
|
+
}
|
|
3054
|
+
if ( c0 === 0x66 /* f */ ) {
|
|
3055
|
+
return this.reIPv6local.test(ipaddr);
|
|
3056
|
+
}
|
|
3057
|
+
return false;
|
|
3058
|
+
}
|
|
3059
|
+
|
|
3060
|
+
static isLoopback(ipaddr) {
|
|
3061
|
+
return ipaddr === '127.0.0.1' || ipaddr === '::1';
|
|
3062
|
+
}
|
|
3063
|
+
|
|
3064
|
+
static compile(details) {
|
|
3065
|
+
return [ FilterIPAddress.fid, details.optionValues.get('ipaddress') ];
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
static fromCompiled(args) {
|
|
3069
|
+
const pattern = args[1];
|
|
3070
|
+
const details = { pattern };
|
|
3071
|
+
return filterDataAlloc(args[0], filterRefAdd(details));
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
static dnrFromCompiled(args, rule) {
|
|
3075
|
+
dnrAddRuleError(rule, `"ipaddress=${args[1]}" not supported`);
|
|
3076
|
+
}
|
|
3077
|
+
|
|
3078
|
+
static logData(idata, details) {
|
|
3079
|
+
const irefs = filterData[idata+1];
|
|
3080
|
+
details.options.push(`ipaddress=${LogData.requote(filterRefs[irefs].pattern)}`);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
|
|
3084
|
+
registerFilterClass(FilterIPAddress);
|
|
3085
|
+
|
|
2971
3086
|
/******************************************************************************/
|
|
2972
3087
|
/******************************************************************************/
|
|
2973
3088
|
|
|
@@ -3151,8 +3266,7 @@ class FilterCompiler {
|
|
|
3151
3266
|
return Object.assign(this, other);
|
|
3152
3267
|
}
|
|
3153
3268
|
this.reToken = /[%0-9A-Za-z]+/g;
|
|
3154
|
-
this.
|
|
3155
|
-
this.toDomainOptList = [];
|
|
3269
|
+
this.optionValues = new Map();
|
|
3156
3270
|
this.tokenIdToNormalizedType = new Map([
|
|
3157
3271
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_CNAME, bitFromType('cname') ],
|
|
3158
3272
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_CSS, bitFromType('stylesheet') ],
|
|
@@ -3184,6 +3298,7 @@ class FilterCompiler {
|
|
|
3184
3298
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM, MODIFIER_TYPE_REMOVEPARAM ],
|
|
3185
3299
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM, MODIFIER_TYPE_URLTRANSFORM ],
|
|
3186
3300
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_REPLACE, MODIFIER_TYPE_REPLACE ],
|
|
3301
|
+
[ sfp.NODE_TYPE_NET_OPTION_NAME_URLSKIP, MODIFIER_TYPE_URLSKIP ],
|
|
3187
3302
|
]);
|
|
3188
3303
|
// These top 100 "bad tokens" are collated using the "miss" histogram
|
|
3189
3304
|
// from tokenHistograms(). The "score" is their occurrence among the
|
|
@@ -3309,13 +3424,9 @@ class FilterCompiler {
|
|
|
3309
3424
|
this.modifyType = undefined;
|
|
3310
3425
|
this.modifyValue = undefined;
|
|
3311
3426
|
this.pattern = '';
|
|
3312
|
-
this.patternMatchCase = false;
|
|
3313
3427
|
this.party = ANYPARTY_REALM;
|
|
3314
3428
|
this.optionUnitBits = 0;
|
|
3315
|
-
this.
|
|
3316
|
-
this.toDomainOpt = '';
|
|
3317
|
-
this.denyallowOpt = '';
|
|
3318
|
-
this.headerOpt = undefined;
|
|
3429
|
+
this.optionValues.clear();
|
|
3319
3430
|
this.isPureHostname = false;
|
|
3320
3431
|
this.isGeneric = false;
|
|
3321
3432
|
this.isRegex = false;
|
|
@@ -3327,8 +3438,6 @@ class FilterCompiler {
|
|
|
3327
3438
|
this.notTypeBits = 0;
|
|
3328
3439
|
this.methodBits = 0;
|
|
3329
3440
|
this.notMethodBits = 0;
|
|
3330
|
-
this.wildcardPos = -1;
|
|
3331
|
-
this.caretPos = -1;
|
|
3332
3441
|
return this;
|
|
3333
3442
|
}
|
|
3334
3443
|
|
|
@@ -3423,63 +3532,74 @@ class FilterCompiler {
|
|
|
3423
3532
|
|
|
3424
3533
|
processOptionWithValue(parser, id) {
|
|
3425
3534
|
switch ( id ) {
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3535
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
|
|
3536
|
+
if ( this.processCspOption(parser.getNetOptionValue(id)) === false ) { return false; }
|
|
3537
|
+
break;
|
|
3538
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW: {
|
|
3539
|
+
const value = this.processHostnameList(
|
|
3540
|
+
parser.getNetFilterDenyallowOptionIterator()
|
|
3541
|
+
);
|
|
3542
|
+
if ( value === '' ) { return false; }
|
|
3543
|
+
this.optionValues.set('denyallow', value);
|
|
3544
|
+
this.optionUnitBits |= DENYALLOW_BIT;
|
|
3545
|
+
break;
|
|
3546
|
+
}
|
|
3547
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM: {
|
|
3548
|
+
const iter = parser.getNetFilterFromOptionIterator();
|
|
3549
|
+
const list = [];
|
|
3550
|
+
const value = this.processHostnameList(iter, list);
|
|
3551
|
+
if ( value === '' ) { return false; }
|
|
3552
|
+
this.optionValues.set('from', value);
|
|
3553
|
+
this.optionValues.set('fromList', list);
|
|
3554
|
+
this.optionUnitBits |= FROM_BIT;
|
|
3555
|
+
break;
|
|
3556
|
+
}
|
|
3557
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER: {
|
|
3558
|
+
this.optionValues.set('header', parser.getNetOptionValue(id) || '');
|
|
3559
|
+
this.optionUnitBits |= HEADER_BIT;
|
|
3560
|
+
break;
|
|
3561
|
+
}
|
|
3562
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
|
|
3563
|
+
this.optionValues.set('ipaddress', parser.getNetOptionValue(id) || '');
|
|
3564
|
+
this.optionUnitBits |= IPADDRESS_BIT;
|
|
3565
|
+
break;
|
|
3566
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
|
3567
|
+
this.processMethodOption(parser.getNetOptionValue(id));
|
|
3568
|
+
this.optionUnitBits |= METHOD_BIT;
|
|
3569
|
+
break;
|
|
3570
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
|
3571
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
|
|
3572
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
|
|
3573
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_REPLACE:
|
|
3574
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_URLSKIP:
|
|
3575
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
|
|
3576
|
+
if ( this.processModifierOption(id, parser.getNetOptionValue(id)) === false ) {
|
|
3577
|
+
return false;
|
|
3448
3578
|
}
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
|
|
3458
|
-
if ( this.processModifierOption(id, parser.getNetOptionValue(id)) === false ) {
|
|
3459
|
-
return false;
|
|
3460
|
-
}
|
|
3461
|
-
this.optionUnitBits |= MODIFY_BIT;
|
|
3462
|
-
break;
|
|
3463
|
-
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: {
|
|
3464
|
-
const actualId = this.action === ALLOW_REALM
|
|
3465
|
-
? sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE
|
|
3466
|
-
: id;
|
|
3467
|
-
if ( this.processModifierOption(actualId, parser.getNetOptionValue(id)) === false ) {
|
|
3468
|
-
return false;
|
|
3469
|
-
}
|
|
3470
|
-
this.optionUnitBits |= MODIFY_BIT;
|
|
3471
|
-
break;
|
|
3579
|
+
this.optionUnitBits |= MODIFY_BIT;
|
|
3580
|
+
break;
|
|
3581
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: {
|
|
3582
|
+
const actualId = this.action === ALLOW_REALM
|
|
3583
|
+
? sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE
|
|
3584
|
+
: id;
|
|
3585
|
+
if ( this.processModifierOption(actualId, parser.getNetOptionValue(id)) === false ) {
|
|
3586
|
+
return false;
|
|
3472
3587
|
}
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3588
|
+
this.optionUnitBits |= MODIFY_BIT;
|
|
3589
|
+
break;
|
|
3590
|
+
}
|
|
3591
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_TO: {
|
|
3592
|
+
const iter = parser.getNetFilterToOptionIterator();
|
|
3593
|
+
const list = [];
|
|
3594
|
+
const value = this.processHostnameList(iter, list);
|
|
3595
|
+
if ( value === '' ) { return false; }
|
|
3596
|
+
this.optionValues.set('to', value);
|
|
3597
|
+
this.optionValues.set('toList', list);
|
|
3598
|
+
this.optionUnitBits |= TO_BIT;
|
|
3599
|
+
break;
|
|
3600
|
+
}
|
|
3601
|
+
default:
|
|
3602
|
+
break;
|
|
3483
3603
|
}
|
|
3484
3604
|
return true;
|
|
3485
3605
|
}
|
|
@@ -3563,6 +3683,7 @@ class FilterCompiler {
|
|
|
3563
3683
|
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
|
|
3564
3684
|
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
|
3565
3685
|
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
|
|
3686
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
|
|
3566
3687
|
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
|
3567
3688
|
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
|
3568
3689
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
|
@@ -3570,6 +3691,7 @@ class FilterCompiler {
|
|
|
3570
3691
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
|
|
3571
3692
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REPLACE:
|
|
3572
3693
|
case sfp.NODE_TYPE_NET_OPTION_NAME_TO:
|
|
3694
|
+
case sfp.NODE_TYPE_NET_OPTION_NAME_URLSKIP:
|
|
3573
3695
|
case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
|
|
3574
3696
|
if ( this.processOptionWithValue(parser, type) === false ) {
|
|
3575
3697
|
return this.FILTER_INVALID;
|
|
@@ -3596,7 +3718,7 @@ class FilterCompiler {
|
|
|
3596
3718
|
this.action = BLOCKIMPORTANT_REALM;
|
|
3597
3719
|
break;
|
|
3598
3720
|
case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
|
3599
|
-
this.
|
|
3721
|
+
this.optionValues.set('match-case', true);
|
|
3600
3722
|
break;
|
|
3601
3723
|
case sfp.NODE_TYPE_NET_OPTION_NAME_MP4: {
|
|
3602
3724
|
const id = this.action === ALLOW_REALM
|
|
@@ -3666,11 +3788,6 @@ class FilterCompiler {
|
|
|
3666
3788
|
return this.FILTER_OK;
|
|
3667
3789
|
}
|
|
3668
3790
|
|
|
3669
|
-
if ( this.isGeneric ) {
|
|
3670
|
-
this.wildcardPos = this.pattern.indexOf('*');
|
|
3671
|
-
this.caretPos = this.pattern.indexOf('^');
|
|
3672
|
-
}
|
|
3673
|
-
|
|
3674
3791
|
if ( this.pattern.length > 1024 ) {
|
|
3675
3792
|
return this.FILTER_UNSUPPORTED;
|
|
3676
3793
|
}
|
|
@@ -3798,7 +3915,7 @@ class FilterCompiler {
|
|
|
3798
3915
|
isJustOrigin() {
|
|
3799
3916
|
if ( this.optionUnitBits !== FROM_BIT ) { return false; }
|
|
3800
3917
|
if ( this.isRegex ) { return false; }
|
|
3801
|
-
if ( /[
|
|
3918
|
+
if ( /[/~]/.test(this.optionValues.get('from')) ) { return false; }
|
|
3802
3919
|
if ( this.pattern === '*' ) { return true; }
|
|
3803
3920
|
if ( this.anchor !== 0b010 ) { return false; }
|
|
3804
3921
|
if ( /^(?:http[s*]?:(?:\/\/)?)$/.test(this.pattern) ) { return true; }
|
|
@@ -3875,7 +3992,7 @@ class FilterCompiler {
|
|
|
3875
3992
|
} else /* 'http:' */ {
|
|
3876
3993
|
this.tokenHash = ANY_HTTP_TOKEN_HASH;
|
|
3877
3994
|
}
|
|
3878
|
-
for ( const hn of this.
|
|
3995
|
+
for ( const hn of this.optionValues.get('fromList') ) {
|
|
3879
3996
|
this.compileToAtomicFilter(hn, writer);
|
|
3880
3997
|
}
|
|
3881
3998
|
return;
|
|
@@ -3916,30 +4033,35 @@ class FilterCompiler {
|
|
|
3916
4033
|
}
|
|
3917
4034
|
|
|
3918
4035
|
// Origin
|
|
3919
|
-
if ( this.
|
|
4036
|
+
if ( (this.optionUnitBits & FROM_BIT) !== 0 ) {
|
|
3920
4037
|
compileFromDomainOpt(
|
|
3921
|
-
this.
|
|
4038
|
+
this.optionValues.get('fromList'),
|
|
3922
4039
|
units.length !== 0 && patternClass.isSlow === true,
|
|
3923
4040
|
units
|
|
3924
4041
|
);
|
|
3925
4042
|
}
|
|
3926
4043
|
|
|
3927
4044
|
// Destination
|
|
3928
|
-
if ( this.
|
|
4045
|
+
if ( (this.optionUnitBits & TO_BIT) !== 0 ) {
|
|
3929
4046
|
compileToDomainOpt(
|
|
3930
|
-
this.
|
|
4047
|
+
this.optionValues.get('toList'),
|
|
3931
4048
|
units.length !== 0 && patternClass.isSlow === true,
|
|
3932
4049
|
units
|
|
3933
4050
|
);
|
|
3934
4051
|
}
|
|
3935
4052
|
|
|
3936
4053
|
// Deny-allow
|
|
3937
|
-
if ( this.
|
|
4054
|
+
if ( (this.optionUnitBits & DENYALLOW_BIT) !== 0 ) {
|
|
3938
4055
|
units.push(FilterDenyAllow.compile(this));
|
|
3939
4056
|
}
|
|
3940
4057
|
|
|
4058
|
+
// IP address
|
|
4059
|
+
if ( (this.optionUnitBits & IPADDRESS_BIT) !== 0 ) {
|
|
4060
|
+
units.push(FilterIPAddress.compile(this));
|
|
4061
|
+
}
|
|
4062
|
+
|
|
3941
4063
|
// Header
|
|
3942
|
-
if ( this.
|
|
4064
|
+
if ( (this.optionUnitBits & HEADER_BIT) !== 0 ) {
|
|
3943
4065
|
units.push(FilterOnHeaders.compile(this));
|
|
3944
4066
|
this.action |= HEADERS_REALM;
|
|
3945
4067
|
}
|
|
@@ -3957,16 +4079,21 @@ class FilterCompiler {
|
|
|
3957
4079
|
// IMPORTANT: the modifier unit MUST always appear first in a sequence
|
|
3958
4080
|
if ( this.modifyType !== undefined ) {
|
|
3959
4081
|
units.unshift(FilterModifier.compile(this));
|
|
3960
|
-
this.action = (this.action & ~
|
|
4082
|
+
this.action = (this.action & ~BLOCKALLOW_REALM) |
|
|
3961
4083
|
modifierBitsFromType.get(this.modifyType);
|
|
3962
4084
|
}
|
|
3963
4085
|
|
|
3964
|
-
|
|
3965
|
-
units
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4086
|
+
const fdata = units.length === 1
|
|
4087
|
+
? units[0]
|
|
4088
|
+
: FilterCompositeAll.compile(units);
|
|
4089
|
+
|
|
4090
|
+
this.compileToAtomicFilter(fdata, writer);
|
|
4091
|
+
|
|
4092
|
+
if ( (this.optionUnitBits & IPADDRESS_BIT) !== 0 ) {
|
|
4093
|
+
if ( (this.action & HEADERS_REALM) !== 0 ) { return; }
|
|
4094
|
+
this.action |= HEADERS_REALM;
|
|
4095
|
+
this.compileToAtomicFilter(fdata, writer);
|
|
4096
|
+
}
|
|
3970
4097
|
}
|
|
3971
4098
|
|
|
3972
4099
|
compilePattern(units) {
|
|
@@ -3982,12 +4109,13 @@ class FilterCompiler {
|
|
|
3982
4109
|
units.push(FilterPatternGeneric.compile(this));
|
|
3983
4110
|
return FilterPatternGeneric;
|
|
3984
4111
|
}
|
|
3985
|
-
if ( this.
|
|
3986
|
-
|
|
4112
|
+
if ( this.pattern.includes('*') === false ) {
|
|
4113
|
+
const caretPos = this.pattern.indexOf('^');
|
|
4114
|
+
if ( caretPos === -1 ) {
|
|
3987
4115
|
units.push(FilterPatternPlain.compile(this));
|
|
3988
4116
|
return FilterPatternPlain;
|
|
3989
4117
|
}
|
|
3990
|
-
if (
|
|
4118
|
+
if ( caretPos === (this.pattern.length - 1) ) {
|
|
3991
4119
|
this.pattern = this.pattern.slice(0, -1);
|
|
3992
4120
|
units.push(FilterPatternPlain.compile(this));
|
|
3993
4121
|
units.push(FilterTrailingSeparator.compile());
|
|
@@ -4020,7 +4148,7 @@ class FilterCompiler {
|
|
|
4020
4148
|
do {
|
|
4021
4149
|
if ( typeBits & 1 ) {
|
|
4022
4150
|
writer.push([
|
|
4023
|
-
catBits | (bitOffset <<
|
|
4151
|
+
catBits | (bitOffset << TYPE_REALM_OFFSET),
|
|
4024
4152
|
this.tokenHash,
|
|
4025
4153
|
fdata
|
|
4026
4154
|
]);
|
|
@@ -4032,15 +4160,16 @@ class FilterCompiler {
|
|
|
4032
4160
|
}
|
|
4033
4161
|
|
|
4034
4162
|
// These are to quickly test whether a filter is composite
|
|
4035
|
-
const FROM_BIT =
|
|
4036
|
-
const TO_BIT =
|
|
4037
|
-
const DENYALLOW_BIT =
|
|
4038
|
-
const HEADER_BIT =
|
|
4039
|
-
const STRICT_PARTY_BIT =
|
|
4040
|
-
const MODIFY_BIT =
|
|
4041
|
-
const NOT_TYPE_BIT =
|
|
4042
|
-
const IMPORTANT_BIT =
|
|
4043
|
-
const METHOD_BIT =
|
|
4163
|
+
const FROM_BIT = 0b0000000001;
|
|
4164
|
+
const TO_BIT = 0b0000000010;
|
|
4165
|
+
const DENYALLOW_BIT = 0b0000000100;
|
|
4166
|
+
const HEADER_BIT = 0b0000001000;
|
|
4167
|
+
const STRICT_PARTY_BIT = 0b0000010000;
|
|
4168
|
+
const MODIFY_BIT = 0b0000100000;
|
|
4169
|
+
const NOT_TYPE_BIT = 0b0001000000;
|
|
4170
|
+
const IMPORTANT_BIT = 0b0010000000;
|
|
4171
|
+
const METHOD_BIT = 0b0100000000;
|
|
4172
|
+
const IPADDRESS_BIT = 0b1000000000;
|
|
4044
4173
|
|
|
4045
4174
|
FilterCompiler.prototype.FILTER_OK = 0;
|
|
4046
4175
|
FilterCompiler.prototype.FILTER_INVALID = 1;
|
|
@@ -4182,7 +4311,7 @@ StaticNetFilteringEngine.prototype.freeze = function() {
|
|
|
4182
4311
|
// the block-important realm should be checked when and only when
|
|
4183
4312
|
// there is a matched exception filter, which important filters are
|
|
4184
4313
|
// meant to override.
|
|
4185
|
-
if ( (bits &
|
|
4314
|
+
if ( (bits & BLOCKALLOW_REALM) === BLOCKIMPORTANT_REALM ) {
|
|
4186
4315
|
this.addFilterUnit(
|
|
4187
4316
|
bits & ~IMPORTANT_REALM,
|
|
4188
4317
|
tokenHash,
|
|
@@ -4325,14 +4454,24 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4325
4454
|
}
|
|
4326
4455
|
}
|
|
4327
4456
|
|
|
4457
|
+
// Priority:
|
|
4458
|
+
// Block: 1 (default priority)
|
|
4459
|
+
// Redirect: 2-9
|
|
4460
|
+
// Excepted redirect: 12-19
|
|
4461
|
+
// Allow: 20
|
|
4462
|
+
// Block important: 30
|
|
4463
|
+
// Redirect important: 32-39
|
|
4464
|
+
|
|
4328
4465
|
const realms = new Map([
|
|
4329
|
-
[ BLOCK_REALM, 'block' ],
|
|
4330
|
-
[ ALLOW_REALM, 'allow' ],
|
|
4331
|
-
[ REDIRECT_REALM, 'redirect' ],
|
|
4332
|
-
[ REMOVEPARAM_REALM, 'removeparam' ],
|
|
4333
|
-
[ CSP_REALM, 'csp' ],
|
|
4334
|
-
[ PERMISSIONS_REALM, 'permissions' ],
|
|
4335
|
-
[ URLTRANSFORM_REALM, 'uritransform' ],
|
|
4466
|
+
[ BLOCK_REALM, { type: 'block', priority: 0 } ],
|
|
4467
|
+
[ ALLOW_REALM, { type: 'allow', priority: 20 } ],
|
|
4468
|
+
[ REDIRECT_REALM, { type: 'redirect', priority: 2 } ],
|
|
4469
|
+
[ REMOVEPARAM_REALM, { type: 'removeparam', priority: 0 } ],
|
|
4470
|
+
[ CSP_REALM, { type: 'csp', priority: 0 } ],
|
|
4471
|
+
[ PERMISSIONS_REALM, { type: 'permissions', priority: 0 } ],
|
|
4472
|
+
[ URLTRANSFORM_REALM, { type: 'uritransform', priority: 0 } ],
|
|
4473
|
+
[ HEADERS_REALM, { type: 'block', priority: 0 } ],
|
|
4474
|
+
[ URLSKIP_REALM, { type: 'urlskip', priority: 0 } ],
|
|
4336
4475
|
]);
|
|
4337
4476
|
const partyness = new Map([
|
|
4338
4477
|
[ ANYPARTY_REALM, '' ],
|
|
@@ -4355,7 +4494,7 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4355
4494
|
'other',
|
|
4356
4495
|
]);
|
|
4357
4496
|
const ruleset = [];
|
|
4358
|
-
for ( const [ realmBits,
|
|
4497
|
+
for ( const [ realmBits, realmDetails ] of realms ) {
|
|
4359
4498
|
for ( const [ partyBits, partyName ] of partyness ) {
|
|
4360
4499
|
for ( const typeName in typeNameToTypeValue ) {
|
|
4361
4500
|
if ( types.has(typeName) === false ) { continue; }
|
|
@@ -4366,7 +4505,10 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4366
4505
|
for ( const rules of bucket.values() ) {
|
|
4367
4506
|
for ( const rule of rules ) {
|
|
4368
4507
|
rule.action = rule.action || {};
|
|
4369
|
-
rule.action.type =
|
|
4508
|
+
rule.action.type = realmDetails.type;
|
|
4509
|
+
if ( realmDetails.priority !== 0 ) {
|
|
4510
|
+
rule.priority = (rule.priority || 0) + realmDetails.priority;
|
|
4511
|
+
}
|
|
4370
4512
|
if ( partyName !== '' ) {
|
|
4371
4513
|
rule.condition = rule.condition || {};
|
|
4372
4514
|
rule.condition.domainType = partyName;
|
|
@@ -4462,12 +4604,11 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4462
4604
|
}
|
|
4463
4605
|
break;
|
|
4464
4606
|
case 'redirect-rule': {
|
|
4465
|
-
let priority = rule.priority || 1;
|
|
4466
4607
|
let token = rule.__modifierValue;
|
|
4467
4608
|
if ( token !== '' ) {
|
|
4468
4609
|
const match = /:(\d+)$/.exec(token);
|
|
4469
4610
|
if ( match !== null ) {
|
|
4470
|
-
priority
|
|
4611
|
+
rule.priority = Math.min(rule.priority + parseInt(match[1], 10), 9);
|
|
4471
4612
|
token = token.slice(0, match.index);
|
|
4472
4613
|
}
|
|
4473
4614
|
}
|
|
@@ -4479,10 +4620,9 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4479
4620
|
const extensionPath = resource || token;
|
|
4480
4621
|
rule.action.type = 'redirect';
|
|
4481
4622
|
rule.action.redirect = { extensionPath };
|
|
4482
|
-
rule.priority = priority + 1;
|
|
4483
4623
|
} else {
|
|
4484
4624
|
rule.action.type = 'block';
|
|
4485
|
-
rule.priority
|
|
4625
|
+
rule.priority += 10;
|
|
4486
4626
|
}
|
|
4487
4627
|
break;
|
|
4488
4628
|
}
|
|
@@ -4746,7 +4886,8 @@ StaticNetFilteringEngine.prototype.matchAndFetchModifiers = function(
|
|
|
4746
4886
|
$docDomain = fctxt.getDocDomain();
|
|
4747
4887
|
$requestHostname = fctxt.getHostname();
|
|
4748
4888
|
$requestMethodBit = fctxt.method || 0;
|
|
4749
|
-
$requestTypeValue = (typeBits &
|
|
4889
|
+
$requestTypeValue = (typeBits & TYPE_REALM) >>> TYPE_REALM_OFFSET;
|
|
4890
|
+
$requestAddress = fctxt.getIPAddress();
|
|
4750
4891
|
|
|
4751
4892
|
const modifierType = modifierTypeFromName.get(modifierName);
|
|
4752
4893
|
const modifierBits = modifierBitsFromType.get(modifierType);
|
|
@@ -4840,7 +4981,7 @@ StaticNetFilteringEngine.prototype.matchAndFetchModifiers = function(
|
|
|
4840
4981
|
const toRemove = new Map();
|
|
4841
4982
|
|
|
4842
4983
|
for ( const result of results ) {
|
|
4843
|
-
const actionBits = result.bits &
|
|
4984
|
+
const actionBits = result.bits & BLOCKALLOW_REALM;
|
|
4844
4985
|
const modifyValue = result.value;
|
|
4845
4986
|
if ( actionBits === BLOCKIMPORTANT_REALM ) {
|
|
4846
4987
|
toAddImportant.set(modifyValue, result);
|
|
@@ -5043,7 +5184,8 @@ StaticNetFilteringEngine.prototype.matchRequestReverse = function(type, url) {
|
|
|
5043
5184
|
$requestURL = urlTokenizer.setURL(url);
|
|
5044
5185
|
$requestURLRaw = url;
|
|
5045
5186
|
$requestMethodBit = 0;
|
|
5046
|
-
$requestTypeValue = (typeBits &
|
|
5187
|
+
$requestTypeValue = (typeBits & TYPE_REALM) >>> TYPE_REALM_OFFSET;
|
|
5188
|
+
$requestAddress = '';
|
|
5047
5189
|
$isBlockImportant = false;
|
|
5048
5190
|
this.$filterUnit = 0;
|
|
5049
5191
|
|
|
@@ -5111,7 +5253,8 @@ StaticNetFilteringEngine.prototype.matchRequest = function(fctxt, modifiers = 0)
|
|
|
5111
5253
|
$docDomain = fctxt.getDocDomain();
|
|
5112
5254
|
$requestHostname = fctxt.getHostname();
|
|
5113
5255
|
$requestMethodBit = fctxt.method || 0;
|
|
5114
|
-
$requestTypeValue = (typeBits &
|
|
5256
|
+
$requestTypeValue = (typeBits & TYPE_REALM) >>> TYPE_REALM_OFFSET;
|
|
5257
|
+
$requestAddress = fctxt.getIPAddress();
|
|
5115
5258
|
$isBlockImportant = false;
|
|
5116
5259
|
|
|
5117
5260
|
// Evaluate block realm before allow realm, and allow realm before
|
|
@@ -5146,7 +5289,8 @@ StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, headers) {
|
|
|
5146
5289
|
$docDomain = fctxt.getDocDomain();
|
|
5147
5290
|
$requestHostname = fctxt.getHostname();
|
|
5148
5291
|
$requestMethodBit = fctxt.method || 0;
|
|
5149
|
-
$requestTypeValue = (typeBits &
|
|
5292
|
+
$requestTypeValue = (typeBits & TYPE_REALM) >>> TYPE_REALM_OFFSET;
|
|
5293
|
+
$requestAddress = fctxt.getIPAddress();
|
|
5150
5294
|
$httpHeaders.init(headers);
|
|
5151
5295
|
|
|
5152
5296
|
let r = 0;
|
|
@@ -5156,6 +5300,10 @@ StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, headers) {
|
|
|
5156
5300
|
if ( r !== 0 && $isBlockImportant !== true ) {
|
|
5157
5301
|
if ( this.realmMatchString(HEADERS_REALM | ALLOW_REALM, typeBits, partyBits) ) {
|
|
5158
5302
|
r = 2;
|
|
5303
|
+
} else if ( this.realmMatchString(ALLOW_REALM, typeBits, partyBits) ) {
|
|
5304
|
+
r = 2;
|
|
5305
|
+
}
|
|
5306
|
+
if ( r === 2 ) {
|
|
5159
5307
|
if ( this.realmMatchString(HEADERS_REALM | BLOCKIMPORTANT_REALM, typeBits, partyBits) ) {
|
|
5160
5308
|
r = 1;
|
|
5161
5309
|
}
|
|
@@ -5187,11 +5335,35 @@ StaticNetFilteringEngine.prototype.redirectRequest = function(redirectEngine, fc
|
|
|
5187
5335
|
return directives;
|
|
5188
5336
|
};
|
|
5189
5337
|
|
|
5190
|
-
|
|
5338
|
+
function parseRedirectRequestValue(directive) {
|
|
5339
|
+
if ( directive.cache === null ) {
|
|
5340
|
+
directive.cache = sfp.parseRedirectValue(directive.value);
|
|
5341
|
+
}
|
|
5342
|
+
return directive.cache;
|
|
5343
|
+
}
|
|
5344
|
+
|
|
5345
|
+
function compareRedirectRequests(redirectEngine, a, b) {
|
|
5346
|
+
const { token: atok, priority: aint, bits: abits } =
|
|
5347
|
+
parseRedirectRequestValue(a);
|
|
5348
|
+
if ( redirectEngine.hasToken(atok) === false ) { return -1; }
|
|
5349
|
+
const { token: btok, priority: bint, bits: bbits } =
|
|
5350
|
+
parseRedirectRequestValue(b);
|
|
5351
|
+
if ( redirectEngine.hasToken(btok) === false ) { return 1; }
|
|
5352
|
+
if ( abits !== bbits ) {
|
|
5353
|
+
if ( (abits & IMPORTANT_REALM) !== 0 ) { return 1; }
|
|
5354
|
+
if ( (bbits & IMPORTANT_REALM) !== 0 ) { return -1; }
|
|
5355
|
+
if ( (abits & ALLOW_REALM) !== 0 ) { return -1; }
|
|
5356
|
+
if ( (bbits & ALLOW_REALM) !== 0 ) { return 1; }
|
|
5357
|
+
}
|
|
5358
|
+
return aint - bint;
|
|
5359
|
+
}
|
|
5360
|
+
|
|
5361
|
+
/******************************************************************************/
|
|
5362
|
+
|
|
5363
|
+
StaticNetFilteringEngine.prototype.transformRequest = function(fctxt, out = []) {
|
|
5191
5364
|
const directives = this.matchAndFetchModifiers(fctxt, 'uritransform');
|
|
5192
5365
|
if ( directives === undefined ) { return; }
|
|
5193
5366
|
const redirectURL = new URL(fctxt.url);
|
|
5194
|
-
const out = [];
|
|
5195
5367
|
for ( const directive of directives ) {
|
|
5196
5368
|
if ( (directive.bits & ALLOW_REALM) !== 0 ) {
|
|
5197
5369
|
out.push(directive);
|
|
@@ -5223,27 +5395,59 @@ StaticNetFilteringEngine.prototype.transformRequest = function(fctxt) {
|
|
|
5223
5395
|
return out;
|
|
5224
5396
|
};
|
|
5225
5397
|
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5398
|
+
/******************************************************************************/
|
|
5399
|
+
|
|
5400
|
+
StaticNetFilteringEngine.prototype.urlSkip = function(fctxt, out = []) {
|
|
5401
|
+
if ( fctxt.redirectURL !== undefined ) { return; }
|
|
5402
|
+
const directives = this.matchAndFetchModifiers(fctxt, 'urlskip');
|
|
5403
|
+
if ( directives === undefined ) { return; }
|
|
5404
|
+
for ( const directive of directives ) {
|
|
5405
|
+
if ( (directive.bits & ALLOW_REALM) !== 0 ) {
|
|
5406
|
+
out.push(directive);
|
|
5407
|
+
continue;
|
|
5408
|
+
}
|
|
5409
|
+
const urlin = fctxt.url;
|
|
5410
|
+
const value = directive.value;
|
|
5411
|
+
const steps = value.includes(' ') && value.split(/ +/) || [ value ];
|
|
5412
|
+
const urlout = urlSkip(urlin, steps);
|
|
5413
|
+
if ( urlout === undefined ) { continue; }
|
|
5414
|
+
if ( urlout === urlin ) { continue; }
|
|
5415
|
+
fctxt.redirectURL = urlout;
|
|
5416
|
+
out.push(directive);
|
|
5417
|
+
break;
|
|
5229
5418
|
}
|
|
5230
|
-
|
|
5231
|
-
|
|
5419
|
+
if ( out.length === 0 ) { return; }
|
|
5420
|
+
return out;
|
|
5421
|
+
};
|
|
5232
5422
|
|
|
5233
|
-
function
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5423
|
+
function urlSkip(urlin, steps) {
|
|
5424
|
+
try {
|
|
5425
|
+
let urlout;
|
|
5426
|
+
for ( const step of steps ) {
|
|
5427
|
+
// Extract from URL parameter
|
|
5428
|
+
if ( step.startsWith('?') ) {
|
|
5429
|
+
urlout = (new URL(urlin)).searchParams.get(step.slice(1));
|
|
5430
|
+
if ( urlout === null ) { return; }
|
|
5431
|
+
if ( urlout.includes(' ') ) {
|
|
5432
|
+
urlout = urlout.replace(/ /g, '%20');
|
|
5433
|
+
}
|
|
5434
|
+
urlin = urlout;
|
|
5435
|
+
continue;
|
|
5436
|
+
}
|
|
5437
|
+
// Enforce https
|
|
5438
|
+
if ( step === '+https' ) {
|
|
5439
|
+
const s = urlin.replace(/^https?:\/\//, '');
|
|
5440
|
+
if ( /^[\w-]:\/\//.test(s) ) { return; }
|
|
5441
|
+
urlin = urlout = `https://${s}`;
|
|
5442
|
+
continue;
|
|
5443
|
+
}
|
|
5444
|
+
// Unknown directive
|
|
5445
|
+
return;
|
|
5446
|
+
}
|
|
5447
|
+
void new URL(urlout);
|
|
5448
|
+
return urlout;
|
|
5449
|
+
} catch(x) {
|
|
5245
5450
|
}
|
|
5246
|
-
return aint - bint;
|
|
5247
5451
|
}
|
|
5248
5452
|
|
|
5249
5453
|
/******************************************************************************/
|
|
@@ -5251,7 +5455,8 @@ function compareRedirectRequests(redirectEngine, a, b) {
|
|
|
5251
5455
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1626
|
|
5252
5456
|
// Do not redirect when the number of query parameters does not change.
|
|
5253
5457
|
|
|
5254
|
-
StaticNetFilteringEngine.prototype.filterQuery = function(fctxt) {
|
|
5458
|
+
StaticNetFilteringEngine.prototype.filterQuery = function(fctxt, out = []) {
|
|
5459
|
+
if ( fctxt.redirectURL !== undefined ) { return; }
|
|
5255
5460
|
const directives = this.matchAndFetchModifiers(fctxt, 'removeparam');
|
|
5256
5461
|
if ( directives === undefined ) { return; }
|
|
5257
5462
|
const url = fctxt.url;
|
|
@@ -5274,7 +5479,6 @@ StaticNetFilteringEngine.prototype.filterQuery = function(fctxt) {
|
|
|
5274
5479
|
}
|
|
5275
5480
|
}
|
|
5276
5481
|
const inParamCount = params.size;
|
|
5277
|
-
const out = [];
|
|
5278
5482
|
for ( const directive of directives ) {
|
|
5279
5483
|
if ( params.size === 0 ) { break; }
|
|
5280
5484
|
const isException = (directive.bits & ALLOW_REALM) !== 0;
|
|
@@ -5384,17 +5588,76 @@ StaticNetFilteringEngine.prototype.enableWASM = function(wasmModuleFetcher, path
|
|
|
5384
5588
|
|
|
5385
5589
|
/******************************************************************************/
|
|
5386
5590
|
|
|
5387
|
-
StaticNetFilteringEngine.prototype.test =
|
|
5591
|
+
StaticNetFilteringEngine.prototype.test = function(details) {
|
|
5592
|
+
const { url, type, from, redirectEngine } = details;
|
|
5593
|
+
if ( url === undefined ) { return; }
|
|
5388
5594
|
const fctxt = new FilteringContext();
|
|
5389
|
-
fctxt.setDocOriginFromURL(docURL);
|
|
5390
|
-
fctxt.setType(type);
|
|
5391
5595
|
fctxt.setURL(url);
|
|
5596
|
+
fctxt.setType(type || '');
|
|
5597
|
+
fctxt.setDocOriginFromURL(from || '');
|
|
5392
5598
|
const r = this.matchRequest(fctxt);
|
|
5393
|
-
|
|
5599
|
+
const out = [ `url: ${url}` ];
|
|
5600
|
+
if ( type ) {
|
|
5601
|
+
out.push(`type: ${type}`);
|
|
5602
|
+
}
|
|
5603
|
+
if ( from ) {
|
|
5604
|
+
out.push(`context: ${from}`);
|
|
5605
|
+
}
|
|
5394
5606
|
if ( r !== 0 ) {
|
|
5395
|
-
|
|
5607
|
+
const logdata = this.toLogData();
|
|
5608
|
+
if ( r === 1 ) {
|
|
5609
|
+
out.push(`blocked: ${logdata.raw}`);
|
|
5610
|
+
} else if ( r === 2 ) {
|
|
5611
|
+
out.push(`unblocked: ${logdata.raw}`);
|
|
5612
|
+
}
|
|
5613
|
+
} else {
|
|
5614
|
+
out.push('not blocked');
|
|
5396
5615
|
}
|
|
5397
|
-
|
|
5616
|
+
if ( r !== 1 ) {
|
|
5617
|
+
const entries = this.transformRequest(fctxt);
|
|
5618
|
+
if ( entries ) {
|
|
5619
|
+
for ( const entry of entries ) {
|
|
5620
|
+
out.push(`modified: ${entry.logData().raw}`);
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
if ( fctxt.redirectURL !== undefined && this.hasQuery(fctxt) ) {
|
|
5624
|
+
const entries = this.filterQuery(fctxt, 'removeparam');
|
|
5625
|
+
if ( entries ) {
|
|
5626
|
+
for ( const entry of entries ) {
|
|
5627
|
+
out.push(`modified: ${entry.logData().raw}`);
|
|
5628
|
+
}
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5631
|
+
if ( fctxt.type === 'main_frame' || fctxt.type === 'sub_frame' ) {
|
|
5632
|
+
const csps = this.matchAndFetchModifiers(fctxt, 'csp');
|
|
5633
|
+
if ( csps ) {
|
|
5634
|
+
for ( const csp of csps ) {
|
|
5635
|
+
out.push(`modified: ${csp.logData().raw}`);
|
|
5636
|
+
}
|
|
5637
|
+
}
|
|
5638
|
+
const pps = this.matchAndFetchModifiers(fctxt, 'permissions');
|
|
5639
|
+
if ( pps ) {
|
|
5640
|
+
for ( const pp of pps ) {
|
|
5641
|
+
out.push(`modified: ${pp.logData().raw}`);
|
|
5642
|
+
}
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5645
|
+
} else if ( redirectEngine ) {
|
|
5646
|
+
const redirects = this.redirectRequest(redirectEngine, fctxt);
|
|
5647
|
+
if ( redirects ) {
|
|
5648
|
+
for ( const redirect of redirects ) {
|
|
5649
|
+
out.push(`modified: ${redirect.logData().raw}`);
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
}
|
|
5653
|
+
const urlskips = this.matchAndFetchModifiers(fctxt, 'urlskip');
|
|
5654
|
+
if ( urlskips ) {
|
|
5655
|
+
for ( const urlskip of urlskips ) {
|
|
5656
|
+
out.push(`modified: ${urlskip.logData().raw}`);
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5659
|
+
return out.join('\n');
|
|
5660
|
+
}
|
|
5398
5661
|
|
|
5399
5662
|
/******************************************************************************/
|
|
5400
5663
|
|
|
@@ -5489,6 +5752,7 @@ StaticNetFilteringEngine.prototype.dump = function() {
|
|
|
5489
5752
|
[ PERMISSIONS_REALM, 'permissions' ],
|
|
5490
5753
|
[ URLTRANSFORM_REALM, 'uritransform' ],
|
|
5491
5754
|
[ REPLACE_REALM, 'replace' ],
|
|
5755
|
+
[ URLSKIP_REALM, 'urlskip' ],
|
|
5492
5756
|
]);
|
|
5493
5757
|
const partyness = new Map([
|
|
5494
5758
|
[ ANYPARTY_REALM, 'any-party' ],
|