mirror of https://github.com/gorhill/uBlock.git
Better align syntax of `header=` option to that of `queryprune=`
The header value is no longer implicitly a regex-based literal, but a plain string against which the header name is compared. The value can be set to a regex literal by bracing the header value with the usual forward slashes, `/.../`. Examples: *$1p,strict3p,script,header=via:1.1 google *$1p,strict3p,script,header=via:/1\.1\s+google/ The first form will cause a strict comparison with the value of the header named `via` against the string `1.1 google`. The second form will cause a regex-based test with the value of the header named `via` against the regex `/1\.1\s+google/`. The header value can be prepended with `~` to reverse the comparison: *$1p,strict3p,script,header=via:~1.1 google The header value is optional and may be ommitted to test only for the presence of a specific header: *$1p,strict3p,script,header=via
This commit is contained in:
parent
ed64039912
commit
5db8d05975
|
@ -1161,8 +1161,9 @@ const Parser = class {
|
|||
BITFlavorError | BITFlavorUnsupported | BITFlavorIgnore
|
||||
);
|
||||
}
|
||||
|
||||
static parseQueryPruneValue(arg) {
|
||||
let s = arg;
|
||||
let s = arg.trim();
|
||||
if ( s === '*' ) { return { all: true }; }
|
||||
const out = { };
|
||||
out.not = s.charCodeAt(0) === 0x7E /* '~' */;
|
||||
|
@ -1196,6 +1197,29 @@ const Parser = class {
|
|||
out.name = s;
|
||||
return out;
|
||||
}
|
||||
|
||||
static parseHeaderValue(arg) {
|
||||
let s = arg.trim();
|
||||
const out = { };
|
||||
let pos = s.indexOf(':');
|
||||
if ( pos === -1 ) { pos = s.length; }
|
||||
out.name = s.slice(0, pos);
|
||||
out.bad = out.name === '';
|
||||
s = s.slice(pos + 1);
|
||||
out.not = s.charCodeAt(0) === 0x7E /* '~' */;
|
||||
if ( out.not ) { s = s.slice(1); }
|
||||
out.value = s;
|
||||
const match = /^\/(.+)\/(i)?$/.exec(s);
|
||||
if ( match !== null ) {
|
||||
try {
|
||||
out.re = new RegExp(match[1], match[2] || '');
|
||||
}
|
||||
catch(ex) {
|
||||
out.bad = true;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -2520,10 +2544,27 @@ const NetOptionsIterator = class {
|
|||
// `header`: can't be used with any modifier type
|
||||
{
|
||||
const i = this.tokenPos[OPTTokenHeader];
|
||||
if ( i !== -1 && hasBits(allBits, OPTModifierType) ) {
|
||||
optSlices[i] = OPTTokenInvalid;
|
||||
if ( this.interactive ) {
|
||||
this.parser.errorSlices(optSlices[i+1], optSlices[i+5]);
|
||||
if ( i !== -1 ) {
|
||||
if ( hasBits(allBits, OPTModifierType) ) {
|
||||
optSlices[i] = OPTTokenInvalid;
|
||||
if ( this.interactive ) {
|
||||
this.parser.errorSlices(optSlices[i+1], optSlices[i+5]);
|
||||
}
|
||||
} else {
|
||||
const val = this.parser.strFromSlices(
|
||||
optSlices[i+4],
|
||||
optSlices[i+5] - 3
|
||||
);
|
||||
const r = Parser.parseHeaderValue(val);
|
||||
if ( r.bad ) {
|
||||
optSlices[i] = OPTTokenInvalid;
|
||||
if ( this.interactive ) {
|
||||
this.parser.errorSlices(
|
||||
optSlices[i+4],
|
||||
optSlices[i+5]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
/* jshint bitwise: false */
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -2389,32 +2387,22 @@ registerFilterClass(FilterStrictParty);
|
|||
const FilterOnHeaders = class {
|
||||
constructor(headerOpt) {
|
||||
this.headerOpt = headerOpt;
|
||||
if ( headerOpt !== '' ) {
|
||||
let pos = headerOpt.indexOf(':');
|
||||
if ( pos === -1 ) { pos = headerOpt.length; }
|
||||
this.name = headerOpt.slice(0, pos);
|
||||
this.value = headerOpt.slice(pos + 1);
|
||||
this.not = this.value.charCodeAt(0) === 0x21 /* '!' */;
|
||||
if ( this.not ) { this.value.slice(1); }
|
||||
} else {
|
||||
this.name = this.value = '';
|
||||
this.not = false;
|
||||
}
|
||||
this.reValue = null;
|
||||
this.parsed = undefined;
|
||||
}
|
||||
|
||||
match() {
|
||||
if ( this.name === '' ) { return true; }
|
||||
const value = $httpHeaders.lookup(this.name);
|
||||
if ( value === undefined ) { return false; }
|
||||
if ( this.value === '' ) { return true; }
|
||||
if ( this.reValue === null ) {
|
||||
let reText = this.value;
|
||||
if ( reText.startsWith('|') ) { reText = '^' + reText.slice(1); }
|
||||
if ( reText.endsWith('|') ) { reText = reText.slice(0, -1) + '$'; }
|
||||
this.reValue = new RegExp(reText, 'i');
|
||||
if ( this.parsed === undefined ) {
|
||||
this.parsed =
|
||||
vAPI.StaticFilteringParser.parseHeaderValue(this.headerOpt);
|
||||
}
|
||||
return this.reValue.test(value) !== this.not;
|
||||
const { bad, name, not, re, value } = this.parsed;
|
||||
if ( bad ) { return false; }
|
||||
const headerValue = $httpHeaders.lookup(name);
|
||||
if ( headerValue === undefined ) { return false; }
|
||||
if ( value === '' ) { return true; }
|
||||
return re === undefined
|
||||
? (headerValue === value) !== not
|
||||
: re.test(headerValue) !== not;
|
||||
}
|
||||
|
||||
logData(details) {
|
||||
|
@ -4231,12 +4219,10 @@ FilterContainer.prototype.matchHeaders = function(fctxt, headers) {
|
|||
let r = 0;
|
||||
if ( this.realmMatchString(Headers | BlockImportant, typeValue, partyBits) ) {
|
||||
r = 1;
|
||||
}
|
||||
if ( r !== 1 && this.realmMatchString(Headers | BlockAction, typeValue, partyBits) ) {
|
||||
r = 1;
|
||||
if ( r === 1 && this.realmMatchString(Headers | AllowAction, typeValue, partyBits) ) {
|
||||
r = 2;
|
||||
}
|
||||
} else if ( this.realmMatchString(Headers | BlockAction, typeValue, partyBits) ) {
|
||||
r = this.realmMatchString(Headers | AllowAction, typeValue, partyBits)
|
||||
? 2
|
||||
: 1;
|
||||
}
|
||||
|
||||
$httpHeaders.reset();
|
||||
|
|
Loading…
Reference in New Issue