diff --git a/src/js/static-filtering-parser.js b/src/js/static-filtering-parser.js index f9dca0000..7ff107786 100644 --- a/src/js/static-filtering-parser.js +++ b/src/js/static-filtering-parser.js @@ -174,6 +174,7 @@ export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++; export const NODE_TYPE_NET_OPTION_NAME_IPADDRESS = iota++; export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++; export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++; +export const NODE_TYPE_NET_OPTION_NAME_MESSAGE = iota++; export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++; export const NODE_TYPE_NET_OPTION_NAME_MP4 = iota++; export const NODE_TYPE_NET_OPTION_NAME_NOOP = iota++; @@ -255,6 +256,7 @@ export const nodeTypeFromOptionName = new Map([ [ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ], [ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ], [ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ], + [ 'message', NODE_TYPE_NET_OPTION_NAME_MESSAGE ], [ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ], [ 'mp4', NODE_TYPE_NET_OPTION_NAME_MP4 ], [ '_', NODE_TYPE_NET_OPTION_NAME_NOOP ], @@ -1350,6 +1352,9 @@ export class AstFilterParser { case NODE_TYPE_NET_OPTION_NAME_MATCHCASE: realBad = this.isRegexPattern() === false; break; + case NODE_TYPE_NET_OPTION_NAME_MESSAGE: + realBad = hasValue === false; + break; case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS: realBad = modifierType !== 0 || (hasValue || isException) === false || @@ -3149,6 +3154,7 @@ export const netOptionTokenDescriptors = new Map([ [ 'ipaddress', { mustAssign: true } ], [ 'match-case', { } ], [ 'media', { canNegate: true } ], + [ 'message', { mustAssign: true } ], [ 'method', { mustAssign: true } ], [ 'mp4', { blockOnly: true } ], [ '_', { } ], diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 65eabf94c..2f0bd8e3f 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -3103,6 +3103,39 @@ class FilterIPAddress { registerFilterClass(FilterIPAddress); +/******************************************************************************/ + +class FilterMessage { + static match() { + return true; + } + + static compile(details) { + return [ + FilterMessage.fid, + encodeURIComponent(details.optionValues.get('message')), + ]; + } + + static fromCompiled(args) { + const msg = args[1]; + return filterDataAlloc(args[0], bidiTrie.storeString(msg), msg.length); + } + + static keyFromArgs() { + } + + static logData(idata, details) { + const msg = bidiTrie.extractString( + filterData[idata+1], + filterData[idata+2] + ); + details.options.push(`message=${decodeURIComponent(msg)}`); + } +} + +registerFilterClass(FilterMessage); + /******************************************************************************/ /******************************************************************************/ @@ -3578,6 +3611,10 @@ class FilterCompiler { this.optionValues.set('ipaddress', parser.getNetOptionValue(id) || ''); this.optionUnitBits |= IPADDRESS_BIT; break; + case sfp.NODE_TYPE_NET_OPTION_NAME_MESSAGE: + this.optionValues.set('message', parser.getNetOptionValue(id)); + this.optionUnitBits |= MESSAGE_BIT; + break; case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD: this.processMethodOption(parser.getNetOptionValue(id)); this.optionUnitBits |= METHOD_BIT; @@ -3699,6 +3736,7 @@ class FilterCompiler { case sfp.NODE_TYPE_NET_OPTION_NAME_FROM: case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER: case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS: + case sfp.NODE_TYPE_NET_OPTION_NAME_MESSAGE: case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD: case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS: case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: @@ -4081,6 +4119,11 @@ class FilterCompiler { this.action |= HEADERS_REALM; } + // Message + if ( (this.optionUnitBits & MESSAGE_BIT) !== 0 ) { + units.push(FilterMessage.compile(this)); + } + // Important // // IMPORTANT: must always appear at the end of the sequence, so as to @@ -4175,16 +4218,17 @@ class FilterCompiler { } // These are to quickly test whether a filter is composite -const FROM_BIT = 0b0000000001; -const TO_BIT = 0b0000000010; -const DENYALLOW_BIT = 0b0000000100; -const HEADER_BIT = 0b0000001000; -const STRICT_PARTY_BIT = 0b0000010000; -const MODIFY_BIT = 0b0000100000; -const NOT_TYPE_BIT = 0b0001000000; -const IMPORTANT_BIT = 0b0010000000; -const METHOD_BIT = 0b0100000000; -const IPADDRESS_BIT = 0b1000000000; +const FROM_BIT = 0b00000000001; +const TO_BIT = 0b00000000010; +const DENYALLOW_BIT = 0b00000000100; +const HEADER_BIT = 0b00000001000; +const STRICT_PARTY_BIT = 0b00000010000; +const MODIFY_BIT = 0b00000100000; +const NOT_TYPE_BIT = 0b00001000000; +const IMPORTANT_BIT = 0b00010000000; +const METHOD_BIT = 0b00100000000; +const IPADDRESS_BIT = 0b01000000000; +const MESSAGE_BIT = 0b10000000000 FilterCompiler.prototype.FILTER_OK = 0; FilterCompiler.prototype.FILTER_INVALID = 1;