Helpviewer/AdBlock/AdBlockSubscription.py

changeset 3000
971d84f7a6d6
parent 2403
e3d7a861547c
child 3020
542e97d4ecb3
child 3057
10516539f238
equal deleted inserted replaced
2999:28c75409a78f 3000:971d84f7a6d6
10 import os 10 import os
11 import re 11 import re
12 import hashlib 12 import hashlib
13 import base64 13 import base64
14 14
15 from PyQt4.QtCore import pyqtSignal, Qt, QObject, QByteArray, QDateTime, QUrl, \ 15 from PyQt4.QtCore import pyqtSignal, Qt, QObject, QByteArray, QDateTime, \
16 QCryptographicHash, QFile, QIODevice, QTextStream, QDate, QTime 16 QUrl, QCryptographicHash, QFile, QIODevice, QTextStream, QDate, QTime
17 from PyQt4.QtNetwork import QNetworkReply 17 from PyQt4.QtNetwork import QNetworkReply
18 18
19 from E5Gui import E5MessageBox 19 from E5Gui import E5MessageBox
20 20
21 import Utilities 21 import Utilities
67 self.__domainRestrictedCssRules = [] 67 self.__domainRestrictedCssRules = []
68 self.__elementHidingRules = "" 68 self.__elementHidingRules = ""
69 self.__documentRules = [] 69 self.__documentRules = []
70 self.__elemhideRules = [] 70 self.__elemhideRules = []
71 71
72 self.__checksumRe = re.compile(r"""^\s*!\s*checksum[\s\-:]+([\w\+\/=]+).*\n""", 72 self.__checksumRe = re.compile(
73 r"""^\s*!\s*checksum[\s\-:]+([\w\+\/=]+).*\n""",
73 re.IGNORECASE | re.MULTILINE) 74 re.IGNORECASE | re.MULTILINE)
74 self.__expiresRe = re.compile( 75 self.__expiresRe = re.compile(
75 r"""(?:expires:|expires after)\s*(\d+)\s*(hour|h)?""", 76 r"""(?:expires:|expires after)\s*(\d+)\s*(hour|h)?""",
76 re.IGNORECASE) 77 re.IGNORECASE)
77 self.__remoteModifiedRe = re.compile( 78 self.__remoteModifiedRe = re.compile(
109 if url.path() != "subscribe": 110 if url.path() != "subscribe":
110 return 111 return
111 112
112 self.__title = \ 113 self.__title = \
113 QUrl.fromPercentEncoding(url.encodedQueryItemValue("title")) 114 QUrl.fromPercentEncoding(url.encodedQueryItemValue("title"))
114 self.__enabled = \ 115 self.__enabled = QUrl.fromPercentEncoding(
115 QUrl.fromPercentEncoding(url.encodedQueryItemValue("enabled")) != "false" 116 url.encodedQueryItemValue("enabled")) != "false"
116 self.__location = \ 117 self.__location = QByteArray(QUrl.fromPercentEncoding(
117 QByteArray(QUrl.fromPercentEncoding(url.encodedQueryItemValue("location"))) 118 url.encodedQueryItemValue("location")))
118 119
119 # Check for required subscription 120 # Check for required subscription
120 self.__requiresLocation = \ 121 self.__requiresLocation = QUrl.fromPercentEncoding(
121 QUrl.fromPercentEncoding(url.encodedQueryItemValue("requiresLocation")) 122 url.encodedQueryItemValue("requiresLocation"))
122 self.__requiresTitle = \ 123 self.__requiresTitle = QUrl.fromPercentEncoding(
123 QUrl.fromPercentEncoding(url.encodedQueryItemValue("requiresTitle")) 124 url.encodedQueryItemValue("requiresTitle"))
124 if self.__requiresLocation and self.__requiresTitle: 125 if self.__requiresLocation and self.__requiresTitle:
125 import Helpviewer.HelpWindow 126 import Helpviewer.HelpWindow
126 Helpviewer.HelpWindow.HelpWindow.adBlockManager().loadRequiredSubscription( 127 Helpviewer.HelpWindow.HelpWindow.adBlockManager()\
127 self.__requiresLocation, self.__requiresTitle) 128 .loadRequiredSubscription(self.__requiresLocation,
129 self.__requiresTitle)
128 130
129 lastUpdateByteArray = url.encodedQueryItemValue("lastUpdate") 131 lastUpdateByteArray = url.encodedQueryItemValue("lastUpdate")
130 lastUpdateString = QUrl.fromPercentEncoding(lastUpdateByteArray) 132 lastUpdateString = QUrl.fromPercentEncoding(lastUpdateByteArray)
131 self.__lastUpdate = QDateTime.fromString(lastUpdateString, Qt.ISODate) 133 self.__lastUpdate = QDateTime.fromString(lastUpdateString, Qt.ISODate)
132 134
243 return self.location().toLocalFile() 245 return self.location().toLocalFile()
244 246
245 if self.__location.isEmpty(): 247 if self.__location.isEmpty():
246 return "" 248 return ""
247 249
248 sha1 = bytes( 250 sha1 = bytes(QCryptographicHash.hash(
249 QCryptographicHash.hash(self.__location, QCryptographicHash.Sha1).toHex())\ 251 self.__location, QCryptographicHash.Sha1).toHex()).decode()
250 .decode() 252 dataDir = os.path.join(
251 dataDir = os.path.join(Utilities.getConfigDir(), "browser", "subscriptions") 253 Utilities.getConfigDir(), "browser", "subscriptions")
252 if not os.path.exists(dataDir): 254 if not os.path.exists(dataDir):
253 os.makedirs(dataDir) 255 os.makedirs(dataDir)
254 fileName = os.path.join(dataDir, "adblock_subscription_{0}".format(sha1)) 256 fileName = os.path.join(
257 dataDir, "adblock_subscription_{0}".format(sha1))
255 return fileName 258 return fileName
256 259
257 def __loadRules(self): 260 def __loadRules(self):
258 """ 261 """
259 Private method to load the rules of the subscription. 262 Private method to load the rules of the subscription.
262 f = QFile(fileName) 265 f = QFile(fileName)
263 if f.exists(): 266 if f.exists():
264 if not f.open(QIODevice.ReadOnly): 267 if not f.open(QIODevice.ReadOnly):
265 E5MessageBox.warning(None, 268 E5MessageBox.warning(None,
266 self.trUtf8("Load subscription rules"), 269 self.trUtf8("Load subscription rules"),
267 self.trUtf8("""Unable to open adblock file '{0}' for reading.""")\ 270 self.trUtf8(
271 """Unable to open adblock file '{0}' for reading.""")\
268 .format(fileName)) 272 .format(fileName))
269 else: 273 else:
270 textStream = QTextStream(f) 274 textStream = QTextStream(f)
271 header = textStream.readLine(1024) 275 header = textStream.readLine(1024)
272 if not header.startswith("[Adblock"): 276 if not header.startswith("[Adblock"):
297 else: 301 else:
298 # days 302 # days
299 self.__updatePeriod = int(period) * 24 303 self.__updatePeriod = int(period) * 24
300 remoteModified = self.__remoteModifiedRe.search(line) 304 remoteModified = self.__remoteModifiedRe.search(line)
301 if remoteModified: 305 if remoteModified:
302 day, month, year, time, hour, minute = remoteModified.groups() 306 day, month, year, time, hour, minute = \
307 remoteModified.groups()
303 self.__remoteModified.setDate( 308 self.__remoteModified.setDate(
304 QDate(int(year), self.__monthNameToNumber[month], 309 QDate(int(year),
305 int(day))) 310 self.__monthNameToNumber[month],
311 int(day))
312 )
306 if time: 313 if time:
307 self.__remoteModified.setTime( 314 self.__remoteModified.setTime(
308 QTime(int(hour), int(minute))) 315 QTime(int(hour), int(minute)))
309 self.__populateCache() 316 self.__populateCache()
310 self.changed.emit() 317 self.changed.emit()
363 if reply.error() != QNetworkReply.NoError: 370 if reply.error() != QNetworkReply.NoError:
364 if not self.__defaultSubscription: 371 if not self.__defaultSubscription:
365 # don't show error if we try to load the default 372 # don't show error if we try to load the default
366 E5MessageBox.warning(None, 373 E5MessageBox.warning(None,
367 self.trUtf8("Downloading subscription rules"), 374 self.trUtf8("Downloading subscription rules"),
368 self.trUtf8("""<p>Subscription rules could not be downloaded.</p>""" 375 self.trUtf8(
369 """<p>Error: {0}</p>""").format(reply.errorString())) 376 """<p>Subscription rules could not be"""
377 """ downloaded.</p><p>Error: {0}</p>""")
378 .format(reply.errorString()))
370 else: 379 else:
371 # reset after first download attempt 380 # reset after first download attempt
372 self.__defaultSubscription = False 381 self.__defaultSubscription = False
373 return 382 return
374 383
382 QFile.remove(fileName) 391 QFile.remove(fileName)
383 f = QFile(fileName) 392 f = QFile(fileName)
384 if not f.open(QIODevice.ReadWrite): 393 if not f.open(QIODevice.ReadWrite):
385 E5MessageBox.warning(None, 394 E5MessageBox.warning(None,
386 self.trUtf8("Downloading subscription rules"), 395 self.trUtf8("Downloading subscription rules"),
387 self.trUtf8("""Unable to open adblock file '{0}' for writing.""")\ 396 self.trUtf8(
397 """Unable to open adblock file '{0}' for writing.""")\
388 .file(fileName)) 398 .file(fileName))
389 return 399 return
390 f.write(response) 400 f.write(response)
391 f.close() 401 f.close()
392 self.__lastUpdate = QDateTime.currentDateTime() 402 self.__lastUpdate = QDateTime.currentDateTime()
425 data = re.sub(self.__checksumRe, "", data) # remove checksum line 435 data = re.sub(self.__checksumRe, "", data) # remove checksum line
426 436
427 # calculate checksum 437 # calculate checksum
428 md5 = hashlib.md5() 438 md5 = hashlib.md5()
429 md5.update(data.encode("utf-8")) 439 md5.update(data.encode("utf-8"))
430 calculatedChecksum = base64.b64encode(md5.digest()).decode().rstrip("=") 440 calculatedChecksum = base64.b64encode(md5.digest()).decode()\
441 .rstrip("=")
431 if calculatedChecksum == expectedChecksum: 442 if calculatedChecksum == expectedChecksum:
432 return True 443 return True
433 else: 444 else:
434 res = E5MessageBox.yesNo(None, 445 res = E5MessageBox.yesNo(None,
435 self.trUtf8("Downloading subscription rules"), 446 self.trUtf8("Downloading subscription rules"),
436 self.trUtf8("""<p>AdBlock subscription <b>{0}</b> has a wrong""" 447 self.trUtf8(
437 """ checksum.<br/>""" 448 """<p>AdBlock subscription <b>{0}</b> has a wrong"""
438 """Found: {1}<br/>""" 449 """ checksum.<br/>"""
439 """Calculated: {2}<br/>""" 450 """Found: {1}<br/>"""
440 """Use it anyway?</p>""")\ 451 """Calculated: {2}<br/>"""
441 .format(self.__title, expectedChecksum, calculatedChecksum)) 452 """Use it anyway?</p>""")\
453 .format(self.__title, expectedChecksum,
454 calculatedChecksum))
442 return res 455 return res
443 456
444 def saveRules(self): 457 def saveRules(self):
445 """ 458 """
446 Public method to save the subscription rules. 459 Public method to save the subscription rules.
451 464
452 f = QFile(fileName) 465 f = QFile(fileName)
453 if not f.open(QIODevice.ReadWrite | QIODevice.Truncate): 466 if not f.open(QIODevice.ReadWrite | QIODevice.Truncate):
454 E5MessageBox.warning(None, 467 E5MessageBox.warning(None,
455 self.trUtf8("Saving subscription rules"), 468 self.trUtf8("Saving subscription rules"),
456 self.trUtf8("""Unable to open adblock file '{0}' for writing.""")\ 469 self.trUtf8(
470 """Unable to open adblock file '{0}' for writing.""")\
457 .format(fileName)) 471 .format(fileName))
458 return 472 return
459 473
460 textStream = QTextStream(f) 474 textStream = QTextStream(f)
461 if not self.__rules or not self.__rules[0].isHeader(): 475 if not self.__rules or not self.__rules[0].isHeader():
495 509
496 return False 510 return False
497 511
498 def elemHideDisabledForUrl(self, url): 512 def elemHideDisabledForUrl(self, url):
499 """ 513 """
500 Public method to check, if element hiding is disabled for the given URL. 514 Public method to check, if element hiding is disabled for the given
515 URL.
501 516
502 @param url URL to check (QUrl) 517 @param url URL to check (QUrl)
503 @return flag indicating disabled state (boolean) 518 @return flag indicating disabled state (boolean)
504 """ 519 """
505 if self.adBlockDisabledForUrl(url): 520 if self.adBlockDisabledForUrl(url):
656 rule = self.__rules[offset] 671 rule = self.__rules[offset]
657 rule.setEnabled(enabled) 672 rule.setEnabled(enabled)
658 if rule.isCSSRule(): 673 if rule.isCSSRule():
659 import Helpviewer.HelpWindow 674 import Helpviewer.HelpWindow
660 self.__populateCache() 675 self.__populateCache()
661 Helpviewer.HelpWindow.HelpWindow.mainWindow().reloadUserStyleSheet() 676 Helpviewer.HelpWindow.HelpWindow.mainWindow()\
677 .reloadUserStyleSheet()
662 678
663 return rule 679 return rule

eric ide

mercurial