From 6f96fcbc445ce3a2a92681261edb5c26c20fa7c1 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 14 Oct 2024 23:53:07 +0900 Subject: [PATCH] fix: resolve alias with slashes before conversion Adguard dnr converter doesn't allow you to convert redirect filters with slash value to dnr. This PR solves the problem by replacing the slash value prior to the dnr conversion. --- src/converters/adguard.js | 2 +- src/converters/helpers.js | 53 ++++++++++++++++++---------- test/unit/converters/helpers.spec.js | 11 ++++++ 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/converters/adguard.js b/src/converters/adguard.js index c2cb6be..5b24224 100644 --- a/src/converters/adguard.js +++ b/src/converters/adguard.js @@ -19,7 +19,7 @@ export default async function convert(rules, { resourcesPath } = {}) { const declarativeRules = await conversionResult.ruleSet.getDeclarativeRules(); return { - rules: declarativeRules.map(normalizeRule), + rules: declarativeRules.map(rule => normalizeRule(rule)), errors: conversionResult.errors, limitations: conversionResult.limitations, }; diff --git a/src/converters/helpers.js b/src/converters/helpers.js index f9ef977..4dd0523 100644 --- a/src/converters/helpers.js +++ b/src/converters/helpers.js @@ -8,22 +8,14 @@ function getPathBasename(path) { return path.slice(lastIndex + 1); } -function getPathDirname(path) { - const lastIndex = path.lastIndexOf('/'); - if (lastIndex === -1) { - return '.'; - } - return path.slice(0, lastIndex); -} - export function generateResourcesMapping() { - const mappings = new Map(); + const resourcesMapping = new Map(); for (const names of definition) { for (const name of names.slice(1)) { - mappings.set(name, names[0]); + resourcesMapping.set(name, names[0]); } } - return mappings; + return resourcesMapping; } export const DEFAULT_PARAM_MAPPING = { @@ -31,8 +23,12 @@ export const DEFAULT_PARAM_MAPPING = { 'xhr': 'xmlhttprequest', 'frame': 'subdocument' }; +export const DEFAULT_RESOURCES_MAPPING = generateResourcesMapping(); -export function normalizeFilter(filter, { mapping = DEFAULT_PARAM_MAPPING } = {}) { +export function normalizeFilter(filter, { + mapping = DEFAULT_PARAM_MAPPING, + resourcesMapping = DEFAULT_RESOURCES_MAPPING, +} = {}) { let [front, ...back] = filter.split("$"); let params = back.join(',').split(','); @@ -53,6 +49,24 @@ export function normalizeFilter(filter, { mapping = DEFAULT_PARAM_MAPPING } = {} front = front.toLowerCase(); } + // adguard converter doesn't work with $redirect with slash value + // replace possible $redirect params including a slash + const indexOfRedirect = params.findIndex(p => p.startsWith('redirect=') && p.includes('/')); + if (indexOfRedirect !== -1) { + const name = resourcesMapping.get(params[indexOfRedirect].slice(9)); + if (name !== undefined) { + params[indexOfRedirect] = 'redirect=' + name; + } + } + + const indexOfRedirectRule = params.findIndex(p => p.startsWith('redirect-rule=') && p.includes('/')); + if (indexOfRedirectRule !== -1) { + const name = resourcesMapping.get(params[indexOfRedirectRule].slice(14)); + if (name !== undefined) { + params[indexOfRedirectRule] = 'redirect-rule=' + name; + } + } + if (back.length === 0) { return front; } @@ -60,9 +74,9 @@ export function normalizeFilter(filter, { mapping = DEFAULT_PARAM_MAPPING } = {} return `${front}$${params.join(',')}`; } -export const DEFAULT_RESOURCE_MAPPING = generateResourcesMapping(); - -export function normalizeRule(rule, { resourcesMapping = DEFAULT_RESOURCE_MAPPING } = {}) { +export function normalizeRule(rule, { + resourcesMapping = DEFAULT_RESOURCES_MAPPING +} = {}) { if (!rule) { return; } @@ -101,11 +115,14 @@ export function normalizeRule(rule, { resourcesMapping = DEFAULT_RESOURCE_MAPPIN if (newRule.action && newRule.action.type === 'redirect') { const filename = getPathBasename(newRule.action.redirect.extensionPath); - const preferredFilename = resourcesMapping.get(filename); - + const preferredFilename = + resourcesMapping.get(filename) ?? + // try searching without an extension + // adguard converter attaches an file extension at the end + resourcesMapping.get(filename.slice(0, filename.lastIndexOf('.'))); if (preferredFilename !== undefined) { newRule.action.redirect.extensionPath = - getPathDirname(newRule.action.redirect.extensionPath) + '/' + preferredFilename; + newRule.action.redirect.extensionPath.slice(0, -filename.length) + preferredFilename; } } diff --git a/test/unit/converters/helpers.spec.js b/test/unit/converters/helpers.spec.js index 4ec0309..55de872 100644 --- a/test/unit/converters/helpers.spec.js +++ b/test/unit/converters/helpers.spec.js @@ -46,6 +46,17 @@ describe("normalizeFilter", () => { ).toEqual("TEST$match-case"); }); }); + + describe("with redirect param", () => { + it("replaces values with slashes", () => { + expect( + normalizeFilter("test$redirect=scorecardresearch.com/beacon.js") + ).toEqual("test$redirect=scorecardresearch_beacon.js"); + expect( + normalizeFilter("test$redirect-rule=scorecardresearch.com/beacon.js") + ).toEqual("test$redirect-rule=scorecardresearch_beacon.js"); + }); + }); }); describe('normalizeRule', () => {