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

`/******************************************************************************/

`