Skip to content

Commit

Permalink
handle noop modifier as multiple underscores
Browse files Browse the repository at this point in the history
  • Loading branch information
slavaleleka committed Aug 8, 2023
1 parent eea2cba commit 601fce7
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/agtree/src/validator/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export const INVALID_ERROR_PREFIX = {
NOT_NEGATABLE: 'Not negatable modifier',
VALUE_REQUIRED: 'Value is required for the modifier',
VALUE_FORBIDDEN: 'Value is not allowed for the modifier',
INVALID_NOOP: 'Invalid noop modifier',
};
32 changes: 31 additions & 1 deletion packages/agtree/src/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* @file Validator for modifiers.
*/

import cloneDeep from 'clone-deep';

import {
type ModifierData,
type ModifierDataMap,
Expand All @@ -10,6 +12,7 @@ import {
} from '../compatibility-tables';
import { Modifier } from '../parser/common';
import { AdblockSyntax } from '../utils/adblockers';
import { UNDERSCORE } from '../utils/constants';
import { INVALID_ERROR_PREFIX } from './constants';

const BLOCKER_PREFIX = {
Expand Down Expand Up @@ -209,6 +212,17 @@ const getBlockerDocumentationLink = (
return specificBlockerData?.docs || null;
};

/**
* Validates the noop modifier (i.e. only underscores).
*
* @param value Value of the modifier.
*
* @returns True if the modifier is valid, false otherwise.
*/
const isValidNoopModifier = (value: string): boolean => {
return value.split('').every((char) => char === UNDERSCORE);
};

/**
* Modifier validator class.
*/
Expand Down Expand Up @@ -259,7 +273,23 @@ class ModifierValidator {
*
* @returns Result of modifier validation.
*/
public validate = (syntax: AdblockSyntax, modifier: Modifier, isException = false): ValidationResult => {
public validate = (syntax: AdblockSyntax, rawModifier: Modifier, isException = false): ValidationResult => {
const modifier = cloneDeep(rawModifier);

// handle noop modifier which may be used as multiple underscores (not just one)
// https://adguard.com/kb/general/ad-filtering/create-own-filters/#noop-modifier
if (modifier.modifier.value.startsWith(UNDERSCORE)) {
// check whether the modifier value contains something else besides underscores
if (!isValidNoopModifier(modifier.modifier.value)) {
return getInvalidValidationResult(
`${INVALID_ERROR_PREFIX.INVALID_NOOP}: '${modifier.modifier.value}'`,
);
}
// otherwise, replace the modifier value with single underscore.
// it is needed to check whether the modifier is supported by specific adblocker due to the syntax
modifier.modifier.value = UNDERSCORE;
}

if (!this.exists(modifier)) {
return getInvalidValidationResult(`${INVALID_ERROR_PREFIX.NOT_EXISTENT}: '${modifier.modifier.value}'`);
}
Expand Down
25 changes: 20 additions & 5 deletions packages/agtree/test/validator/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ describe('ModifierValidator', () => {
'app=com.test.app',
'~third-party',
'badfilter',
// valid noop modifiers may be used like this:
'____',
];
test.each(supportedModifiers)('%s', (rawModifier) => {
const modifier = getModifier(rawModifier);
Expand All @@ -196,7 +198,7 @@ describe('ModifierValidator', () => {
});
});

describe('unsupported', () => {
describe('invalid', () => {
const unsupportedModifiersCases = [
{
actual: 'not-existent',
Expand Down Expand Up @@ -246,6 +248,10 @@ describe('ModifierValidator', () => {
actual: 'third-party=true',
expected: INVALID_ERROR_PREFIX.VALUE_FORBIDDEN,
},
{
actual: '__noop__',
expected: INVALID_ERROR_PREFIX.INVALID_NOOP,
},
];
test.each(unsupportedModifiersCases)('$actual', ({ actual, expected }) => {
const modifier = getModifier(actual);
Expand Down Expand Up @@ -322,12 +328,13 @@ describe('ModifierValidator', () => {
});

describe('validate for UblockOrigin', () => {
describe('supported', () => {
describe('valid', () => {
const supportedModifiers = [
'all',
'~third-party',
'badfilter',
'popunder',
'____',
];
test.each(supportedModifiers)('%s', (rawModifier) => {
const modifier = getModifier(rawModifier);
Expand All @@ -336,7 +343,7 @@ describe('ModifierValidator', () => {
});
});

describe('unsupported', () => {
describe('invalid', () => {
const unsupportedModifiersCases = [
{
actual: 'not-existent',
Expand Down Expand Up @@ -386,6 +393,10 @@ describe('ModifierValidator', () => {
actual: 'third-party=true',
expected: INVALID_ERROR_PREFIX.VALUE_FORBIDDEN,
},
{
actual: '__-__',
expected: INVALID_ERROR_PREFIX.INVALID_NOOP,
},
];
test.each(unsupportedModifiersCases)('$actual', ({ actual, expected }) => {
const modifier = getModifier(actual);
Expand Down Expand Up @@ -451,7 +462,7 @@ describe('ModifierValidator', () => {
});

describe('validate for AdblockPlus', () => {
describe('supported', () => {
describe('valid', () => {
const supportedModifiers = [
'domain=example.com',
'third-party',
Expand All @@ -465,7 +476,7 @@ describe('ModifierValidator', () => {
});
});

describe('unsupported', () => {
describe('invalid', () => {
const unsupportedModifiersCases = [
{
actual: 'not-existent',
Expand Down Expand Up @@ -507,6 +518,10 @@ describe('ModifierValidator', () => {
actual: 'third-party=true',
expected: INVALID_ERROR_PREFIX.VALUE_FORBIDDEN,
},
{
actual: '___',
expected: INVALID_ERROR_PREFIX.NOT_SUPPORTED,
},
];
test.each(unsupportedModifiersCases)('$actual', ({ actual, expected }) => {
const modifier = getModifier(actual);
Expand Down

0 comments on commit 601fce7

Please sign in to comment.