Add support for match-case option; fine-tune behavior of redirect= · gorhill/uBlock@eae7cd5 (original) (raw)
`@@ -146,6 +146,7 @@ const typeValueToTypeName = [
`
146
146
`// valid until the next evaluation.
`
147
147
``
148
148
`let $requestURL = '';
`
``
149
`+
let $requestURLRaw = '';
`
149
150
`let $requestHostname = '';
`
150
151
`let $docHostname = '';
`
151
152
`let $docDomain = '';
`
`@@ -867,9 +868,13 @@ const FilterPatternGeneric = class {
`
867
868
`}
`
868
869
``
869
870
`static compile(details) {
`
870
``
`-
const anchor = details.anchor;
`
``
871
`+
const out = [
`
``
872
`+
FilterPatternGeneric.fid,
`
``
873
`+
details.pattern,
`
``
874
`+
details.anchor,
`
``
875
`+
];
`
871
876
`details.anchor = 0;
`
872
``
`-
return [ FilterPatternGeneric.fid, details.pattern, anchor ];
`
``
877
`+
return out;
`
873
878
`}
`
874
879
``
875
880
`static fromCompiled(args) {
`
`@@ -1107,54 +1112,59 @@ registerFilterClass(FilterTrailingSeparator);
`
1107
1112
`/******************************************************************************/
`
1108
1113
``
1109
1114
`const FilterRegex = class {
`
1110
``
`-
constructor(s) {
`
``
1115
`+
constructor(s, matchCase = false) {
`
1111
1116
`this.s = s;
`
``
1117
`+
if ( matchCase ) {
`
``
1118
`+
this.matchCase = true;
`
``
1119
`+
}
`
1112
1120
`}
`
1113
1121
``
1114
1122
`match() {
`
1115
1123
`if ( this.re === null ) {
`
1116
``
`-
this.re = FilterRegex.dict.get(this.s);
`
1117
``
`-
if ( this.re === undefined ) {
`
1118
``
`-
this.re = new RegExp(this.s, 'i');
`
1119
``
`-
FilterRegex.dict.set(this.s, this.re);
`
1120
``
`-
}
`
``
1124
`+
this.re = new RegExp(
`
``
1125
`+
this.s,
`
``
1126
`+
this.matchCase ? '' : 'i'
`
``
1127
`+
);
`
1121
1128
`}
`
1122
``
`-
if ( this.re.test($requestURL) === false ) { return false; }
`
1123
``
`- patternMatchLeft=patternMatchLeft = patternMatchLeft=requestURL.search(this.re);
`
``
1129
`+
if ( this.re.test($requestURLRaw) === false ) { return false; }
`
``
1130
`+ patternMatchLeft=patternMatchLeft = patternMatchLeft=requestURLRaw.search(this.re);
`
1124
1131
`return true;
`
1125
1132
`}
`
1126
1133
``
1127
1134
`logData(details) {
`
1128
1135
`details.pattern.push('/', this.s, '/');
`
1129
1136
`details.regex.push(this.s);
`
1130
1137
`details.isRegex = true;
`
``
1138
`+
if ( this.matchCase ) {
`
``
1139
`+
details.options.push('match-case');
`
``
1140
`+
}
`
1131
1141
`}
`
1132
1142
``
1133
1143
`toSelfie() {
`
1134
``
`-
return [ this.fid, this.s ];
`
``
1144
`+
return [ this.fid, this.s, this.matchCase ];
`
1135
1145
`}
`
1136
1146
``
1137
1147
`static compile(details) {
`
1138
``
`-
return [ FilterRegex.fid, details.pattern ];
`
``
1148
`+
return [ FilterRegex.fid, details.pattern, details.patternMatchCase ];
`
1139
1149
`}
`
1140
1150
``
1141
1151
`static fromCompiled(args) {
`
1142
``
`-
return new FilterRegex(args[1]);
`
``
1152
`+
return new FilterRegex(args[1], args[2]);
`
1143
1153
`}
`
1144
1154
``
1145
1155
`static fromSelfie(args) {
`
1146
``
`-
return new FilterRegex(args[1]);
`
``
1156
`+
return new FilterRegex(args[1], args[2]);
`
1147
1157
`}
`
1148
1158
``
1149
1159
`static keyFromArgs(args) {
`
1150
``
`-
return args[1];
`
``
1160
`` +
return ${args[1]}\t${args[2]};
``
1151
1161
`}
`
1152
1162
`};
`
1153
1163
``
1154
1164
`FilterRegex.prototype.re = null;
`
``
1165
`+
FilterRegex.prototype.matchCase = false;
`
1155
1166
``
1156
1167
`FilterRegex.isSlow = true;
`
1157
``
`-
FilterRegex.dict = new Map();
`
1158
1168
``
1159
1169
`registerFilterClass(FilterRegex);
`
1160
1170
``
`@@ -2783,6 +2793,7 @@ const FilterParser = class {
`
2783
2793
`this.modifyValue = undefined;
`
2784
2794
`this.invalid = false;
`
2785
2795
`this.pattern = '';
`
``
2796
`+
this.patternMatchCase = false;
`
2786
2797
`this.party = AnyParty;
`
2787
2798
`this.optionUnitBits = 0;
`
2788
2799
`this.domainOpt = '';
`
`@@ -2944,6 +2955,9 @@ const FilterParser = class {
`
2944
2955
`}
`
2945
2956
`this.optionUnitBits |= this.REDIRECT_BIT;
`
2946
2957
`break;
`
``
2958
`+
case this.parser.OPTTokenMatchCase:
`
``
2959
`+
this.patternMatchCase = true;
`
``
2960
`+
break;
`
2947
2961
`case this.parser.OPTTokenMp4:
`
2948
2962
`id = this.action === AllowAction
`
2949
2963
` ? this.parser.OPTTokenRedirectRule
`
`@@ -3833,6 +3847,7 @@ FilterContainer.prototype.matchAndFetchModifiers = function(
`
3833
3847
`modifierType
`
3834
3848
`) {
`
3835
3849
`$requestURL = urlTokenizer.setURL(fctxt.url);
`
``
3850
`+
$requestURLRaw = fctxt.url;
`
3836
3851
`$docHostname = fctxt.getDocHostname();
`
3837
3852
`$docDomain = fctxt.getDocDomain();
`
3838
3853
`$docEntity.reset();
`
`@@ -4126,6 +4141,7 @@ FilterContainer.prototype.matchStringReverse = function(type, url) {
`
4126
4141
``
4127
4142
`// Prime tokenizer: we get a normalized URL in return.
`
4128
4143
`$requestURL = urlTokenizer.setURL(url);
`
``
4144
`+
$requestURLRaw = url;
`
4129
4145
`this.$filterUnit = 0;
`
4130
4146
``
4131
4147
`// These registers will be used by various filters
`
`@@ -4172,6 +4188,7 @@ FilterContainer.prototype.matchString = function(fctxt, modifiers = 0) {
`
4172
4188
``
4173
4189
`// Prime tokenizer: we get a normalized URL in return.
`
4174
4190
`$requestURL = urlTokenizer.setURL(fctxt.url);
`
``
4191
`+
$requestURLRaw = fctxt.url;
`
4175
4192
`this.$filterUnit = 0;
`
4176
4193
``
4177
4194
`// These registers will be used by various filters
`
`@@ -4203,6 +4220,7 @@ FilterContainer.prototype.matchHeaders = function(fctxt, headers) {
`
4203
4220
``
4204
4221
`// Prime tokenizer: we get a normalized URL in return.
`
4205
4222
`$requestURL = urlTokenizer.setURL(fctxt.url);
`
``
4223
`+
$requestURLRaw = fctxt.url;
`
4206
4224
`this.$filterUnit = 0;
`
4207
4225
``
4208
4226
`// These registers will be used by various filters
`
`@@ -4239,13 +4257,9 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
`
4239
4257
`const directive = directives[0];
`
4240
4258
`if ( (directive.bits & AllowAction) !== 0 ) { return directive; }
`
4241
4259
`const modifier = directive.modifier;
`
4242
``
`-
if ( modifier.cache === undefined ) {
`
4243
``
`-
modifier.cache = this.parseRedirectRequestValue(modifier.value);
`
4244
``
`-
}
`
4245
``
`-
fctxt.redirectURL = µb.redirectEngine.tokenToURL(
`
4246
``
`-
fctxt,
`
4247
``
`-
modifier.cache.token
`
4248
``
`-
);
`
``
4260
`+
const { token } = this.parseRedirectRequestValue(modifier);
`
``
4261
`+
fctxt.redirectURL = µb.redirectEngine.tokenToURL(fctxt, token);
`
``
4262
`+
if ( fctxt.redirectURL === undefined ) { return; }
`
4249
4263
`return directive;
`
4250
4264
`}
`
4251
4265
`// Multiple directives mean more work to do.
`
`@@ -4258,15 +4272,11 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
`
4258
4272
`winningDirective = directive;
`
4259
4273
`break;
`
4260
4274
`}
`
4261
``
`-
if ( modifier.cache === undefined ) {
`
4262
``
`-
modifier.cache = this.parseRedirectRequestValue(modifier.value);
`
4263
``
`-
}
`
4264
``
`-
if (
`
4265
``
`-
winningDirective === undefined ||
`
4266
``
`-
modifier.cache.priority > winningPriority
`
4267
``
`-
) {
`
``
4275
`+
const { token, priority } = this.parseRedirectRequestValue(modifier);
`
``
4276
`+
if ( µb.redirectEngine.hasToken(token) === false ) { continue; }
`
``
4277
`+
if ( winningDirective === undefined || priority > winningPriority ) {
`
4268
4278
`winningDirective = directive;
`
4269
``
`-
winningPriority = modifier.cache.priority;
`
``
4279
`+
winningPriority = priority;
`
4270
4280
`}
`
4271
4281
`}
`
4272
4282
`if ( winningDirective === undefined ) { return; }
`
`@@ -4279,15 +4289,18 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
`
4279
4289
`return winningDirective;
`
4280
4290
`};
`
4281
4291
``
4282
``
`-
FilterContainer.prototype.parseRedirectRequestValue = function(rawValue) {
`
4283
``
`-
let token = rawValue;
`
4284
``
`-
let priority = 0;
`
4285
``
`-
const match = /:(\d+)$/.exec(rawValue);
`
4286
``
`-
if ( match !== null ) {
`
4287
``
`-
token = rawValue.slice(0, match.index);
`
4288
``
`-
priority = parseInt(match[1], 10);
`
``
4292
`+
FilterContainer.prototype.parseRedirectRequestValue = function(modifier) {
`
``
4293
`+
if ( modifier.cache === undefined ) {
`
``
4294
`+
let token = modifier.value;
`
``
4295
`+
let priority = 1;
`
``
4296
`+
const match = /:(\d+)$/.exec(token);
`
``
4297
`+
if ( match !== null ) {
`
``
4298
`+
token = token.slice(0, match.index);
`
``
4299
`+
priority = parseInt(match[1], 10);
`
``
4300
`+
}
`
``
4301
`+
modifier.cache = { token, priority };
`
4289
4302
`}
`
4290
``
`-
return { token, priority };
`
``
4303
`+
return modifier.cache;
`
4291
4304
`};
`
4292
4305
``
4293
4306
`/******************************************************************************/
`