| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2014 Eyeo GmbH | 3 * Copyright (C) 2006-2014 Eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
| 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 16 */ | 16 */ |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * @fileOverview Definition of Filter class and its subclasses. | 19 * @fileOverview Definition of Filter class and its subclasses. |
| 20 */ | 20 */ |
| 21 | 21 |
| 22 let {FilterNotifier} = require("filterNotifier"); | 22 let {FilterNotifier} = require("filterNotifier"); |
| 23 let {Utils} = require("utils"); | |
|
Wladimir Palant
2014/08/01 10:50:21
This is a pretty self-contained module, it shouldn
Thomas Greiner
2014/08/11 17:18:15
Done.
| |
| 24 | 23 |
| 25 /** | 24 /** |
| 26 * Abstract base class for filters | 25 * Abstract base class for filters |
| 27 * | 26 * |
| 28 * @param {String} text string representation of the filter | 27 * @param {String} text string representation of the filter |
| 29 * @constructor | 28 * @constructor |
| 30 */ | 29 */ |
| 31 function Filter(text) | 30 function Filter(text) |
| 32 { | 31 { |
| 33 this.text = text; | 32 this.text = text; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 | 208 |
| 210 /** | 209 /** |
| 211 * See Filter.serialize() | 210 * See Filter.serialize() |
| 212 */ | 211 */ |
| 213 serialize: function(buffer) {} | 212 serialize: function(buffer) {} |
| 214 }; | 213 }; |
| 215 | 214 |
| 216 /** | 215 /** |
| 217 * Abstract base class for filters that can get hits | 216 * Abstract base class for filters that can get hits |
| 218 * @param {String} text see Filter() | 217 * @param {String} text see Filter() |
| 219 * @param {String} domains (optional) Domains that the filter is restricted to separated by domainSeparator e.g. "foo.com|bar.com|~baz.com" | 218 * @param {String} [domains] Domains that the filter is restricted to separated by domainSeparator e.g. "foo.com|bar.com|~baz.com" |
| 220 * @param {String} siteKeys (optional) Public keys of websites that this filter should apply to, e.g. "foo|bar|~baz" | |
|
Wladimir Palant
2014/08/01 10:50:21
I don't really see how exceptions are useful here,
Thomas Greiner
2014/08/11 17:18:15
The issue stated that $sitekey should be handled e
| |
| 221 * @constructor | 219 * @constructor |
| 222 * @augments Filter | 220 * @augments Filter |
| 223 */ | 221 */ |
| 224 function ActiveFilter(text, domains, siteKeys) | 222 function ActiveFilter(text, domains) |
| 225 { | 223 { |
| 226 Filter.call(this, text); | 224 Filter.call(this, text); |
| 227 | 225 |
| 228 this.domainSource = domains; | 226 this.domainSource = domains; |
| 229 this.siteKeySource = siteKeys; | |
|
Thomas Greiner
2014/08/11 17:18:15
Done.
| |
| 230 } | 227 } |
| 231 exports.ActiveFilter = ActiveFilter; | 228 exports.ActiveFilter = ActiveFilter; |
| 232 | 229 |
| 233 ActiveFilter.prototype = | 230 ActiveFilter.prototype = |
| 234 { | 231 { |
| 235 __proto__: Filter.prototype, | 232 __proto__: Filter.prototype, |
| 236 | 233 |
| 237 _disabled: false, | 234 _disabled: false, |
| 238 _hitCount: 0, | 235 _hitCount: 0, |
| 239 _lastHit: 0, | 236 _lastHit: 0, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 * @type Boolean | 317 * @type Boolean |
| 321 */ | 318 */ |
| 322 domainSourceIsUpperCase: false, | 319 domainSourceIsUpperCase: false, |
| 323 | 320 |
| 324 /** | 321 /** |
| 325 * Map containing domains that this filter should match on/not match on or nul l if the filter should match on all domains | 322 * Map containing domains that this filter should match on/not match on or nul l if the filter should match on all domains |
| 326 * @type Object | 323 * @type Object |
| 327 */ | 324 */ |
| 328 get domains() | 325 get domains() |
| 329 { | 326 { |
| 327 // Despite this property being cached, the getter is called | |
| 328 // several times on Safari, due to WebKit bug 132872 | |
| 329 let prop = Object.getOwnPropertyDescriptor(this, "domains"); | |
| 330 if (prop) | |
| 331 return prop.value; | |
| 332 | |
| 330 let domains = null; | 333 let domains = null; |
| 331 | 334 |
| 332 if (this.domainSource) | 335 if (this.domainSource) |
| 333 { | 336 { |
| 334 let source = this.domainSource; | 337 let source = this.domainSource; |
| 335 if (!this.domainSourceIsUpperCase) { | 338 if (!this.domainSourceIsUpperCase) { |
| 336 // RegExpFilter already have uppercase domains | 339 // RegExpFilter already have uppercase domains |
| 337 source = source.toUpperCase(); | 340 source = source.toUpperCase(); |
| 338 } | 341 } |
| 339 let list = source.split(this.domainSeparator); | 342 let list = source.split(this.domainSeparator); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 } | 380 } |
| 378 | 381 |
| 379 this.domainSource = null; | 382 this.domainSource = null; |
| 380 } | 383 } |
| 381 | 384 |
| 382 Object.defineProperty(this, "domains", {value: domains, enumerable: true}); | 385 Object.defineProperty(this, "domains", {value: domains, enumerable: true}); |
| 383 return this.domains; | 386 return this.domains; |
| 384 }, | 387 }, |
| 385 | 388 |
| 386 /** | 389 /** |
| 387 * String that the siteKey property should be generated from | 390 * Array containing public keys of websites that this filter should apply to |
| 388 * @type String | 391 * @type Array of String |
| 389 */ | 392 */ |
| 390 siteKeySource: null, | 393 sitekeys: null, |
| 391 | |
| 392 /** | |
| 393 * Map containing public keys of websites that this filter should apply to | |
| 394 * @type Object | |
| 395 */ | |
| 396 get siteKeys() | |
| 397 { | |
| 398 let siteKeys = null; | |
| 399 | |
| 400 if (this.siteKeySource) | |
| 401 { | |
| 402 let source = this.siteKeySource; | |
| 403 let list = source.split("|"); | |
| 404 if (list.length == 1 && list[0][0] != "~") | |
| 405 { | |
| 406 // Fast track for the common one-sitekey scenario | |
| 407 siteKeys = {__proto__: null, "": false}; | |
| 408 siteKeys[list[0]] = true; | |
| 409 } | |
| 410 else | |
| 411 { | |
| 412 let hasIncludes = false; | |
| 413 for (let i = 0; i < list.length; i++) | |
| 414 { | |
| 415 let siteKey = list[i]; | |
| 416 if (siteKey == "") | |
| 417 continue; | |
| 418 | |
| 419 let include; | |
| 420 if (siteKey[0] == "~") | |
| 421 { | |
| 422 include = false; | |
| 423 siteKey = siteKey.substr(1); | |
| 424 } | |
| 425 else | |
| 426 { | |
| 427 include = true; | |
| 428 hasIncludes = true; | |
| 429 } | |
| 430 | |
| 431 if (!siteKeys) | |
| 432 siteKeys = Object.create(null); | |
| 433 | |
| 434 siteKeys[siteKey] = include; | |
| 435 } | |
| 436 siteKeys[""] = !hasIncludes; | |
| 437 } | |
| 438 | |
| 439 this.siteKeySource = null; | |
| 440 } | |
| 441 | |
| 442 Object.defineProperty(this, "siteKeys", {value: siteKeys, enumerable: true}) ; | |
| 443 return this.siteKeys; | |
| 444 }, | |
| 445 | 394 |
| 446 /** | 395 /** |
| 447 * Checks whether this filter is active on a domain. | 396 * Checks whether this filter is active on a domain. |
| 448 */ | 397 * @param {String} docDomain domain name of the document that loads the URL |
| 449 isActiveOnDomain: function(/**String*/ docDomain) /**Boolean*/ | 398 * @param {String} [sitekey] public key provided by the document |
| 450 { | 399 * @return {Boolean} true in case of the filter being active |
| 400 */ | |
| 401 isActiveOnDomain: function(docDomain, sitekey) | |
| 402 { | |
| 403 // Sitekeys are case-sensitive so we shouldn't convert them to upper-case to avoid false | |
| 404 // positives here. Instead we need to change the way filter options are pars ed. | |
| 405 if (this.sitekeys && (!sitekey || this.sitekeys.indexOf(sitekey.toUpperCase( )) < 0)) | |
| 406 return false; | |
| 407 | |
| 451 // If no domains are set the rule matches everywhere | 408 // If no domains are set the rule matches everywhere |
| 452 if (!this.domains) | 409 if (!this.domains) |
| 453 return true; | 410 return true; |
| 454 | 411 |
| 455 // If the document has no host name, match only if the filter isn't restrict ed to specific domains | 412 // If the document has no host name, match only if the filter isn't restrict ed to specific domains |
| 456 if (!docDomain) | 413 if (!docDomain) |
| 457 return this.domains[""]; | 414 return this.domains[""]; |
| 458 | 415 |
| 459 if (this.ignoreTrailingDot) | 416 if (this.ignoreTrailingDot) |
| 460 docDomain = docDomain.replace(/\.+$/, ""); | 417 docDomain = docDomain.replace(/\.+$/, ""); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 483 | 440 |
| 484 if (this.ignoreTrailingDot) | 441 if (this.ignoreTrailingDot) |
| 485 docDomain = docDomain.replace(/\.+$/, ""); | 442 docDomain = docDomain.replace(/\.+$/, ""); |
| 486 docDomain = docDomain.toUpperCase(); | 443 docDomain = docDomain.toUpperCase(); |
| 487 | 444 |
| 488 for (let domain in this.domains) | 445 for (let domain in this.domains) |
| 489 if (this.domains[domain] && domain != docDomain && (domain.length <= docDo main.length || domain.indexOf("." + docDomain) != domain.length - docDomain.leng th - 1)) | 446 if (this.domains[domain] && domain != docDomain && (domain.length <= docDo main.length || domain.indexOf("." + docDomain) != domain.length - docDomain.leng th - 1)) |
| 490 return false; | 447 return false; |
| 491 | 448 |
| 492 return true; | 449 return true; |
| 493 }, | |
| 494 | |
| 495 /** | |
| 496 * Checks whether the provided site key is valid and active on a page | |
| 497 */ | |
| 498 isActiveOnPage: function(/**String*/ docDomain, /**String*/ docLocation, /**St ring*/ siteKey) /**Boolean*/ | |
|
Wladimir Palant
2014/08/01 10:50:21
I don't think that this is the right place to perf
Thomas Greiner
2014/08/11 17:18:15
Done.
| |
| 499 { | |
| 500 // If no site keys are set the rule matches everywhere | |
| 501 if (!this.siteKeys) | |
| 502 return true; | |
| 503 | |
| 504 // If the document has not provided a sitekey, match only if the filter isn' t restricted by sitekeys | |
| 505 if (!docDomain || !siteKey) | |
| 506 return this.siteKeys[""]; | |
| 507 | |
| 508 // If the document has provided an invalid sitekey the filter should not mat ch | |
| 509 if (siteKey.indexOf("_") < 0) | |
| 510 return false; | |
| 511 | |
| 512 let [key, signature] = siteKey.split("_", 2); | |
| 513 let formattedKey = key.replace(/=/g, "").toUpperCase(); | |
| 514 if (!(formattedKey in this.siteKeys) || !Utils.crypto) | |
| 515 return this.siteKeys[""]; | |
| 516 | |
| 517 // Website specifies a key that we know but is the signature valid? | |
| 518 let uri = Services.io.newURI(docLocation, null, null); | |
| 519 let host = uri.asciiHost; | |
| 520 if (uri.port > 0) | |
| 521 host += ":" + uri.port; | |
| 522 let params = [ | |
| 523 uri.path.replace(/#.*/, ""), // REQUEST_URI | |
| 524 host, // HTTP_HOST | |
| 525 Utils.httpProtocol.userAgent // HTTP_USER_AGENT | |
| 526 ]; | |
| 527 if (Utils.verifySignature(key, signature, params.join("\0"))) | |
| 528 return this.siteKeys[formattedKey]; | |
| 529 | |
| 530 return !this.siteKeys[formattedKey]; | |
| 531 }, | 450 }, |
| 532 | 451 |
| 533 /** | 452 /** |
| 534 * See Filter.serialize() | 453 * See Filter.serialize() |
| 535 */ | 454 */ |
| 536 serialize: function(buffer) | 455 serialize: function(buffer) |
| 537 { | 456 { |
| 538 if (this._disabled || this._hitCount || this._lastHit) | 457 if (this._disabled || this._hitCount || this._lastHit) |
| 539 { | 458 { |
| 540 Filter.prototype.serialize.call(this, buffer); | 459 Filter.prototype.serialize.call(this, buffer); |
| 541 if (this._disabled) | 460 if (this._disabled) |
| 542 buffer.push("disabled=true"); | 461 buffer.push("disabled=true"); |
| 543 if (this._hitCount) | 462 if (this._hitCount) |
| 544 buffer.push("hitCount=" + this._hitCount); | 463 buffer.push("hitCount=" + this._hitCount); |
| 545 if (this._lastHit) | 464 if (this._lastHit) |
| 546 buffer.push("lastHit=" + this._lastHit); | 465 buffer.push("lastHit=" + this._lastHit); |
| 547 } | 466 } |
| 548 } | 467 } |
| 549 }; | 468 }; |
| 550 | 469 |
| 551 /** | 470 /** |
| 552 * Abstract base class for RegExp-based filters | 471 * Abstract base class for RegExp-based filters |
| 553 * @param {String} text see Filter() | 472 * @param {String} text see Filter() |
| 554 * @param {String} regexpSource filter part that the regular expression should b e build from | 473 * @param {String} regexpSource filter part that the regular expression should b e build from |
| 555 * @param {Number} contentType (optional) Content types the filter applies to, combination of values from RegExpFilter.typeMap | 474 * @param {Number} [contentType] Content types the filter applies to, combinatio n of values from RegExpFilter.typeMap |
| 556 * @param {Boolean} matchCase (optional) Defines whether the filter should dis tinguish between lower and upper case letters | 475 * @param {Boolean} [matchCase] Defines whether the filter should distinguish be tween lower and upper case letters |
| 557 * @param {String} domains (optional) Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" | 476 * @param {String} [domains] Domains that the filter is restricted to, e.g. "foo .com|bar.com|~baz.com" |
| 558 * @param {Boolean} thirdParty (optional) Defines whether the filter should app ly to third-party or first-party content only | 477 * @param {Boolean} [thirdParty] Defines whether the filter should apply to thir d-party or first-party content only |
| 559 * @param {String} siteKeys (optional) Public keys of websites that this fil ter should apply to, e.g. "foo|bar|~baz" | 478 * @param {String} [sitekeys] Public keys of websites that this filter should ap ply to |
| 560 * @constructor | 479 * @constructor |
| 561 * @augments ActiveFilter | 480 * @augments ActiveFilter |
| 562 */ | 481 */ |
| 563 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, third Party, siteKeys) | 482 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, third Party, sitekeys) |
| 564 { | 483 { |
| 565 ActiveFilter.call(this, text, domains, siteKeys); | 484 ActiveFilter.call(this, text, domains, sitekeys); |
| 566 | 485 |
| 567 if (contentType != null) | 486 if (contentType != null) |
| 568 this.contentType = contentType; | 487 this.contentType = contentType; |
| 569 if (matchCase) | 488 if (matchCase) |
| 570 this.matchCase = matchCase; | 489 this.matchCase = matchCase; |
| 571 if (thirdParty != null) | 490 if (thirdParty != null) |
| 572 this.thirdParty = thirdParty; | 491 this.thirdParty = thirdParty; |
| 492 if (sitekeys != null) | |
| 493 this.sitekeySource = sitekeys; | |
| 573 | 494 |
| 574 if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regexpS ource.length - 1] == "/") | 495 if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regexpS ource.length - 1] == "/") |
| 575 { | 496 { |
| 576 // The filter is a regular expression - convert it immediately to catch synt ax errors | 497 // The filter is a regular expression - convert it immediately to catch synt ax errors |
| 577 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), thi s.matchCase ? "" : "i"); | 498 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), thi s.matchCase ? "" : "i"); |
| 578 Object.defineProperty(this, "regexp", {value: regexp}); | 499 Object.defineProperty(this, "regexp", {value: regexp}); |
| 579 } | 500 } |
| 580 else | 501 else |
| 581 { | 502 { |
| 582 // No need to convert this filter to regular expression yet, do it on demand | 503 // No need to convert this filter to regular expression yet, do it on demand |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 609 * Expression from which a regular expression should be generated - for delaye d creation of the regexp property | 530 * Expression from which a regular expression should be generated - for delaye d creation of the regexp property |
| 610 * @type String | 531 * @type String |
| 611 */ | 532 */ |
| 612 regexpSource: null, | 533 regexpSource: null, |
| 613 /** | 534 /** |
| 614 * Regular expression to be used when testing against this filter | 535 * Regular expression to be used when testing against this filter |
| 615 * @type RegExp | 536 * @type RegExp |
| 616 */ | 537 */ |
| 617 get regexp() | 538 get regexp() |
| 618 { | 539 { |
| 540 // Despite this property being cached, the getter is called | |
| 541 // several times on Safari, due to WebKit bug 132872 | |
| 542 let prop = Object.getOwnPropertyDescriptor(this, "regexp"); | |
| 543 if (prop) | |
| 544 return prop.value; | |
| 545 | |
| 619 // Remove multiple wildcards | 546 // Remove multiple wildcards |
| 620 let source = this.regexpSource | 547 let source = this.regexpSource |
| 621 .replace(/\*+/g, "*") // remove multiple wildcards | 548 .replace(/\*+/g, "*") // remove multiple wildcards |
| 622 .replace(/\^\|$/, "^") // remove anchors following separator placeho lder | 549 .replace(/\^\|$/, "^") // remove anchors following separator placeho lder |
| 623 .replace(/\W/g, "\\$&") // escape special symbols | 550 .replace(/\W/g, "\\$&") // escape special symbols |
| 624 .replace(/\\\*/g, ".*") // replace wildcards by .* | 551 .replace(/\\\*/g, ".*") // replace wildcards by .* |
| 625 // process separator placeholders (all ANSI characters but alphanumeric ch aracters and _%.-) | 552 // process separator placeholders (all ANSI characters but alphanumeric ch aracters and _%.-) |
| 626 .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\ x60\\x7B-\\x7F]|$)") | 553 .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\ x60\\x7B-\\x7F]|$)") |
| 627 .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process extended anchor at expression start | 554 .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process extended anchor at expression start |
| 628 .replace(/^\\\|/, "^") // process anchor at expression start | 555 .replace(/^\\\|/, "^") // process anchor at expression start |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 644 * @type Boolean | 571 * @type Boolean |
| 645 */ | 572 */ |
| 646 matchCase: false, | 573 matchCase: false, |
| 647 /** | 574 /** |
| 648 * Defines whether the filter should apply to third-party or first-party conte nt only. Can be null (apply to all content). | 575 * Defines whether the filter should apply to third-party or first-party conte nt only. Can be null (apply to all content). |
| 649 * @type Boolean | 576 * @type Boolean |
| 650 */ | 577 */ |
| 651 thirdParty: null, | 578 thirdParty: null, |
| 652 | 579 |
| 653 /** | 580 /** |
| 581 * String that the sitekey property should be generated from | |
| 582 * @type String | |
| 583 */ | |
| 584 sitekeySource: null, | |
| 585 | |
| 586 /** | |
| 587 * Array containing public keys of websites that this filter should apply to | |
| 588 * @type Array of String | |
| 589 */ | |
| 590 get sitekeys() | |
| 591 { | |
| 592 // Despite this property being cached, the getter is called | |
| 593 // several times on Safari, due to WebKit bug 132872 | |
| 594 let prop = Object.getOwnPropertyDescriptor(this, "sitekeys"); | |
| 595 if (prop) | |
| 596 return prop.value; | |
| 597 | |
| 598 let sitekeys = null; | |
| 599 | |
| 600 if (this.sitekeySource) | |
| 601 { | |
| 602 sitekeys = this.sitekeySource.split("|"); | |
| 603 this.sitekeySource = null; | |
| 604 } | |
| 605 | |
| 606 Object.defineProperty(this, "sitekeys", {value: sitekeys, enumerable: true}) ; | |
| 607 return this.sitekeys; | |
| 608 }, | |
| 609 | |
| 610 /** | |
| 654 * Tests whether the URL matches this filter | 611 * Tests whether the URL matches this filter |
| 655 * @param {String} location URL to be tested | 612 * @param {String} location URL to be tested |
| 656 * @param {String} contentType content type identifier of the URL | 613 * @param {String} contentType content type identifier of the URL |
| 657 * @param {String} docDomain domain name of the document that loads the URL | 614 * @param {String} docDomain domain name of the document that loads the URL |
| 658 * @param {Boolean} thirdParty should be true if the URL is a third-party requ est | 615 * @param {Boolean} thirdParty should be true if the URL is a third-party requ est |
| 659 * @param {String} docLocation location of the document that loads the URL | 616 * @param {String} sitekey public key provided by the document |
| 660 * @param {String} siteKey public key provided by the document | |
| 661 * @return {Boolean} true in case of a match | 617 * @return {Boolean} true in case of a match |
| 662 */ | 618 */ |
| 663 matches: function(location, contentType, docDomain, thirdParty, docLocation, s iteKey) | 619 matches: function(location, contentType, docDomain, thirdParty, sitekey) |
| 664 { | 620 { |
| 665 if (this.regexp.test(location) && | 621 if (this.regexp.test(location) && |
| 666 (RegExpFilter.typeMap[contentType] & this.contentType) != 0 && | 622 (RegExpFilter.typeMap[contentType] & this.contentType) != 0 && |
| 667 (this.thirdParty == null || this.thirdParty == thirdParty) && | 623 (this.thirdParty == null || this.thirdParty == thirdParty) && |
| 668 this.isActiveOnDomain(docDomain) && | 624 this.isActiveOnDomain(docDomain, sitekey)) |
| 669 this.isActiveOnPage(docDomain, docLocation, siteKey)) | |
| 670 { | 625 { |
| 671 return true; | 626 return true; |
| 672 } | 627 } |
| 673 | 628 |
| 674 return false; | 629 return false; |
| 675 } | 630 } |
| 676 }; | 631 }; |
| 677 | 632 |
| 678 // Required to optimize Matcher, see also RegExpFilter.prototype.length | 633 // Required to optimize Matcher, see also RegExpFilter.prototype.length |
| 679 Object.defineProperty(RegExpFilter.prototype, "0", | 634 Object.defineProperty(RegExpFilter.prototype, "0", |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 691 let origText = text; | 646 let origText = text; |
| 692 if (text.indexOf("@@") == 0) | 647 if (text.indexOf("@@") == 0) |
| 693 { | 648 { |
| 694 blocking = false; | 649 blocking = false; |
| 695 text = text.substr(2); | 650 text = text.substr(2); |
| 696 } | 651 } |
| 697 | 652 |
| 698 let contentType = null; | 653 let contentType = null; |
| 699 let matchCase = null; | 654 let matchCase = null; |
| 700 let domains = null; | 655 let domains = null; |
| 701 let siteKeys = null; | 656 let sitekeys = null; |
| 702 let thirdParty = null; | 657 let thirdParty = null; |
| 703 let collapse = null; | 658 let collapse = null; |
| 704 let options; | 659 let options; |
| 705 let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null); | 660 let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null); |
| 706 if (match) | 661 if (match) |
| 707 { | 662 { |
| 708 options = match[1].toUpperCase().split(","); | 663 options = match[1].toUpperCase().split(","); |
| 709 text = match.input.substr(0, match.index); | 664 text = match.input.substr(0, match.index); |
| 710 for (let option of options) | 665 for (let option of options) |
| 711 { | 666 { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 737 domains = value; | 692 domains = value; |
| 738 else if (option == "THIRD_PARTY") | 693 else if (option == "THIRD_PARTY") |
| 739 thirdParty = true; | 694 thirdParty = true; |
| 740 else if (option == "~THIRD_PARTY") | 695 else if (option == "~THIRD_PARTY") |
| 741 thirdParty = false; | 696 thirdParty = false; |
| 742 else if (option == "COLLAPSE") | 697 else if (option == "COLLAPSE") |
| 743 collapse = true; | 698 collapse = true; |
| 744 else if (option == "~COLLAPSE") | 699 else if (option == "~COLLAPSE") |
| 745 collapse = false; | 700 collapse = false; |
| 746 else if (option == "SITEKEY" && typeof value != "undefined") | 701 else if (option == "SITEKEY" && typeof value != "undefined") |
| 747 siteKeys = value; | 702 sitekeys = value; |
| 748 else | 703 else |
| 749 return new InvalidFilter(origText, "Unknown option " + option.toLowerCas e()); | 704 return new InvalidFilter(origText, "Unknown option " + option.toLowerCas e()); |
| 750 } | 705 } |
| 751 } | 706 } |
| 752 | 707 |
| 753 if (!blocking && (contentType == null || (contentType & RegExpFilter.typeMap.D OCUMENT)) && | 708 if (!blocking && (contentType == null || (contentType & RegExpFilter.typeMap.D OCUMENT)) && |
| 754 (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text )) | 709 (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text )) |
| 755 { | 710 { |
| 756 // Exception filters shouldn't apply to pages by default unless they start w ith a protocol name | 711 // Exception filters shouldn't apply to pages by default unless they start w ith a protocol name |
| 757 if (contentType == null) | 712 if (contentType == null) |
| 758 contentType = RegExpFilter.prototype.contentType; | 713 contentType = RegExpFilter.prototype.contentType; |
| 759 contentType &= ~RegExpFilter.typeMap.DOCUMENT; | 714 contentType &= ~RegExpFilter.typeMap.DOCUMENT; |
| 760 } | 715 } |
| 761 | 716 |
| 762 try | 717 try |
| 763 { | 718 { |
| 764 if (blocking) | 719 if (blocking) |
| 765 return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, siteKeys, collapse); | 720 return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, sitekeys, collapse); |
| 766 else | 721 else |
| 767 return new WhitelistFilter(origText, text, contentType, matchCase, domains , thirdParty, siteKeys); | 722 return new WhitelistFilter(origText, text, contentType, matchCase, domains , thirdParty, sitekeys); |
| 768 } | 723 } |
| 769 catch (e) | 724 catch (e) |
| 770 { | 725 { |
| 771 return new InvalidFilter(origText, e); | 726 return new InvalidFilter(origText, e); |
| 772 } | 727 } |
| 773 } | 728 } |
| 774 | 729 |
| 775 /** | 730 /** |
| 776 * Maps type strings like "SCRIPT" or "OBJECT" to bit masks | 731 * Maps type strings like "SCRIPT" or "OBJECT" to bit masks |
| 777 */ | 732 */ |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 801 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFi lter.typeMap.POPUP); | 756 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFi lter.typeMap.POPUP); |
| 802 | 757 |
| 803 /** | 758 /** |
| 804 * Class for blocking filters | 759 * Class for blocking filters |
| 805 * @param {String} text see Filter() | 760 * @param {String} text see Filter() |
| 806 * @param {String} regexpSource see RegExpFilter() | 761 * @param {String} regexpSource see RegExpFilter() |
| 807 * @param {Number} contentType see RegExpFilter() | 762 * @param {Number} contentType see RegExpFilter() |
| 808 * @param {Boolean} matchCase see RegExpFilter() | 763 * @param {Boolean} matchCase see RegExpFilter() |
| 809 * @param {String} domains see RegExpFilter() | 764 * @param {String} domains see RegExpFilter() |
| 810 * @param {Boolean} thirdParty see RegExpFilter() | 765 * @param {Boolean} thirdParty see RegExpFilter() |
| 811 * @param {String} siteKeys see RegExpFilter() | 766 * @param {String} sitekeys see RegExpFilter() |
| 812 * @param {Boolean} collapse defines whether the filter should collapse blocked content, can be null | 767 * @param {Boolean} collapse defines whether the filter should collapse blocked content, can be null |
| 813 * @constructor | 768 * @constructor |
| 814 * @augments RegExpFilter | 769 * @augments RegExpFilter |
| 815 */ | 770 */ |
| 816 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thi rdParty, siteKeys, collapse) | 771 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thi rdParty, sitekeys, collapse) |
| 817 { | 772 { |
| 818 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty, siteKeys); | 773 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty, sitekeys); |
| 819 | 774 |
| 820 this.collapse = collapse; | 775 this.collapse = collapse; |
| 821 } | 776 } |
| 822 exports.BlockingFilter = BlockingFilter; | 777 exports.BlockingFilter = BlockingFilter; |
| 823 | 778 |
| 824 BlockingFilter.prototype = | 779 BlockingFilter.prototype = |
| 825 { | 780 { |
| 826 __proto__: RegExpFilter.prototype, | 781 __proto__: RegExpFilter.prototype, |
| 827 | 782 |
| 828 /** | 783 /** |
| 829 * Defines whether the filter should collapse blocked content. Can be null (us e the global preference). | 784 * Defines whether the filter should collapse blocked content. Can be null (us e the global preference). |
| 830 * @type Boolean | 785 * @type Boolean |
| 831 */ | 786 */ |
| 832 collapse: null | 787 collapse: null |
| 833 }; | 788 }; |
| 834 | 789 |
| 835 /** | 790 /** |
| 836 * Class for whitelist filters | 791 * Class for whitelist filters |
| 837 * @param {String} text see Filter() | 792 * @param {String} text see Filter() |
| 838 * @param {String} regexpSource see RegExpFilter() | 793 * @param {String} regexpSource see RegExpFilter() |
| 839 * @param {Number} contentType see RegExpFilter() | 794 * @param {Number} contentType see RegExpFilter() |
| 840 * @param {Boolean} matchCase see RegExpFilter() | 795 * @param {Boolean} matchCase see RegExpFilter() |
| 841 * @param {String} domains see RegExpFilter() | 796 * @param {String} domains see RegExpFilter() |
| 842 * @param {Boolean} thirdParty see RegExpFilter() | 797 * @param {Boolean} thirdParty see RegExpFilter() |
| 843 * @param {String} siteKeys see RegExpFilter() | 798 * @param {String} sitekeys see RegExpFilter() |
| 844 * @constructor | 799 * @constructor |
| 845 * @augments RegExpFilter | 800 * @augments RegExpFilter |
| 846 */ | 801 */ |
| 847 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, th irdParty, siteKeys) | 802 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, th irdParty, sitekeys) |
| 848 { | 803 { |
| 849 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty, siteKeys); | 804 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty, sitekeys); |
| 850 } | 805 } |
| 851 exports.WhitelistFilter = WhitelistFilter; | 806 exports.WhitelistFilter = WhitelistFilter; |
| 852 | 807 |
| 853 WhitelistFilter.prototype = | 808 WhitelistFilter.prototype = |
| 854 { | 809 { |
| 855 __proto__: RegExpFilter.prototype | 810 __proto__: RegExpFilter.prototype |
| 856 } | 811 } |
| 857 | 812 |
| 858 /** | 813 /** |
| 859 * Base class for element hiding filters | 814 * Base class for element hiding filters |
| 860 * @param {String} text see Filter() | 815 * @param {String} text see Filter() |
| 861 * @param {String} domains (optional) Host names or domains the filter should be restricted to | 816 * @param {String} [domains] Host names or domains the filter should be restrict ed to |
| 862 * @param {String} selector CSS selector for the HTML elements that should be hidden | 817 * @param {String} selector CSS selector for the HTML elements that should be hidden |
| 863 * @constructor | 818 * @constructor |
| 864 * @augments ActiveFilter | 819 * @augments ActiveFilter |
| 865 */ | 820 */ |
| 866 function ElemHideBase(text, domains, selector) | 821 function ElemHideBase(text, domains, selector) |
| 867 { | 822 { |
| 868 ActiveFilter.call(this, text, domains || null); | 823 ActiveFilter.call(this, text, domains || null); |
| 869 | 824 |
| 870 if (domains) | 825 if (domains) |
| 871 this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, " ").toLowerCase(); | 826 this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, " ").toLowerCase(); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 985 function ElemHideException(text, domains, selector) | 940 function ElemHideException(text, domains, selector) |
| 986 { | 941 { |
| 987 ElemHideBase.call(this, text, domains, selector); | 942 ElemHideBase.call(this, text, domains, selector); |
| 988 } | 943 } |
| 989 exports.ElemHideException = ElemHideException; | 944 exports.ElemHideException = ElemHideException; |
| 990 | 945 |
| 991 ElemHideException.prototype = | 946 ElemHideException.prototype = |
| 992 { | 947 { |
| 993 __proto__: ElemHideBase.prototype | 948 __proto__: ElemHideBase.prototype |
| 994 }; | 949 }; |
| LEFT | RIGHT |