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

Side by Side Diff: compiled/filter/ElemHideBase.cpp

Issue 29595633: Issue 5870 - Implement the new ElemHideEmulation filter type (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Reworked the logic and added tests Created Jan. 31, 2018, 9:07 p.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 | « compiled/filter/ElemHideBase.h ('k') | compiled/filter/Filter.cpp » ('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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 else 45 else
46 text[pos - delta] = text[pos]; 46 text[pos - delta] = text[pos];
47 } 47 }
48 selectorStart -= delta; 48 selectorStart -= delta;
49 49
50 text.reset(text, 0, len - delta); 50 text.reset(text, 0, len - delta);
51 } 51 }
52 } 52 }
53 53
54 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da ta) 54 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da ta)
55 : ActiveFilter(type, text, false), mData(data) 55 : ActiveFilter(type, text, false),
56 mData(data)
56 { 57 {
57 if (mData.HasDomains()) 58 if (mData.HasDomains())
58 ParseDomains(mData.GetDomainsSource(mText), u','); 59 ParseDomains(mData.GetDomainsSource(mText), u',');
59 } 60 }
60 61
61 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data) 62 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data)
62 { 63 {
63 StringScanner scanner(text); 64 StringScanner scanner(text);
64 65
65 // Domains part 66 // Domains part
(...skipping 16 matching lines...) Expand all
82 case u'"': 83 case u'"':
83 case u'!': 84 case u'!':
84 return Type::UNKNOWN; 85 return Type::UNKNOWN;
85 case u' ': 86 case u' ':
86 seenSpaces = true; 87 seenSpaces = true;
87 break; 88 break;
88 } 89 }
89 } 90 }
90 91
91 seenSpaces |= scanner.skip(u' '); 92 seenSpaces |= scanner.skip(u' ');
93 bool emulation = false;
92 bool exception = scanner.skipOne(u'@'); 94 bool exception = scanner.skipOne(u'@');
93 if (exception) 95 if (exception)
94 seenSpaces |= scanner.skip(u' '); 96 seenSpaces |= scanner.skip(u' ');
97 else
98 emulation = scanner.skipOne(u'?');
95 99
96 String::value_type next = scanner.next(); 100 String::value_type next = scanner.next();
97 if (next != u'#') 101 if (next != u'#')
98 return Type::UNKNOWN; 102 return Type::UNKNOWN;
99 103
100 // Selector part 104 // Selector part
101 105
102 // Selector shouldn't be empty 106 // Selector shouldn't be empty
103 seenSpaces |= scanner.skip(u' '); 107 seenSpaces |= scanner.skip(u' ');
104 if (scanner.done()) 108 if (scanner.done())
105 return Type::UNKNOWN; 109 return Type::UNKNOWN;
106 110
107 data.mSelectorStart = scanner.position() + 1; 111 data.mSelectorStart = scanner.position() + 1;
112 data.mNeedConversion = false;
108 113
109 // We are done validating, now we can normalize whitespace and the domain part 114 // We are done validating, now we can normalize whitespace and the domain part
110 if (seenSpaces) 115 if (seenSpaces)
111 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); 116 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart);
112 DependentString(text, 0, data.mDomainsEnd).toLower(); 117 DependentString(text, 0, data.mDomainsEnd).toLower();
113 118
119 // We still need to check the old syntax. It will be converted when
120 // we instantiate the filter.
121 if (!emulation &&
122 text.find(u"[-abp-properties="_str, data.mSelectorStart) != text.npos)
123 {
124 data.mNeedConversion = true;
125 emulation = !exception;
sergei 2018/02/05 14:51:04 Should it be an invalid filter if it's exception w
hub 2018/02/07 04:13:35 no. This is actually how exceptions for element hi
126 }
127
114 if (exception) 128 if (exception)
115 return Type::ELEMHIDEEXCEPTION; 129 return Type::ELEMHIDEEXCEPTION;
116 130
117 if (text.find(u"[-abp-properties="_str, data.mSelectorStart) != text.npos) 131 if (emulation)
118 return Type::ELEMHIDEEMULATION; 132 return Type::ELEMHIDEEMULATION;
119 133
120 return Type::ELEMHIDE; 134 return Type::ELEMHIDE;
121 } 135 }
122 136
137 // Convert filter from the old syntax to the new.
138 OwnedString ElemHideBase::ConvertFilter(const String& text, String::size_type& a t)
139 {
140 static const auto propsSelector = u"[-abp-properties="_str;
141 static const auto newPropsSelector = u":-abp-properties("_str;
142 static const auto elemHideDelimiter = u"##"_str;
143 auto selectorPos = text.find(propsSelector, at);
144 if (selectorPos != text.npos)
145 {
146 auto length = text.length();
147 auto properties = selectorPos + propsSelector.length();
148 String::value_type quote = 0;
149 bool escape = false;
150 String::size_type removed = 0; // how many chars we remove
151 String::size_type end = properties;
152 String::size_type quote_start = 0;
153 String::size_type quote_end = 0;
154 for (auto index = properties;
155 index < length && end == properties; index++)
156 {
157 if (escape)
158 {
159 escape = false;
160 continue;
161 }
162
163 auto c = text[index];
164 switch (c)
165 {
166 case '\\':
167 escape = true;
168 break;
169 case '"':
170 case '\'':
171 if (quote == 0)
172 {
173 quote = c;
174 quote_start = index + 1;
175 }
176 else if (quote == c)
177 {
178 // end of quoted.
179 quote = 0;
180 removed += 2;
181 quote_end = index;
182 }
183 break;
184 case ']':
185 if (quote == 0)
186 end = index + 1; // end of properties (after ])
187 break;
188 default:
189 break;
190 }
191 }
192
193 if (quote != 0)
194 quote_end = end - 1;
195 else if (quote_end <= quote_start)
196 {
197 // we likely didn't find a quoted content so we just take it as is.
198 quote_start = properties;
199 quote_end = end - 1;
200 }
201
202 // +1 for the replacement of "##" by "#?#"
203 String::size_type offset = 0;
204
205 String::size_type delimiter = text.find(elemHideDelimiter);
206 OwnedString converted(length + ((delimiter != text.npos) ? 1 : 0) - removed) ;
207 if (delimiter != text.npos)
208 {
209 if (delimiter >= selectorPos)
210 return OwnedString(text);
211
212 at++;
213 std::memcpy(converted.data(), text.data(),
214 delimiter * sizeof(String::value_type));
215 offset += delimiter;
216 std::memcpy(converted.data() + offset, u"#?#",
217 3 * sizeof(String::value_type));
218 offset += 3;
219 delimiter += 2;
220 // we have already parsed to past the delimiter.
221 selectorPos -= delimiter;
222 }
223 else
224 delimiter = 0;
225
226
227 std::memcpy(converted.data() + offset, text.data() + delimiter,
228 selectorPos * sizeof(String::value_type));
229 offset += selectorPos;
230
231 std::memcpy(converted.data() + offset, newPropsSelector.data(),
232 newPropsSelector.length() * sizeof(String::value_type));
233 offset += newPropsSelector.length();
234
235 std::memcpy(converted.data() + offset, text.data() + quote_start,
236 (quote_end - quote_start) * sizeof(String::value_type));
237 offset += quote_end - quote_start;
238
239 std::memcpy(converted.data() + offset, u")", sizeof(String::value_type));
240 offset++;
241
242 std::memcpy(converted.data() + offset, text.data() + end,
243 (length - end) * sizeof(String::value_type));
244 offset += (length - end) * sizeof(String::value_type);
245
246 return converted;
247 }
248
249 return OwnedString(text);
250 }
251
123 namespace 252 namespace
124 { 253 {
125 static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B "; 254 static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B ";
126 static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D "; 255 static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D ";
127 static constexpr String::size_type CURLY_REPLACEMENT_SIZE = sizeof(OPENING_CUR LY_REPLACEMENT) / sizeof(OPENING_CURLY_REPLACEMENT[0]) - 1; 256 static constexpr String::size_type CURLY_REPLACEMENT_SIZE = sizeof(OPENING_CUR LY_REPLACEMENT) / sizeof(OPENING_CURLY_REPLACEMENT[0]) - 1;
128 257
129 OwnedString EscapeCurlies(String::size_type replacementCount, 258 OwnedString EscapeCurlies(String::size_type replacementCount,
130 const DependentString& str) 259 const DependentString& str)
131 { 260 {
132 OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE - 1)); 261 OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE - 1));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 if (item.second && !item.first.empty()) 310 if (item.second && !item.first.empty())
182 { 311 {
183 if (!result.empty()) 312 if (!result.empty())
184 result.append(u','); 313 result.append(u',');
185 result.append(item.first); 314 result.append(item.first);
186 } 315 }
187 } 316 }
188 } 317 }
189 return result; 318 return result;
190 } 319 }
OLDNEW
« no previous file with comments | « compiled/filter/ElemHideBase.h ('k') | compiled/filter/Filter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld