Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/filterClasses.js

Issue 30045566: Fixed #4 - Disable rewrite option for all but internal redirect (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Reworked patch Created April 16, 2019, 4:55 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/filterClasses.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 686 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 * Defines whether the filter should distinguish between lower and upper case 697 * Defines whether the filter should distinguish between lower and upper case
698 * letters 698 * letters
699 * @param {string} [domains] 699 * @param {string} [domains]
700 * Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" 700 * Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com"
701 * @param {boolean} [thirdParty] 701 * @param {boolean} [thirdParty]
702 * Defines whether the filter should apply to third-party or first-party 702 * Defines whether the filter should apply to third-party or first-party
703 * content only 703 * content only
704 * @param {string} [sitekeys] 704 * @param {string} [sitekeys]
705 * Public keys of websites that this filter should apply to 705 * Public keys of websites that this filter should apply to
706 * @param {?string} [rewrite] 706 * @param {?string} [rewrite]
707 * The (optional) rule specifying how to rewrite the URL. See
708 * RegExpFilter.prototype.rewrite.
709 * @param {?string} [resourceName]
710 * The name of the internal resource to which to rewrite the 707 * The name of the internal resource to which to rewrite the
711 * URL. e.g. if the value of the <code>rewrite</code> parameter is 708 * URL. e.g. if the value of the <code>rewrite</code> parameter is
712 * <code>abp-resource:blank-html</code>, this should be 709 * <code>abp-resource:blank-html</code>, this should be
713 * <code>blank-html</code>. 710 * <code>blank-html</code>.
714 * @constructor 711 * @constructor
715 * @augments ActiveFilter 712 * @augments ActiveFilter
716 */ 713 */
717 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, 714 function RegExpFilter(text, regexpSource, contentType, matchCase, domains,
718 thirdParty, sitekeys, rewrite, resourceName) 715 thirdParty, sitekeys, rewrite)
719 { 716 {
720 ActiveFilter.call(this, text, domains); 717 ActiveFilter.call(this, text, domains);
721 718
722 if (contentType != null) 719 if (contentType != null)
723 this.contentType = contentType; 720 this.contentType = contentType;
724 if (matchCase) 721 if (matchCase)
725 this.matchCase = matchCase; 722 this.matchCase = matchCase;
726 if (thirdParty != null) 723 if (thirdParty != null)
727 this.thirdParty = thirdParty; 724 this.thirdParty = thirdParty;
728 if (sitekeys != null) 725 if (sitekeys != null)
729 this.sitekeySource = sitekeys; 726 this.sitekeySource = sitekeys;
730 if (rewrite != null) 727 if (rewrite != null)
731 this.rewrite = rewrite; 728 this.rewrite = rewrite;
732 if (resourceName)
733 this.resourceName = resourceName;
734 729
735 if (regexpSource.length >= 2 && 730 if (regexpSource.length >= 2 &&
736 regexpSource[0] == "/" && 731 regexpSource[0] == "/" &&
737 regexpSource[regexpSource.length - 1] == "/") 732 regexpSource[regexpSource.length - 1] == "/")
738 { 733 {
739 // The filter is a regular expression - convert it immediately to 734 // The filter is a regular expression - convert it immediately to
740 // catch syntax errors 735 // catch syntax errors
741 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), 736 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2),
742 this.matchCase ? "" : "i"); 737 this.matchCase ? "" : "i");
743 Object.defineProperty(this, "regexp", {value: regexp}); 738 Object.defineProperty(this, "regexp", {value: regexp});
744 } 739 }
745 else 740 else
746 { 741 {
747 // Patterns like /foo/bar/* exist so that they are not treated as regular 742 // Patterns like /foo/bar/* exist so that they are not treated as regular
748 // expressions. We drop any superfluous wildcards here so our optimizations 743 // expressions. We drop any superfluous wildcards here so our optimizations
749 // can kick in. 744 // can kick in.
750 if (this.rewrite == null || this.resourceName) 745 if (this.rewrite)
Manish Jethani 2019/04/16 05:52:58 This actually has a somewhat opposite of the inten
hub 2019/04/16 12:23:06 Good catch.
751 regexpSource = regexpSource.replace(/^\*+/, "").replace(/\*+$/, ""); 746 regexpSource = regexpSource.replace(/^\*+/, "").replace(/\*+$/, "");
752 747
753 if (!this.matchCase && isLiteralPattern(regexpSource)) 748 if (!this.matchCase && isLiteralPattern(regexpSource))
754 regexpSource = regexpSource.toLowerCase(); 749 regexpSource = regexpSource.toLowerCase();
755 750
756 // No need to convert this filter to regular expression yet, do it on demand 751 // No need to convert this filter to regular expression yet, do it on demand
757 this.pattern = regexpSource; 752 this.pattern = regexpSource;
758 } 753 }
759 } 754 }
760 exports.RegExpFilter = RegExpFilter; 755 exports.RegExpFilter = RegExpFilter;
(...skipping 19 matching lines...) Expand all
780 */ 775 */
781 pattern: null, 776 pattern: null,
782 /** 777 /**
783 * Regular expression to be used when testing against this filter 778 * Regular expression to be used when testing against this filter
784 * @type {RegExp} 779 * @type {RegExp}
785 */ 780 */
786 get regexp() 781 get regexp()
787 { 782 {
788 let value = null; 783 let value = null;
789 784
790 let {pattern, rewrite, resourceName} = this; 785 let {pattern} = this;
791 if ((rewrite != null && !resourceName) || !isLiteralPattern(pattern)) 786 if (!isLiteralPattern(pattern))
792 { 787 value = new RegExp(filterToRegExp(pattern), this.matchCase ? "" : "i");
793 value = new RegExp(filterToRegExp(pattern, rewrite != null),
794 this.matchCase ? "" : "i");
795 }
796 788
797 Object.defineProperty(this, "regexp", {value}); 789 Object.defineProperty(this, "regexp", {value});
798 return value; 790 return value;
799 }, 791 },
800 /** 792 /**
801 * Content types the filter applies to, combination of values from 793 * Content types the filter applies to, combination of values from
802 * RegExpFilter.typeMap 794 * RegExpFilter.typeMap
803 * @type {number} 795 * @type {number}
804 */ 796 */
805 contentType: 0x7FFFFFFF, 797 contentType: 0x7FFFFFFF,
(...skipping 29 matching lines...) Expand all
835 this.sitekeySource = null; 827 this.sitekeySource = null;
836 } 828 }
837 829
838 Object.defineProperty( 830 Object.defineProperty(
839 this, "sitekeys", {value: sitekeys, enumerable: true} 831 this, "sitekeys", {value: sitekeys, enumerable: true}
840 ); 832 );
841 return this.sitekeys; 833 return this.sitekeys;
842 }, 834 },
843 835
844 /** 836 /**
845 * The rule specifying how to rewrite the URL.
846 * The syntax is similar to the one of String.prototype.replace().
847 * @type {?string}
848 */
849 rewrite: null,
850
851 /**
852 * The name of the internal resource to which to rewrite the 837 * The name of the internal resource to which to rewrite the
853 * URL. e.g. if the value of the <code>rewrite</code> property is 838 * URL. e.g. if the value of the <code>rewrite</code> property is
Manish Jethani 2019/04/16 05:52:58 I think we can replace `<code>rewrite</code> prope
hub 2019/04/16 12:23:06 Done.
854 * <code>abp-resource:blank-html</code>, this should be 839 * <code>abp-resource:blank-html</code>, this should be
855 * <code>blank-html</code>. 840 * <code>blank-html</code>.
856 * @type {?string} 841 * @type {?string}
857 */ 842 */
858 resourceName: null, 843 rewrite: null,
859 844
860 /** 845 /**
861 * Tests whether the URL matches this filter 846 * Tests whether the URL matches this filter
862 * @param {string} location URL to be tested 847 * @param {string} location URL to be tested
863 * @param {number} typeMask bitmask of content / request types to match 848 * @param {number} typeMask bitmask of content / request types to match
864 * @param {string} [docDomain] domain name of the document that loads the URL 849 * @param {string} [docDomain] domain name of the document that loads the URL
865 * @param {boolean} [thirdParty] should be true if the URL is a third-party 850 * @param {boolean} [thirdParty] should be true if the URL is a third-party
866 * request 851 * request
867 * @param {string} [sitekey] public key provided by the document 852 * @param {string} [sitekey] public key provided by the document
868 * @return {boolean} true in case of a match 853 * @return {boolean} true in case of a match
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 } 972 }
988 973
989 let contentType = null; 974 let contentType = null;
990 let matchCase = null; 975 let matchCase = null;
991 let domains = null; 976 let domains = null;
992 let sitekeys = null; 977 let sitekeys = null;
993 let thirdParty = null; 978 let thirdParty = null;
994 let collapse = null; 979 let collapse = null;
995 let csp = null; 980 let csp = null;
996 let rewrite = null; 981 let rewrite = null;
997 let resourceName = null;
998 let options; 982 let options;
999 let match = text.includes("$") ? Filter.optionsRegExp.exec(text) : null; 983 let match = text.includes("$") ? Filter.optionsRegExp.exec(text) : null;
1000 if (match) 984 if (match)
1001 { 985 {
1002 options = match[1].split(","); 986 options = match[1].split(",");
1003 text = match.input.substr(0, match.index); 987 text = match.input.substr(0, match.index);
1004 for (let option of options) 988 for (let option of options)
1005 { 989 {
1006 let value = null; 990 let value = null;
1007 let separatorIndex = option.indexOf("="); 991 let separatorIndex = option.indexOf("=");
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 break; 1037 break;
1054 case "collapse": 1038 case "collapse":
1055 collapse = !inverse; 1039 collapse = !inverse;
1056 break; 1040 break;
1057 case "sitekey": 1041 case "sitekey":
1058 if (!value) 1042 if (!value)
1059 return new InvalidFilter(origText, "filter_unknown_option"); 1043 return new InvalidFilter(origText, "filter_unknown_option");
1060 sitekeys = value.toUpperCase(); 1044 sitekeys = value.toUpperCase();
1061 break; 1045 break;
1062 case "rewrite": 1046 case "rewrite":
1063 if (value == null) 1047 if (!value || !value.startsWith("abp-resource:"))
Manish Jethani 2019/04/16 05:52:58 It doesn't matter _that_ much, but I'd just like t
hub 2019/04/16 12:23:06 I think I'm gonna go the safe route. Change was in
1064 return new InvalidFilter(origText, "filter_unknown_option"); 1048 return new InvalidFilter(origText, "filter_invalid_rewrite");
1065 rewrite = value; 1049 rewrite = value.substr("abp-resource:".length);
1066 if (value.startsWith("abp-resource:"))
1067 resourceName = value.substr("abp-resource:".length);
1068 break; 1050 break;
1069 default: 1051 default:
1070 return new InvalidFilter(origText, "filter_unknown_option"); 1052 return new InvalidFilter(origText, "filter_unknown_option");
1071 } 1053 }
1072 } 1054 }
1073 } 1055 }
1074 } 1056 }
1075 1057
1076 // For security reasons, never match $rewrite filters
1077 // against requests that might load any code to be executed.
1078 // Unless it is to an internal resource.
1079 if (rewrite != null && !resourceName)
1080 {
1081 if (contentType == null)
1082 ({contentType} = RegExpFilter.prototype);
1083 contentType &= ~(RegExpFilter.typeMap.SCRIPT |
1084 RegExpFilter.typeMap.SUBDOCUMENT |
1085 RegExpFilter.typeMap.OBJECT |
1086 RegExpFilter.typeMap.OBJECT_SUBREQUEST);
1087 }
1088
1089 try 1058 try
1090 { 1059 {
1091 if (blocking) 1060 if (blocking)
1092 { 1061 {
1093 if (csp && Filter.invalidCSPRegExp.test(csp)) 1062 if (csp && Filter.invalidCSPRegExp.test(csp))
1094 return new InvalidFilter(origText, "filter_invalid_csp"); 1063 return new InvalidFilter(origText, "filter_invalid_csp");
1095 1064
1096 if (resourceName) 1065 if (rewrite)
1097 { 1066 {
1098 if (text[0] == "|" && text[1] == "|") 1067 if (text[0] == "|" && text[1] == "|")
1099 { 1068 {
1100 if (!domains && thirdParty != false) 1069 if (!domains && thirdParty != false)
1101 return new InvalidFilter(origText, "filter_invalid_rewrite"); 1070 return new InvalidFilter(origText, "filter_invalid_rewrite");
1102 } 1071 }
1103 else if (text[0] == "*") 1072 else if (text[0] == "*")
1104 { 1073 {
1105 if (!domains) 1074 if (!domains)
1106 return new InvalidFilter(origText, "filter_invalid_rewrite"); 1075 return new InvalidFilter(origText, "filter_invalid_rewrite");
1107 } 1076 }
1108 else 1077 else
1109 { 1078 {
1110 return new InvalidFilter(origText, "filter_invalid_rewrite"); 1079 return new InvalidFilter(origText, "filter_invalid_rewrite");
1111 } 1080 }
1112 } 1081 }
1113 1082
1114 return new BlockingFilter(origText, text, contentType, matchCase, domains, 1083 return new BlockingFilter(origText, text, contentType, matchCase, domains,
1115 thirdParty, sitekeys, rewrite, resourceName, 1084 thirdParty, sitekeys, rewrite,
1116 collapse, csp); 1085 collapse, csp);
1117 } 1086 }
1118 return new WhitelistFilter(origText, text, contentType, matchCase, domains, 1087 return new WhitelistFilter(origText, text, contentType, matchCase, domains,
1119 thirdParty, sitekeys); 1088 thirdParty, sitekeys);
1120 } 1089 }
1121 catch (e) 1090 catch (e)
1122 { 1091 {
1123 return new InvalidFilter(origText, "filter_invalid_regexp"); 1092 return new InvalidFilter(origText, "filter_invalid_regexp");
1124 } 1093 }
1125 }; 1094 };
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 /** 1135 /**
1167 * Class for blocking filters 1136 * Class for blocking filters
1168 * @param {string} text see {@link Filter Filter()} 1137 * @param {string} text see {@link Filter Filter()}
1169 * @param {string} regexpSource see {@link RegExpFilter RegExpFilter()} 1138 * @param {string} regexpSource see {@link RegExpFilter RegExpFilter()}
1170 * @param {number} [contentType] see {@link RegExpFilter RegExpFilter()} 1139 * @param {number} [contentType] see {@link RegExpFilter RegExpFilter()}
1171 * @param {boolean} [matchCase] see {@link RegExpFilter RegExpFilter()} 1140 * @param {boolean} [matchCase] see {@link RegExpFilter RegExpFilter()}
1172 * @param {string} [domains] see {@link RegExpFilter RegExpFilter()} 1141 * @param {string} [domains] see {@link RegExpFilter RegExpFilter()}
1173 * @param {boolean} [thirdParty] see {@link RegExpFilter RegExpFilter()} 1142 * @param {boolean} [thirdParty] see {@link RegExpFilter RegExpFilter()}
1174 * @param {string} [sitekeys] see {@link RegExpFilter RegExpFilter()} 1143 * @param {string} [sitekeys] see {@link RegExpFilter RegExpFilter()}
1175 * @param {?string} [rewrite] 1144 * @param {?string} [rewrite]
1176 * The (optional) rule specifying how to rewrite the URL. See
1177 * RegExpFilter.prototype.rewrite.
1178 * @param {?string} [resourceName]
1179 * The name of the internal resource to which to rewrite the 1145 * The name of the internal resource to which to rewrite the
1180 * URL. e.g. if the value of the <code>rewrite</code> parameter is 1146 * URL. e.g. if the value of the <code>rewrite</code> parameter is
1181 * <code>abp-resource:blank-html</code>, this should be 1147 * <code>abp-resource:blank-html</code>, this should be
1182 * <code>blank-html</code>. 1148 * <code>blank-html</code>.
1183 * @param {boolean} [collapse] 1149 * @param {boolean} [collapse]
1184 * defines whether the filter should collapse blocked content, can be null 1150 * defines whether the filter should collapse blocked content, can be null
1185 * @param {string} [csp] 1151 * @param {string} [csp]
1186 * Content Security Policy to inject when the filter matches 1152 * Content Security Policy to inject when the filter matches
1187 * @constructor 1153 * @constructor
1188 * @augments RegExpFilter 1154 * @augments RegExpFilter
1189 */ 1155 */
1190 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, 1156 function BlockingFilter(text, regexpSource, contentType, matchCase, domains,
1191 thirdParty, sitekeys, rewrite, resourceName, 1157 thirdParty, sitekeys, rewrite,
1192 collapse, csp) 1158 collapse, csp)
1193 { 1159 {
1194 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, 1160 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains,
1195 thirdParty, sitekeys, rewrite, resourceName); 1161 thirdParty, sitekeys, rewrite);
1196 1162
1197 if (collapse != null) 1163 if (collapse != null)
1198 this.collapse = collapse; 1164 this.collapse = collapse;
1199 1165
1200 if (csp != null) 1166 if (csp != null)
1201 this.csp = csp; 1167 this.csp = csp;
1202 } 1168 }
1203 exports.BlockingFilter = BlockingFilter; 1169 exports.BlockingFilter = BlockingFilter;
1204 1170
1205 BlockingFilter.prototype = extend(RegExpFilter, { 1171 BlockingFilter.prototype = extend(RegExpFilter, {
(...skipping 12 matching lines...) Expand all
1218 */ 1184 */
1219 csp: null, 1185 csp: null,
1220 1186
1221 /** 1187 /**
1222 * Rewrites an URL. 1188 * Rewrites an URL.
1223 * @param {string} url the URL to rewrite 1189 * @param {string} url the URL to rewrite
1224 * @return {string} the rewritten URL, or the original in case of failure 1190 * @return {string} the rewritten URL, or the original in case of failure
1225 */ 1191 */
1226 rewriteUrl(url) 1192 rewriteUrl(url)
1227 { 1193 {
1228 if (this.resourceName) 1194 return resourceMap.get(this.rewrite) || url;
1229 return resourceMap.get(this.resourceName) || url;
1230
1231 try
1232 {
1233 let rewrittenUrl = new URL(url.replace(this.regexp, this.rewrite), url);
1234 if (rewrittenUrl.origin == new URL(url).origin)
1235 return rewrittenUrl.href;
1236 }
1237 catch (e)
1238 {
1239 }
1240
1241 return url;
1242 } 1195 }
1243 }); 1196 });
1244 1197
1245 /** 1198 /**
1246 * Class for whitelist filters 1199 * Class for whitelist filters
1247 * @param {string} text see {@link Filter Filter()} 1200 * @param {string} text see {@link Filter Filter()}
1248 * @param {string} regexpSource see {@link RegExpFilter RegExpFilter()} 1201 * @param {string} regexpSource see {@link RegExpFilter RegExpFilter()}
1249 * @param {number} [contentType] see {@link RegExpFilter RegExpFilter()} 1202 * @param {number} [contentType] see {@link RegExpFilter RegExpFilter()}
1250 * @param {boolean} [matchCase] see {@link RegExpFilter RegExpFilter()} 1203 * @param {boolean} [matchCase] see {@link RegExpFilter RegExpFilter()}
1251 * @param {string} [domains] see {@link RegExpFilter RegExpFilter()} 1204 * @param {string} [domains] see {@link RegExpFilter RegExpFilter()}
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1446 1399
1447 /** 1400 /**
1448 * Script that should be executed 1401 * Script that should be executed
1449 * @type {string} 1402 * @type {string}
1450 */ 1403 */
1451 get script() 1404 get script()
1452 { 1405 {
1453 return this.body; 1406 return this.body;
1454 } 1407 }
1455 }); 1408 });
OLDNEW
« no previous file with comments | « no previous file | test/filterClasses.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld