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 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 text = text.substr(2); | 764 text = text.substr(2); |
765 } | 765 } |
766 | 766 |
767 let contentType = null; | 767 let contentType = null; |
768 let matchCase = null; | 768 let matchCase = null; |
769 let domains = null; | 769 let domains = null; |
770 let sitekeys = null; | 770 let sitekeys = null; |
771 let thirdParty = null; | 771 let thirdParty = null; |
772 let collapse = null; | 772 let collapse = null; |
773 let csp = null; | 773 let csp = null; |
| 774 let snippets = null; |
774 let options; | 775 let options; |
775 let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null); | 776 let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null); |
776 if (match) | 777 if (match) |
777 { | 778 { |
778 options = match[1].split(","); | 779 options = match[1].split(","); |
779 text = match.input.substr(0, match.index); | 780 text = match.input.substr(0, match.index); |
780 for (let option of options) | 781 for (let option of options) |
781 { | 782 { |
782 let value = null; | 783 let value = null; |
783 let separatorIndex = option.indexOf("="); | 784 let separatorIndex = option.indexOf("="); |
784 if (separatorIndex >= 0) | 785 if (separatorIndex >= 0) |
785 { | 786 { |
786 value = option.substr(separatorIndex + 1); | 787 value = option.substr(separatorIndex + 1); |
787 option = option.substr(0, separatorIndex); | 788 option = option.substr(0, separatorIndex); |
788 } | 789 } |
789 option = option.replace(/-/, "_").toUpperCase(); | 790 option = option.replace(/-/, "_").toUpperCase(); |
790 if (option in RegExpFilter.typeMap) | 791 if (option in RegExpFilter.typeMap) |
791 { | 792 { |
792 if (contentType == null) | 793 if (contentType == null) |
793 contentType = 0; | 794 contentType = 0; |
794 contentType |= RegExpFilter.typeMap[option]; | 795 contentType |= RegExpFilter.typeMap[option]; |
795 | 796 |
796 if (option == "CSP" && value) | 797 if (option == "CSP" && value) |
797 csp = value; | 798 csp = value; |
| 799 else if (option == "SNIPPET" && value) |
| 800 snippets = value.split("|"); |
798 } | 801 } |
799 else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap) | 802 else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap) |
800 { | 803 { |
801 if (contentType == null) | 804 if (contentType == null) |
802 ({contentType} = RegExpFilter.prototype); | 805 ({contentType} = RegExpFilter.prototype); |
803 contentType &= ~RegExpFilter.typeMap[option.substr(1)]; | 806 contentType &= ~RegExpFilter.typeMap[option.substr(1)]; |
804 } | 807 } |
805 else if (option == "MATCH_CASE") | 808 else if (option == "MATCH_CASE") |
806 matchCase = true; | 809 matchCase = true; |
807 else if (option == "~MATCH_CASE") | 810 else if (option == "~MATCH_CASE") |
(...skipping 16 matching lines...) Expand all Loading... |
824 } | 827 } |
825 | 828 |
826 try | 829 try |
827 { | 830 { |
828 if (blocking) | 831 if (blocking) |
829 { | 832 { |
830 if (csp && Filter.invalidCSPRegExp.test(csp)) | 833 if (csp && Filter.invalidCSPRegExp.test(csp)) |
831 return new InvalidFilter(origText, "filter_invalid_csp"); | 834 return new InvalidFilter(origText, "filter_invalid_csp"); |
832 | 835 |
833 return new BlockingFilter(origText, text, contentType, matchCase, domains, | 836 return new BlockingFilter(origText, text, contentType, matchCase, domains, |
834 thirdParty, sitekeys, collapse, csp); | 837 thirdParty, sitekeys, collapse, csp, snippets); |
835 } | 838 } |
836 return new WhitelistFilter(origText, text, contentType, matchCase, domains, | 839 return new WhitelistFilter(origText, text, contentType, matchCase, domains, |
837 thirdParty, sitekeys); | 840 thirdParty, sitekeys); |
838 } | 841 } |
839 catch (e) | 842 catch (e) |
840 { | 843 { |
841 return new InvalidFilter(origText, "filter_invalid_regexp"); | 844 return new InvalidFilter(origText, "filter_invalid_regexp"); |
842 } | 845 } |
843 }; | 846 }; |
844 | 847 |
845 /** | 848 /** |
846 * Maps type strings like "SCRIPT" or "OBJECT" to bit masks | 849 * Maps type strings like "SCRIPT" or "OBJECT" to bit masks |
847 */ | 850 */ |
848 RegExpFilter.typeMap = { | 851 RegExpFilter.typeMap = { |
849 OTHER: 1, | 852 OTHER: 1, |
850 SCRIPT: 2, | 853 SCRIPT: 2, |
851 IMAGE: 4, | 854 IMAGE: 4, |
852 STYLESHEET: 8, | 855 STYLESHEET: 8, |
853 OBJECT: 16, | 856 OBJECT: 16, |
854 SUBDOCUMENT: 32, | 857 SUBDOCUMENT: 32, |
855 DOCUMENT: 64, | 858 DOCUMENT: 64, |
856 WEBSOCKET: 128, | 859 WEBSOCKET: 128, |
857 WEBRTC: 256, | 860 WEBRTC: 256, |
858 CSP: 512, | 861 CSP: 512, |
859 XBL: 1, | 862 XBL: 1, |
860 PING: 1024, | 863 PING: 1024, |
861 XMLHTTPREQUEST: 2048, | 864 XMLHTTPREQUEST: 2048, |
862 OBJECT_SUBREQUEST: 4096, | 865 OBJECT_SUBREQUEST: 4096, |
| 866 SNIPPET: 8192, |
863 DTD: 1, | 867 DTD: 1, |
864 MEDIA: 16384, | 868 MEDIA: 16384, |
865 FONT: 32768, | 869 FONT: 32768, |
866 | 870 |
867 BACKGROUND: 4, // Backwards compat, same as IMAGE | 871 BACKGROUND: 4, // Backwards compat, same as IMAGE |
868 | 872 |
869 POPUP: 0x10000000, | 873 POPUP: 0x10000000, |
870 GENERICBLOCK: 0x20000000, | 874 GENERICBLOCK: 0x20000000, |
871 ELEMHIDE: 0x40000000, | 875 ELEMHIDE: 0x40000000, |
872 GENERICHIDE: 0x80000000 | 876 GENERICHIDE: 0x80000000 |
873 }; | 877 }; |
874 | 878 |
875 // CSP, DOCUMENT, ELEMHIDE, POPUP, GENERICHIDE and GENERICBLOCK options | 879 // CSP, SNIPPET, DOCUMENT, ELEMHIDE, POPUP, GENERICHIDE and GENERICBLOCK options |
876 // shouldn't be there by default | 880 // shouldn't be there by default |
877 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.CSP | | 881 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.CSP | |
| 882 RegExpFilter.typeMap.SNIPPET | |
878 RegExpFilter.typeMap.DOCUMENT | | 883 RegExpFilter.typeMap.DOCUMENT | |
879 RegExpFilter.typeMap.ELEMHIDE | | 884 RegExpFilter.typeMap.ELEMHIDE | |
880 RegExpFilter.typeMap.POPUP | | 885 RegExpFilter.typeMap.POPUP | |
881 RegExpFilter.typeMap.GENERICHIDE | | 886 RegExpFilter.typeMap.GENERICHIDE | |
882 RegExpFilter.typeMap.GENERICBLOCK); | 887 RegExpFilter.typeMap.GENERICBLOCK); |
883 | 888 |
884 /** | 889 /** |
885 * Class for blocking filters | 890 * Class for blocking filters |
886 * @param {string} text see Filter() | 891 * @param {string} text see Filter() |
887 * @param {string} regexpSource see RegExpFilter() | 892 * @param {string} regexpSource see RegExpFilter() |
888 * @param {number} contentType see RegExpFilter() | 893 * @param {number} contentType see RegExpFilter() |
889 * @param {boolean} matchCase see RegExpFilter() | 894 * @param {boolean} matchCase see RegExpFilter() |
890 * @param {string} domains see RegExpFilter() | 895 * @param {string} domains see RegExpFilter() |
891 * @param {boolean} thirdParty see RegExpFilter() | 896 * @param {boolean} thirdParty see RegExpFilter() |
892 * @param {string} sitekeys see RegExpFilter() | 897 * @param {string} sitekeys see RegExpFilter() |
893 * @param {boolean} collapse | 898 * @param {boolean} collapse |
894 * defines whether the filter should collapse blocked content, can be null | 899 * defines whether the filter should collapse blocked content, can be null |
895 * @param {string} [csp] | 900 * @param {string} [csp] |
896 * Content Security Policy to inject when the filter matches | 901 * Content Security Policy to inject when the filter matches |
| 902 * @param {string} [snippets] |
| 903 * the code snippets to inject when the filter matches |
897 * @constructor | 904 * @constructor |
898 * @augments RegExpFilter | 905 * @augments RegExpFilter |
899 */ | 906 */ |
900 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, | 907 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, |
901 thirdParty, sitekeys, collapse, csp) | 908 thirdParty, sitekeys, collapse, csp, snippets) |
902 { | 909 { |
903 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, | 910 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, |
904 thirdParty, sitekeys); | 911 thirdParty, sitekeys); |
905 | 912 |
906 this.collapse = collapse; | 913 this.collapse = collapse; |
907 this.csp = csp; | 914 this.csp = csp; |
| 915 this.snippets = snippets; |
908 } | 916 } |
909 exports.BlockingFilter = BlockingFilter; | 917 exports.BlockingFilter = BlockingFilter; |
910 | 918 |
911 BlockingFilter.prototype = extend(RegExpFilter, { | 919 BlockingFilter.prototype = extend(RegExpFilter, { |
912 type: "blocking", | 920 type: "blocking", |
913 | 921 |
914 /** | 922 /** |
915 * Defines whether the filter should collapse blocked content. | 923 * Defines whether the filter should collapse blocked content. |
916 * Can be null (use the global preference). | 924 * Can be null (use the global preference). |
917 * @type {boolean} | 925 * @type {boolean} |
918 */ | 926 */ |
919 collapse: null, | 927 collapse: null, |
920 | 928 |
921 /** | 929 /** |
922 * Content Security Policy to inject for matching requests. | 930 * Content Security Policy to inject for matching requests. |
923 * @type {string} | 931 * @type {string} |
924 */ | 932 */ |
925 csp: null | 933 csp: null, |
| 934 |
| 935 /** |
| 936 * The code snippets to inject for matching requests. |
| 937 * @type {string[]} |
| 938 */ |
| 939 snippets: null |
926 }); | 940 }); |
927 | 941 |
928 /** | 942 /** |
929 * Class for whitelist filters | 943 * Class for whitelist filters |
930 * @param {string} text see Filter() | 944 * @param {string} text see Filter() |
931 * @param {string} regexpSource see RegExpFilter() | 945 * @param {string} regexpSource see RegExpFilter() |
932 * @param {number} contentType see RegExpFilter() | 946 * @param {number} contentType see RegExpFilter() |
933 * @param {boolean} matchCase see RegExpFilter() | 947 * @param {boolean} matchCase see RegExpFilter() |
934 * @param {string} domains see RegExpFilter() | 948 * @param {string} domains see RegExpFilter() |
935 * @param {boolean} thirdParty see RegExpFilter() | 949 * @param {boolean} thirdParty see RegExpFilter() |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 */ | 1094 */ |
1081 function ElemHideEmulationFilter(text, domains, selector) | 1095 function ElemHideEmulationFilter(text, domains, selector) |
1082 { | 1096 { |
1083 ElemHideBase.call(this, text, domains, selector); | 1097 ElemHideBase.call(this, text, domains, selector); |
1084 } | 1098 } |
1085 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; | 1099 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; |
1086 | 1100 |
1087 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { | 1101 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { |
1088 type: "elemhideemulation" | 1102 type: "elemhideemulation" |
1089 }); | 1103 }); |
OLD | NEW |