Left: | ||
Right: |
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-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 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 /** @module filterValidation */ | 18 /** @module filterValidation */ |
19 | 19 |
20 let {Filter, InvalidFilter, ElemHideBase} = require("filterClasses"); | 20 let {Filter, InvalidFilter, ElemHideBase} = require("filterClasses"); |
21 | 21 |
22 function isValidCSSSelector(selector) | |
23 { | |
24 let style = document.createElement("style"); | |
25 document.documentElement.appendChild(style); | |
26 let sheet = style.sheet; | |
27 document.documentElement.removeChild(style); | |
28 | |
29 try | |
30 { | |
31 document.querySelector(selector); | |
32 sheet.insertRule(selector + "{}", 0); | |
33 } | |
34 catch (e) | |
35 { | |
36 return false; | |
37 } | |
38 return true; | |
39 } | |
40 | |
41 /** | |
42 * @typedef ParsedFilter | |
43 * @property {?Filter} [filter] The parsed filter is it is valid. Or null if | |
kzar
2015/06/08 11:28:04
Nit: Typo "The parsed filter_if_ it is valid"
Sebastian Noack
2015/06/08 12:00:08
Done.
| |
44 * the given string is empty or a filter list head er. | |
45 * @property {string} [error] An error message indicated that the filter cann ot | |
46 * be parsed or contains an invalid CSS selector. | |
47 */ | |
48 | |
49 let parseFilter = | |
22 /** | 50 /** |
23 * Parses and validates a filter given by the user. | 51 * Parses and validates a filter given by the user. |
24 * | 52 * |
25 * @param {string} text | 53 * @param {string} text |
26 * @param {Boolean} [ignoreHeaders=false] If true, no exception is raised | 54 * @param {Boolean} [ignoreHeaders=false] If true, no error is produced |
27 * for filter list headers, instead | 55 * for filter list headers, instead |
28 * the function will return null. | 56 * {filter: null} is returned. |
29 * @return {Filter} | 57 * @return {ParsedFilter} |
30 * @throws Will throw an exception if filter cannot be | |
31 * parsed or contains an invalid CSS selector. | |
32 * @static | |
33 */ | 58 */ |
34 function parseFilter(text, ignoreHeaders) | 59 exports.parseFilter = function(text, ignoreHeaders) |
35 { | 60 { |
61 let filter = null; | |
36 text = Filter.normalize(text); | 62 text = Filter.normalize(text); |
37 if (!text) | |
38 return null; | |
39 | 63 |
40 if (text[0] == "[") | 64 if (text) |
41 { | 65 { |
42 if (ignoreHeaders) | 66 if (text[0] != "[") |
43 return null; | 67 { |
68 filter = Filter.fromText(text); | |
44 | 69 |
45 throw ext.i18n.getMessage("unexpected_filter_list_header"); | 70 if (filter instanceof InvalidFilter) |
46 } | 71 return {error: filter.reason}; |
47 | 72 |
48 let filter = Filter.fromText(text); | 73 if (filter instanceof ElemHideBase && !isValidCSSSelector(filter.selector) ) |
49 | 74 return {error: ext.i18n.getMessage("invalid_css_selector", "'" + filter. selector + "'")}; |
50 if (filter instanceof InvalidFilter) | 75 } |
51 throw filter.reason; | 76 else if (!ignoreHeaders) |
52 | |
53 if (filter instanceof ElemHideBase) | |
54 { | |
55 let style = document.createElement("style"); | |
56 document.documentElement.appendChild(style); | |
57 let sheet = style.sheet; | |
58 document.documentElement.removeChild(style); | |
59 | |
60 try | |
61 { | 77 { |
62 document.querySelector(filter.selector); | 78 return {error: ext.i18n.getMessage("unexpected_filter_list_header")}; |
63 sheet.insertRule(filter.selector + "{}", 0); | |
64 } | |
65 catch (error) | |
66 { | |
67 throw ext.i18n.getMessage("invalid_css_selector", "'" + filter.selector + "'"); | |
68 } | 79 } |
69 } | 80 } |
70 | 81 |
71 return filter; | 82 return {filter: filter}; |
72 } | 83 }; |
73 exports.parseFilter = parseFilter; | 84 |
85 /** | |
86 * @typedef ParsedFilters | |
87 * @property {Filter[]} [filters] The parsed filters if all of them are valid. | |
88 * @property {string} [error] An error message indicated that any filter ca nnot | |
89 * be parsed or contains an invalid CSS selector . | |
90 */ | |
74 | 91 |
75 /** | 92 /** |
76 * Parses and validates a newline-separated list of filters given by the user. | 93 * Parses and validates a newline-separated list of filters given by the user. |
77 * | 94 * |
78 * @param {string} text | 95 * @param {string} text |
79 * @param {Boolean} [ignoreHeaders=false] If true, filter list headers | 96 * @param {Boolean} [ignoreHeaders=false] If true, filter list headers |
80 * will be stripped instead of | 97 * will be stripped instead of |
81 * raising an exception. | 98 * producing an error. |
kzar
2015/06/08 11:28:04
Nit: "returning"?
Sebastian Noack
2015/06/08 12:00:08
I did not say to "return" an error, because strict
| |
82 * @return {Filter[]} | 99 * @return {ParsedFilters} |
83 * @throws Will throw an exception if one of the filters cannot | |
84 be parsed or contains an invalid CSS selector. | |
85 */ | 100 */ |
86 exports.parseFilters = function(text, ignoreHeaders) | 101 exports.parseFilters = function(text, ignoreHeaders) |
87 { | 102 { |
88 let lines = text.split("\n"); | 103 let lines = text.split("\n"); |
89 let filters = []; | 104 let filters = []; |
90 | 105 |
91 for (let i = 0; i < lines.length; i++) | 106 for (let i = 0; i < lines.length; i++) |
92 { | 107 { |
93 let filter; | 108 let {filter, error} = parseFilter(lines[i], ignoreHeaders); |
94 try | 109 |
95 { | 110 if (error) |
96 filter = parseFilter(lines[i], ignoreHeaders); | 111 return {error: ext.i18n.getMessage("line", (i + 1).toString()) + ": " + er ror}; |
97 } | |
98 catch (error) | |
99 { | |
100 throw ext.i18n.getMessage("line", (i + 1).toString()) + ": " + error; | |
101 } | |
102 | 112 |
103 if (filter) | 113 if (filter) |
kzar
2015/06/08 11:28:04
Nit: Should be `else if (filter)` IMO
Sebastian Noack
2015/06/08 12:00:08
No, it shouldn't. The else would be redundant, as
| |
104 filters.push(filter); | 114 filters.push(filter); |
105 } | 115 } |
106 | 116 |
107 return filters; | 117 return {filters: filters}; |
108 }; | 118 }; |
OLD | NEW |