OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present 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 |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 domainSource: null, | 380 domainSource: null, |
381 | 381 |
382 /** | 382 /** |
383 * Separator character used in domainSource property, must be | 383 * Separator character used in domainSource property, must be |
384 * overridden by subclasses | 384 * overridden by subclasses |
385 * @type {string} | 385 * @type {string} |
386 */ | 386 */ |
387 domainSeparator: null, | 387 domainSeparator: null, |
388 | 388 |
389 /** | 389 /** |
390 * Determines whether domainSource is already upper-case, | 390 * Determines whether domainSource is already lower-case, |
391 * can be overridden by subclasses. | 391 * can be overridden by subclasses. |
392 * @type {boolean} | 392 * @type {boolean} |
393 */ | 393 */ |
394 domainSourceIsUpperCase: false, | 394 domainSourceIsLowerCase: false, |
395 | 395 |
396 /** | 396 /** |
397 * Map containing domains that this filter should match on/not match | 397 * Map containing domains that this filter should match on/not match |
398 * on or null if the filter should match on all domains | 398 * on or null if the filter should match on all domains |
399 * @type {?Map.<string,boolean>} | 399 * @type {?Map.<string,boolean>} |
400 */ | 400 */ |
401 get domains() | 401 get domains() |
402 { | 402 { |
403 // Despite this property being cached, the getter is called | 403 // Despite this property being cached, the getter is called |
404 // several times on Safari, due to WebKit bug 132872 | 404 // several times on Safari, due to WebKit bug 132872 |
405 let prop = Object.getOwnPropertyDescriptor(this, "domains"); | 405 let prop = Object.getOwnPropertyDescriptor(this, "domains"); |
406 if (prop) | 406 if (prop) |
407 return prop.value; | 407 return prop.value; |
408 | 408 |
409 let domains = null; | 409 let domains = null; |
410 | 410 |
411 if (this.domainSource) | 411 if (this.domainSource) |
412 { | 412 { |
413 let source = this.domainSource; | 413 let source = this.domainSource; |
414 if (!this.domainSourceIsUpperCase) | 414 if (!this.domainSourceIsLowerCase) |
415 { | 415 { |
416 // RegExpFilter already have uppercase domains | 416 // RegExpFilter already have lowercase domains |
417 source = source.toUpperCase(); | 417 source = source.toLowerCase(); |
418 } | 418 } |
419 let list = source.split(this.domainSeparator); | 419 let list = source.split(this.domainSeparator); |
420 if (list.length == 1 && list[0][0] != "~") | 420 if (list.length == 1 && list[0][0] != "~") |
421 { | 421 { |
422 // Fast track for the common one-domain scenario | 422 // Fast track for the common one-domain scenario |
423 domains = new Map([["", false], [list[0], true]]); | 423 domains = new Map([["", false], [list[0], true]]); |
424 } | 424 } |
425 else | 425 else |
426 { | 426 { |
427 let hasIncludes = false; | 427 let hasIncludes = false; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 | 484 |
485 // If no domains are set the rule matches everywhere | 485 // If no domains are set the rule matches everywhere |
486 if (!this.domains) | 486 if (!this.domains) |
487 return true; | 487 return true; |
488 | 488 |
489 // If the document has no host name, match only if the filter | 489 // If the document has no host name, match only if the filter |
490 // isn't restricted to specific domains | 490 // isn't restricted to specific domains |
491 if (!docDomain) | 491 if (!docDomain) |
492 return this.domains.get(""); | 492 return this.domains.get(""); |
493 | 493 |
494 docDomain = docDomain.replace(/\.+$/, "").toUpperCase(); | 494 docDomain = docDomain.replace(/\.+$/, "").toLowerCase(); |
495 | 495 |
496 while (true) | 496 while (true) |
497 { | 497 { |
498 let isDomainIncluded = this.domains.get(docDomain); | 498 let isDomainIncluded = this.domains.get(docDomain); |
499 if (typeof isDomainIncluded != "undefined") | 499 if (typeof isDomainIncluded != "undefined") |
500 return isDomainIncluded; | 500 return isDomainIncluded; |
501 | 501 |
502 let nextDot = docDomain.indexOf("."); | 502 let nextDot = docDomain.indexOf("."); |
503 if (nextDot < 0) | 503 if (nextDot < 0) |
504 break; | 504 break; |
505 docDomain = docDomain.substr(nextDot + 1); | 505 docDomain = docDomain.substr(nextDot + 1); |
506 } | 506 } |
507 return this.domains.get(""); | 507 return this.domains.get(""); |
508 }, | 508 }, |
509 | 509 |
510 /** | 510 /** |
511 * Checks whether this filter is active only on a domain and its subdomains. | 511 * Checks whether this filter is active only on a domain and its subdomains. |
512 * @param {string} docDomain | 512 * @param {string} docDomain |
513 * @return {boolean} | 513 * @return {boolean} |
514 */ | 514 */ |
515 isActiveOnlyOnDomain(docDomain) | 515 isActiveOnlyOnDomain(docDomain) |
516 { | 516 { |
517 if (!docDomain || !this.domains || this.domains.get("")) | 517 if (!docDomain || !this.domains || this.domains.get("")) |
518 return false; | 518 return false; |
519 | 519 |
520 docDomain = docDomain.replace(/\.+$/, "").toUpperCase(); | 520 docDomain = docDomain.replace(/\.+$/, "").toLowerCase(); |
521 | 521 |
522 for (let [domain, isIncluded] of this.domains) | 522 for (let [domain, isIncluded] of this.domains) |
523 { | 523 { |
524 if (isIncluded && domain != docDomain) | 524 if (isIncluded && domain != docDomain) |
525 { | 525 { |
526 if (domain.length <= docDomain.length) | 526 if (domain.length <= docDomain.length) |
527 return false; | 527 return false; |
528 | 528 |
529 if (!domain.endsWith("." + docDomain)) | 529 if (!domain.endsWith("." + docDomain)) |
530 return false; | 530 return false; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 else | 611 else |
612 { | 612 { |
613 // No need to convert this filter to regular expression yet, do it on demand | 613 // No need to convert this filter to regular expression yet, do it on demand |
614 this.regexpSource = regexpSource; | 614 this.regexpSource = regexpSource; |
615 } | 615 } |
616 } | 616 } |
617 exports.RegExpFilter = RegExpFilter; | 617 exports.RegExpFilter = RegExpFilter; |
618 | 618 |
619 RegExpFilter.prototype = extend(ActiveFilter, { | 619 RegExpFilter.prototype = extend(ActiveFilter, { |
620 /** | 620 /** |
621 * @see ActiveFilter.domainSourceIsUpperCase | 621 * @see ActiveFilter.domainSourceIsLowerCase |
622 */ | 622 */ |
623 domainSourceIsUpperCase: true, | 623 domainSourceIsLowerCase: true, |
624 | 624 |
625 /** | 625 /** |
626 * Number of filters contained, will always be 1 (required to | 626 * Number of filters contained, will always be 1 (required to |
627 * optimize Matcher). | 627 * optimize Matcher). |
628 * @type {number} | 628 * @type {number} |
629 */ | 629 */ |
630 length: 1, | 630 length: 1, |
631 | 631 |
632 /** | 632 /** |
633 * @see ActiveFilter.domainSeparator | 633 * @see ActiveFilter.domainSeparator |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 text = match.input.substr(0, match.index); | 766 text = match.input.substr(0, match.index); |
767 for (let option of options) | 767 for (let option of options) |
768 { | 768 { |
769 let value = null; | 769 let value = null; |
770 let separatorIndex = option.indexOf("="); | 770 let separatorIndex = option.indexOf("="); |
771 if (separatorIndex >= 0) | 771 if (separatorIndex >= 0) |
772 { | 772 { |
773 value = option.substr(separatorIndex + 1); | 773 value = option.substr(separatorIndex + 1); |
774 option = option.substr(0, separatorIndex); | 774 option = option.substr(0, separatorIndex); |
775 } | 775 } |
776 option = option.replace(/-/, "_").toUpperCase(); | 776 let type = (option[0] == "~" ? option.substr(1) : option) |
777 if (option in RegExpFilter.typeMap) | 777 .replace(/-/, "_").toUpperCase(); |
| 778 option = option.toLowerCase(); |
| 779 if (type in RegExpFilter.typeMap) |
778 { | 780 { |
779 if (contentType == null) | 781 if (option[0] == "~") |
780 contentType = 0; | 782 { |
781 contentType |= RegExpFilter.typeMap[option]; | 783 if (contentType == null) |
| 784 ({contentType} = RegExpFilter.prototype); |
| 785 contentType &= ~RegExpFilter.typeMap[type]; |
| 786 } |
| 787 else |
| 788 { |
| 789 if (contentType == null) |
| 790 contentType = 0; |
| 791 contentType |= RegExpFilter.typeMap[type]; |
782 | 792 |
783 if (option == "CSP" && value) | 793 if (type == "CSP" && value) |
784 csp = value; | 794 csp = value; |
| 795 } |
785 } | 796 } |
786 else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap) | 797 else if (option == "match-case") |
787 { | |
788 if (contentType == null) | |
789 ({contentType} = RegExpFilter.prototype); | |
790 contentType &= ~RegExpFilter.typeMap[option.substr(1)]; | |
791 } | |
792 else if (option == "MATCH_CASE") | |
793 matchCase = true; | 798 matchCase = true; |
794 else if (option == "~MATCH_CASE") | 799 else if (option == "~match-case") |
795 matchCase = false; | 800 matchCase = false; |
796 else if (option == "DOMAIN" && value) | 801 else if (option == "domain" && value) |
797 domains = value.toUpperCase(); | 802 domains = value.toLowerCase(); |
798 else if (option == "THIRD_PARTY") | 803 else if (option == "third-party") |
799 thirdParty = true; | 804 thirdParty = true; |
800 else if (option == "~THIRD_PARTY") | 805 else if (option == "~third-party") |
801 thirdParty = false; | 806 thirdParty = false; |
802 else if (option == "COLLAPSE") | 807 else if (option == "collapse") |
803 collapse = true; | 808 collapse = true; |
804 else if (option == "~COLLAPSE") | 809 else if (option == "~collapse") |
805 collapse = false; | 810 collapse = false; |
806 else if (option == "SITEKEY" && value) | 811 else if (option == "sitekey" && value) |
807 sitekeys = value.toUpperCase(); | 812 sitekeys = value.toUpperCase(); |
808 else if (option == "REWRITE" && value) | 813 else if (option == "rewrite" && value) |
809 rewrite = value; | 814 rewrite = value; |
810 else | 815 else |
811 return new InvalidFilter(origText, "filter_unknown_option"); | 816 return new InvalidFilter(origText, "filter_unknown_option"); |
812 } | 817 } |
813 } | 818 } |
814 | 819 |
815 // For security reasons, never match $rewrite filters | 820 // For security reasons, never match $rewrite filters |
816 // against requests that might load any code to be executed. | 821 // against requests that might load any code to be executed. |
817 if (rewrite != null) | 822 if (rewrite != null) |
818 { | 823 { |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 */ | 1105 */ |
1101 function ElemHideEmulationFilter(text, domains, selector) | 1106 function ElemHideEmulationFilter(text, domains, selector) |
1102 { | 1107 { |
1103 ElemHideBase.call(this, text, domains, selector); | 1108 ElemHideBase.call(this, text, domains, selector); |
1104 } | 1109 } |
1105 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; | 1110 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; |
1106 | 1111 |
1107 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { | 1112 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { |
1108 type: "elemhideemulation" | 1113 type: "elemhideemulation" |
1109 }); | 1114 }); |
OLD | NEW |