1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-15 15:32:28 +02:00

Improve reporting of matching redirect= rules in logger

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.
This commit is contained in:
Raymond Hill 2020-12-01 09:29:40 -05:00
parent e08f8cb001
commit cf2c638d8e
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
4 changed files with 42 additions and 46 deletions

View File

@ -192,11 +192,12 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
parser.commentSpan.i, parser.commentSpan.i,
parser.BITComma 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 ) { if ( redirectNames.has(token) === false ) {
style += ' warning'; style += ' warning';
} }
stream.pos += token.length; stream.pos += raw.length;
parserSlot = end; parserSlot = end;
return style; return style;
} }

View File

@ -716,10 +716,10 @@ const PageStore = class {
redirectBlockedRequest(fctxt) { redirectBlockedRequest(fctxt) {
if ( µb.hiddenSettings.ignoreRedirectFilters === true ) { return; } if ( µb.hiddenSettings.ignoreRedirectFilters === true ) { return; }
const directive = µb.staticNetFilteringEngine.redirectRequest(fctxt); const directives = µb.staticNetFilteringEngine.redirectRequest(fctxt);
if ( directive === undefined ) { return; } if ( directives === undefined ) { return; }
if ( µb.logger.enabled !== true ) { return; } if ( µb.logger.enabled !== true ) { return; }
fctxt.pushFilter(directive.logData()); fctxt.pushFilters(directives.map(a => a.logData()));
if ( fctxt.redirectURL === undefined ) { return; } if ( fctxt.redirectURL === undefined ) { return; }
fctxt.pushFilter({ fctxt.pushFilter({
source: 'redirect', source: 'redirect',

View File

@ -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) { static parseQueryPruneValue(arg) {
let s = arg.trim(); let s = arg.trim();
if ( s === '' ) { return { all: true }; } if ( s === '' ) { return { all: true }; }

View File

@ -4236,57 +4236,41 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
const directives = this.matchAndFetchModifiers(fctxt, 'redirect-rule'); const directives = this.matchAndFetchModifiers(fctxt, 'redirect-rule');
// No directive is the most common occurrence. // No directive is the most common occurrence.
if ( directives === undefined ) { return; } if ( directives === undefined ) { return; }
// A single directive should be the next most common occurrence. // More than a single directive means more work.
if ( directives.length === 1 ) { if ( directives.length !== 1 ) {
const directive = directives[0]; directives.sort(FilterContainer.compareRedirectRequests);
if ( (directive.bits & AllowAction) !== 0 ) { return directive; } }
const modifier = directive.modifier; // Redirect to highest-ranked directive
const { token } = this.parseRedirectRequestValue(modifier); const directive = directives[directives.length - 1];
if ( (directive.bits & AllowAction) === 0 ) {
const { token } =
FilterContainer.parseRedirectRequestValue(directive.modifier);
fctxt.redirectURL = µb.redirectEngine.tokenToURL(fctxt, token); fctxt.redirectURL = µb.redirectEngine.tokenToURL(fctxt, token);
if ( fctxt.redirectURL === undefined ) { return; } if ( fctxt.redirectURL === undefined ) { return; }
return directive;
} }
// Multiple directives mean more work to do. return directives;
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;
}; };
FilterContainer.prototype.parseRedirectRequestValue = function(modifier) { FilterContainer.parseRedirectRequestValue = function(modifier) {
if ( modifier.cache === undefined ) { if ( modifier.cache === undefined ) {
let token = modifier.value; modifier.cache =
let priority = 1; vAPI.StaticFilteringParser.parseRedirectValue(modifier.value);
const match = /:(\d+)$/.exec(token);
if ( match !== null ) {
token = token.slice(0, match.index);
priority = parseInt(match[1], 10);
}
modifier.cache = { token, priority };
} }
return modifier.cache; 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) { FilterContainer.prototype.filterQuery = function(fctxt) {