Skip to content

Commit e871d6e

Browse files
committed
Add new filter option: requestheader
Related issue: uBlockOrigin/uAssets#32194 (comment) Usage of `requestheader=` option is exactly same as current `header=` option. `header=` option has been renamed `responseheader=` and the current `header=` option is now an alias for `responseheader=`. Filter authors must cease using `header=` option and instead use the more accurate `responseheader=` option when uBO 1.71.0 is released. uBOL for Chromium does support conversion of `requestheader` to a DNR `requestHeaders` condition. Currently other browser platforms do not support `requestHeaders` condition.
1 parent 9026920 commit e871d6e

File tree

11 files changed

+291
-193
lines changed

11 files changed

+291
-193
lines changed

platform/mv3/firefox/patch-ruleset.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
export function patchRuleset(ruleset) {
2323
const out = [];
2424
for ( const rule of ruleset ) {
25-
const condition = rule.condition;
25+
const { condition } = rule;
2626
if ( Array.isArray(condition.responseHeaders) ) { continue; }
27+
if ( Array.isArray(condition.requestHeaders) ) { continue; }
2728
out.push(rule);
2829
}
2930
return out;

platform/mv3/make-rulesets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ function toStrictBlockRule(rule, out) {
424424
if ( condition.requestMethods ) { return; }
425425
if ( condition.excludedRequestMethods ) { return; }
426426
if ( condition.responseHeaders ) { return; }
427+
if ( condition.requestHeaders ) { return; }
427428
if ( condition.excludedResponseHeaders ) { return; }
428429
if ( condition.initiatorDomains ) { return; }
429430
if ( condition.excludedInitiatorDomains ) { return; }

platform/mv3/safari/ext-compat.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const nativeDNR = webext.declarativeNetRequest;
7171

7272
const isSupportedRule = r => {
7373
if ( r.action.responseHeaders ) { return false; }
74+
if ( r.action.requestHeaders ) { return false; }
7475
const { condition } = r;
7576
if ( condition.tabIds !== undefined ) { return false; }
7677
if ( condition.resourceTypes?.includes('object') ) {

platform/mv3/safari/patch-ruleset.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ function patchRule(rule, out) {
4444
const condition = copy.condition;
4545
if ( copy.action.type === 'modifyHeaders' ) { return; }
4646
if ( Array.isArray(copy.condition.responseHeaders) ) { return; }
47+
if ( Array.isArray(copy.condition.requestHeaders) ) { return; }
4748
// https://github.com/uBlockOrigin/uBOL-home/issues/476#issuecomment-3299309478
4849
// https://github.com/uBlockOrigin/uBOL-home/issues/608
4950
if ( copy.action.redirect?.transform?.queryTransform?.removeParams ) {

src/js/background.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ const µBlock = { // jshint ignore:line
180180

181181
// Read-only
182182
systemSettings: {
183-
compiledMagic: 60, // Increase when compiled format changes
184-
selfieMagic: 60, // Increase when selfie format changes
183+
compiledMagic: 70, // Increase when compiled format changes
184+
selfieMagic: 70, // Increase when selfie format changes
185185
},
186186

187187
// https://github.com/uBlockOrigin/uBlock-issues/issues/759#issuecomment-546654501

src/js/benchmarks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export async function benchmarkStaticNetFiltering(options = {}) {
202202
permissionsCount += 1;
203203
}
204204
}
205-
sfne.matchHeaders(fctxt, []);
205+
sfne.matchHeaders(fctxt, [], []);
206206
if ( sfne.matchAndFetchModifiers(fctxt, 'replace') ) {
207207
replaceCount += 1;
208208
}

src/js/codemirror/ubo-static-filtering.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ const uBOStaticFilteringMode = (( ) => {
166166
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
167167
case sfp.NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK:
168168
case sfp.NODE_TYPE_NET_OPTION_NAME_GHIDE:
169-
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
170169
case sfp.NODE_TYPE_NET_OPTION_NAME_IMAGE:
171170
case sfp.NODE_TYPE_NET_OPTION_NAME_IMPORTANT:
172171
case sfp.NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
@@ -184,6 +183,8 @@ const uBOStaticFilteringMode = (( ) => {
184183
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
185184
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
186185
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
186+
case sfp.NODE_TYPE_NET_OPTION_NAME_RESPONSEHEADER:
187+
case sfp.NODE_TYPE_NET_OPTION_NAME_REQUESTHEADER:
187188
case sfp.NODE_TYPE_NET_OPTION_NAME_SCRIPT:
188189
case sfp.NODE_TYPE_NET_OPTION_NAME_SHIDE:
189190
case sfp.NODE_TYPE_NET_OPTION_NAME_TO:

src/js/pagestore.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,12 +892,12 @@ const PageStore = class {
892892
return result;
893893
}
894894

895-
filterOnHeaders(fctxt, headers) {
895+
filterOnHeaders(fctxt, ...headers) {
896896
fctxt.filter = undefined;
897897

898898
if ( this.getNetFilteringSwitch(fctxt) === false ) { return 0; }
899899

900-
let result = staticNetFilteringEngine.matchHeaders(fctxt, headers);
900+
let result = staticNetFilteringEngine.matchHeaders(fctxt, ...headers);
901901
if ( result === 0 ) { return 0; }
902902

903903
const loggerEnabled = logger.enabled;

src/js/static-filtering-parser.js

Lines changed: 160 additions & 154 deletions
Large diffs are not rendered by default.

src/js/static-net-filtering.js

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -290,21 +290,23 @@ const $requestEntity = {
290290
};
291291

292292
const $httpHeaders = {
293-
init(headers) {
294-
this.headers = headers;
293+
init(...headers) {
294+
this.headers = headers.flat();
295295
this.parsed.clear();
296296
},
297297
reset() {
298298
this.headers = [];
299299
this.parsed.clear();
300300
},
301301
lookup(name) {
302-
if ( this.parsed.size === 0 ) {
303-
for ( const { name, value } of this.headers ) {
304-
this.parsed.set(name.toLowerCase(), value);
305-
}
306-
}
307-
return this.parsed.get(name);
302+
let value = this.parsed.get(name);
303+
if ( value === undefined ) {
304+
const headers = this.headers;
305+
const i = headers.findIndex(a => name === a.name.toLowerCase());
306+
value = i !== -1 ? headers[i].value : null;
307+
this.parsed.set(name, value);
308+
}
309+
return value ?? undefined;
308310
},
309311
headers: [],
310312
parsed: new Map(),
@@ -2943,13 +2945,14 @@ class FilterOnHeaders {
29432945
return re.test(headerValue) !== not;
29442946
}
29452947

2946-
static compile(details) {
2947-
const parsed = sfp.parseHeaderValue(details.optionValues.get('header'));
2948+
static compile(fid, details) {
2949+
const fc = filterClasses[fid];
2950+
const parsed = sfp.parseHeaderValue(details.optionValues.get(`${fc.headerRealm}header`));
29482951
let normalized = parsed.name;
29492952
if ( parsed.value !== '' ) {
29502953
normalized += `:${parsed.value}`;
29512954
}
2952-
return [ FilterOnHeaders.fid, normalized ];
2955+
return [ fid, normalized ];
29532956
}
29542957

29552958
static fromCompiled(args) {
@@ -2962,7 +2965,8 @@ class FilterOnHeaders {
29622965
);
29632966
}
29642967

2965-
static dnrFromCompiled(args, rule) {
2968+
static dnrFromCompiled(fid, args, rule) {
2969+
const fc = filterClasses[fid];
29662970
rule.condition ||= {};
29672971
const parsed = sfp.parseHeaderValue(args[1]);
29682972
if ( parsed.bad !== true ) {
@@ -2971,8 +2975,8 @@ class FilterOnHeaders {
29712975
: parsed.value;
29722976
if ( value !== undefined ) {
29732977
const prop = parsed.not
2974-
? 'excludedResponseHeaders'
2975-
: 'responseHeaders';
2978+
? `excludedR${fc.headerRealm.slice(1)}Headers`
2979+
: `${fc.headerRealm}Headers`;
29762980
rule.condition[prop] ||= [];
29772981
const details = {
29782982
header: parsed.name,
@@ -2984,21 +2988,52 @@ class FilterOnHeaders {
29842988
return;
29852989
}
29862990
}
2987-
dnrAddRuleError(rule, `header="${args[1]}" not supported`);
2991+
dnrAddRuleError(rule, `${fc.headerRealm}header="${args[1]}" not supported`);
29882992
}
29892993

2990-
static logData(idata, details) {
2994+
static logData(fid, idata, details) {
2995+
const fc = filterClasses[fid];
29912996
const irefs = filterData[idata+1];
29922997
const headerOpt = filterRefs[irefs].headerOpt;
2993-
let opt = 'header';
2998+
let opt = `${fc.headerRealm}header`;
29942999
if ( headerOpt !== '' ) {
29953000
opt += `=${LogData.requote(headerOpt)}`;
29963001
}
29973002
details.options.push(opt);
29983003
}
29993004
}
30003005

3001-
registerFilterClass(FilterOnHeaders);
3006+
class FilterOnResponseHeaders extends FilterOnHeaders {
3007+
static headerRealm = 'response';
3008+
static compile(details) {
3009+
return super.compile(FilterOnResponseHeaders.fid, details);
3010+
}
3011+
3012+
static dnrFromCompiled(args, rule) {
3013+
super.dnrFromCompiled(FilterOnResponseHeaders.fid, args, rule);
3014+
}
3015+
3016+
static logData(idata, details) {
3017+
super.logData(FilterOnResponseHeaders.fid, idata, details);
3018+
}
3019+
}
3020+
registerFilterClass(FilterOnResponseHeaders);
3021+
3022+
class FilterOnRequestHeaders extends FilterOnHeaders {
3023+
static headerRealm = 'request';
3024+
static compile(details) {
3025+
return super.compile(FilterOnRequestHeaders.fid, details);
3026+
}
3027+
3028+
static dnrFromCompiled(args, rule) {
3029+
super.dnrFromCompiled(FilterOnRequestHeaders.fid, args, rule);
3030+
}
3031+
3032+
static logData(idata, details) {
3033+
super.logData(FilterOnRequestHeaders.fid, idata, details);
3034+
}
3035+
}
3036+
registerFilterClass(FilterOnRequestHeaders);
30023037

30033038
/******************************************************************************/
30043039

@@ -3604,11 +3639,6 @@ class FilterCompiler {
36043639
this.optionUnitBits |= FROM_BIT;
36053640
break;
36063641
}
3607-
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER: {
3608-
this.optionValues.set('header', parser.getNetOptionValue(id) || '');
3609-
this.optionUnitBits |= HEADER_BIT;
3610-
break;
3611-
}
36123642
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
36133643
this.optionValues.set('ipaddress', parser.getNetOptionValue(id) || '');
36143644
this.optionUnitBits |= IPADDRESS_BIT;
@@ -3642,6 +3672,16 @@ class FilterCompiler {
36423672
this.optionUnitBits |= MODIFY_BIT;
36433673
break;
36443674
}
3675+
case sfp.NODE_TYPE_NET_OPTION_NAME_REQUESTHEADER: {
3676+
this.optionValues.set('requestheader', parser.getNetOptionValue(id) || '');
3677+
this.optionUnitBits |= HEADER_BIT;
3678+
break;
3679+
}
3680+
case sfp.NODE_TYPE_NET_OPTION_NAME_RESPONSEHEADER: {
3681+
this.optionValues.set('responseheader', parser.getNetOptionValue(id) || '');
3682+
this.optionUnitBits |= HEADER_BIT;
3683+
break;
3684+
}
36453685
case sfp.NODE_TYPE_NET_OPTION_NAME_TO: {
36463686
const iter = parser.getNetFilterToOptionIterator();
36473687
const list = [];
@@ -3736,7 +3776,6 @@ class FilterCompiler {
37363776
case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
37373777
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
37383778
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
3739-
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
37403779
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
37413780
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
37423781
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
@@ -3745,6 +3784,8 @@ class FilterCompiler {
37453784
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
37463785
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
37473786
case sfp.NODE_TYPE_NET_OPTION_NAME_REPLACE:
3787+
case sfp.NODE_TYPE_NET_OPTION_NAME_REQUESTHEADER:
3788+
case sfp.NODE_TYPE_NET_OPTION_NAME_RESPONSEHEADER:
37483789
case sfp.NODE_TYPE_NET_OPTION_NAME_TO:
37493790
case sfp.NODE_TYPE_NET_OPTION_NAME_URLSKIP:
37503791
case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
@@ -4117,7 +4158,12 @@ class FilterCompiler {
41174158

41184159
// Header
41194160
if ( (this.optionUnitBits & HEADER_BIT) !== 0 ) {
4120-
units.push(FilterOnHeaders.compile(this));
4161+
if ( this.optionValues.has('requestheader') ) {
4162+
units.push(FilterOnRequestHeaders.compile(this));
4163+
}
4164+
if ( this.optionValues.has('responseheader') ) {
4165+
units.push(FilterOnResponseHeaders.compile(this));
4166+
}
41214167
this.action |= HEADERS_REALM;
41224168
}
41234169

@@ -5432,7 +5478,7 @@ StaticNetFilteringEngine.prototype.matchRequest = function(fctxt, modifiers = 0)
54325478

54335479
/******************************************************************************/
54345480

5435-
StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, headers) {
5481+
StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, ...headers) {
54365482
const typeBits = typeNameToTypeValue[fctxt.type] || otherTypeBitValue;
54375483
const partyBits = fctxt.is3rdPartyToDoc() ? THIRDPARTY_REALM : FIRSTPARTY_REALM;
54385484

@@ -5449,7 +5495,7 @@ StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, headers) {
54495495
$requestTypeValue = (typeBits & TYPE_REALM) >>> TYPE_REALM_OFFSET;
54505496
$requestAddress = fctxt.getIPAddress();
54515497
$isBlockImportant = false;
5452-
$httpHeaders.init(headers);
5498+
$httpHeaders.init(...headers);
54535499

54545500
let r = 0;
54555501
if ( this.realmMatchString(HEADERS_REALM | BLOCK_REALM, typeBits, partyBits) ) {

0 commit comments

Comments
 (0)