WebBrowser/AdBlock/AdBlockRule.py

changeset 6028
859f6894eed9
parent 5921
d4797da58218
child 6048
82ad8ec9548c
equal deleted inserted replaced
6027:d056a536670e 6028:859f6894eed9
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import re 12 import re
13 13
14 from enum import IntFlag
15
14 from PyQt5.QtCore import PYQT_VERSION, Qt, QRegExp 16 from PyQt5.QtCore import PYQT_VERSION, Qt, QRegExp
15 from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInfo 17 from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInfo
16 18
17 from Globals import qVersionTuple 19 from Globals import qVersionTuple
18 20
19 21
20 def toSecondLevelDomain(url): 22 def toSecondLevelDomain(url):
21 """ 23 """
22 Module function to get a second level domain from the given URL. 24 Module function to get a second level domain from the given URL.
23 25
24 @param url URL to extract domain from (QUrl) 26 @param url URL to extract domain from
25 @return name of second level domain (string) 27 @type QUrl
28 @return name of second level domain
29 @rtype str
26 """ 30 """
27 topLevelDomain = url.topLevelDomain() 31 topLevelDomain = url.topLevelDomain()
28 urlHost = url.host() 32 urlHost = url.host()
29 33
30 if not topLevelDomain or not urlHost: 34 if not topLevelDomain or not urlHost:
36 40
37 while domain.count(".") != 0: 41 while domain.count(".") != 0:
38 domain = domain[domain.find(".") + 1:] 42 domain = domain[domain.find(".") + 1:]
39 43
40 return domain + topLevelDomain 44 return domain + topLevelDomain
45
46
47 class AdBlockRuleType(IntFlag):
48 """
49 Class implementing the rule type enum.
50 """
51 CssRule = 0
52 DomainMatchRule = 1
53 RegExpMatchRule = 2
54 StringEndsMatchRule = 3
55 StringContainsMatchRule = 4
56 MatchAllUrlsRule = 5
57 Invalid = 6
58
59
60 class AdBlockRuleOption(IntFlag):
61 """
62 Class implementing the rule option enum.
63 """
64 NoOption = 0
65 DomainRestrictedOption = 1
66 ThirdPartyOption = 2
67 ObjectOption = 4
68 SubdocumentOption = 8
69 XMLHttpRequestOption = 16
70 ImageOption = 32
71 ScriptOption = 64
72 StyleSheetOption = 128
73 ObjectSubrequestOption = 256
74 PingOption = 512
75 MediaOption = 1024
76 FontOption = 2048
77 OtherOption = 4096
78
79 # Exception only options
80 DocumentOption = 8192
81 ElementHideOption = 16384
41 82
42 83
43 class AdBlockRule(object): 84 class AdBlockRule(object):
44 """ 85 """
45 Class implementing the AdBlock rule. 86 Class implementing the AdBlock rule.
46 """ 87 """
47 def __init__(self, filterRule="", subscription=None): 88 def __init__(self, filterRule="", subscription=None):
48 """ 89 """
49 Constructor 90 Constructor
50 91
51 @param filterRule filter string of the rule (string) 92 @param filterRule filter string of the rule
93 @type str
52 @param subscription reference to the subscription object 94 @param subscription reference to the subscription object
53 (AdBlockSubscription) 95 @type AdBlockSubscription
54 """ 96 """
55 self.__subscription = subscription 97 self.__subscription = subscription
56 98
57 self.__regExp = QRegExp() 99 self.__regExp = None
58 self.__options = [] 100 self.__stringMatchers = []
101
59 self.__blockedDomains = [] 102 self.__blockedDomains = []
60 self.__allowedDomains = [] 103 self.__allowedDomains = []
61 104
62 self.__enabled = True 105 self.__isEnabled = True
63 self.__cssRule = False 106 self.__isException = False
64 self.__exception = False 107 self.__isInternalDisabled = False
65 self.__internalDisabled = False
66 self.__domainRestricted = False
67 self.__useRegExp = False
68 self.__useDomainMatch = False
69 self.__useEndsMatch = False
70 self.__thirdParty = False
71 self.__thirdPartyException = False
72 self.__object = False
73 self.__objectException = False
74 self.__subdocument = False
75 self.__subdocumentException = False
76 self.__xmlhttprequest = False
77 self.__xmlhttprequestException = False
78 self.__document = False
79 self.__elemhide = False
80 self.__caseSensitivity = Qt.CaseInsensitive 108 self.__caseSensitivity = Qt.CaseInsensitive
81 self.__image = False 109
82 self.__imageException = False 110 self.__type = AdBlockRuleType.StringContainsMatchRule
83 self.__script = False 111 self.__options = AdBlockRuleOption.NoOption
84 self.__scriptException = False 112 self.__exceptions = AdBlockRuleOption.NoOption
85 self.__stylesheet = False
86 self.__stylesheetException = False
87 self.__objectSubrequest = False
88 self.__objectSubrequestException = False
89 self.__stringMatchRule = False
90 113
91 self.setFilter(filterRule) 114 self.setFilter(filterRule)
92 115
93 def subscription(self): 116 def subscription(self):
94 """ 117 """
95 Public method to get the subscription this rule belongs to. 118 Public method to get the subscription this rule belongs to.
96 119
97 @return subscription of the rule (AdBlockSubscription) 120 @return subscription of the rule
121 @rtype AdBlockSubscription
98 """ 122 """
99 return self.__subscription 123 return self.__subscription
100 124
125 def setSubscription(self, subscription):
126 """
127 Public method to set the subscription this rule belongs to.
128
129 @param subscription subscription of the rule
130 @type AdBlockSubscription
131 """
132 self.__subscription = subscription
133
101 def filter(self): 134 def filter(self):
102 """ 135 """
103 Public method to get the rule filter string. 136 Public method to get the rule filter string.
104 137
105 @return rule filter string (string) 138 @return rule filter string
139 @rtype str
106 """ 140 """
107 return self.__filter 141 return self.__filter
108 142
109 def setFilter(self, filterRule): 143 def setFilter(self, filterRule):
110 """ 144 """
111 Public method to set the rule filter string. 145 Public method to set the rule filter string.
112 146
113 @param filterRule rule filter string (string) 147 @param filterRule rule filter string
148 @type str
114 """ 149 """
115 self.__filter = filterRule 150 self.__filter = filterRule
116 self.__parseFilter() 151 self.__parseFilter()
117 152
118 def __parseFilter(self): 153 def __parseFilter(self):
120 Private method to parse the filter pattern. 155 Private method to parse the filter pattern.
121 """ 156 """
122 parsedLine = self.__filter 157 parsedLine = self.__filter
123 158
124 # empty rule or just a comment 159 # empty rule or just a comment
125 if not parsedLine.strip() or parsedLine.startswith(("!", "[Adblock")): 160 if not parsedLine.strip() or parsedLine.startswith("!"):
126 self.__enabled = False 161 self.__isEnabled = False
162 self.__isInternalDisabled = True
163 self.__type = AdBlockRuleType.Invalid
127 return 164 return
128 165
129 # CSS element hiding rule 166 # CSS element hiding rule
130 if "##" in parsedLine or "#@#" in parsedLine: 167 if "##" in parsedLine or "#@#" in parsedLine:
131 self.__cssRule = True 168 self.__type = AdBlockRuleType.CssRule
132 pos = parsedLine.find("#") 169 pos = parsedLine.find("#")
133 170
134 # domain restricted rule 171 # domain restricted rule
135 if not parsedLine.startswith("##"): 172 if not parsedLine.startswith("##"):
136 domains = parsedLine[:pos] 173 domains = parsedLine[:pos]
137 self.__parseDomains(domains, ",") 174 self.__parseDomains(domains, ",")
138 175
139 self.__exception = parsedLine[pos + 1] == "@" 176 self.__isException = parsedLine[pos + 1] == "@"
140 177 if self.__isException:
141 if self.__exception: 178 self.__matchString = parsedLine[pos + 3:]
142 self.__cssSelector = parsedLine[pos + 3:]
143 else: 179 else:
144 self.__cssSelector = parsedLine[pos + 2:] 180 self.__matchString = parsedLine[pos + 2:]
181
145 # CSS rule cannot have more options -> stop parsing 182 # CSS rule cannot have more options -> stop parsing
146 return 183 return
147 184
148 # Exception always starts with @@ 185 # Exception always starts with @@
149 if parsedLine.startswith("@@"): 186 if parsedLine.startswith("@@"):
150 self.__exception = True 187 self.__isException = True
151 parsedLine = parsedLine[2:] 188 parsedLine = parsedLine[2:]
152 189
153 # Parse all options following '$' character 190 # Parse all options following '$' character
154 optionsIndex = parsedLine.find("$") 191 optionsIndex = parsedLine.find("$")
155 if optionsIndex >= 0: 192 if optionsIndex >= 0:
156 options = parsedLine[optionsIndex + 1:].split(",") 193 options = [opt
194 for opt in parsedLine[optionsIndex + 1:].split(",")
195 if opt]
157 196
158 handledOptions = 0 197 handledOptions = 0
159 for option in options: 198 for option in options:
160 if option.startswith("domain="): 199 if option.startswith("domain="):
161 self.__parseDomains(option[7:], "|") 200 self.__parseDomains(option[7:], "|")
162 handledOptions += 1 201 handledOptions += 1
163 elif option == "match-case": 202 elif option == "match-case":
164 self.__caseSensitivity = Qt.CaseSensitive 203 self.__caseSensitivity = Qt.CaseSensitive
165 handledOptions += 1 204 handledOptions += 1
166 elif option.endswith("third-party"): 205 elif option.endswith("third-party"):
167 self.__thirdParty = True 206 self.setOption(AdBlockRuleOption.ThirdPartyOption)
168 self.__thirdPartyException = option.startswith("~") 207 self.__setException(AdBlockRuleOption.ThirdPartyOption,
208 option.startswith("~"))
169 handledOptions += 1 209 handledOptions += 1
170 elif option.endswith("object"): 210 elif option.endswith("object"):
171 self.__object = True 211 self.setOption(AdBlockRuleOption.ObjectOption)
172 self.__objectException = option.startswith("~") 212 self.__setException(AdBlockRuleOption.ObjectOption,
213 option.startswith("~"))
173 handledOptions += 1 214 handledOptions += 1
174 elif option.endswith("subdocument"): 215 elif option.endswith("subdocument"):
175 self.__subdocument = True 216 self.setOption(AdBlockRuleOption.SubdocumentOption)
176 self.__subdocumentException = option.startswith("~") 217 self.__setException(AdBlockRuleOption.SubdocumentOption,
218 option.startswith("~"))
177 handledOptions += 1 219 handledOptions += 1
178 elif option.endswith("xmlhttprequest"): 220 elif option.endswith("xmlhttprequest"):
179 self.__xmlhttprequest = True 221 self.setOption(AdBlockRuleOption.XMLHttpRequestOption)
180 self.__xmlhttprequestException = option.startswith("~") 222 self.__setException(AdBlockRuleOption.XMLHttpRequestOption,
223 option.startswith("~"))
181 handledOptions += 1 224 handledOptions += 1
182 elif option.endswith("image"): 225 elif option.endswith("image"):
183 self.__image = True 226 self.setOption(AdBlockRuleOption.ImageOption)
184 self.__imageException = option.startswith("~") 227 self.__setException(AdBlockRuleOption.ImageOption,
228 option.startswith("~"))
185 elif option.endswith("script"): 229 elif option.endswith("script"):
186 self.__script = True 230 self.setOption(AdBlockRuleOption.ScriptOption)
187 self.__scriptException = option.startswith("~") 231 self.__setException(AdBlockRuleOption.ScriptOption,
232 option.startswith("~"))
188 elif option.endswith("stylesheet"): 233 elif option.endswith("stylesheet"):
189 self.__stylesheet = True 234 self.setOption(AdBlockRuleOption.StyleSheetOption)
190 self.__stylesheetException = option.startswith("~") 235 self.__setException(AdBlockRuleOption.StyleSheetOption,
236 option.startswith("~"))
191 elif option.endswith("object-subrequest"): 237 elif option.endswith("object-subrequest"):
192 self.__objectSubrequest = True 238 self.setOption(AdBlockRuleOption.ObjectSubrequestOption)
193 self.__objectSubrequestException = option.startswith("~") 239 self.__setException(
194 elif option == "document" and self.__exception: 240 AdBlockRuleOption.ObjectSubrequestOption,
195 self.__document = True 241 option.startswith("~"))
242 elif option.endswith("ping"):
243 self.setOption(AdBlockRuleOption.PingOption)
244 self.__setException(AdBlockRuleOption.PingOption,
245 option.startswith("~"))
246 elif option.endswith("media"):
247 self.setOption(AdBlockRuleOption.MediaOption)
248 self.__setException(AdBlockRuleOption.MediaOption,
249 option.startswith("~"))
250 elif option.endswith("font"):
251 self.setOption(AdBlockRuleOption.FontOption)
252 self.__setException(AdBlockRuleOption.FontOption,
253 option.startswith("~"))
254 elif option.endswith("other"):
255 self.setOption(AdBlockRuleOption.OtherOption)
256 self.__setException(AdBlockRuleOption.OtherOption,
257 option.startswith("~"))
258 elif option == "document" and self.__isException:
259 self.setOption(AdBlockRuleOption.DocumentOption)
196 handledOptions += 1 260 handledOptions += 1
197 elif option == "elemhide" and self.__exception: 261 elif option == "elemhide" and self.__isException:
198 self.__elemhide = True 262 self.setOption(AdBlockRuleOption.ElementHideOption)
199 handledOptions += 1 263 handledOptions += 1
200 elif option == "collapse": 264 elif option == "collapse":
201 # Hiding placeholders of blocked elements 265 # Hiding placeholders of blocked elements is enabled by
266 # default
202 handledOptions += 1 267 handledOptions += 1
203 268
204 # If we don't handle all options, it's safer to just disable 269 # If we don't handle all options, it's safer to just disable
205 # this rule 270 # this rule
206 if handledOptions != len(options): 271 if handledOptions != len(options):
207 self.__internalDisabled = True 272 self.__isInternalDisabled = True
273 self.__type = AdBlockRuleType.Invalid
208 return 274 return
209 275
210 parsedLine = parsedLine[:optionsIndex] 276 parsedLine = parsedLine[:optionsIndex]
211 277
212 # Rule is classic regexp 278 # Rule is classic regexp
213 if parsedLine.startswith("/") and parsedLine.endswith("/"): 279 if parsedLine.startswith("/") and parsedLine.endswith("/"):
214 parsedLine = parsedLine[1:-1] 280 parsedLine = parsedLine[1:-1]
215 self.__useRegExp = True 281 self.__type = AdBlockRuleType.RegExpMatchRule
216 self.__regExp = QRegExp(parsedLine, self.__caseSensitivity, 282 self.__regExp = QRegExp(parsedLine, self.__caseSensitivity,
217 QRegExp.RegExp) 283 QRegExp.RegExp)
284 self.__stringMatchers = self.__parseRegExpFilter(parsedLine)
218 return 285 return
219 286
220 # Remove starting / ending wildcards 287 # Remove starting / ending wildcards (*)
221 if parsedLine.startswith("*"): 288 if parsedLine.startswith("*"):
222 parsedLine = parsedLine[1:] 289 parsedLine = parsedLine[1:]
223 if parsedLine.endswith("*"): 290 if parsedLine.endswith("*"):
224 parsedLine = parsedLine[:-1] 291 parsedLine = parsedLine[:-1]
225 292
226 # Fast string matching for domain can be used 293 # Fast string matching for domain here
227 if parsedLine.startswith("||") and \ 294 if self.__filterIsOnlyDomain(parsedLine):
228 parsedLine.endswith("^") and \
229 QRegExp("[/:?=&\\*]").indexIn(parsedLine) == -1:
230 parsedLine = parsedLine[2:-1] 295 parsedLine = parsedLine[2:-1]
231 self.__useDomainMatch = True 296 self.__type = AdBlockRuleType.DomainMatchRule
232 self.__matchString = parsedLine 297 self.__matchString = parsedLine
233 return 298 return
234 299
235 # If rule contains '|' only at the end, string matching can be used 300 # If rule contains '|' only at the end, string matching can be used
236 if parsedLine.endswith("|") and \ 301 if self.__filterIsOnlyEndsMatch(parsedLine):
237 QRegExp("[\\^\\*]").indexIn(parsedLine) == -1 and \
238 parsedLine.count("|") == 1:
239 parsedLine = parsedLine[:-1] 302 parsedLine = parsedLine[:-1]
240 self.__useEndsMatch = True 303 self.__type = AdBlockRuleType.StringEndsMatchRule
241 self.__matchString = parsedLine 304 self.__matchString = parsedLine
242 return 305 return
243 306
244 # If there is still a wildcard (*) or separator (^) or (|), 307 # If there is still a wildcard (*) or separator (^) or (|),
245 # the rule must be modified to comply with QRegExp. 308 # the rule must be modified to comply with QRegExp.
246 if "*" in parsedLine or "^" in parsedLine or "|" in parsedLine: 309 if "*" in parsedLine or "^" in parsedLine or "|" in parsedLine:
310 self.__type = AdBlockRuleType.RegExpMatchRule
247 pattern = self.__convertPatternToRegExp(parsedLine) 311 pattern = self.__convertPatternToRegExp(parsedLine)
248 self.__useRegExp = True
249 self.__regExp = QRegExp(pattern, self.__caseSensitivity, 312 self.__regExp = QRegExp(pattern, self.__caseSensitivity,
250 QRegExp.RegExp) 313 QRegExp.RegExp)
314 self.__stringMatchers = self.__parseRegExpFilter(parsedLine)
251 return 315 return
252 316
317 # This rule matches all URLs
318 if len(parsedLine) == 0:
319 if self.__options == AdBlockRuleOption.NoOption:
320 self.__isInternalDisabled = True
321 self.__type = AdBlockRuleType.Invalid
322 return
323
324 self.__type = AdBlockRuleType.MatchAllUrlsRule
325 return
326
253 # no regexp required 327 # no regexp required
254 self.__useRegExp = False 328 self.__type = AdBlockRuleType.StringContainsMatchRule
255 self.__matchString = parsedLine 329 self.__matchString = parsedLine
256 self.__stringMatchRule = True
257 330
258 def __parseDomains(self, domains, separator): 331 def __parseDomains(self, domains, separator):
259 """ 332 """
260 Private method to parse a string with a domain list. 333 Private method to parse a string with a domain list.
261 334
262 @param domains list of domains (string) 335 @param domains list of domains
263 @param separator separator character used by the list (string) 336 @type str
264 """ 337 @param separator separator character used by the list
265 domainsList = domains.split(separator) 338 @type str
339 """
340 domainsList = [d for d in domains.split(separator) if d]
266 341
267 for domain in domainsList: 342 for domain in domainsList:
268 if not domain: 343 if not domain:
269 continue 344 continue
270 if domain.startswith("~"): 345 if domain.startswith("~"):
271 self.__blockedDomains.append(domain[1:]) 346 self.__blockedDomains.append(domain[1:])
272 else: 347 else:
273 self.__allowedDomains.append(domain) 348 self.__allowedDomains.append(domain)
274 349
275 self.__domainRestricted = \ 350 if bool(self.__blockedDomains) or bool(self.__allowedDomains):
276 bool(self.__blockedDomains) or bool(self.__allowedDomains) 351 self.setOption(AdBlockRuleOption.DomainRestrictedOption)
277 352
278 def networkMatch(self, request, domain, encodedUrl): 353 def networkMatch(self, request, domain, encodedUrl):
279 """ 354 """
280 Public method to check the rule for a match. 355 Public method to check the rule for a match.
281 356
286 @param encodedUrl string encoded URL to be checked 361 @param encodedUrl string encoded URL to be checked
287 @type str 362 @type str
288 @return flag indicating a match 363 @return flag indicating a match
289 @rtype bool 364 @rtype bool
290 """ 365 """
291 if self.__cssRule or not self.__enabled or self.__internalDisabled: 366 if self.__type == AdBlockRuleType.CssRule or \
367 not self.__isEnabled or \
368 self.__isInternalDisabled:
292 return False 369 return False
293 370
294 matched = self.__stringMatch(domain, encodedUrl) 371 matched = self.__stringMatch(domain, encodedUrl)
295 372
296 if matched: 373 if matched:
297 # check domain restrictions 374 # check domain restrictions
298 if self.__domainRestricted and \ 375 if self.__hasOption(AdBlockRuleOption.DomainRestrictedOption) and \
299 not self.matchDomain(request.firstPartyUrl().host()): 376 not self.matchDomain(request.firstPartyUrl().host()):
300 return False 377 return False
301 378
302 # check third-party restrictions 379 # check third-party restrictions
303 if self.__thirdParty and not self.matchThirdParty(request): 380 if self.__hasOption(AdBlockRuleOption.ThirdPartyOption) and \
381 not self.matchThirdParty(request):
304 return False 382 return False
305 383
306 # check object restrictions 384 # check object restrictions
307 if self.__object and not self.matchObject(request): 385 if self.__hasOption(AdBlockRuleOption.ObjectOption) and \
386 not self.matchObject(request):
308 return False 387 return False
309 388
310 # check subdocument restrictions 389 # check subdocument restrictions
311 if self.__subdocument and not self.matchSubdocument(request): 390 if self.__hasOption(AdBlockRuleOption.SubdocumentOption) and \
391 not self.matchSubdocument(request):
312 return False 392 return False
313 393
314 # check xmlhttprequest restriction 394 # check xmlhttprequest restriction
315 if self.__xmlhttprequest and not self.matchXmlHttpRequest(request): 395 if self.__hasOption(AdBlockRuleOption.XMLHttpRequestOption) and \
396 not self.matchXmlHttpRequest(request):
316 return False 397 return False
317 398
318 # check image restriction 399 # check image restriction
319 if self.__image and not self.matchImage(request): 400 if self.__hasOption(AdBlockRuleOption.ImageOption) and \
401 not self.matchImage(request):
320 return False 402 return False
321 403
322 # check script restriction 404 # check script restriction
323 if self.__script and not self.matchScript(request): 405 if self.__hasOption(AdBlockRuleOption.ScriptOption) and \
406 not self.matchScript(request):
324 return False 407 return False
325 408
326 # check stylesheet restriction 409 # check stylesheet restriction
327 if self.__stylesheet and not self.matchStyleSheet(request): 410 if self.__hasOption(AdBlockRuleOption.StyleSheetOption) and \
411 not self.matchStyleSheet(request):
328 return False 412 return False
329 413
330 # check object-subrequest restriction 414 # check object-subrequest restriction
331 if self.__objectSubrequest and \ 415 if self.__hasOption(AdBlockRuleOption.ObjectSubrequestOption) and \
332 not self.matchObjectSubrequest(request): 416 not self.matchObjectSubrequest(request):
417 return False
418
419 # check ping restriction
420 if self.__hasOption(AdBlockRuleOption.PingOption) and \
421 not self.matchPing(request):
422 return False
423
424 # check media restriction
425 if self.__hasOption(AdBlockRuleOption.MediaOption) and \
426 not self.matchMedia(request):
427 return False
428
429 # check font restriction
430 if self.__hasOption(AdBlockRuleOption.FontOption) and \
431 not self.matchFont(request):
333 return False 432 return False
334 433
335 return matched 434 return matched
336 435
337 def urlMatch(self, url): 436 def urlMatch(self, url):
338 """ 437 """
339 Public method to check an URL against the rule. 438 Public method to check an URL against the rule.
340 439
341 @param url URL to check (QUrl) 440 @param url URL to check
342 @return flag indicating a match (boolean) 441 @type QUrl
343 """ 442 @return flag indicating a match
344 if not self.__document and not self.__elemhide: 443 @rtype bool
444 """
445 if not self.__hasOption(AdBlockRuleOption.DocumentOption) and \
446 not self.__hasOption(AdBlockRuleOption.ElementHideOption):
345 return False 447 return False
346 448
347 encodedUrl = bytes(url.toEncoded()).decode() 449 encodedUrl = bytes(url.toEncoded()).decode()
348 domain = url.host() 450 domain = url.host()
349 return self.__stringMatch(domain, encodedUrl) 451 return self.__stringMatch(domain, encodedUrl)
357 @param encodedUrl URL in encoded form 459 @param encodedUrl URL in encoded form
358 @type str 460 @type str
359 @return flag indicating a match 461 @return flag indicating a match
360 @rtype bool 462 @rtype bool
361 """ 463 """
362 if self.__cssRule or not self.__enabled or self.__internalDisabled:
363 return False
364
365 matched = False 464 matched = False
366 465
367 if self.__useRegExp: 466 if self.__type == AdBlockRuleType.StringContainsMatchRule:
368 matched = self.__regExp.indexIn(encodedUrl) != -1 467 if self.__caseSensitivity == Qt.CaseInsensitive:
369 elif self.__useDomainMatch: 468 matched = self.__matchString.lower() in encodedUrl.lower()
370 matched = domain.endswith(self.__matchString) 469 else:
371 elif self.__useEndsMatch: 470 matched = self.__matchString in encodedUrl
471 elif self.__type == AdBlockRuleType.DomainMatchRule:
472 matched = self.__isMatchingDomain(domain, self.__matchString)
473 elif self.__type == AdBlockRuleType.StringEndsMatchRule:
372 if self.__caseSensitivity == Qt.CaseInsensitive: 474 if self.__caseSensitivity == Qt.CaseInsensitive:
373 matched = encodedUrl.lower().endswith( 475 matched = encodedUrl.lower().endswith(
374 self.__matchString.lower()) 476 self.__matchString.lower())
375 else: 477 else:
376 matched = encodedUrl.endswith(self.__matchString) 478 matched = encodedUrl.endswith(self.__matchString)
377 else: 479 elif self.__type == AdBlockRuleType.RegExpMatchRule:
378 if self.__caseSensitivity == Qt.CaseInsensitive: 480 if not self.__isMatchingRegExpStrings(encodedUrl):
379 matched = self.__matchString.lower() in encodedUrl.lower() 481 matched = False
380 else: 482 else:
381 matched = self.__matchString in encodedUrl 483 matched = self.__regExp.indexIn(encodedUrl) != -1
484 elif self.__type == AdBlockRuleType.MatchAllUrlsRule:
485 matched = True
382 486
383 return matched 487 return matched
384 488
385 def matchDomain(self, domain): 489 def matchDomain(self, domain):
386 """ 490 """
387 Public method to match a domain. 491 Public method to match a domain.
388 492
389 @param domain domain name to check (string) 493 @param domain domain name to check
390 @return flag indicating a match (boolean) 494 @type str
391 """ 495 @return flag indicating a match
392 if not self.__enabled: 496 @rtype bool
497 """
498 if not self.__isEnabled:
393 return False 499 return False
394 500
395 if not self.__domainRestricted: 501 if not self.__hasOption(AdBlockRuleOption.DomainRestrictedOption):
396 return True 502 return True
397 503
398 if len(self.__blockedDomains) == 0: 504 if len(self.__blockedDomains) == 0:
399 for dom in self.__allowedDomains: 505 for dom in self.__allowedDomains:
400 if domain.endswith(dom): 506 if self.__isMatchingDomain(domain, dom):
401 return True 507 return True
402 elif len(self.__allowedDomains) == 0: 508 elif len(self.__allowedDomains) == 0:
403 for dom in self.__blockedDomains: 509 for dom in self.__blockedDomains:
404 if domain.endswith(dom): 510 if self.__isMatchingDomain(domain, dom):
405 return False 511 return False
406 return True 512 return True
407 else: 513 else:
408 for dom in self.__blockedDomains: 514 for dom in self.__blockedDomains:
409 if domain.endswith(dom): 515 if self.__isMatchingDomain(domain, dom):
410 return False 516 return False
411 for dom in self.__allowedDomains: 517 for dom in self.__allowedDomains:
412 if domain.endswith(dom): 518 if self.__isMatchingDomain(domain, dom):
413 return True 519 return True
414 520
415 return False 521 return False
416 522
417 def matchThirdParty(self, req): 523 def matchThirdParty(self, req):
418 """ 524 """
419 Public slot to match a third-party rule. 525 Public method to match a third-party rule.
420 526
421 @param req request object to check (QWebEngineUrlRequestInfo) 527 @param req request object to check
422 @return flag indicating a match (boolean) 528 @type QWebEngineUrlRequestInfo
529 @return flag indicating a match
530 @rtype boolean
423 """ 531 """
424 # Third-party matching should be performed on second-level domains 532 # Third-party matching should be performed on second-level domains
425 firstPartyHost = toSecondLevelDomain(req.firstPartyUrl()) 533 firstPartyHost = toSecondLevelDomain(req.firstPartyUrl())
426 host = toSecondLevelDomain(req.requestUrl()) 534 host = toSecondLevelDomain(req.requestUrl())
427 535
428 match = firstPartyHost != host 536 match = firstPartyHost != host
429 537
430 if self.__thirdPartyException: 538 if self.__hasException(AdBlockRuleOption.ThirdPartyOption):
431 return not match 539 return not match
432 else: 540 else:
433 return match 541 return match
434 542
435 def matchObject(self, req): 543 def matchObject(self, req):
436 """ 544 """
437 Public slot to match an object rule. 545 Public method to match an object rule.
438 546
439 @param req request object to check (QWebEngineUrlRequestInfo) 547 @param req request object to check
440 @return flag indicating a match (boolean) 548 @type QWebEngineUrlRequestInfo
549 @return flag indicating a match
550 @rtype bool
441 """ 551 """
442 match = ( 552 match = (
443 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeObject) 553 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeObject)
444 554
445 if self.__objectException: 555 if self.__hasException(AdBlockRuleOption.ObjectOption):
446 return not match 556 return not match
447 else: 557 else:
448 return match 558 return match
449 559
450 def matchSubdocument(self, req): 560 def matchSubdocument(self, req):
451 """ 561 """
452 Public slot to match a sub-document rule. 562 Public method to match a sub-document rule.
453 563
454 @param req request object to check (QWebEngineUrlRequestInfo) 564 @param req request object to check
455 @return flag indicating a match (boolean) 565 @type QWebEngineUrlRequestInfo
566 @return flag indicating a match
567 @rtype boolean
456 """ 568 """
457 match = ( 569 match = (
458 req.resourceType() == 570 req.resourceType() ==
459 QWebEngineUrlRequestInfo.ResourceTypeSubFrame) 571 QWebEngineUrlRequestInfo.ResourceTypeSubFrame)
460 572
461 if self.__subdocumentException: 573 if self.__hasException(AdBlockRuleOption.SubdocumentOption):
462 return not match 574 return not match
463 else: 575 else:
464 return match 576 return match
465 577
466 def matchXmlHttpRequest(self, req): 578 def matchXmlHttpRequest(self, req):
467 """ 579 """
468 Public slot to match a XmlHttpRequest rule. 580 Public method to match a XmlHttpRequest rule.
469 581
470 @param req request object to check (QWebEngineUrlRequestInfo) 582 @param req request object to check
471 @return flag indicating a match (boolean) 583 @type QWebEngineUrlRequestInfo
584 @return flag indicating a match
585 @rtype bool
472 """ 586 """
473 match = ( 587 match = (
474 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeXhr) 588 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeXhr)
475 589
476 if self.__xmlhttprequestException: 590 if self.__hasException(AdBlockRuleOption.XMLHttpRequestOption):
477 return not match 591 return not match
478 else: 592 else:
479 return match 593 return match
480 594
481 def matchImage(self, req): 595 def matchImage(self, req):
482 """ 596 """
483 Public slot to match an Image rule. 597 Public method to match an Image rule.
484 598
485 @param req request object to check (QWebEngineUrlRequestInfo) 599 @param req request object to check
486 @return flag indicating a match (boolean) 600 @type QWebEngineUrlRequestInfo
601 @return flag indicating a match
602 @rtype bool
487 """ 603 """
488 match = ( 604 match = (
489 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeImage) 605 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeImage)
490 606
491 if self.__imageException: 607 if self.__hasException(AdBlockRuleOption.ImageOption):
492 return not match 608 return not match
493 else: 609 else:
494 return match 610 return match
495 611
496 def matchScript(self, req): 612 def matchScript(self, req):
497 """ 613 """
498 Public slot to match a Script rule. 614 Public method to match a Script rule.
499 615
500 @param req request object to check (QWebEngineUrlRequestInfo) 616 @param req request object to check
501 @return flag indicating a match (boolean) 617 @type QWebEngineUrlRequestInfo
618 @return flag indicating a match
619 @rtype bool
502 """ 620 """
503 match = ( 621 match = (
504 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeScript) 622 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeScript)
505 623
506 if self.__scriptException: 624 if self.__hasException(AdBlockRuleOption.ScriptOption):
507 return not match 625 return not match
508 else: 626 else:
509 return match 627 return match
510 628
511 def matchStyleSheet(self, req): 629 def matchStyleSheet(self, req):
512 """ 630 """
513 Public slot to match a StyleSheet rule. 631 Public method to match a StyleSheet rule.
514 632
515 @param req request object to check (QWebEngineUrlRequestInfo) 633 @param req request object to check
516 @return flag indicating a match (boolean) 634 @type QWebEngineUrlRequestInfo
635 @return flag indicating a match
636 @rtype bool
517 """ 637 """
518 match = ( 638 match = (
519 req.resourceType() == 639 req.resourceType() ==
520 QWebEngineUrlRequestInfo.ResourceTypeStylesheet) 640 QWebEngineUrlRequestInfo.ResourceTypeStylesheet)
521 641
522 if self.__stylesheetException: 642 if self.__hasException(AdBlockRuleOption.StyleSheetOption):
523 return not match 643 return not match
524 else: 644 else:
525 return match 645 return match
526 646
527 def matchObjectSubrequest(self, req): 647 def matchObjectSubrequest(self, req):
528 """ 648 """
529 Public slot to match an Object Subrequest rule. 649 Public method to match an Object Subrequest rule.
530 650
531 @param req request object to check (QWebEngineUrlRequestInfo) 651 @param req request object to check
532 @return flag indicating a match (boolean) 652 @type QWebEngineUrlRequestInfo
653 @return flag indicating a match
654 @rtype boolean
533 """ 655 """
534 match = ( 656 match = (
535 req.resourceType() == 657 req.resourceType() ==
536 QWebEngineUrlRequestInfo.ResourceTypeSubResource) 658 QWebEngineUrlRequestInfo.ResourceTypeSubResource)
537 if qVersionTuple() >= (5, 7, 0) and PYQT_VERSION >= 0x50700: 659 if qVersionTuple() >= (5, 7, 0) and PYQT_VERSION >= 0x50700:
542 if self.__objectSubrequestException: 664 if self.__objectSubrequestException:
543 return not match 665 return not match
544 else: 666 else:
545 return match 667 return match
546 668
669 def matchPing(self, req):
670 """
671 Public method to match a Ping rule.
672
673 @param req request object to check
674 @type QWebEngineUrlRequestInfo
675 @return flag indicating a match
676 @rtype bool
677 """
678 match = (
679 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypePing)
680
681 if self.__hasException(AdBlockRuleOption.PingOption):
682 return not match
683 else:
684 return match
685
686 def matchMedia(self, req):
687 """
688 Public method to match a Media rule.
689
690 @param req request object to check
691 @type QWebEngineUrlRequestInfo
692 @return flag indicating a match
693 @rtype bool
694 """
695 match = (
696 req.resourceType() == QWebEngineUrlRequestInfo.ResourceTypeMedia)
697
698 if self.__hasException(AdBlockRuleOption.MediaOption):
699 return not match
700 else:
701 return match
702
703 def matchFont(self, req):
704 """
705 Public method to match a Font rule.
706
707 @param req request object to check
708 @type QWebEngineUrlRequestInfo
709 @return flag indicating a match
710 @rtype bool
711 """
712 match = (
713 req.resourceType() ==
714 QWebEngineUrlRequestInfo.ResourceTypeFontResource)
715
716 if self.__hasException(AdBlockRuleOption.FontOption):
717 return not match
718 else:
719 return match
720
721 def matchOther(self, req):
722 """
723 Public method to match any other rule.
724
725 @param req request object to check
726 @type QWebEngineUrlRequestInfo
727 @return flag indicating a match
728 @rtype bool
729 """
730 match = req.resourceType() in [
731 QWebEngineUrlRequestInfo.ResourceTypeSubResource,
732 QWebEngineUrlRequestInfo.ResourceTypeWorker,
733 QWebEngineUrlRequestInfo.ResourceTypeSharedWorker,
734 QWebEngineUrlRequestInfo.ResourceTypeServiceWorker,
735 QWebEngineUrlRequestInfo.ResourceTypePrefetch,
736 QWebEngineUrlRequestInfo.ResourceTypeFavicon,
737 QWebEngineUrlRequestInfo.ResourceTypeUnknown,
738 ]
739
740 if self.__hasException(AdBlockRuleOption.OtherOption):
741 return not match
742 else:
743 return match
744
547 def isException(self): 745 def isException(self):
548 """ 746 """
549 Public method to check, if the rule defines an exception. 747 Public method to check, if the rule defines an exception.
550 748
551 @return flag indicating an exception (boolean) 749 @return flag indicating an exception
552 """ 750 @rtype bool
553 return self.__exception 751 """
752 return self.__isException
554 753
555 def setException(self, exception): 754 def setException(self, exception):
556 """ 755 """
557 Public method to set the rule's exception flag. 756 Public method to set the rule's exception flag.
558 757
559 @param exception flag indicating an exception rule (boolean) 758 @param exception flag indicating an exception rule
560 """ 759 @type bool
561 self.__exception = exception 760 """
761 self.__isException = exception
562 762
563 def isEnabled(self): 763 def isEnabled(self):
564 """ 764 """
565 Public method to check, if the rule is enabled. 765 Public method to check, if the rule is enabled.
566 766
567 @return flag indicating enabled state (boolean) 767 @return flag indicating enabled state
568 """ 768 @rtype bool
569 return self.__enabled 769 """
770 return self.__isEnabled
570 771
571 def setEnabled(self, enabled): 772 def setEnabled(self, enabled):
572 """ 773 """
573 Public method to set the rule's enabled state. 774 Public method to set the rule's enabled state.
574 775
575 @param enabled flag indicating the new enabled state (boolean) 776 @param enabled flag indicating the new enabled state
576 """ 777 @type bool
577 self.__enabled = enabled 778 """
578 if not enabled: 779 self.__isEnabled = enabled
579 self.__filter = "!" + self.__filter
580 else:
581 self.__filter = self.__filter[1:]
582 780
583 def isCSSRule(self): 781 def isCSSRule(self):
584 """ 782 """
585 Public method to check, if the rule is a CSS rule. 783 Public method to check, if the rule is a CSS rule.
586 784
587 @return flag indicating a CSS rule (boolean) 785 @return flag indicating a CSS rule
588 """ 786 @rtype bool
589 return self.__cssRule 787 """
788 return self.__type == AdBlockRuleType.CssRule
590 789
591 def cssSelector(self): 790 def cssSelector(self):
592 """ 791 """
593 Public method to get the CSS selector of the rule. 792 Public method to get the CSS selector of the rule.
594 793
595 @return CSS selector (string) 794 @return CSS selector
596 """ 795 @rtype str
597 return self.__cssSelector 796 """
797 return self.__matchString
598 798
599 def isDocument(self): 799 def isDocument(self):
600 """ 800 """
601 Public method to check, if this is a document rule. 801 Public method to check, if this is a document rule.
602 802
603 @return flag indicating a document rule (boolean) 803 @return flag indicating a document rule
604 """ 804 @rtype bool
605 return self.__document 805 """
806 return self.__hasOption(AdBlockRuleOption.DocumentOption)
606 807
607 def isElementHiding(self): 808 def isElementHiding(self):
608 """ 809 """
609 Public method to check, if this is an element hiding rule. 810 Public method to check, if this is an element hiding rule.
610 811
611 @return flag indicating an element hiding rule (boolean) 812 @return flag indicating an element hiding rule
612 """ 813 @rtype bool
613 return self.__elemhide 814 """
815 return self.__hasOption(AdBlockRuleOption.ElementHideOption)
614 816
615 def isDomainRestricted(self): 817 def isDomainRestricted(self):
616 """ 818 """
617 Public method to check, if this rule is restricted by domain. 819 Public method to check, if this rule is restricted by domain.
618 820
619 @return flag indicating a domain restriction (boolean) 821 @return flag indicating a domain restriction
620 """ 822 @rtype bool
621 return self.__domainRestricted 823 """
824 return self.__hasOption(AdBlockRuleOption.DomainRestrictedOption)
622 825
623 def isComment(self): 826 def isComment(self):
624 """ 827 """
625 Public method to check, if this is a comment. 828 Public method to check, if this is a comment.
626 829
627 @return flag indicating a comment (boolean) 830 @return flag indicating a comment
831 @rtype bool
628 """ 832 """
629 return self.__filter.startswith("!") 833 return self.__filter.startswith("!")
630 834
631 def isHeader(self): 835 def isHeader(self):
632 """ 836 """
633 Public method to check, if this is a header. 837 Public method to check, if this is a header.
634 838
635 @return flag indicating a header (boolean) 839 @return flag indicating a header
840 @rtype bool
636 """ 841 """
637 return self.__filter.startswith("[Adblock") 842 return self.__filter.startswith("[Adblock")
638 843
639 def isSlow(self): 844 def isSlow(self):
640 """ 845 """
641 Public method to check, if this is a slow rule. 846 Public method to check, if this is a slow rule.
642 847
643 @return flag indicating a slow rule (boolean) 848 @return flag indicating a slow rule
644 """ 849 @rtype bool
645 return self.__useRegExp 850 """
851 return self.__regExp is not None
646 852
647 def isInternalDisabled(self): 853 def isInternalDisabled(self):
648 """ 854 """
649 Public method to check, if this rule was disabled internally. 855 Public method to check, if this rule was disabled internally.
650 856
651 @return flag indicating an internally disabled rule (boolean) 857 @return flag indicating an internally disabled rule
652 """ 858 @rtype bool
653 return self.__internalDisabled 859 """
860 return self.__isInternalDisabled
654 861
655 def __convertPatternToRegExp(self, wildcardPattern): 862 def __convertPatternToRegExp(self, wildcardPattern):
656 """ 863 """
657 Private method to convert a wildcard pattern to a regular expression. 864 Private method to convert a wildcard pattern to a regular expression.
658 865
659 @param wildcardPattern string containing the wildcard pattern (string) 866 @param wildcardPattern string containing the wildcard pattern
660 @return string containing a regular expression (string) 867 @type str
868 @return string containing a regular expression
869 @rtype string
661 """ 870 """
662 pattern = wildcardPattern 871 pattern = wildcardPattern
663 872
664 # remove multiple wildcards 873 # remove multiple wildcards
665 pattern = re.sub(r"\*+", "*", pattern) 874 pattern = re.sub(r"\*+", "*", pattern)
683 pattern = re.sub(r"\\\|$", "$", pattern) 892 pattern = re.sub(r"\\\|$", "$", pattern)
684 # replace wildcards by .* 893 # replace wildcards by .*
685 pattern = re.sub(r"\\\*", ".*", pattern) 894 pattern = re.sub(r"\\\*", ".*", pattern)
686 895
687 return pattern 896 return pattern
897
898 def __hasOption(self, opt):
899 """
900 Private method to check, if the given option has been set.
901
902 @param opt option to check for
903 @type AdBlockRuleOption
904 @return flag indicating the state of the option
905 @rtype bool
906 """
907 return bool(self.__options & opt)
908
909 def setOption(self, opt):
910 """
911 Public method to set the given option.
912
913 @param opt option to be set
914 @type AdBlockRuleOption
915 """
916 self.__options |= opt
917
918 def __hasException(self, opt):
919 """
920 Private method to check, if the given option has been set as an
921 exception.
922
923 @param opt option to check for
924 @type AdBlockRuleOption
925 @return flag indicating the exception state of the option
926 @rtype bool
927 """
928 return bool(self.__exceptions & opt)
929
930 def __setException(self, opt, on):
931 """
932 Private method to set the given option as an exception.
933
934 @param opt option to be set
935 @type AdBlockRuleOption
936 @param on flag indicating to set or unset the exception
937 @type bool
938 """
939 if on:
940 self.__exceptions |= opt
941 else:
942 self.__exceptions &= ~opt
943
944 def __filterIsOnlyDomain(self, filterString):
945 """
946 Private method to check, if the given filter is a domain only filter.
947
948 @param filterString filter string to be checked
949 @type str
950 @return flag indicating a domain only filter
951 @rtype bool
952 """
953 if not filterString.endswith("^") or not filterString.startswith("||"):
954 return False
955
956 for filterChar in filterString:
957 if filterChar in ["/", ":", "?", "=", "&", "*"]:
958 return False
959
960 return True
961
962 def __filterIsOnlyEndsMatch(self, filterString):
963 """
964 Private method to check, if the given filter is to match against the
965 end of a string.
966
967 @param filterString filter string to be checked
968 @type str
969 @return flag indicating a end of string match filter
970 @rtype bool
971 """
972 index = 0
973 for filterChar in filterString:
974 if filterChar in ["^", "*"]:
975 return False
976 elif filterChar == "|":
977 return bool(index == len(filterString) - 1)
978 index += 1
979
980 return False
981
982 def __isMatchingDomain(self, domain, filterString):
983 """
984 Private method to check, if a given domain matches the given filter
985 string.
986
987 @param domain domain to be checked
988 @type str
989 @param filterString filter string to check against
990 @type str
991 @return flag indicating a match
992 @rtype bool
993 """
994 if filterString == domain:
995 return True
996
997 if not domain.endswith(filterString):
998 return False
999
1000 index = domain.find(filterString)
1001
1002 return bool(index > 0 and domain[index - 1] == ".")
1003
1004 def __isMatchingRegExpStrings(self, url):
1005 """
1006 Private method to check the given URL against the fixed parts of
1007 the regexp.
1008
1009 @param url URL to be checked
1010 @type str
1011 @return flag indicating a match
1012 @rtype bool
1013 """
1014 assert self.__regExp is not None
1015
1016 for matcher in self.__stringMatchers:
1017 if matcher not in url:
1018 return False
1019
1020 return True
1021
1022 def __parseRegExpFilter(self, filterString):
1023 """
1024 Private method to split the given regular expression into strings that
1025 can be used with 'in'.
1026
1027 @param filterString regexp filter string to be parsed
1028 @type str
1029 @return fixed string parts of the filter
1030 @rtype list of str
1031 """
1032 matchers = []
1033
1034 startPos = -1
1035 for index in range(len(filterString)):
1036 filterChar = filterString[index]
1037 if filterChar in ["|", "*", "^"]:
1038 sub = filterString[startPos:index]
1039 if len(sub) > 1:
1040 matchers.append(sub)
1041 startPos = index + 1
1042
1043 sub = filterString[startPos:]
1044 if len(sub) > 1:
1045 matchers.append(sub)
1046
1047 return list(set(matchers))
1048
1049 def ruleType(self):
1050 """
1051 Public method to get the rule type.
1052
1053 @return rule type
1054 @rtype AdBlockRuleType
1055 """
1056 return self.__type
1057
1058 def ruleOptions(self):
1059 """
1060 Public method to get the rule options.
1061
1062 @return rule options
1063 @rtype AdBlockRuleOption
1064 """
1065 return self.__options
1066
1067 def ruleExceptions(self):
1068 """
1069 Public method to get the rule exceptions.
1070
1071 @return rule exceptions
1072 @rtype AdBlockRuleOption
1073 """
1074 return self.__exceptions
1075
1076 def matchString(self):
1077 """
1078 Public method to get the match string.
1079
1080 @return match string
1081 @rtype str
1082 """
1083 return self.__matchString
1084
1085 def caseSensitivity(self):
1086 """
1087 Public method to get the case sensitivity.
1088
1089 @return case sensitivity
1090 @rtype Qt.CaseSensitivity
1091 """
1092 return self.__caseSensitivity
1093
1094 def allowedDomains(self):
1095 """
1096 Public method to get a copy of the list of allowed domains.
1097
1098 @return list of allowed domains
1099 @rtype list of str
1100 """
1101 return self.__allowedDomains[:]
1102
1103 def blockedDomains(self):
1104 """
1105 Public method to get a copy of the list of blocked domains.
1106
1107 @return list of blocked domains
1108 @rtype list of str
1109 """
1110 return self.__blockedDomains[:]
1111
1112 def addBlockedDomains(self, domains):
1113 """
1114 Public method to add to the list of blocked domains.
1115
1116 @param domains list of domains to be added
1117 @type str or list of str
1118 """
1119 if isinstance(domains, list):
1120 self.__blockedDomains.extend(domains)
1121 else:
1122 self.__blockedDomains.append(domains)
1123
1124 def getRegExpAndMatchers(self):
1125 """
1126 Public method to get the regular expression and associated string
1127 matchers.
1128
1129 @return tuple containing the regular expression and the list of
1130 string matchers
1131 @rtype tuple of (QRegExp, list of str)
1132 """
1133 if self.__regExp is not None:
1134 return (QRegExp(self.__regExp), self.__stringMatchers[:])
1135 else:
1136 return (None, [])
1137
1138 def copyFrom(self, other):
1139 """
1140 Public method to copy another AdBlock rule.
1141
1142 @param other reference to the AdBlock rule to copy from
1143 @type AdBlockRule
1144 """
1145 self.__subscription = other.subscription()
1146 self.__type = other.ruleType()
1147 self.__options = other.ruleOptions()
1148 self.__exceptions = other.ruleExceptions()
1149 self.__filter = other.filter()
1150 self.__matchString = other.matchString()
1151 self.__caseSensitivity = other.caseSensitivity()
1152 self.__isEnabled = other.isEnabled()
1153 self.__isException = other.isException()
1154 self.__isInternalDisabled = other.isInternalDisabled()
1155 self.__allowedDomains = other.allowedDomains()
1156 self.__blockedDomains = other.blockedDomains()
1157 self.__regExp, self.__stringMatchers = other.getRegExpAndMatchers()

eric ide

mercurial