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

Side by Side Diff: src/plugin/PluginFilter.cpp

Issue 29331055: Issue #1234 - Remove 'CString' from PluginFilter.* (Closed)
Patch Set: Created Nov. 29, 2015, 3:49 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
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-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 #include "PluginStdAfx.h" 18 #include "PluginStdAfx.h"
19 #include "AdblockPlusClient.h" 19 #include "AdblockPlusClient.h"
20 #include "PluginFilter.h" 20 #include "PluginFilter.h"
21 #include "PluginSettings.h" 21 #include "PluginSettings.h"
22 #include "PluginMutex.h" 22 #include "PluginMutex.h"
23 #include "PluginSettings.h" 23 #include "PluginSettings.h"
24 #include "PluginSystem.h" 24 #include "PluginSystem.h"
25 #include "PluginClass.h" 25 #include "PluginClass.h"
26 #include "mlang.h" 26 #include "mlang.h"
27 #include "TokenSequence.h"
27 #include "..\shared\CriticalSection.h" 28 #include "..\shared\CriticalSection.h"
28 #include "..\shared\Utils.h" 29 #include "..\shared\Utils.h"
29 #include "..\shared\MsHTMLUtils.h" 30 #include "..\shared\MsHTMLUtils.h"
30 31
31 // The filters are described at http://adblockplus.org/en/filters 32 // The filters are described at http://adblockplus.org/en/filters
32 33
33 static CriticalSection s_criticalSectionFilterMap; 34 static CriticalSection s_criticalSectionFilterMap;
34 35
35 // ============================================================================ 36 std::wstring ToLowerString(const std::wstring& s)
sergei 2015/11/30 12:37:53 It should be in anonymous namespace.
Eric 2015/11/30 15:54:06 Done.
36 // CFilterElementHideAttrSelector
37 // ============================================================================
38
39 CFilterElementHideAttrSelector::CFilterElementHideAttrSelector() : m_type(TYPE_N ONE), m_pos(POS_NONE), m_bstrAttr(NULL)
40 { 37 {
38 return ToWstring(ToCString(s).MakeLower());
41 } 39 }
42 40
43 CFilterElementHideAttrSelector::CFilterElementHideAttrSelector(const CFilterElem entHideAttrSelector& filter)
44 {
45 m_type = filter.m_type;
46 m_pos = filter.m_pos;
47 m_bstrAttr = filter.m_bstrAttr;
48
49 m_value = filter.m_value;
50 }
51
52 CFilterElementHideAttrSelector::~CFilterElementHideAttrSelector()
53 {
54 }
55
56
57 // ============================================================================ 41 // ============================================================================
58 // CFilterElementHide 42 // CFilterElementHide
59 // ============================================================================ 43 // ============================================================================
44 void ElementHideParseError(const std::wstring& filterText, const std::string& re ason)
sergei 2015/11/30 12:37:52 It seems to know the current position would be als
sergei 2015/11/30 12:37:52 It's really not clear from the name of the method
sergei 2015/11/30 12:37:53 It should be in anonymous namespace.
Eric 2015/11/30 15:54:05 I changed the function to a subclass of std::runti
Eric 2015/11/30 15:54:05 Done.
Eric 2015/11/30 15:54:06 I thought about doing that. I decided not to since
45 {
46 std::string message(
47 "CFilterElementHide::CFilterElementHide, error parsing selector \""
48 + ToUtf8String(filterText) + "\" (" + reason + ")"
49 );
50 DEBUG_FILTER(ToUtf16String(message));
51 throw std::runtime_error(message);
52 }
60 53
61 CFilterElementHide::CFilterElementHide(const CString& filterText) : m_filterText (filterText), m_type(ETraverserComplexType::TRAVERSER_TYPE_ERROR) 54 CFilterElementHide::CFilterElementHide(const std::wstring& filterText)
55 : m_filterText(filterText), m_type(ETraverserComplexType::TRAVERSER_TYPE_ERROR )
62 { 56 {
57 std::wstring filterSuffix(filterText); // The unparsed remainder of the input filter text
58
63 // Find tag name, class or any (*) 59 // Find tag name, class or any (*)
64 CString filterString = filterText; 60 wchar_t firstTag = filterText[0];
65
66 wchar_t firstTag = filterString.GetAt(0);
67 // Any tag
68 if (firstTag == '*') 61 if (firstTag == '*')
69 { 62 {
70 filterString = filterString.Mid(1); 63 // Any tag
64 filterSuffix = filterSuffix.substr(1);
71 } 65 }
72 // Any tag (implicitely)
73 else if (firstTag == '[' || firstTag == '.' || firstTag == '#') 66 else if (firstTag == '[' || firstTag == '.' || firstTag == '#')
74 { 67 {
68 // Any tag (implicitly)
75 } 69 }
76 // Real tag
77 else if (isalnum(firstTag)) 70 else if (isalnum(firstTag))
78 { 71 {
79 //TODO: Add support for descendant selectors 72 // Real tag
80 int pos = filterString.FindOneOf(L".#[("); 73 //TODO: Add support for descendant selectors
81 74 auto pos = filterSuffix.find_first_of(L".#[(");
82 if (pos < 0) 75 if (pos == std::wstring::npos)
83 pos = filterString.GetLength(); 76 {
84 m_tag = filterString.Left(pos).MakeLower(); 77 pos = filterSuffix.length();
85 78 }
86 filterString = filterString.Mid(pos); 79 m_tag = ToLowerString(filterSuffix.substr(0,pos));
sergei 2015/11/30 12:37:52 space after comma is missed
Eric 2015/11/30 15:54:06 Done.
80 filterSuffix = filterSuffix.substr(pos);
87 } 81 }
88 // Error
89 else 82 else
90 { 83 {
91 DEBUG_FILTER("Filter::Error parsing selector:" + filterText + " (invalid tag )"); 84 // Error
92 throw std::runtime_error(CStringA("Filter::Error parsing selector:" + filter Text + " (invalid tag)").GetString()); 85 ElementHideParseError(filterText, "invalid tag");
93 } 86 }
94 87
95 // Find Id and class name 88 // Find Id and class name
96 89 if (!filterSuffix.empty())
97 if (!filterString.IsEmpty())
98 { 90 {
99 wchar_t firstId = filterString.GetAt(0); 91 wchar_t firstId = filterSuffix[0];
100 92
101 // Id 93 // Id
102 if (firstId == '#') 94 if (firstId == '#')
103 { 95 {
104 int pos = filterString.Find('['); 96 auto pos = filterSuffix.find('[');
105 if (pos < 0) 97 if (pos == std::wstring::npos)
106 { 98 {
107 pos = filterString.GetLength(); 99 pos = filterSuffix.length();
108 } 100 }
109 m_tagId = filterString.Mid(1, pos - 1); 101 m_tagId = filterSuffix.substr(1, pos - 1);
110 filterString = filterString.Mid(pos); 102 filterSuffix = filterSuffix.substr(pos);
111 pos = m_tagId.Find(L"."); 103 pos = m_tagId.find(L".");
112 if (pos > 0) 104 if (pos != std::wstring::npos)
113 { 105 {
114 m_tagClassName = m_tagId.Mid(pos + 1); 106 if (pos == 0)
115 m_tagId = m_tagId.Left(pos); 107 {
108 ElementHideParseError(filterText, "empty tag id");
109 }
110 m_tagClassName = m_tagId.substr(pos + 1);
111 m_tagId = m_tagId.substr(0, pos);
116 } 112 }
117 } 113 }
118 // Class name 114 // Class name
119 else if (firstId == '.') 115 else if (firstId == '.')
120 { 116 {
121 int pos = filterString.Find('['); 117 auto pos = filterSuffix.find('[');
122 if (pos < 0) 118 if (pos == std::wstring::npos)
123 { 119 {
124 pos = filterString.GetLength(); 120 pos = filterSuffix.length();
125 } 121 }
126 m_tagClassName = filterString.Mid(1, pos - 1); 122 m_tagClassName = filterSuffix.substr(1, pos - 1);
127 filterString = filterString.Mid(pos); 123 filterSuffix = filterSuffix.substr(pos);
128 } 124 }
129 } 125 }
130 126
131 char chAttrStart = '['; 127 while (!filterSuffix.empty())
132 char chAttrEnd = ']'; 128 {
129 if (filterSuffix[0] != '[')
130 {
131 ElementHideParseError(filterText, "expected '['");
132 }
133 auto endPos = filterSuffix.find(']') ;
134 if (endPos == std::wstring::npos)
135 {
136 ElementHideParseError(filterText, "expected ']'");
137 }
138 std::wstring arg = filterSuffix.substr(1, endPos - 1);
139 filterSuffix = filterSuffix.substr(endPos + 1);
133 140
134 while (!filterString.IsEmpty()) 141 CFilterElementHideAttrSelector attrSelector;
135 { 142 auto posEquals = arg.find('=');
136 if (filterString.GetAt(0) != chAttrStart) 143 if (posEquals != std::wstring::npos)
137 { 144 {
138 DEBUG_FILTER("Filter::Error parsing selector:" + filterText + " (more data )"); 145 if (posEquals == 0)
139 throw std::runtime_error(CStringA("Filter::Error parsing selector:" + filt erText + " (more data)").GetString());
140 }
141 int endPos = filterString.Find(']') ;
142 if (endPos < 0)
143 {
144 DEBUG_FILTER("Filter::Error parsing selector:" + filterText + " (more data )");
145 throw std::runtime_error(CStringA("Filter::Error parsing selector:" + filt erText + " (more data)").GetString());
146 }
147
148 CFilterElementHideAttrSelector attrSelector;
149
150 CString arg = filterString.Mid(1, endPos - 1);
151 filterString = filterString.Mid(endPos + 1);
152
153 int delimiterPos = arg.Find('=');
154 if (delimiterPos > 0)
155 {
156 attrSelector.m_value = arg.Mid(delimiterPos + 1);
157 if (attrSelector.m_value.GetLength() >= 2 && attrSelector.m_value.GetAt(0) == '\"' && attrSelector.m_value.GetAt(attrSelector.m_value.GetLength() - 1) == '\"')
158 { 146 {
159 attrSelector.m_value = attrSelector.m_value.Mid(1, attrSelector.m_value. GetLength() - 2); 147 ElementHideParseError(filterText, "empty attribute name before '='");
148 }
149 attrSelector.m_value = arg.substr(posEquals + 1);
150 if (attrSelector.m_value.length() >= 2 && attrSelector.m_value[0] == '\"' && attrSelector.m_value[attrSelector.m_value.length() - 1] == '\"')
151 {
152 attrSelector.m_value = attrSelector.m_value.substr(1, attrSelector.m_val ue.length() - 2);
160 } 153 }
161 154
162 if (arg.GetAt(delimiterPos - 1) == '^') 155 if (arg[posEquals - 1] == '^')
163 { 156 {
164 attrSelector.m_bstrAttr = arg.Left(delimiterPos - 1);
165 attrSelector.m_pos = CFilterElementHideAttrPos::STARTING; 157 attrSelector.m_pos = CFilterElementHideAttrPos::STARTING;
166 } 158 }
167 else if (arg.GetAt(delimiterPos - 1) == '*') 159 else if (arg[posEquals - 1] == '*')
168 { 160 {
169 attrSelector.m_bstrAttr = arg.Left(delimiterPos - 1);
170 attrSelector.m_pos = CFilterElementHideAttrPos::ANYWHERE; 161 attrSelector.m_pos = CFilterElementHideAttrPos::ANYWHERE;
171 } 162 }
172 else if (arg.GetAt(delimiterPos - 1) == '$') 163 else if (arg[posEquals - 1] == '$')
173 { 164 {
174 attrSelector.m_bstrAttr = arg.Left(delimiterPos - 1);
175 attrSelector.m_pos = CFilterElementHideAttrPos::ENDING; 165 attrSelector.m_pos = CFilterElementHideAttrPos::ENDING;
176 } 166 }
167 if (attrSelector.m_pos != CFilterElementHideAttrPos::POS_NONE)
168 {
169 if (posEquals == 1)
170 {
171 ElementHideParseError(filterText, "empty attribute name before " + std ::string(1, static_cast<char>(arg[0])) + "'='");
sergei 2015/11/30 12:37:52 std::string(1, static_cast<char>(arg[0])) it seems
Eric 2015/11/30 15:54:06 ToUtf8String only takes wstring arguments. The onl
sergei 2015/11/30 16:36:03 Acknowledged.
172 }
173 attrSelector.m_attr = arg.substr(0, posEquals - 1);
174 }
177 else 175 else
178 { 176 {
179 attrSelector.m_bstrAttr = arg.Left(delimiterPos);
180 attrSelector.m_pos = CFilterElementHideAttrPos::EXACT; 177 attrSelector.m_pos = CFilterElementHideAttrPos::EXACT;
178 attrSelector.m_attr = arg.substr(0, posEquals);
181 } 179 }
182 } 180 }
183 CString tag = attrSelector.m_bstrAttr; 181
184 if (tag == "style") 182 if (attrSelector.m_attr == L"style")
185 { 183 {
186 attrSelector.m_type = CFilterElementHideAttrType::STYLE; 184 attrSelector.m_type = CFilterElementHideAttrType::STYLE;
187 attrSelector.m_value.MakeLower(); 185 attrSelector.m_value = ToLowerString(attrSelector.m_value);
188 } 186 }
189 else if (tag == "id") 187 else if (attrSelector.m_attr == L"id")
190 { 188 {
191 attrSelector.m_type = CFilterElementHideAttrType::ID; 189 attrSelector.m_type = CFilterElementHideAttrType::ID;
192 } 190 }
193 else if (tag == "class") 191 else if (attrSelector.m_attr == L"class")
194 { 192 {
195 attrSelector.m_type = CFilterElementHideAttrType::CLASS; 193 attrSelector.m_type = CFilterElementHideAttrType::CLASS;
196 } 194 }
197 m_attributeSelectors.push_back(attrSelector); 195 m_attributeSelectors.push_back(attrSelector);
198
199 } 196 }
200 197
201 // End check 198 // End check
202 if (!filterString.IsEmpty()) 199 if (!filterSuffix.empty())
203 { 200 {
204 DEBUG_FILTER("Filter::Error parsing selector:" + filterFile + "/" + filterTe xt + " (more data)") 201 ElementHideParseError(filterText, "extra characters at end");
205 throw new std::runtime_error(CStringA("Filter::Error parsing selector:" + f ilterText + " (more data)").GetString());
206 } 202 }
207 } 203 }
208 204
209 CFilterElementHide::CFilterElementHide(const CFilterElementHide& filter) 205 CFilterElementHide::CFilterElementHide(const CFilterElementHide& filter)
210 { 206 {
211 m_filterText = filter.m_filterText; 207 m_filterText = filter.m_filterText;
212 208
213 m_tagId = filter.m_tagId; 209 m_tagId = filter.m_tagId;
214 m_tagClassName = filter.m_tagClassName; 210 m_tagClassName = filter.m_tagClassName;
215 211
(...skipping 27 matching lines...) Expand all
243 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), 239 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false),
244 m_isThirdParty(false), 240 m_isThirdParty(false),
245 m_isFromStart(false), m_isFromEnd(false), m_hitCount(0) 241 m_isFromStart(false), m_isFromEnd(false), m_hitCount(0)
246 { 242 {
247 } 243 }
248 244
249 245
250 bool CFilterElementHide::IsMatchFilterElementHide(IHTMLElement* pEl) const 246 bool CFilterElementHide::IsMatchFilterElementHide(IHTMLElement* pEl) const
251 { 247 {
252 HRESULT hr; 248 HRESULT hr;
253 249 /*
254 if (!m_tagId.IsEmpty()) 250 * If a tag id is specified, it must match
251 */
252 if (!m_tagId.empty())
255 { 253 {
256 CComBSTR id; 254 CComBSTR idBstr;
257 hr = pEl->get_id(&id); 255 if (FAILED( pEl->get_id(&idBstr)) || !idBstr || m_tagId != ToWstring(idBstr) )
sergei 2015/11/30 12:37:53 additional space after '('
258 if ((hr != S_OK) || (id != CComBSTR(m_tagId)))
259 { 256 {
260 return false; 257 return false;
261 } 258 }
262 } 259 }
263 if (!m_tagClassName.IsEmpty()) 260 /*
261 * If a class name is specified, it must match
262 */
263 if (!m_tagClassName.empty())
264 { 264 {
265 CComBSTR classNameBSTR; 265 CComBSTR classNameListBstr;
266 hr = pEl->get_className(&classNameBSTR); 266 hr = pEl->get_className(&classNameListBstr);
267 if (hr == S_OK) 267 if (FAILED(hr) || !classNameListBstr)
268 { 268 {
269 CString className = classNameBSTR; 269 return false; // We can't match a class name if there's no class name
270 int start = 0; 270 }
271 CString specificClass; 271 std::wstring classNameList(ToWstring(classNameListBstr));
272 bool foundMatch = false; 272 if (classNameList.empty())
273 while ((specificClass = className.Tokenize(L" ", start)) != L"") 273 {
274 return false;
275 }
276 // TODO: Consider case of multiple classes. (m_tagClassName can be something like "foo.bar")
277 /*
278 * Match when 'm_tagClassName' appears as a token within classNameList
279 */
280 bool foundMatch = false;
281 TokenSequence<std::wstring> ts(classNameList, L" ");
sergei 2015/11/30 12:37:52 Did we decide to use `wcstok_s` instead of custom
Eric 2015/11/30 15:54:05 We're using that function at present in exactly on
sergei 2015/11/30 16:36:03 Of course it's better than 'wcstok_s', it's diffic
Eric 2015/11/30 17:05:46 FWIW, the standard library function it replaced, t
Oleksandr 2015/12/04 01:03:15 TokenSequence looks beautiful but unnecessary, IMH
Eric 2015/12/06 17:39:56 No one ever needs beautiful code. It does, however
282 for (auto iterClassName = ts.cbegin(); iterClassName != ts.cend(); ++iterCla ssName)
283 {
284 if (*iterClassName == m_tagClassName)
274 { 285 {
275 // TODO: Consider case of multiple classes. (m_tagClassName can be somet hing like "foo.bar") 286 foundMatch = true;
276 if (specificClass == m_tagClassName) 287 break;
277 {
278 foundMatch = true;
279 }
280 }
281 if (!foundMatch)
282 {
283 return false;
284 } 288 }
285 } 289 }
286 } 290 if (!foundMatch)
287 if (!m_tag.IsEmpty())
288 {
289 CComBSTR tagName;
290 hr = pEl->get_tagName(&tagName);
291 tagName.ToLower();
292 if ((hr != S_OK) || (tagName != CComBSTR(m_tag)))
293 { 291 {
294 return false; 292 return false;
295 } 293 }
296 } 294 }
297 295 /*
298 // Check attributes 296 * If a tag name is specified, it must match
299 for (std::vector<CFilterElementHideAttrSelector>::const_iterator attrIt = m_at tributeSelectors.begin(); 297 */
300 attrIt != m_attributeSelectors.end(); ++ attrIt) 298 if (!m_tag.empty())
301 { 299 {
302 ATL::CString value; 300 CComBSTR tagNameBstr;
301 if (FAILED(pEl->get_tagName(&tagNameBstr)) || !tagNameBstr)
302 {
303 return false;
304 }
305 if (m_tag != ToLowerString(ToWstring(tagNameBstr)))
306 {
307 return false;
308 }
309 }
310 /*
311 * Match each attribute
312 */
313 for (auto attrIt = m_attributeSelectors.begin(); attrIt != m_attributeSelector s.end(); ++ attrIt)
sergei 2015/11/30 12:37:52 additional space after `++`
Eric 2015/11/30 15:54:07 Done.
314 {
315 std::wstring value;
303 bool attrFound = false; 316 bool attrFound = false;
304 if (attrIt->m_type == CFilterElementHideAttrType::STYLE) 317 if (attrIt->m_type == CFilterElementHideAttrType::STYLE)
305 { 318 {
306 CComPtr<IHTMLStyle> pStyle; 319 CComPtr<IHTMLStyle> pStyle;
307 if (SUCCEEDED(pEl->get_style(&pStyle)) && pStyle) 320 if (SUCCEEDED(pEl->get_style(&pStyle)) && pStyle)
308 { 321 {
309 CComBSTR bstrStyle; 322 CComBSTR styleBstr;
310 323 if (SUCCEEDED(pStyle->get_cssText(&styleBstr)) && styleBstr)
311 if (SUCCEEDED(pStyle->get_cssText(&bstrStyle)) && bstrStyle)
312 { 324 {
313 value = bstrStyle; 325 value = ToLowerString(ToWstring(styleBstr));
314 value.MakeLower();
315 attrFound = true; 326 attrFound = true;
316 } 327 }
317 } 328 }
318 } 329 }
319 else if (attrIt->m_type == CFilterElementHideAttrType::CLASS) 330 else if (attrIt->m_type == CFilterElementHideAttrType::CLASS)
320 { 331 {
321 CComBSTR bstrClassNames; 332 CComBSTR classNamesBstr;
322 if (SUCCEEDED(pEl->get_className(&bstrClassNames)) && bstrClassNames) 333 if (SUCCEEDED(pEl->get_className(&classNamesBstr)) && classNamesBstr)
323 { 334 {
324 value = bstrClassNames; 335 value = ToWstring(classNamesBstr);
325 attrFound = true; 336 attrFound = true;
326 } 337 }
327 } 338 }
328 else if (attrIt->m_type == CFilterElementHideAttrType::ID) 339 else if (attrIt->m_type == CFilterElementHideAttrType::ID)
329 { 340 {
330 CComBSTR bstrId; 341 CComBSTR idBstr;
331 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) 342 if (SUCCEEDED(pEl->get_id(&idBstr)) && idBstr)
332 { 343 {
333 value = bstrId; 344 value = ToWstring(idBstr);
334 attrFound = true; 345 attrFound = true;
335 } 346 }
336 } 347 }
337 else 348 else
338 { 349 {
339 auto attributeValue = GetHtmlElementAttribute(*pEl, attrIt->m_bstrAttr); 350 CComBSTR attrArgument(attrIt->m_attr.length(), attrIt->m_attr.c_str());
340 if (attrFound = attributeValue.isAttributeFound) 351 auto x = GetHtmlElementAttribute(*pEl, attrArgument);
352 attrFound = x.isAttributeFound;
353 if (attrFound)
341 { 354 {
342 value = ToCString(attributeValue.attributeValue); 355 value = x.attributeValue;
343 } 356 }
344 } 357 }
345 358
346 if (attrFound) 359 if (attrFound)
347 { 360 {
348 if (attrIt->m_pos == CFilterElementHideAttrPos::EXACT) 361 if (attrIt->m_pos == CFilterElementHideAttrPos::EXACT)
349 { 362 {
350 // TODO: IE rearranges the style attribute completely. Figure out if any thing can be done about it. 363 // TODO: IE rearranges the style attribute completely. Figure out if any thing can be done about it.
351 if (value != attrIt->m_value) 364 if (value != attrIt->m_value)
352 return false; 365 return false;
353 } 366 }
354 else if (attrIt->m_pos == CFilterElementHideAttrPos::STARTING) 367 else if (attrIt->m_pos == CFilterElementHideAttrPos::STARTING)
355 { 368 {
356 if (value.Left(attrIt->m_value.GetLength()) != attrIt->m_value) 369 if (value.compare(0, attrIt->m_value.length(), attrIt->m_value) != 0)
357 return false; 370 return false;
358 } 371 }
359 else if (attrIt->m_pos == CFilterElementHideAttrPos::ENDING) 372 else if (attrIt->m_pos == CFilterElementHideAttrPos::ENDING)
360 { 373 {
361 if (value.Right(attrIt->m_value.GetLength()) != attrIt->m_value) 374 size_t valueLength = value.length();
375 size_t attrLength = attrIt->m_value.length();
376 if (valueLength < attrLength)
377 return false;
378 if (value.compare(valueLength - attrLength, attrLength, attrIt->m_value) != 0)
362 return false; 379 return false;
363 } 380 }
364 else if (attrIt->m_pos == CFilterElementHideAttrPos::ANYWHERE) 381 else if (attrIt->m_pos == CFilterElementHideAttrPos::ANYWHERE)
365 { 382 {
366 if (value.Find(attrIt->m_value) < 0) 383 if (value.find(attrIt->m_value) == std::wstring::npos)
367 return false; 384 return false;
368 } 385 }
369 else if (attrIt->m_value.IsEmpty()) 386 else if (attrIt->m_value.empty())
370 { 387 {
371 return true; 388 return true;
372 } 389 }
373 } 390 }
374 else 391 else
375 { 392 {
376 return false; 393 return false;
377 } 394 }
378 } 395 }
379 396
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 433
417 return true; 434 return true;
418 } 435 }
419 436
420 437
421 438
422 // ============================================================================ 439 // ============================================================================
423 // CPluginFilter 440 // CPluginFilter
424 // ============================================================================ 441 // ============================================================================
425 442
426 CPluginFilter::CPluginFilter(const CString& dataPath) : m_dataPath(dataPath) 443 CPluginFilter::CPluginFilter(const std::wstring& dataPath)
444 : m_dataPath(dataPath)
427 { 445 {
428 ClearFilters(); 446 ClearFilters();
429 } 447 }
430 448
431 449
432 bool CPluginFilter::AddFilterElementHide(CString filterText) 450 bool CPluginFilter::AddFilterElementHide(std::wstring filterText)
433 { 451 {
434 DEBUG_FILTER("Input: " + filterText + " filterFile" + filterFile); 452 DEBUG_FILTER(L"Input: " + filterText + L" filterFile" + filterFile);
435 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); 453 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap);
436 { 454 {
437 CString filterString = filterText;
438 // Create filter descriptor 455 // Create filter descriptor
439 std::auto_ptr<CFilterElementHide> filter; 456 std::auto_ptr<CFilterElementHide> filter;
440
441 CString wholeFilterString = filterString;
442 wchar_t separatorChar; 457 wchar_t separatorChar;
443 do 458 do
444 { 459 {
445 int chunkEnd = filterText.FindOneOf(L"+>"); 460 auto chunkEnd = filterText.find_first_of(L"+>");
446 if (chunkEnd > 0) 461 if (chunkEnd != std::wstring::npos && chunkEnd > 0)
447 { 462 {
448 separatorChar = filterText.GetAt(chunkEnd); 463 separatorChar = filterText[chunkEnd];
449 } 464 }
450 else 465 else
451 { 466 {
452 chunkEnd = filterText.GetLength(); 467 chunkEnd = filterText.length();
453 separatorChar = L'\0'; 468 separatorChar = L'\0';
454 } 469 }
455 470
456 CString filterChunk = filterText.Left(chunkEnd).TrimRight();
457 std::auto_ptr<CFilterElementHide> filterParent(filter); 471 std::auto_ptr<CFilterElementHide> filterParent(filter);
458 472 filter.reset(new CFilterElementHide(TrimStringRight(filterText.substr(0, c hunkEnd))));
459 filter.reset(new CFilterElementHide(filterChunk));
460
461 if (filterParent.get() != 0) 473 if (filterParent.get() != 0)
462 { 474 {
463 filter->m_predecessor.reset(filterParent.release()); 475 filter->m_predecessor.reset(filterParent.release());
464 } 476 }
465 477
466 if (separatorChar != L'\0') // complex selector 478 if (separatorChar != L'\0') // complex selector
467 { 479 {
468 filterText = filterText.Mid(chunkEnd + 1).TrimLeft(); 480 filterText = TrimStringLeft(filterText.substr(chunkEnd + 1));
469 if (separatorChar == '+') 481 if (separatorChar == '+')
470 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_IMMEDIATE; 482 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_IMMEDIATE;
471 else if (separatorChar == '>') 483 else if (separatorChar == '>')
472 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_PARENT; 484 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_PARENT;
473 } 485 }
474 else // Terminating element (simple selector) 486 else // Terminating element (simple selector)
475 { 487 {
476 if (!filter->m_tagId.IsEmpty()) 488 if (!filter->m_tagId.empty())
477 { 489 {
478 m_elementHideTagsId.insert(std::make_pair(std::make_pair(filter->m_tag , filter->m_tagId), *filter)); 490 m_elementHideTagsId.insert(std::make_pair(std::make_pair(filter->m_tag , filter->m_tagId), *filter));
479 } 491 }
480 else if (!filter->m_tagClassName.IsEmpty()) 492 else if (!filter->m_tagClassName.empty())
481 { 493 {
482 m_elementHideTagsClass.insert(std::make_pair(std::make_pair(filter->m_ tag, filter->m_tagClassName), *filter)); 494 m_elementHideTagsClass.insert(std::make_pair(std::make_pair(filter->m_ tag, filter->m_tagClassName), *filter));
483 } 495 }
484 else 496 else
485 { 497 {
486 std::pair<CString, CFilterElementHide> pair = std::make_pair(filter->m _tag, *filter); 498 m_elementHideTags.insert(std::make_pair(filter->m_tag, *filter));
487 m_elementHideTags.insert(pair);
488 } 499 }
489 } 500 }
490 } while (separatorChar != '\0'); 501 } while (separatorChar != '\0');
491 } 502 }
492 503
493 return true; 504 return true;
494 } 505 }
495 506
496 bool CPluginFilter::IsElementHidden(const std::wstring& tag, IHTMLElement* pEl, const std::wstring& domain, const std::wstring& indent) const 507 bool CPluginFilter::IsElementHidden(const std::wstring& tag, IHTMLElement* pEl, const std::wstring& domain, const std::wstring& indent) const
497 { 508 {
498 CString tagCString = ToCString(tag); 509 std::wstring id;
499 510 CComBSTR idBstr;
500 CString id; 511 if (SUCCEEDED(pEl->get_id(&idBstr)) && idBstr)
501 CComBSTR bstrId;
502 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId)
503 { 512 {
504 id = bstrId; 513 id = std::wstring(ToWstring(idBstr));
sergei 2015/11/30 12:37:52 It should be just `id = ToWstring(idBstr);`
Eric 2015/11/30 15:54:05 Done. Good catch. That's leftover code from an ea
505 } 514 }
506 515 std::wstring classNames;
507 CString classNames; 516 CComBSTR classNamesBstr;
508 CComBSTR bstrClassNames; 517 if (SUCCEEDED(pEl->get_className(&classNamesBstr)) && classNamesBstr)
509 if (SUCCEEDED(pEl->get_className(&bstrClassNames)) && bstrClassNames)
510 { 518 {
511 classNames = bstrClassNames; 519 classNames = ToWstring(classNamesBstr);
512 } 520 }
513 521
514 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); 522 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap);
515 { 523 {
516 // Search tag/id filters 524 // Search tag/id filters
517 if (!id.IsEmpty()) 525 if (!id.empty())
518 { 526 {
519 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHideT agsNamed::const_iterator> idItEnum = 527 auto idItEnum = m_elementHideTagsId.equal_range(std::make_pair(tag, id));
520 m_elementHideTagsId.equal_range(std::make_pair(tagCString, id)); 528 for (auto idIt = idItEnum.first; idIt != idItEnum.second; idIt ++)
sergei 2015/11/30 12:37:53 Good chance to change `idIt ++` to `++idIt`.
Eric 2015/11/30 15:54:06 Done.
521 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id It != idItEnum.second; idIt ++)
522 { 529 {
523 if (idIt->second.IsMatchFilterElementHide(pEl)) 530 if (idIt->second.IsMatchFilterElementHide(pEl))
524 { 531 {
525 #ifdef ENABLE_DEBUG_RESULT 532 #ifdef ENABLE_DEBUG_RESULT
526 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/id) filter:" + idIt->second .m_filterText) 533 DEBUG_HIDE_EL(indent + L"HideEl::Found (tag/id) filter:" + idIt->secon d.m_filterText);
527 CPluginDebug::DebugResultHiding(tag, L"id:" + ToWstring(id), ToWstri ng(idIt->second.m_filterText)); 534 CPluginDebug::DebugResultHiding(tag, L"id:" + id, idIt->second.m_filte rText);
528 #endif 535 #endif
529 return true; 536 return true;
530 } 537 }
531 } 538 }
532 539
533 // Search general id 540 // Search general id
534 idItEnum = m_elementHideTagsId.equal_range(std::make_pair("", id)); 541 idItEnum = m_elementHideTagsId.equal_range(std::make_pair(L"", id));
535 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id It != idItEnum.second; idIt ++) 542 for (auto idIt = idItEnum.first; idIt != idItEnum.second; idIt ++)
sergei 2015/11/30 12:37:51 Good chance to change `idIt ++` to `++idIt`
Eric 2015/11/30 15:54:06 Done.
536 { 543 {
537 if (idIt->second.IsMatchFilterElementHide(pEl)) 544 if (idIt->second.IsMatchFilterElementHide(pEl))
538 { 545 {
539 #ifdef ENABLE_DEBUG_RESULT 546 #ifdef ENABLE_DEBUG_RESULT
540 DEBUG_HIDE_EL(indent + "HideEl::Found (?/id) filter:" + idIt->second.m _filterText) 547 DEBUG_HIDE_EL(indent + L"HideEl::Found (?/id) filter:" + idIt->second. m_filterText);
541 CPluginDebug::DebugResultHiding(tag, L"id:" + ToWstring(id), ToWstri ng(idIt->second.m_filterText)); 548 CPluginDebug::DebugResultHiding(tag, L"id:" + id, idIt->second.m_filte rText);
542 #endif 549 #endif
543 return true; 550 return true;
544 } 551 }
545 } 552 }
546 } 553 }
547 554
548 // Search tag/className filters 555 // Search tag/className filters
549 if (!classNames.IsEmpty()) 556 if (!classNames.empty())
550 { 557 {
551 int pos = 0; 558 TokenSequence<std::wstring> ts(classNames, L" \t\n\r");
sergei 2015/11/30 12:37:52 Same here, let's use `wcstok_s` instead of custom
Eric 2015/11/30 15:54:06 See above comment.
552 CString className = classNames.Tokenize(L" \t\n\r", pos); 559 for (auto iterClassName = ts.cbegin(); iterClassName != ts.cend(); ++iterC lassName)
553 while (pos >= 0)
554 { 560 {
555 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHid eTagsNamed::const_iterator> classItEnum = 561 std::wstring className = *iterClassName;
556 m_elementHideTagsClass.equal_range(std::make_pair(tagCString, classNam e)); 562 auto classItEnum = m_elementHideTagsClass.equal_range(std::make_pair(tag , className));
557 563 for (auto classIt = classItEnum.first; classIt != classItEnum.second; ++ classIt)
558 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f irst; classIt != classItEnum.second; ++classIt)
559 { 564 {
560 if (classIt->second.IsMatchFilterElementHide(pEl)) 565 if (classIt->second.IsMatchFilterElementHide(pEl))
561 { 566 {
562 #ifdef ENABLE_DEBUG_RESULT 567 #ifdef ENABLE_DEBUG_RESULT
563 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/class) filter:" + classIt ->second.m_filterText) 568 DEBUG_HIDE_EL(indent + L"HideEl::Found (tag/class) filter:" + classI t->second.m_filterText);
564 CPluginDebug::DebugResultHiding(tag, L"class:" + ToWstring(classNa me), ToWstring(classIt->second.m_filterText)); 569 CPluginDebug::DebugResultHiding(tag, L"class:" + className, classIt- >second.m_filterText);
565 #endif 570 #endif
566 return true; 571 return true;
567 } 572 }
568 } 573 }
569 574
570 // Search general class name 575 // Search general class name
571 classItEnum = m_elementHideTagsClass.equal_range(std::make_pair("", clas sName)); 576 classItEnum = m_elementHideTagsClass.equal_range(std::make_pair(L"", cla ssName));
572 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f irst; classIt != classItEnum.second; ++ classIt) 577 for (auto classIt = classItEnum.first; classIt != classItEnum.second; ++ classIt)
573 { 578 {
574 if (classIt->second.IsMatchFilterElementHide(pEl)) 579 if (classIt->second.IsMatchFilterElementHide(pEl))
575 { 580 {
576 #ifdef ENABLE_DEBUG_RESULT 581 #ifdef ENABLE_DEBUG_RESULT
577 DEBUG_HIDE_EL(indent + L"HideEl::Found (?/class) filter:" + ToWStrin g(classIt->second.m_filterText)); 582 DEBUG_HIDE_EL(indent + L"HideEl::Found (?/class) filter:" + classIt- >second.m_filterText);
578 CPluginDebug::DebugResultHiding(tag, L"class:" + ToWstring(className ), ToWstring(classIt->second.m_filterText)); 583 CPluginDebug::DebugResultHiding(tag, L"class:" + className, classIt- >second.m_filterText);
579 #endif 584 #endif
580 return true; 585 return true;
581 } 586 }
582 } 587 }
583
584 // Next class name
585 className = classNames.Tokenize(L" \t\n\r", pos);
586 } 588 }
587 } 589 }
588 590
589 // Search tag filters 591 // Search tag filters
590 std::pair<TFilterElementHideTags::const_iterator, TFilterElementHideTags::co nst_iterator> tagItEnum 592 auto tagItEnum = m_elementHideTags.equal_range(tag);
591 = m_elementHideTags.equal_range(tagCString); 593 for (auto tagIt = tagItEnum.first; tagIt != tagItEnum.second; ++ tagIt)
sergei 2015/11/30 12:37:53 additional space after `++`
Eric 2015/11/30 15:54:06 Done.
592 for (TFilterElementHideTags::const_iterator tagIt = tagItEnum.first; tagIt ! = tagItEnum.second; ++ tagIt)
593 { 594 {
594 if (tagIt->second.IsMatchFilterElementHide(pEl)) 595 if (tagIt->second.IsMatchFilterElementHide(pEl))
595 { 596 {
596 #ifdef ENABLE_DEBUG_RESULT 597 #ifdef ENABLE_DEBUG_RESULT
597 DEBUG_HIDE_EL(indent + "HideEl::Found (tag) filter:" + tagIt->second.m_f ilterText) 598 DEBUG_HIDE_EL(indent + L"HideEl::Found (tag) filter:" + tagIt->second.m_ filterText);
598 CPluginDebug::DebugResultHiding(tag, L"-", ToWstring(tagIt->second.m_f ilterText)); 599 CPluginDebug::DebugResultHiding(tag, L"-", tagIt->second.m_filterText);
599 #endif 600 #endif
600 return true; 601 return true;
601 } 602 }
602 } 603 }
603 } 604 }
604 605
605 return false; 606 return false;
606 } 607 }
607 608
608 bool CPluginFilter::LoadHideFilters(std::vector<std::wstring> filters) 609 bool CPluginFilter::LoadHideFilters(std::vector<std::wstring> filters)
609 { 610 {
610 ClearFilters(); 611 ClearFilters();
611 bool isRead = false; 612 bool isRead = false;
612 CPluginClient* client = CPluginClient::GetInstance(); 613 CPluginClient* client = CPluginClient::GetInstance();
613 614
614 // Parse hide string 615 // Parse hide string
615 int pos = 0; 616 int pos = 0;
616 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); 617 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap);
617 { 618 {
618 for (std::vector<std::wstring>::iterator it = filters.begin(); it < filters. end(); ++it) 619 for (auto it = filters.begin(); it < filters.end(); ++it)
619 { 620 {
620 CString filter((*it).c_str()); 621 std::wstring filter(TrimString(*it));
621 // If the line is not commented out 622 // If the line is not commented out
622 if (!filter.Trim().IsEmpty() && filter.GetAt(0) != '!' && filter.GetAt(0) != '[') 623 if (!filter.empty() && filter[0] != '!' && filter[0] != '[')
623 { 624 {
624 int filterType = 0; 625 int filterType = 0;
625 626
626 // See http://adblockplus.org/en/filters for further documentation 627 // See http://adblockplus.org/en/filters for further documentation
627 628
628 try 629 try
629 { 630 {
630 AddFilterElementHide(filter); 631 AddFilterElementHide(filter);
631 } 632 }
632 catch(...) 633 catch(...)
633 { 634 {
634 #ifdef ENABLE_DEBUG_RESULT 635 #ifdef ENABLE_DEBUG_RESULT
635 CPluginDebug::DebugResult(L"Error loading hide filter: " + ToWstring(f ilter)); 636 CPluginDebug::DebugResult(L"Error loading hide filter: " + filter);
636 #endif 637 #endif
637 } 638 }
638 } 639 }
639 } 640 }
640 } 641 }
641 642
642 return isRead; 643 return isRead;
643 } 644 }
644 645
645 void CPluginFilter::ClearFilters() 646 void CPluginFilter::ClearFilters()
(...skipping 30 matching lines...) Expand all
676 CPluginDebug::DebugResultBlocking(type, srcTrimmed, domain); 677 CPluginDebug::DebugResultBlocking(type, srcTrimmed, domain);
677 } 678 }
678 else 679 else
679 { 680 {
680 CPluginDebug::DebugResultIgnoring(type, srcTrimmed, domain); 681 CPluginDebug::DebugResultIgnoring(type, srcTrimmed, domain);
681 } 682 }
682 } 683 }
683 #endif 684 #endif
684 return result; 685 return result;
685 } 686 }
OLDNEW

Powered by Google App Engine
This is Rietveld