Index: lib/filterClasses.js |
=================================================================== |
--- a/lib/filterClasses.js |
+++ b/lib/filterClasses.js |
@@ -683,45 +683,56 @@ |
* letters |
* @param {string} [domains] |
* Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" |
* @param {boolean} [thirdParty] |
* Defines whether the filter should apply to third-party or first-party |
* content only |
* @param {string} [sitekeys] |
* Public keys of websites that this filter should apply to |
+ * @param {?string} [rewrite] |
+ * The (optional) rule specifying how to rewrite the URL. See |
+ * RegExpFilter.prototype.rewrite. |
* @constructor |
* @augments ActiveFilter |
*/ |
function RegExpFilter(text, regexpSource, contentType, matchCase, domains, |
- thirdParty, sitekeys) |
+ thirdParty, sitekeys, rewrite) |
{ |
ActiveFilter.call(this, text, domains); |
if (contentType != null) |
this.contentType = contentType; |
if (matchCase) |
this.matchCase = matchCase; |
if (thirdParty != null) |
this.thirdParty = thirdParty; |
if (sitekeys != null) |
this.sitekeySource = sitekeys; |
+ if (rewrite != null) |
+ this.rewrite = rewrite; |
if (regexpSource.length >= 2 && |
regexpSource[0] == "/" && |
regexpSource[regexpSource.length - 1] == "/") |
{ |
// The filter is a regular expression - convert it immediately to |
// catch syntax errors |
let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), |
this.matchCase ? "" : "i"); |
Object.defineProperty(this, "regexp", {value: regexp}); |
} |
else |
{ |
+ // Patterns like /foo/bar/* exist so that they are not treated as regular |
+ // expressions. We drop any superfluous wildcards here so our optimizations |
+ // can kick in. |
+ if (this.rewrite == null) |
+ regexpSource = regexpSource.replace(/^\*+/, "").replace(/\*+$/, ""); |
+ |
if (!this.matchCase && isLiteralPattern(regexpSource)) |
regexpSource = regexpSource.toLowerCase(); |
// No need to convert this filter to regular expression yet, do it on demand |
this.pattern = regexpSource; |
} |
} |
exports.RegExpFilter = RegExpFilter; |
@@ -803,16 +814,23 @@ |
Object.defineProperty( |
this, "sitekeys", {value: sitekeys, enumerable: true} |
); |
return this.sitekeys; |
}, |
/** |
+ * The rule specifying how to rewrite the URL. |
+ * The syntax is similar to the one of String.prototype.replace(). |
+ * @type {?string} |
+ */ |
+ rewrite: null, |
+ |
+ /** |
* Tests whether the URL matches this filter |
* @param {string} location URL to be tested |
* @param {number} typeMask bitmask of content / request types to match |
* @param {string} [docDomain] domain name of the document that loads the URL |
* @param {boolean} [thirdParty] should be true if the URL is a third-party |
* request |
* @param {string} [sitekey] public key provided by the document |
* @return {boolean} true in case of a match |
@@ -992,17 +1010,17 @@ |
try |
{ |
if (blocking) |
{ |
if (csp && Filter.invalidCSPRegExp.test(csp)) |
return new InvalidFilter(origText, "filter_invalid_csp"); |
return new BlockingFilter(origText, text, contentType, matchCase, domains, |
- thirdParty, sitekeys, collapse, csp, rewrite); |
+ thirdParty, sitekeys, rewrite, collapse, csp); |
} |
return new WhitelistFilter(origText, text, contentType, matchCase, domains, |
thirdParty, sitekeys); |
} |
catch (e) |
{ |
return new InvalidFilter(origText, "filter_invalid_regexp"); |
} |
@@ -1051,40 +1069,37 @@ |
* Class for blocking filters |
* @param {string} text see {@link Filter Filter()} |
* @param {string} regexpSource see {@link RegExpFilter RegExpFilter()} |
* @param {number} [contentType] see {@link RegExpFilter RegExpFilter()} |
* @param {boolean} [matchCase] see {@link RegExpFilter RegExpFilter()} |
* @param {string} [domains] see {@link RegExpFilter RegExpFilter()} |
* @param {boolean} [thirdParty] see {@link RegExpFilter RegExpFilter()} |
* @param {string} [sitekeys] see {@link RegExpFilter RegExpFilter()} |
+ * @param {?string} [rewrite] |
+ * The (optional) rule specifying how to rewrite the URL. See |
+ * RegExpFilter.prototype.rewrite. |
* @param {boolean} [collapse] |
* defines whether the filter should collapse blocked content, can be null |
* @param {string} [csp] |
* Content Security Policy to inject when the filter matches |
- * @param {?string} [rewrite] |
- * The (optional) rule specifying how to rewrite the URL. See |
- * BlockingFilter.prototype.rewrite. |
* @constructor |
* @augments RegExpFilter |
*/ |
function BlockingFilter(text, regexpSource, contentType, matchCase, domains, |
- thirdParty, sitekeys, collapse, csp, rewrite) |
+ thirdParty, sitekeys, rewrite, collapse, csp) |
{ |
RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, |
- thirdParty, sitekeys); |
+ thirdParty, sitekeys, rewrite); |
if (collapse != null) |
this.collapse = collapse; |
if (csp != null) |
this.csp = csp; |
- |
- if (rewrite != null) |
- this.rewrite = rewrite; |
} |
exports.BlockingFilter = BlockingFilter; |
BlockingFilter.prototype = extend(RegExpFilter, { |
type: "blocking", |
/** |
* Defines whether the filter should collapse blocked content. |
@@ -1095,23 +1110,16 @@ |
/** |
* Content Security Policy to inject for matching requests. |
* @type {?string} |
*/ |
csp: null, |
/** |
- * The rule specifying how to rewrite the URL. |
- * The syntax is similar to the one of String.prototype.replace(). |
- * @type {?string} |
- */ |
- rewrite: null, |
- |
- /** |
* Rewrites an URL. |
* @param {string} url the URL to rewrite |
* @return {string} the rewritten URL, or the original in case of failure |
*/ |
rewriteUrl(url) |
{ |
try |
{ |