Skip to content

Commit

Permalink
Improve reporting of matching redirect= rules in logger
Browse files Browse the repository at this point in the history
All matching `redirect-rule` directives will now be reported
in the logger, instead of just the effective one.

The highest-ranked redirect directive will be the one
effectively used for redirection. This way filter list
authors can see whether a lower priority redirect is
being overriden by a higher priority one.

The default priority has been changed to 10, so as to allow
more leeway to create lower ranked redirect directives.

Additonally, rendering of redirect directives with explicit
priority has been fixed in the logger, they will no longer
be rendered as unknown redirect tokens.
  • Loading branch information
gorhill committed Dec 1, 2020
1 parent e08f8cb commit cf2c638
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 46 deletions.
5 changes: 3 additions & 2 deletions src/js/codemirror/ubo-static-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,12 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
parser.commentSpan.i,
parser.BITComma
);
const token = parser.strFromSlices(parserSlot, end - 3);
const raw = parser.strFromSlices(parserSlot, end - 3);
const { token } = StaticFilteringParser.parseRedirectValue(raw);
if ( redirectNames.has(token) === false ) {
style += ' warning';
}
stream.pos += token.length;
stream.pos += raw.length;
parserSlot = end;
return style;
}
Expand Down
6 changes: 3 additions & 3 deletions src/js/pagestore.js
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,10 @@ const PageStore = class {

redirectBlockedRequest(fctxt) {
if ( µb.hiddenSettings.ignoreRedirectFilters === true ) { return; }
const directive = µb.staticNetFilteringEngine.redirectRequest(fctxt);
if ( directive === undefined ) { return; }
const directives = µb.staticNetFilteringEngine.redirectRequest(fctxt);
if ( directives === undefined ) { return; }
if ( µb.logger.enabled !== true ) { return; }
fctxt.pushFilter(directive.logData());
fctxt.pushFilters(directives.map(a => a.logData()));
if ( fctxt.redirectURL === undefined ) { return; }
fctxt.pushFilter({
source: 'redirect',
Expand Down
11 changes: 11 additions & 0 deletions src/js/static-filtering-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,17 @@ const Parser = class {
);
}

static parseRedirectValue(arg) {
let token = arg.trim();
let priority = 10;
const match = /:\d+$/.exec(token);
if ( match !== null ) {
token = token.slice(0, match.index);
priority = parseInt(token.slice(match.index + 1), 10);
}
return { token, priority };
}

static parseQueryPruneValue(arg) {
let s = arg.trim();
if ( s === '' ) { return { all: true }; }
Expand Down
66 changes: 25 additions & 41 deletions src/js/static-net-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -4236,57 +4236,41 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
const directives = this.matchAndFetchModifiers(fctxt, 'redirect-rule');
// No directive is the most common occurrence.
if ( directives === undefined ) { return; }
// A single directive should be the next most common occurrence.
if ( directives.length === 1 ) {
const directive = directives[0];
if ( (directive.bits & AllowAction) !== 0 ) { return directive; }
const modifier = directive.modifier;
const { token } = this.parseRedirectRequestValue(modifier);
// More than a single directive means more work.
if ( directives.length !== 1 ) {
directives.sort(FilterContainer.compareRedirectRequests);
}
// Redirect to highest-ranked directive
const directive = directives[directives.length - 1];
if ( (directive.bits & AllowAction) === 0 ) {
const { token } =
FilterContainer.parseRedirectRequestValue(directive.modifier);
fctxt.redirectURL = µb.redirectEngine.tokenToURL(fctxt, token);
if ( fctxt.redirectURL === undefined ) { return; }
return directive;
}
// Multiple directives mean more work to do.
let winningDirective;
let winningPriority = 0;
for ( const directive of directives ) {
const modifier = directive.modifier;
const isException = (directive.bits & AllowAction) !== 0;
if ( isException && modifier.value === '' ) {
winningDirective = directive;
break;
}
const { token, priority } = this.parseRedirectRequestValue(modifier);
if ( µb.redirectEngine.hasToken(token) === false ) { continue; }
if ( winningDirective === undefined || priority > winningPriority ) {
winningDirective = directive;
winningPriority = priority;
}
}
if ( winningDirective === undefined ) { return; }
if ( (winningDirective.bits & AllowAction) === 0 ) {
fctxt.redirectURL = µb.redirectEngine.tokenToURL(
fctxt,
winningDirective.modifier.cache.token
);
}
return winningDirective;
return directives;
};

FilterContainer.prototype.parseRedirectRequestValue = function(modifier) {
FilterContainer.parseRedirectRequestValue = function(modifier) {
if ( modifier.cache === undefined ) {
let token = modifier.value;
let priority = 1;
const match = /:(\d+)$/.exec(token);
if ( match !== null ) {
token = token.slice(0, match.index);
priority = parseInt(match[1], 10);
}
modifier.cache = { token, priority };
modifier.cache =
vAPI.StaticFilteringParser.parseRedirectValue(modifier.value);
}
return modifier.cache;
};

FilterContainer.compareRedirectRequests = function(a, b) {
if ( (a.bits & AllowAction) !== 0 ) { return -1; }
if ( (b.bits & AllowAction) !== 0 ) { return 1; }
const { token: atok, priority: aint } =
FilterContainer.parseRedirectRequestValue(a.modifier);
if ( µb.redirectEngine.hasToken(atok) === false ) { return -1; }
const { token: btok, priority: bint } =
FilterContainer.parseRedirectRequestValue(b.modifier);
if ( µb.redirectEngine.hasToken(btok) === false ) { return 1; }
return aint - bint;
};

/******************************************************************************/

FilterContainer.prototype.filterQuery = function(fctxt) {
Expand Down

0 comments on commit cf2c638

Please sign in to comment.