mirror of https://github.com/gorhill/uBlock.git
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.setMethod(details.method);
|
||||||
this.setURL(details.url);
|
this.setURL(details.url);
|
||||||
this.aliasURL = details.aliasURL || undefined;
|
this.aliasURL = details.aliasURL || undefined;
|
||||||
|
this.ipaddress = details.ip || undefined;
|
||||||
this.redirectURL = undefined;
|
this.redirectURL = undefined;
|
||||||
this.filter = undefined;
|
this.filter = undefined;
|
||||||
if ( this.itype !== this.SUB_FRAME ) {
|
if ( this.itype !== this.SUB_FRAME ) {
|
||||||
|
|
|
@ -19,13 +19,9 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
hostnameFromURI,
|
|
||||||
domainFromHostname,
|
domainFromHostname,
|
||||||
|
hostnameFromURI,
|
||||||
originFromURI,
|
originFromURI,
|
||||||
} from './uri-utils.js';
|
} from './uri-utils.js';
|
||||||
|
|
||||||
|
@ -140,6 +136,7 @@ export const FilteringContext = class {
|
||||||
this.stype = undefined;
|
this.stype = undefined;
|
||||||
this.url = undefined;
|
this.url = undefined;
|
||||||
this.aliasURL = undefined;
|
this.aliasURL = undefined;
|
||||||
|
this.ipaddress = undefined;
|
||||||
this.hostname = undefined;
|
this.hostname = undefined;
|
||||||
this.domain = undefined;
|
this.domain = undefined;
|
||||||
this.docId = -1;
|
this.docId = -1;
|
||||||
|
@ -418,42 +415,72 @@ export const FilteringContext = class {
|
||||||
static getMethodName(a) {
|
static getMethodName(a) {
|
||||||
return methodBitToStrMap.get(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_IMPORTANT = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_INLINEFONT = 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_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_MATCHCASE = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
|
export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_METHOD = 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 ],
|
[ 'important', NODE_TYPE_NET_OPTION_NAME_IMPORTANT ],
|
||||||
[ 'inline-font', NODE_TYPE_NET_OPTION_NAME_INLINEFONT ],
|
[ 'inline-font', NODE_TYPE_NET_OPTION_NAME_INLINEFONT ],
|
||||||
[ 'inline-script', NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT ],
|
[ 'inline-script', NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT ],
|
||||||
|
[ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ],
|
||||||
[ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
|
[ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
|
||||||
[ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
|
[ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
|
||||||
[ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
|
[ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
|
||||||
|
@ -1401,6 +1403,14 @@ export class AstFilterParser {
|
||||||
modifierType = type;
|
modifierType = type;
|
||||||
unredirectableTypeCount += 1;
|
unredirectableTypeCount += 1;
|
||||||
break;
|
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:
|
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
||||||
realBad = this.isRegexPattern() === false;
|
realBad = this.isRegexPattern() === false;
|
||||||
break;
|
break;
|
||||||
|
@ -3104,6 +3114,7 @@ export const netOptionTokenDescriptors = new Map([
|
||||||
[ 'important', { blockOnly: true } ],
|
[ 'important', { blockOnly: true } ],
|
||||||
[ 'inline-font', { canNegate: true } ],
|
[ 'inline-font', { canNegate: true } ],
|
||||||
[ 'inline-script', { canNegate: true } ],
|
[ 'inline-script', { canNegate: true } ],
|
||||||
|
[ 'ipaddress', { mustAssign: true } ],
|
||||||
[ 'match-case', { } ],
|
[ 'match-case', { } ],
|
||||||
[ 'media', { canNegate: true } ],
|
[ 'media', { canNegate: true } ],
|
||||||
[ 'method', { mustAssign: true } ],
|
[ 'method', { mustAssign: true } ],
|
||||||
|
@ -4324,6 +4335,7 @@ export const utils = (( ) => {
|
||||||
[ 'env_safari', 'safari' ],
|
[ 'env_safari', 'safari' ],
|
||||||
[ 'cap_html_filtering', 'html_filtering' ],
|
[ 'cap_html_filtering', 'html_filtering' ],
|
||||||
[ 'cap_user_stylesheet', 'user_stylesheet' ],
|
[ 'cap_user_stylesheet', 'user_stylesheet' ],
|
||||||
|
[ 'cap_ipaddress', 'ipaddress' ],
|
||||||
[ 'false', 'false' ],
|
[ 'false', 'false' ],
|
||||||
// Hoping ABP-only list maintainers can at least make use of it to
|
// Hoping ABP-only list maintainers can at least make use of it to
|
||||||
// help non-ABP content blockers better deal with filters benefiting
|
// help non-ABP content blockers better deal with filters benefiting
|
||||||
|
@ -4358,8 +4370,11 @@ export const utils = (( ) => {
|
||||||
static evaluateExprToken(token, env = []) {
|
static evaluateExprToken(token, env = []) {
|
||||||
const not = token.charCodeAt(0) === 0x21 /* ! */;
|
const not = token.charCodeAt(0) === 0x21 /* ! */;
|
||||||
if ( not ) { token = token.slice(1); }
|
if ( not ) { token = token.slice(1); }
|
||||||
const state = preparserTokens.get(token);
|
let state = preparserTokens.get(token);
|
||||||
if ( state === undefined ) { return; }
|
if ( state === undefined ) {
|
||||||
|
if ( token.startsWith('cap_') === false ) { return; }
|
||||||
|
state = 'false';
|
||||||
|
}
|
||||||
return state === 'false' && not || env.includes(state) !== not;
|
return state === 'false' && not || env.includes(state) !== not;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,6 +242,7 @@ let $requestTypeValue = 0;
|
||||||
let $requestURL = '';
|
let $requestURL = '';
|
||||||
let $requestURLRaw = '';
|
let $requestURLRaw = '';
|
||||||
let $requestHostname = '';
|
let $requestHostname = '';
|
||||||
|
let $requestAddress = '';
|
||||||
let $docHostname = '';
|
let $docHostname = '';
|
||||||
let $docDomain = '';
|
let $docDomain = '';
|
||||||
let $tokenBeg = 0;
|
let $tokenBeg = 0;
|
||||||
|
@ -702,6 +703,8 @@ const dnrAddRuleWarning = (rule, msg) => {
|
||||||
FilterNotType
|
FilterNotType
|
||||||
FilterStrictParty
|
FilterStrictParty
|
||||||
FilterModifier
|
FilterModifier
|
||||||
|
FilterOnHeaders
|
||||||
|
FilterIPAddress
|
||||||
|
|
||||||
Collection:
|
Collection:
|
||||||
FilterCollection
|
FilterCollection
|
||||||
|
@ -1234,7 +1237,7 @@ class FilterRegex {
|
||||||
return [
|
return [
|
||||||
FilterRegex.fid,
|
FilterRegex.fid,
|
||||||
details.pattern,
|
details.pattern,
|
||||||
details.patternMatchCase ? 1 : 0
|
details.optionValues.has('match-case') ? 1 : 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2075,7 +2078,7 @@ const compileToDomainOpt = (...args) => {
|
||||||
|
|
||||||
class FilterDenyAllow extends FilterToDomainMissSet {
|
class FilterDenyAllow extends FilterToDomainMissSet {
|
||||||
static compile(details) {
|
static compile(details) {
|
||||||
return super.compile(details.denyallowOpt, 0b01);
|
return super.compile(details.optionValues.get('denyallow'), 0b01);
|
||||||
}
|
}
|
||||||
|
|
||||||
static logData(idata, details) {
|
static logData(idata, details) {
|
||||||
|
@ -2937,12 +2940,12 @@ class FilterOnHeaders {
|
||||||
}
|
}
|
||||||
|
|
||||||
static compile(details) {
|
static compile(details) {
|
||||||
return [ FilterOnHeaders.fid, details.headerOpt ];
|
return [ FilterOnHeaders.fid, details.optionValues.get('header') ];
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromCompiled(args) {
|
static fromCompiled(args) {
|
||||||
return filterDataAlloc(
|
return filterDataAlloc(
|
||||||
args[0], // fid
|
args[0], // fid
|
||||||
filterRefAdd({
|
filterRefAdd({
|
||||||
headerOpt: args[1],
|
headerOpt: args[1],
|
||||||
$parsed: null,
|
$parsed: null,
|
||||||
|
@ -2963,6 +2966,41 @@ class FilterOnHeaders {
|
||||||
|
|
||||||
registerFilterClass(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);
|
return Object.assign(this, other);
|
||||||
}
|
}
|
||||||
this.reToken = /[%0-9A-Za-z]+/g;
|
this.reToken = /[%0-9A-Za-z]+/g;
|
||||||
this.fromDomainOptList = [];
|
this.optionValues = new Map();
|
||||||
this.toDomainOptList = [];
|
|
||||||
this.tokenIdToNormalizedType = new Map([
|
this.tokenIdToNormalizedType = new Map([
|
||||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_CNAME, bitFromType('cname') ],
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_CNAME, bitFromType('cname') ],
|
||||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_CSS, bitFromType('stylesheet') ],
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_CSS, bitFromType('stylesheet') ],
|
||||||
|
@ -3304,13 +3341,9 @@ class FilterCompiler {
|
||||||
this.modifyType = undefined;
|
this.modifyType = undefined;
|
||||||
this.modifyValue = undefined;
|
this.modifyValue = undefined;
|
||||||
this.pattern = '';
|
this.pattern = '';
|
||||||
this.patternMatchCase = false;
|
|
||||||
this.party = ANYPARTY_REALM;
|
this.party = ANYPARTY_REALM;
|
||||||
this.optionUnitBits = 0;
|
this.optionUnitBits = 0;
|
||||||
this.fromDomainOpt = '';
|
this.optionValues.clear();
|
||||||
this.toDomainOpt = '';
|
|
||||||
this.denyallowOpt = '';
|
|
||||||
this.headerOpt = undefined;
|
|
||||||
this.isPureHostname = false;
|
this.isPureHostname = false;
|
||||||
this.isGeneric = false;
|
this.isGeneric = false;
|
||||||
this.isRegex = false;
|
this.isRegex = false;
|
||||||
|
@ -3322,8 +3355,7 @@ class FilterCompiler {
|
||||||
this.notTypeBits = 0;
|
this.notTypeBits = 0;
|
||||||
this.methodBits = 0;
|
this.methodBits = 0;
|
||||||
this.notMethodBits = 0;
|
this.notMethodBits = 0;
|
||||||
this.wildcardPos = -1;
|
this.responseHeadersRealm = false;
|
||||||
this.caretPos = -1;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3421,26 +3453,36 @@ class FilterCompiler {
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
|
||||||
if ( this.processCspOption(parser.getNetOptionValue(id)) === false ) { return false; }
|
if ( this.processCspOption(parser.getNetOptionValue(id)) === false ) { return false; }
|
||||||
break;
|
break;
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW: {
|
||||||
this.denyallowOpt = this.processHostnameList(
|
const value = this.processHostnameList(
|
||||||
parser.getNetFilterDenyallowOptionIterator(),
|
parser.getNetFilterDenyallowOptionIterator()
|
||||||
);
|
);
|
||||||
if ( this.denyallowOpt === '' ) { return false; }
|
if ( value === '' ) { return false; }
|
||||||
|
this.optionValues.set('denyallow', value);
|
||||||
this.optionUnitBits |= DENYALLOW_BIT;
|
this.optionUnitBits |= DENYALLOW_BIT;
|
||||||
break;
|
break;
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
}
|
||||||
this.fromDomainOpt = this.processHostnameList(
|
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM: {
|
||||||
parser.getNetFilterFromOptionIterator(),
|
const iter = parser.getNetFilterFromOptionIterator();
|
||||||
this.fromDomainOptList
|
const list = [];
|
||||||
);
|
const value = this.processHostnameList(iter, list);
|
||||||
if ( this.fromDomainOpt === '' ) { return false; }
|
if ( value === '' ) { return false; }
|
||||||
|
this.optionValues.set('from', value);
|
||||||
|
this.optionValues.set('fromList', list);
|
||||||
this.optionUnitBits |= FROM_BIT;
|
this.optionUnitBits |= FROM_BIT;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER: {
|
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.optionUnitBits |= HEADER_BIT;
|
||||||
|
this.responseHeadersRealm = true;
|
||||||
break;
|
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:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
||||||
this.processMethodOption(parser.getNetOptionValue(id));
|
this.processMethodOption(parser.getNetOptionValue(id));
|
||||||
this.optionUnitBits |= METHOD_BIT;
|
this.optionUnitBits |= METHOD_BIT;
|
||||||
|
@ -3465,14 +3507,16 @@ class FilterCompiler {
|
||||||
this.optionUnitBits |= MODIFY_BIT;
|
this.optionUnitBits |= MODIFY_BIT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_TO:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_TO: {
|
||||||
this.toDomainOpt = this.processHostnameList(
|
const iter = parser.getNetFilterToOptionIterator();
|
||||||
parser.getNetFilterToOptionIterator(),
|
const list = [];
|
||||||
this.toDomainOptList
|
const value = this.processHostnameList(iter, list);
|
||||||
);
|
if ( value === '' ) { return false; }
|
||||||
if ( this.toDomainOpt === '' ) { return false; }
|
this.optionValues.set('to', value);
|
||||||
|
this.optionValues.set('toList', list);
|
||||||
this.optionUnitBits |= TO_BIT;
|
this.optionUnitBits |= TO_BIT;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3558,6 +3602,7 @@ class FilterCompiler {
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
|
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_METHOD:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
||||||
|
@ -3591,7 +3636,7 @@ class FilterCompiler {
|
||||||
this.action = BLOCKIMPORTANT_REALM;
|
this.action = BLOCKIMPORTANT_REALM;
|
||||||
break;
|
break;
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
||||||
this.patternMatchCase = true;
|
this.optionValues.set('match-case', true);
|
||||||
break;
|
break;
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_MP4: {
|
case sfp.NODE_TYPE_NET_OPTION_NAME_MP4: {
|
||||||
const id = this.action === ALLOW_REALM
|
const id = this.action === ALLOW_REALM
|
||||||
|
@ -3661,11 +3706,6 @@ class FilterCompiler {
|
||||||
return this.FILTER_OK;
|
return this.FILTER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this.isGeneric ) {
|
|
||||||
this.wildcardPos = this.pattern.indexOf('*');
|
|
||||||
this.caretPos = this.pattern.indexOf('^');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( this.pattern.length > 1024 ) {
|
if ( this.pattern.length > 1024 ) {
|
||||||
return this.FILTER_UNSUPPORTED;
|
return this.FILTER_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -3793,7 +3833,7 @@ class FilterCompiler {
|
||||||
isJustOrigin() {
|
isJustOrigin() {
|
||||||
if ( this.optionUnitBits !== FROM_BIT ) { return false; }
|
if ( this.optionUnitBits !== FROM_BIT ) { return false; }
|
||||||
if ( this.isRegex ) { 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.pattern === '*' ) { return true; }
|
||||||
if ( this.anchor !== 0b010 ) { return false; }
|
if ( this.anchor !== 0b010 ) { return false; }
|
||||||
if ( /^(?:http[s*]?:(?:\/\/)?)$/.test(this.pattern) ) { return true; }
|
if ( /^(?:http[s*]?:(?:\/\/)?)$/.test(this.pattern) ) { return true; }
|
||||||
|
@ -3870,7 +3910,7 @@ class FilterCompiler {
|
||||||
} else /* 'http:' */ {
|
} else /* 'http:' */ {
|
||||||
this.tokenHash = ANY_HTTP_TOKEN_HASH;
|
this.tokenHash = ANY_HTTP_TOKEN_HASH;
|
||||||
}
|
}
|
||||||
for ( const hn of this.fromDomainOptList ) {
|
for ( const hn of this.optionValues.get('fromList') ) {
|
||||||
this.compileToAtomicFilter(hn, writer);
|
this.compileToAtomicFilter(hn, writer);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -3911,31 +3951,36 @@ class FilterCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Origin
|
// Origin
|
||||||
if ( this.fromDomainOpt !== '' ) {
|
if ( this.optionValues.has('from') ) {
|
||||||
compileFromDomainOpt(
|
compileFromDomainOpt(
|
||||||
this.fromDomainOptList,
|
this.optionValues.get('fromList'),
|
||||||
units.length !== 0 && patternClass.isSlow === true,
|
units.length !== 0 && patternClass.isSlow === true,
|
||||||
units
|
units
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destination
|
// Destination
|
||||||
if ( this.toDomainOpt !== '' ) {
|
if ( this.optionValues.has('to') ) {
|
||||||
compileToDomainOpt(
|
compileToDomainOpt(
|
||||||
this.toDomainOptList,
|
this.optionValues.get('toList'),
|
||||||
units.length !== 0 && patternClass.isSlow === true,
|
units.length !== 0 && patternClass.isSlow === true,
|
||||||
units
|
units
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deny-allow
|
// Deny-allow
|
||||||
if ( this.denyallowOpt !== '' ) {
|
if ( this.optionValues.has('denyallow') ) {
|
||||||
units.push(FilterDenyAllow.compile(this));
|
units.push(FilterDenyAllow.compile(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
if ( this.headerOpt !== undefined ) {
|
if ( this.responseHeadersRealm ) {
|
||||||
units.push(FilterOnHeaders.compile(this));
|
if ( this.optionValues.has('ipaddress') ) {
|
||||||
|
units.push(FilterIPAddress.compile(this));
|
||||||
|
}
|
||||||
|
if ( this.optionValues.has('header') ) {
|
||||||
|
units.push(FilterOnHeaders.compile(this));
|
||||||
|
}
|
||||||
this.action |= HEADERS_REALM;
|
this.action |= HEADERS_REALM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3977,12 +4022,13 @@ class FilterCompiler {
|
||||||
units.push(FilterPatternGeneric.compile(this));
|
units.push(FilterPatternGeneric.compile(this));
|
||||||
return FilterPatternGeneric;
|
return FilterPatternGeneric;
|
||||||
}
|
}
|
||||||
if ( this.wildcardPos === -1 ) {
|
if ( this.pattern.includes('*') === false ) {
|
||||||
if ( this.caretPos === -1 ) {
|
const caretPos = this.pattern.indexOf('^');
|
||||||
|
if ( caretPos === -1 ) {
|
||||||
units.push(FilterPatternPlain.compile(this));
|
units.push(FilterPatternPlain.compile(this));
|
||||||
return FilterPatternPlain;
|
return FilterPatternPlain;
|
||||||
}
|
}
|
||||||
if ( this.caretPos === (this.pattern.length - 1) ) {
|
if ( caretPos === (this.pattern.length - 1) ) {
|
||||||
this.pattern = this.pattern.slice(0, -1);
|
this.pattern = this.pattern.slice(0, -1);
|
||||||
units.push(FilterPatternPlain.compile(this));
|
units.push(FilterPatternPlain.compile(this));
|
||||||
units.push(FilterTrailingSeparator.compile());
|
units.push(FilterTrailingSeparator.compile());
|
||||||
|
@ -4027,15 +4073,16 @@ class FilterCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are to quickly test whether a filter is composite
|
// These are to quickly test whether a filter is composite
|
||||||
const FROM_BIT = 0b000000001;
|
const FROM_BIT = 0b0000000001;
|
||||||
const TO_BIT = 0b000000010;
|
const TO_BIT = 0b0000000010;
|
||||||
const DENYALLOW_BIT = 0b000000100;
|
const DENYALLOW_BIT = 0b0000000100;
|
||||||
const HEADER_BIT = 0b000001000;
|
const HEADER_BIT = 0b0000001000;
|
||||||
const STRICT_PARTY_BIT = 0b000010000;
|
const STRICT_PARTY_BIT = 0b0000010000;
|
||||||
const MODIFY_BIT = 0b000100000;
|
const MODIFY_BIT = 0b0000100000;
|
||||||
const NOT_TYPE_BIT = 0b001000000;
|
const NOT_TYPE_BIT = 0b0001000000;
|
||||||
const IMPORTANT_BIT = 0b010000000;
|
const IMPORTANT_BIT = 0b0010000000;
|
||||||
const METHOD_BIT = 0b100000000;
|
const METHOD_BIT = 0b0100000000;
|
||||||
|
const IPADDRESS_BIT = 0b1000000000;
|
||||||
|
|
||||||
FilterCompiler.prototype.FILTER_OK = 0;
|
FilterCompiler.prototype.FILTER_OK = 0;
|
||||||
FilterCompiler.prototype.FILTER_INVALID = 1;
|
FilterCompiler.prototype.FILTER_INVALID = 1;
|
||||||
|
@ -4751,6 +4798,7 @@ StaticNetFilteringEngine.prototype.matchAndFetchModifiers = function(
|
||||||
$requestHostname = fctxt.getHostname();
|
$requestHostname = fctxt.getHostname();
|
||||||
$requestMethodBit = fctxt.method || 0;
|
$requestMethodBit = fctxt.method || 0;
|
||||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||||
|
$requestAddress = fctxt.ipaddress || '';
|
||||||
|
|
||||||
const modifierType = modifierTypeFromName.get(modifierName);
|
const modifierType = modifierTypeFromName.get(modifierName);
|
||||||
const modifierBits = modifierBitsFromType.get(modifierType);
|
const modifierBits = modifierBitsFromType.get(modifierType);
|
||||||
|
@ -5048,6 +5096,7 @@ StaticNetFilteringEngine.prototype.matchRequestReverse = function(type, url) {
|
||||||
$requestURLRaw = url;
|
$requestURLRaw = url;
|
||||||
$requestMethodBit = 0;
|
$requestMethodBit = 0;
|
||||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||||
|
$requestAddress = '';
|
||||||
$isBlockImportant = false;
|
$isBlockImportant = false;
|
||||||
this.$filterUnit = 0;
|
this.$filterUnit = 0;
|
||||||
|
|
||||||
|
@ -5116,6 +5165,7 @@ StaticNetFilteringEngine.prototype.matchRequest = function(fctxt, modifiers = 0)
|
||||||
$requestHostname = fctxt.getHostname();
|
$requestHostname = fctxt.getHostname();
|
||||||
$requestMethodBit = fctxt.method || 0;
|
$requestMethodBit = fctxt.method || 0;
|
||||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||||
|
$requestAddress = fctxt.ipaddress || '';
|
||||||
$isBlockImportant = false;
|
$isBlockImportant = false;
|
||||||
|
|
||||||
// Evaluate block realm before allow realm, and allow realm before
|
// Evaluate block realm before allow realm, and allow realm before
|
||||||
|
@ -5151,6 +5201,7 @@ StaticNetFilteringEngine.prototype.matchHeaders = function(fctxt, headers) {
|
||||||
$requestHostname = fctxt.getHostname();
|
$requestHostname = fctxt.getHostname();
|
||||||
$requestMethodBit = fctxt.method || 0;
|
$requestMethodBit = fctxt.method || 0;
|
||||||
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
$requestTypeValue = (typeBits & TypeBitsMask) >>> TypeBitsOffset;
|
||||||
|
$requestAddress = fctxt.ipaddress || '';
|
||||||
$httpHeaders.init(headers);
|
$httpHeaders.init(headers);
|
||||||
|
|
||||||
let r = 0;
|
let r = 0;
|
||||||
|
|
Loading…
Reference in New Issue