Skip to content

Commit c6dedd2

Browse files
committed
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
1 parent 2011569 commit c6dedd2

File tree

4 files changed

+194
-100
lines changed

4 files changed

+194
-100
lines changed

src/js/background.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ const µBlock = { // jshint ignore:line
307307
this.setMethod(details.method);
308308
this.setURL(details.url);
309309
this.aliasURL = details.aliasURL || undefined;
310+
this.ipaddress = details.ip || undefined;
310311
this.redirectURL = undefined;
311312
this.filter = undefined;
312313
if ( this.itype !== this.SUB_FRAME ) {

src/js/filtering-context.js

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,9 @@
1919
Home: https://github.com/gorhill/uBlock
2020
*/
2121

22-
'use strict';
23-
24-
/******************************************************************************/
25-
2622
import {
27-
hostnameFromURI,
2823
domainFromHostname,
24+
hostnameFromURI,
2925
originFromURI,
3026
} from './uri-utils.js';
3127

@@ -140,6 +136,7 @@ export const FilteringContext = class {
140136
this.stype = undefined;
141137
this.url = undefined;
142138
this.aliasURL = undefined;
139+
this.ipaddress = undefined;
143140
this.hostname = undefined;
144141
this.domain = undefined;
145142
this.docId = -1;
@@ -418,42 +415,72 @@ export const FilteringContext = class {
418415
static getMethodName(a) {
419416
return methodBitToStrMap.get(a) || '';
420417
}
421-
};
422-
423-
/******************************************************************************/
424418

425-
FilteringContext.prototype.BEACON = FilteringContext.BEACON = BEACON;
426-
FilteringContext.prototype.CSP_REPORT = FilteringContext.CSP_REPORT = CSP_REPORT;
427-
FilteringContext.prototype.FONT = FilteringContext.FONT = FONT;
428-
FilteringContext.prototype.IMAGE = FilteringContext.IMAGE = IMAGE;
429-
FilteringContext.prototype.IMAGESET = FilteringContext.IMAGESET = IMAGESET;
430-
FilteringContext.prototype.MAIN_FRAME = FilteringContext.MAIN_FRAME = MAIN_FRAME;
431-
FilteringContext.prototype.MEDIA = FilteringContext.MEDIA = MEDIA;
432-
FilteringContext.prototype.OBJECT = FilteringContext.OBJECT = OBJECT;
433-
FilteringContext.prototype.OBJECT_SUBREQUEST = FilteringContext.OBJECT_SUBREQUEST = OBJECT_SUBREQUEST;
434-
FilteringContext.prototype.PING = FilteringContext.PING = PING;
435-
FilteringContext.prototype.SCRIPT = FilteringContext.SCRIPT = SCRIPT;
436-
FilteringContext.prototype.STYLESHEET = FilteringContext.STYLESHEET = STYLESHEET;
437-
FilteringContext.prototype.SUB_FRAME = FilteringContext.SUB_FRAME = SUB_FRAME;
438-
FilteringContext.prototype.WEBSOCKET = FilteringContext.WEBSOCKET = WEBSOCKET;
439-
FilteringContext.prototype.XMLHTTPREQUEST = FilteringContext.XMLHTTPREQUEST = XMLHTTPREQUEST;
440-
FilteringContext.prototype.INLINE_FONT = FilteringContext.INLINE_FONT = INLINE_FONT;
441-
FilteringContext.prototype.INLINE_SCRIPT = FilteringContext.INLINE_SCRIPT = INLINE_SCRIPT;
442-
FilteringContext.prototype.OTHER = FilteringContext.OTHER = OTHER;
443-
FilteringContext.prototype.FRAME_ANY = FilteringContext.FRAME_ANY = FRAME_ANY;
444-
FilteringContext.prototype.FONT_ANY = FilteringContext.FONT_ANY = FONT_ANY;
445-
FilteringContext.prototype.INLINE_ANY = FilteringContext.INLINE_ANY = INLINE_ANY;
446-
FilteringContext.prototype.PING_ANY = FilteringContext.PING_ANY = PING_ANY;
447-
FilteringContext.prototype.SCRIPT_ANY = FilteringContext.SCRIPT_ANY = SCRIPT_ANY;
448-
449-
FilteringContext.prototype.METHOD_NONE = FilteringContext.METHOD_NONE = METHOD_NONE;
450-
FilteringContext.prototype.METHOD_CONNECT = FilteringContext.METHOD_CONNECT = METHOD_CONNECT;
451-
FilteringContext.prototype.METHOD_DELETE = FilteringContext.METHOD_DELETE = METHOD_DELETE;
452-
FilteringContext.prototype.METHOD_GET = FilteringContext.METHOD_GET = METHOD_GET;
453-
FilteringContext.prototype.METHOD_HEAD = FilteringContext.METHOD_HEAD = METHOD_HEAD;
454-
FilteringContext.prototype.METHOD_OPTIONS = FilteringContext.METHOD_OPTIONS = METHOD_OPTIONS;
455-
FilteringContext.prototype.METHOD_PATCH = FilteringContext.METHOD_PATCH = METHOD_PATCH;
456-
FilteringContext.prototype.METHOD_POST = FilteringContext.METHOD_POST = METHOD_POST;
457-
FilteringContext.prototype.METHOD_PUT = FilteringContext.METHOD_PUT = METHOD_PUT;
419+
BEACON = BEACON;
420+
CSP_REPORT = CSP_REPORT;
421+
FONT = FONT;
422+
IMAGE = IMAGE;
423+
IMAGESET = IMAGESET;
424+
MAIN_FRAME = MAIN_FRAME;
425+
MEDIA = MEDIA;
426+
OBJECT = OBJECT;
427+
OBJECT_SUBREQUEST = OBJECT_SUBREQUEST;
428+
PING = PING;
429+
SCRIPT = SCRIPT;
430+
STYLESHEET = STYLESHEET;
431+
SUB_FRAME = SUB_FRAME;
432+
WEBSOCKET = WEBSOCKET;
433+
XMLHTTPREQUEST = XMLHTTPREQUEST;
434+
INLINE_FONT = INLINE_FONT;
435+
INLINE_SCRIPT = INLINE_SCRIPT;
436+
OTHER = OTHER;
437+
FRAME_ANY = FRAME_ANY;
438+
FONT_ANY = FONT_ANY;
439+
INLINE_ANY = INLINE_ANY;
440+
PING_ANY = PING_ANY;
441+
SCRIPT_ANY = SCRIPT_ANY;
442+
METHOD_NONE = METHOD_NONE;
443+
METHOD_CONNECT = METHOD_CONNECT;
444+
METHOD_DELETE = METHOD_DELETE;
445+
METHOD_GET = METHOD_GET;
446+
METHOD_HEAD = METHOD_HEAD;
447+
METHOD_OPTIONS = METHOD_OPTIONS;
448+
METHOD_PATCH = METHOD_PATCH;
449+
METHOD_POST = METHOD_POST;
450+
METHOD_PUT = METHOD_PUT;
451+
452+
static BEACON = BEACON;
453+
static CSP_REPORT = CSP_REPORT;
454+
static FONT = FONT;
455+
static IMAGE = IMAGE;
456+
static IMAGESET = IMAGESET;
457+
static MAIN_FRAME = MAIN_FRAME;
458+
static MEDIA = MEDIA;
459+
static OBJECT = OBJECT;
460+
static OBJECT_SUBREQUEST = OBJECT_SUBREQUEST;
461+
static PING = PING;
462+
static SCRIPT = SCRIPT;
463+
static STYLESHEET = STYLESHEET;
464+
static SUB_FRAME = SUB_FRAME;
465+
static WEBSOCKET = WEBSOCKET;
466+
static XMLHTTPREQUEST = XMLHTTPREQUEST;
467+
static INLINE_FONT = INLINE_FONT;
468+
static INLINE_SCRIPT = INLINE_SCRIPT;
469+
static OTHER = OTHER;
470+
static FRAME_ANY = FRAME_ANY;
471+
static FONT_ANY = FONT_ANY;
472+
static INLINE_ANY = INLINE_ANY;
473+
static PING_ANY = PING_ANY;
474+
static SCRIPT_ANY = SCRIPT_ANY;
475+
static METHOD_NONE = METHOD_NONE;
476+
static METHOD_CONNECT = METHOD_CONNECT;
477+
static METHOD_DELETE = METHOD_DELETE;
478+
static METHOD_GET = METHOD_GET;
479+
static METHOD_HEAD = METHOD_HEAD;
480+
static METHOD_OPTIONS = METHOD_OPTIONS;
481+
static METHOD_PATCH = METHOD_PATCH;
482+
static METHOD_POST = METHOD_POST;
483+
static METHOD_PUT = METHOD_PUT;
484+
};
458485

459486
/******************************************************************************/

src/js/static-filtering-parser.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export const NODE_TYPE_NET_OPTION_NAME_IMAGE = iota++;
172172
export const NODE_TYPE_NET_OPTION_NAME_IMPORTANT = iota++;
173173
export const NODE_TYPE_NET_OPTION_NAME_INLINEFONT = iota++;
174174
export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++;
175+
export const NODE_TYPE_NET_OPTION_NAME_IPADDRESS = iota++;
175176
export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++;
176177
export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
177178
export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++;
@@ -249,6 +250,7 @@ export const nodeTypeFromOptionName = new Map([
249250
[ 'important', NODE_TYPE_NET_OPTION_NAME_IMPORTANT ],
250251
[ 'inline-font', NODE_TYPE_NET_OPTION_NAME_INLINEFONT ],
251252
[ 'inline-script', NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT ],
253+
[ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ],
252254
[ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
253255
[ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
254256
[ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
@@ -1401,6 +1403,14 @@ export class AstFilterParser {
14011403
modifierType = type;
14021404
unredirectableTypeCount += 1;
14031405
break;
1406+
case NODE_TYPE_NET_OPTION_NAME_IPADDRESS: {
1407+
const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_IPADDRESS);
1408+
if ( /^\/.+\/$/.test(value) ) {
1409+
try { void new RegExp(value); }
1410+
catch(_) { realBad = true; }
1411+
}
1412+
break;
1413+
}
14041414
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
14051415
realBad = this.isRegexPattern() === false;
14061416
break;
@@ -3104,6 +3114,7 @@ export const netOptionTokenDescriptors = new Map([
31043114
[ 'important', { blockOnly: true } ],
31053115
[ 'inline-font', { canNegate: true } ],
31063116
[ 'inline-script', { canNegate: true } ],
3117+
[ 'ipaddress', { mustAssign: true } ],
31073118
[ 'match-case', { } ],
31083119
[ 'media', { canNegate: true } ],
31093120
[ 'method', { mustAssign: true } ],
@@ -4324,6 +4335,7 @@ export const utils = (( ) => {
43244335
[ 'env_safari', 'safari' ],
43254336
[ 'cap_html_filtering', 'html_filtering' ],
43264337
[ 'cap_user_stylesheet', 'user_stylesheet' ],
4338+
[ 'cap_ipaddress', 'ipaddress' ],
43274339
[ 'false', 'false' ],
43284340
// Hoping ABP-only list maintainers can at least make use of it to
43294341
// help non-ABP content blockers better deal with filters benefiting
@@ -4358,8 +4370,11 @@ export const utils = (( ) => {
43584370
static evaluateExprToken(token, env = []) {
43594371
const not = token.charCodeAt(0) === 0x21 /* ! */;
43604372
if ( not ) { token = token.slice(1); }
4361-
const state = preparserTokens.get(token);
4362-
if ( state === undefined ) { return; }
4373+
let state = preparserTokens.get(token);
4374+
if ( state === undefined ) {
4375+
if ( token.startsWith('cap_') === false ) { return; }
4376+
state = 'false';
4377+
}
43634378
return state === 'false' && not || env.includes(state) !== not;
43644379
}
43654380

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy