From d7c99b46e6221276189ad4edef879f75ae58b0f2 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 5 Nov 2023 11:19:03 -0500 Subject: [PATCH] Have `urltransform=` use the same syntax as `replace=` Related issue: https://github.com/uBlockOrigin/uBlock-issues/issues/2924 --- src/js/static-filtering-parser.js | 12 +++++++----- src/js/static-net-filtering.js | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/js/static-filtering-parser.js b/src/js/static-filtering-parser.js index 49b66d36280f4..a15d78906dd4e 100644 --- a/src/js/static-filtering-parser.js +++ b/src/js/static-filtering-parser.js @@ -1490,9 +1490,10 @@ export class AstFilterParser { realBad = true; break; } - if ( this.interactive ) { - const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_REPLACE); - realBad = parseReplaceValue(value) === undefined; + const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_REPLACE); + if ( parseReplaceValue(value) === undefined ) { + this.astError = AST_ERROR_OPTION_BADVALUE; + realBad = true; } break; } @@ -1504,8 +1505,8 @@ export class AstFilterParser { realBad = true; break; } - const path = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM); - if ( path.charCodeAt(0) !== 0x2F /* / */ ) { + const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM); + if ( parseReplaceValue(value) === undefined ) { this.astError = AST_ERROR_OPTION_BADVALUE; realBad = true; } @@ -3008,6 +3009,7 @@ export function parseReplaceValue(s) { if ( parser.transform ) { pattern = parser.normalizeArg(pattern); } + if ( pattern === '' ) { return; } pattern = pattern .replace(reEscapedDollarSign, '$1$$$') .replace(reEscapedComma, '$1,'); diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index c8bf51059bb61..26248d3874d6d 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -5275,9 +5275,21 @@ FilterContainer.prototype.transformRequest = function(fctxt) { if ( directives === undefined ) { return; } const directive = directives[directives.length-1]; if ( (directive.bits & ALLOW_REALM) !== 0 ) { return directives; } + if ( directive.refs instanceof Object === false ) { return; } + const { refs } = directive; + if ( refs.$cache === null ) { + refs.$cache = sfp.parseReplaceValue(refs.value); + } + const cache = refs.$cache; + if ( cache === undefined ) { return; } const redirectURL = new URL(fctxt.url); - if ( directive.value === redirectURL.pathname ) { return; } - redirectURL.pathname = directive.value; + const before = redirectURL.pathname + redirectURL.search; + if ( cache.re.test(before) !== true ) { return; } + const after = before.replace(cache.re, cache.replacement); + if ( after === before ) { return; } + const searchPos = after.includes('?') && after.indexOf('?') || after.length; + redirectURL.pathname = after.slice(0, searchPos); + redirectURL.search = after.slice(searchPos); fctxt.redirectURL = redirectURL.href; return directives; };