mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-16 15:33:38 +01:00
New static network filter option ipaddress=
The purpose is to block according to the ip address of a network request. In the current implementation, the filter option can only be enforced at onHeadersReceived time. The new filter option cannot be enforced in Chromium-based browsers since the ip address of network requests is available only at onResponseStarted time, which is not blocking. The value assigned to `ipaddress` can either be a plain string which must match exactly a given ip address, or a regex which will be matched against the ip address. The `ipaddress` option can only be enforced when the extension framework does provide a valid ip address in a onHeadersReceived listener. For instance, cached resources do not have a valid ip address and thus can't be a match to `ipaddress` option. Example: *$script,ipaddress=93.184.215.14
This commit is contained in:
parent
20115697e5
commit
c6dedd253f
@ -307,6 +307,7 @@ const µBlock = { // jshint ignore:line
|
||||
this.setMethod(details.method);
|
||||
this.setURL(details.url);
|
||||
this.aliasURL = details.aliasURL || undefined;
|
||||
this.ipaddress = details.ip || undefined;
|
||||
this.redirectURL = undefined;
|
||||
this.filter = undefined;
|
||||
if ( this.itype !== this.SUB_FRAME ) {
|
||||
|
@ -19,13 +19,9 @@
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
import {
|
||||
hostnameFromURI,
|
||||
domainFromHostname,
|
||||
hostnameFromURI,
|
||||
originFromURI,
|
||||
} from './uri-utils.js';
|
||||
|
||||
@ -140,6 +136,7 @@ export const FilteringContext = class {
|
||||
this.stype = undefined;
|
||||
this.url = undefined;
|
||||
this.aliasURL = undefined;
|
||||
this.ipaddress = undefined;
|
||||
this.hostname = undefined;
|
||||
this.domain = undefined;
|
||||
this.docId = -1;
|
||||
@ -418,42 +415,72 @@ export const FilteringContext = class {
|
||||
static getMethodName(a) {
|
||||
return methodBitToStrMap.get(a) || '';
|
||||
}
|
||||
|
||||
BEACON = BEACON;
|
||||
CSP_REPORT = CSP_REPORT;
|
||||
FONT = FONT;
|
||||
IMAGE = IMAGE;
|
||||
IMAGESET = IMAGESET;
|
||||
MAIN_FRAME = MAIN_FRAME;
|
||||
MEDIA = MEDIA;
|
||||
OBJECT = OBJECT;
|
||||
OBJECT_SUBREQUEST = OBJECT_SUBREQUEST;
|
||||
PING = PING;
|
||||
SCRIPT = SCRIPT;
|
||||
STYLESHEET = STYLESHEET;
|
||||
SUB_FRAME = SUB_FRAME;
|
||||
WEBSOCKET = WEBSOCKET;
|
||||
XMLHTTPREQUEST = XMLHTTPREQUEST;
|
||||
INLINE_FONT = INLINE_FONT;
|
||||
INLINE_SCRIPT = INLINE_SCRIPT;
|
||||
OTHER = OTHER;
|
||||
FRAME_ANY = FRAME_ANY;
|
||||
FONT_ANY = FONT_ANY;
|
||||
INLINE_ANY = INLINE_ANY;
|
||||
PING_ANY = PING_ANY;
|
||||
SCRIPT_ANY = SCRIPT_ANY;
|
||||
METHOD_NONE = METHOD_NONE;
|
||||
METHOD_CONNECT = METHOD_CONNECT;
|
||||
METHOD_DELETE = METHOD_DELETE;
|
||||
METHOD_GET = METHOD_GET;
|
||||
METHOD_HEAD = METHOD_HEAD;
|
||||
METHOD_OPTIONS = METHOD_OPTIONS;
|
||||
METHOD_PATCH = METHOD_PATCH;
|
||||
METHOD_POST = METHOD_POST;
|
||||
METHOD_PUT = METHOD_PUT;
|
||||
|
||||
static BEACON = BEACON;
|
||||
static CSP_REPORT = CSP_REPORT;
|
||||
static FONT = FONT;
|
||||
static IMAGE = IMAGE;
|
||||
static IMAGESET = IMAGESET;
|
||||
static MAIN_FRAME = MAIN_FRAME;
|
||||
static MEDIA = MEDIA;
|
||||
static OBJECT = OBJECT;
|
||||
static OBJECT_SUBREQUEST = OBJECT_SUBREQUEST;
|
||||
static PING = PING;
|
||||
static SCRIPT = SCRIPT;
|
||||
static STYLESHEET = STYLESHEET;
|
||||
static SUB_FRAME = SUB_FRAME;
|
||||
static WEBSOCKET = WEBSOCKET;
|
||||
static XMLHTTPREQUEST = XMLHTTPREQUEST;
|
||||
static INLINE_FONT = INLINE_FONT;
|
||||
static INLINE_SCRIPT = INLINE_SCRIPT;
|
||||
static OTHER = OTHER;
|
||||
static FRAME_ANY = FRAME_ANY;
|
||||
static FONT_ANY = FONT_ANY;
|
||||
static INLINE_ANY = INLINE_ANY;
|
||||
static PING_ANY = PING_ANY;
|
||||
static SCRIPT_ANY = SCRIPT_ANY;
|
||||
static METHOD_NONE = METHOD_NONE;
|
||||
static METHOD_CONNECT = METHOD_CONNECT;
|
||||
static METHOD_DELETE = METHOD_DELETE;
|
||||
static METHOD_GET = METHOD_GET;
|
||||
static METHOD_HEAD = METHOD_HEAD;
|
||||
static METHOD_OPTIONS = METHOD_OPTIONS;
|
||||
static METHOD_PATCH = METHOD_PATCH;
|
||||
static METHOD_POST = METHOD_POST;
|
||||
static METHOD_PUT = METHOD_PUT;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilteringContext.prototype.BEACON = FilteringContext.BEACON = BEACON;
|
||||
FilteringContext.prototype.CSP_REPORT = FilteringContext.CSP_REPORT = CSP_REPORT;
|
||||
FilteringContext.prototype.FONT = FilteringContext.FONT = FONT;
|
||||
FilteringContext.prototype.IMAGE = FilteringContext.IMAGE = IMAGE;
|
||||
FilteringContext.prototype.IMAGESET = FilteringContext.IMAGESET = IMAGESET;
|
||||
FilteringContext.prototype.MAIN_FRAME = FilteringContext.MAIN_FRAME = MAIN_FRAME;
|
||||
FilteringContext.prototype.MEDIA = FilteringContext.MEDIA = MEDIA;
|
||||
FilteringContext.prototype.OBJECT = FilteringContext.OBJECT = OBJECT;
|
||||
FilteringContext.prototype.OBJECT_SUBREQUEST = FilteringContext.OBJECT_SUBREQUEST = OBJECT_SUBREQUEST;
|
||||
FilteringContext.prototype.PING = FilteringContext.PING = PING;
|
||||
FilteringContext.prototype.SCRIPT = FilteringContext.SCRIPT = SCRIPT;
|
||||
FilteringContext.prototype.STYLESHEET = FilteringContext.STYLESHEET = STYLESHEET;
|
||||
FilteringContext.prototype.SUB_FRAME = FilteringContext.SUB_FRAME = SUB_FRAME;
|
||||
FilteringContext.prototype.WEBSOCKET = FilteringContext.WEBSOCKET = WEBSOCKET;
|
||||
FilteringContext.prototype.XMLHTTPREQUEST = FilteringContext.XMLHTTPREQUEST = XMLHTTPREQUEST;
|
||||
FilteringContext.prototype.INLINE_FONT = FilteringContext.INLINE_FONT = INLINE_FONT;
|
||||
FilteringContext.prototype.INLINE_SCRIPT = FilteringContext.INLINE_SCRIPT = INLINE_SCRIPT;
|
||||
FilteringContext.prototype.OTHER = FilteringContext.OTHER = OTHER;
|
||||
FilteringContext.prototype.FRAME_ANY = FilteringContext.FRAME_ANY = FRAME_ANY;
|
||||
FilteringContext.prototype.FONT_ANY = FilteringContext.FONT_ANY = FONT_ANY;
|
||||
FilteringContext.prototype.INLINE_ANY = FilteringContext.INLINE_ANY = INLINE_ANY;
|
||||
FilteringContext.prototype.PING_ANY = FilteringContext.PING_ANY = PING_ANY;
|
||||
FilteringContext.prototype.SCRIPT_ANY = FilteringContext.SCRIPT_ANY = SCRIPT_ANY;
|
||||
|
||||
FilteringContext.prototype.METHOD_NONE = FilteringContext.METHOD_NONE = METHOD_NONE;
|
||||
FilteringContext.prototype.METHOD_CONNECT = FilteringContext.METHOD_CONNECT = METHOD_CONNECT;
|
||||
FilteringContext.prototype.METHOD_DELETE = FilteringContext.METHOD_DELETE = METHOD_DELETE;
|
||||
FilteringContext.prototype.METHOD_GET = FilteringContext.METHOD_GET = METHOD_GET;
|
||||
FilteringContext.prototype.METHOD_HEAD = FilteringContext.METHOD_HEAD = METHOD_HEAD;
|
||||
FilteringContext.prototype.METHOD_OPTIONS = FilteringContext.METHOD_OPTIONS = METHOD_OPTIONS;
|
||||
FilteringContext.prototype.METHOD_PATCH = FilteringContext.METHOD_PATCH = METHOD_PATCH;
|
||||
FilteringContext.prototype.METHOD_POST = FilteringContext.METHOD_POST = METHOD_POST;
|
||||
FilteringContext.prototype.METHOD_PUT = FilteringContext.METHOD_PUT = METHOD_PUT;
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -172,6 +172,7 @@ export const NODE_TYPE_NET_OPTION_NAME_IMAGE = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_IMPORTANT = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_INLINEFONT = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_IPADDRESS = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++;
|
||||
@ -249,6 +250,7 @@ export const nodeTypeFromOptionName = new Map([
|
||||
[ 'important', NODE_TYPE_NET_OPTION_NAME_IMPORTANT ],
|
||||
[ 'inline-font', NODE_TYPE_NET_OPTION_NAME_INLINEFONT ],
|
||||
[ 'inline-script', NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT ],
|
||||
[ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ],
|
||||
[ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
|
||||
[ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
|
||||
[ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
|
||||
@ -1401,6 +1403,14 @@ export class AstFilterParser {
|
||||
modifierType = type;
|
||||
unredirectableTypeCount += 1;
|
||||
break;
|
||||
case NODE_TYPE_NET_OPTION_NAME_IPADDRESS: {
|
||||
const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_IPADDRESS);
|
||||
if ( /^\/.+\/$/.test(value) ) {
|
||||
try { void new RegExp(value); }
|
||||
catch(_) { realBad = true; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
||||
realBad = this.isRegexPattern() === false;
|
||||
break;
|
||||
@ -3104,6 +3114,7 @@ export const netOptionTokenDescriptors = new Map([
|
||||
[ 'important', { blockOnly: true } ],
|
||||
[ 'inline-font', { canNegate: true } ],
|
||||
[ 'inline-script', { canNegate: true } ],
|
||||
[ 'ipaddress', { mustAssign: true } ],
|
||||
[ 'match-case', { } ],
|
||||
[ 'media', { canNegate: true } ],
|
||||
[ 'method', { mustAssign: true } ],
|
||||
@ -4324,6 +4335,7 @@ export const utils = (( ) => {
|
||||
[ 'env_safari', 'safari' ],
|
||||
[ 'cap_html_filtering', 'html_filtering' ],
|
||||
[ 'cap_user_stylesheet', 'user_stylesheet' ],
|
||||
[ 'cap_ipaddress', 'ipaddress' ],
|
||||
[ 'false', 'false' ],
|
||||
// Hoping ABP-only list maintainers can at least make use of it to
|
||||
// help non-ABP content blockers better deal with filters benefiting
|
||||
@ -4358,8 +4370,11 @@ export const utils = (( ) => {
|
||||
static evaluateExprToken(token, env = []) {
|
||||
const not = token.charCodeAt(0) === 0x21 /* ! */;
|
||||
if ( not ) { token = token.slice(1); }
|
||||
const state = preparserTokens.get(token);
|
||||
if ( state === undefined ) { return; }
|
||||
let state = preparserTokens.get(token);
|
||||
if ( state === undefined ) {
|
||||
if ( token.startsWith('cap_') === false ) { return; }
|
||||
state = 'false';
|
||||
}
|
||||
return state === 'false' && not || env.includes(state) !== not;
|
||||
}
|
||||
|
||||
|
@ -242,6 +242,7 @@ let $requestTypeValue = 0;
|
||||
let $requestURL = '';
|
||||
let $requestURLRaw = '';
|
||||
let $requestHostname = '';
|
||||
let $requestAddress = '';
|
||||
let $docHostname = '';
|
||||
let $docDomain = '';
|
||||
let $tokenBeg = 0;
|
||||
@ -702,6 +703,8 @@ const dnrAddRuleWarning = (rule, msg) => {
|
||||
FilterNotType
|
||||
FilterStrictParty
|
||||
FilterModifier
|
||||
FilterOnHeaders
|
||||
FilterIPAddress
|
||||
|
||||
Collection:
|
||||
FilterCollection
|
||||
@ -1234,7 +1237,7 @@ class FilterRegex {
|
||||
return [
|
||||
FilterRegex.fid,
|
||||
details.pattern,
|
||||
details.patternMatchCase ? 1 : 0
|
||||
details.optionValues.has('match-case') ? 1 : 0,
|
||||
];
|
||||
}
|
||||
|
||||
@ -2075,7 +2078,7 @@ const compileToDomainOpt = (...args) => {
|
||||
|
||||
class FilterDenyAllow extends FilterToDomainMissSet {
|
||||
static compile(details) {
|
||||
return super.compile(details.denyallowOpt, 0b01);
|
||||
return super.compile(details.optionValues.get('denyallow'), 0b01);
|
||||
}
|
||||
|
||||
static logData(idata, details) {
|
||||
@ -2937,12 +2940,12 @@ class FilterOnHeaders {
|
||||
}
|
||||
|
||||
static compile(details) {
|
||||
return [ FilterOnHeaders.fid, details.headerOpt ];
|
||||
return [ FilterOnHeaders.fid, details.optionValues.get('header') ];
|
||||
}
|
||||
|
||||
static fromCompiled(args) {
|
||||
return filterDataAlloc(
|
||||
args[0], // fid
|
||||
args[0], // fid
|
||||
filterRefAdd({
|
||||
headerOpt: args[1],
|
||||
$parsed: null,
|
||||
@ -2963,6 +2966,41 @@ class FilterOnHeaders {
|
||||
|
||||
registerFilterClass(FilterOnHeaders);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class FilterIPAddress {
|
||||
static match(idata) {
|
||||
const details = filterRefs[filterData[idata+1]];
|
||||
if ( details.isRegex === false ) {
|
||||
return $requestAddress === details.pattern;
|
||||
}
|
||||
if ( details.$re === undefined ) {
|
||||
details.$re = new RegExp(details.pattern.slice(1, -1));
|
||||
}
|
||||
return details.$re.test($requestAddress);
|
||||
}
|
||||
|
||||
static compile(details) {
|
||||
return [ FilterIPAddress.fid, details.optionValues.get('ipaddress') ];
|
||||
}
|
||||
|
||||
static fromCompiled(args) {
|
||||
const pattern = args[1];
|
||||
const details = {
|
||||
pattern,
|
||||
isRegex: pattern.startsWith('/') && pattern.endsWith('/'),
|
||||
};
|
||||
return filterDataAlloc(args[0], filterRefAdd(details));
|
||||
}
|
||||
|
||||
static logData(idata, details) {
|
||||
const irefs = filterData[idata+1];
|
||||
details.options.push(`ipaddress=${LogData.requote(filterRefs[irefs].pattern)}`);
|
||||
}
|
||||
}
|
||||
|
||||
registerFilterClass(FilterIPAddress);
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
@ -3146,8 +3184,7 @@ class FilterCompiler {
|
||||
return Object.assign(this, other);
|
||||
}
|
||||
this.reToken = /[%0-9A-Za-z]+/g;
|
||||
this.fromDomainOptList = [];
|
||||
this.toDomainOptList = [];
|
||||
this.optionValues = new Map();
|
||||
this.tokenIdToNormalizedType = new Map([
|
||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_CNAME, bitFromType('cname') ],
|
||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_CSS, bitFromType('stylesheet') ],
|
||||
@ -3304,13 +3341,9 @@ class FilterCompiler {
|
||||
this.modifyType = undefined;
|
||||
this.modifyValue = undefined;
|
||||
this.pattern = '';
|
||||
this.patternMatchCase = false;
|
||||
this.party = ANYPARTY_REALM;
|
||||
this.optionUnitBits = 0;
|
||||
this.fromDomainOpt = '';
|
||||
this.toDomainOpt = '';
|
||||
this.denyallowOpt = '';
|
||||
this.headerOpt = undefined;
|
||||
this.optionValues.clear();
|
||||
this.isPureHostname = false;
|
||||
this.isGeneric = false;
|
||||
this.isRegex = false;
|
||||
@ -3322,8 +3355,7 @@ class FilterCompiler {
|
||||
this.notTypeBits = 0;
|
||||
this.methodBits = 0;
|
||||
this.notMethodBits = 0;
|
||||
this.wildcardPos = -1;
|
||||
this.caretPos = -1;
|
||||
this.responseHeadersRealm = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -3421,26 +3453,36 @@ class FilterCompiler {
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
|
||||
if ( this.processCspOption(parser.getNetOptionValue(id)) === false ) { return false; }
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
|
||||
this.denyallowOpt = this.processHostnameList(
|
||||
parser.getNetFilterDenyallowOptionIterator(),
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW: {
|
||||
const value = this.processHostnameList(
|
||||
parser.getNetFilterDenyallowOptionIterator()
|
||||
);
|
||||
if ( this.denyallowOpt === '' ) { return false; }
|
||||
if ( value === '' ) { return false; }
|
||||
this.optionValues.set('denyallow', value);
|
||||
this.optionUnitBits |= DENYALLOW_BIT;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
||||
this.fromDomainOpt = this.processHostnameList(
|
||||
parser.getNetFilterFromOptionIterator(),
|
||||
this.fromDomainOptList
|
||||
);
|
||||
if ( this.fromDomainOpt === '' ) { return false; }
|
||||
}
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM: {
|
||||
const iter = parser.getNetFilterFromOptionIterator();
|
||||
const list = [];
|
||||
const value = this.processHostnameList(iter, list);
|
||||
if ( value === '' ) { return false; }
|
||||
this.optionValues.set('from', value);
|
||||
this.optionValues.set('fromList', list);
|
||||
this.optionUnitBits |= FROM_BIT;
|
||||
break;
|
||||
}
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER: {
|
||||
this.headerOpt = parser.getNetOptionValue(id) || '';
|
||||
this.optionValues.set('header', parser.getNetOptionValue(id) || '');
|
||||
this.optionUnitBits |= HEADER_BIT;
|
||||
this.responseHeadersRealm = true;
|
||||
break;
|
||||
}
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
|
||||
this.optionValues.set('ipaddress', parser.getNetOptionValue(id) || '');
|
||||
this.optionUnitBits |= IPADDRESS_BIT;
|
||||
this.responseHeadersRealm = true;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
||||
this.processMethodOption(parser.getNetOptionValue(id));
|
||||
this.optionUnitBits |= METHOD_BIT;
|
||||
@ -3465,14 +3507,16 @@ class FilterCompiler {
|
||||
this.optionUnitBits |= MODIFY_BIT;
|
||||
break;
|
||||
}
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_TO:
|
||||
this.toDomainOpt = this.processHostnameList(
|
||||
parser.getNetFilterToOptionIterator(),
|
||||
this.toDomainOptList
|
||||
);
|
||||
if ( this.toDomainOpt === '' ) { return false; }
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_TO: {
|
||||
const iter = parser.getNetFilterToOptionIterator();
|
||||
const list = [];
|
||||
const value = this.processHostnameList(iter, list);
|
||||
if ( value === '' ) { return false; }
|
||||
this.optionValues.set('to', value);
|
||||
this.optionValues.set('toList', list);
|
||||
this.optionUnitBits |= TO_BIT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3558,6 +3602,7 @@ class FilterCompiler {
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
||||
@ -3591,7 +3636,7 @@ class FilterCompiler {
|
||||
this.action = BLOCKIMPORTANT_REALM;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
||||
this.patternMatchCase = true;
|
||||
this.optionValues.set('match-case', true);
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_MP4: {
|
||||
const id = this.action === ALLOW_REALM
|
||||
@ -3661,11 +3706,6 @@ class FilterCompiler {
|
||||
return this.FILTER_OK;
|
||||
}
|
||||
|
||||
if ( this.isGeneric ) {
|
||||
this.wildcardPos = this.pattern.indexOf('*');
|
||||
this.caretPos = this.pattern.indexOf('^');
|
||||
}
|
||||
|
||||
if ( this.pattern.length > 1024 ) {
|
||||
return this.FILTER_UNSUPPORTED;
|
||||
}
|
||||
@ -3793,7 +3833,7 @@ class FilterCompiler {
|
||||
isJustOrigin() {
|
||||
if ( this.optionUnitBits !== FROM_BIT ) { return false; }
|
||||
if ( this.isRegex ) { return false; }
|
||||
if ( /[/~]/.test(this.fromDomainOpt) ) { return false; }
|
||||
if ( /[/~]/.test(this.optionValues.get('from')) ) { return false; }
|
||||
if ( this.pattern === '*' ) { return true; }
|
||||
if ( this.anchor !== 0b010 ) { return false; }
|
||||
if ( /^(?:http[s*]?:(?:\/\/)?)$/.test(this.pattern) ) { return true; }
|
||||
@ -3870,7 +3910,7 @@ class FilterCompiler {
|
||||
} else /* 'http:' */ {
|
||||
this.tokenHash = ANY_HTTP_TOKEN_HASH;
|
||||
}
|
||||
for ( const hn of this.fromDomainOptList ) {
|
||||
for ( const hn of this.optionValues.get('fromList') ) {
|
||||
this.compileToAtomicFilter(hn, writer);
|
||||
}
|
||||
return;
|
||||
@ -3911,31 +3951,36 @@ class FilterCompiler {
|
||||
}
|
||||
|
||||
// Origin
|
||||
if ( this.fromDomainOpt !== '' ) {
|
||||
if ( this.optionValues.has('from') ) {
|
||||
compileFromDomainOpt(
|
||||
this.fromDomainOptList,
|
||||
this.optionValues.get('fromList'),
|
||||
units.length !== 0 && patternClass.isSlow === true,
|
||||
units
|
||||
);
|
||||
}
|
||||
|
||||
// Destination
|
||||
if ( this.toDomainOpt !== '' ) {
|
||||
if ( this.optionValues.has('to') ) {
|
||||
compileToDomainOpt(
|
||||
this.toDomainOptList,
|
||||
this.optionValues.get('toList'),
|
||||
units.length !== 0 && patternClass.isSlow === true,
|
||||
units
|
||||
);
|
||||
}
|
||||
|
||||
// Deny-allow
|
||||
if ( this.denyallowOpt !== '' ) {
|
||||
if ( this.optionValues.has('denyallow') ) {
|
||||
units.push(FilterDenyAllow.compile(this));
|
||||
}
|
||||
|
||||
// Header
|
||||
if ( this.headerOpt !== undefined ) {
|
||||
units.push(FilterOnHeaders.compile(this));
|
||||
if ( this.responseHeadersRealm ) {
|
||||
if ( this.optionValues.has('ipaddress') ) {
|
||||
units.push(FilterIPAddress.compile(this));
|
||||
}
|
||||
if ( this.optionValues.has('header') ) {
|
||||
units.push(FilterOnHeaders.compile(this));
|
||||
}
|
||||
this.action |= HEADERS_REALM;
|
||||
}
|
||||
|
||||
@ -3977,12 +4022,13 @@ class FilterCompiler {
|
||||
units.push(FilterPatternGeneric.compile(this));
|
||||
return FilterPatternGeneric;
|
||||
}
|
||||
if ( this.wildcardPos === -1 ) {
|
||||
if ( this.caretPos === -1 ) {
|
||||
if ( this.pattern.includes('*') === false ) {
|
||||
const caretPos = this.pattern.indexOf('^');
|
||||
if ( caretPos === -1 ) {
|
||||
units.push(FilterPatternPlain.compile(this));
|
||||
return FilterPatternPlain;
|
||||
}
|
||||
if ( this.caretPos === (this.pattern.length - 1) ) {
|
||||
if ( caretPos === (this.pattern.length - 1) ) {
|
||||
this.pattern = this.pattern.slice(0, -1);
|
||||
units.push(FilterPatternPlain.compile(this));
|
||||
units.push(FilterTrailingSeparator.compile());
|
||||
@ -4027,15 +4073,16 @@ class FilterCompiler {
|
||||
}
|
||||
|
||||
// These are to quickly test whether a filter is composite
|
||||
const FROM_BIT = 0b000000001;
|
||||
const TO_BIT = 0b000000010;
|
||||
const DENYALLOW_BIT = 0b000000100;
|
||||
const HEADER_BIT = 0b000001000;
|
||||
const STRICT_PARTY_BIT = 0b000010000;
|
||||
const MODIFY_BIT = 0b000100000;
|
||||
const NOT_TYPE_BIT = 0b001000000;
|
||||
const IMPORTANT_BIT = 0b010000000;
|
||||
const METHOD_BIT = 0b100000000;
|
||||
const FROM_BIT = 0b0000000001;
|
||||
const TO_BIT = 0b0000000010;
|
||||
const DENYALLOW_BIT = 0b0000000100;
|
||||
const HEADER_BIT = 0b0000001000;
|
||||
const STRICT_PARTY_BIT = 0b0000010000;
|
||||
const MODIFY_BIT = 0b0000100000;
|
||||
const NOT_TYPE_BIT = 0b0001000000;
|
||||
const IMPORTANT_BIT = 0b0010000000;
|
||||
const METHOD_BIT = 0b0100000000;
|
||||
const IPADDRESS_BIT = 0b1000000000;
|
||||
|
||||
FilterCompiler.prototype.FILTER_OK = 0;
|
||||
FilterCompiler.prototype.FILTER_INVALID = 1;
|
||||
@ -4751,6 +4798,7 @@ StaticNetFilteringEngine.prototype.matchAndFetchModifiers = function(
|
||||
$requestHostname = fctxt.getHostname();
|
||||
$requestMethodBit = fctxt.method || 0;
|
||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||
$requestAddress = fctxt.ipaddress || '';
|
||||
|
||||
const modifierType = modifierTypeFromName.get(modifierName);
|
||||
const modifierBits = modifierBitsFromType.get(modifierType);
|
||||
@ -5048,6 +5096,7 @@ StaticNetFilteringEngine.prototype.matchRequestReverse = function(type, url) {
|
||||
$requestURLRaw = url;
|
||||
$requestMethodBit = 0;
|
||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||
$requestAddress = '';
|
||||
$isBlockImportant = false;
|
||||
this.$filterUnit = 0;
|
||||
|
||||
@ -5116,6 +5165,7 @@ StaticNetFilteringEngine.prototype.matchRequest = function(fctxt, modifiers = 0)
|
||||
$requestHostname = fctxt.getHostname();
|
||||
$requestMethodBit = fctxt.method || 0;
|
||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||
$requestAddress = fctxt.ipaddress || '';
|
||||
$isBlockImportant = false;
|
||||
|
||||
// Evaluate block realm before allow realm, and allow realm before
|
||||
@ -5151,6 +5201,7 @@ StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, headers) {
|
||||
$requestHostname = fctxt.getHostname();
|
||||
$requestMethodBit = fctxt.method || 0;
|
||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||
$requestAddress = fctxt.ipaddress || '';
|
||||
$httpHeaders.init(headers);
|
||||
|
||||
let r = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user