WebBrowser/SafeBrowsing/SafeBrowsingManager.py

branch
safe_browsing
changeset 5820
b610cb5b501a
child 5821
6c7766cde4c1
equal deleted inserted replaced
5819:69fa45e95673 5820:b610cb5b501a
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the interface for Google Safe Browsing.
8 """
9
10 #
11 # Some part of this code were ported from gglsbl.client and adapted
12 # to Qt.
13 #
14 # https://github.com/afilipovich/gglsbl
15 #
16
17 from __future__ import unicode_literals
18
19 import os
20 import base64
21
22 from PyQt5.QtCore import QObject
23
24 import Preferences
25 import Utilities
26
27 from .SafeBrowsingAPIClient import SafeBrowsingAPIClient
28 from .SafeBrowsingCache import SafeBrowsingCache, ThreatList, HashPrefixList
29
30
31 class SafeBrowsingManager(QObject):
32 """
33 Class implementing the interface for Google Safe Browsing.
34 """
35 def __init__(self):
36 """
37 Constructor
38 """
39 super(SafeBrowsingManager, self).__init__()
40
41 self.__apiKey = Preferences.getWebBrowser("SafeBrowsingApiKey")
42 if self.__apiKey:
43 ## self.__apiClient = SafeBrowsingAPIClient(self.__apiKey,
44 ## parent=self)
45 # TODO: switch these after debugging is finished
46 self.__apiClient = SafeBrowsingAPIClient(self.__apiKey,
47 parent=self,
48 fairUse=False)
49 else:
50 self.__apiClient = None
51
52 self.__enabled = (
53 Preferences.getWebBrowser("SafeBrowsingEnabled") and
54 bool(self.__apiKey))
55
56 gsbCachePath = os.path.join(
57 Utilities.getConfigDir(), "web_browser", "safe_browsing")
58 self.__cache = SafeBrowsingCache(gsbCachePath, self)
59
60 self.__gsbDialog = None
61 self.__platforms = None # TODO: delete if not needed
62
63 def configurationChanged(self):
64 """
65 Public method to handle changes of the settings.
66 """
67 apiKey = Preferences.getWebBrowser("SafeBrowsingApiKey")
68 if apiKey != self.__apiKey:
69 self.__apiKey = apiKey
70 if self.__apiKey:
71 if self.__apiClient:
72 self.__apiClient.setApiKey(self.__apiKey)
73 else:
74 ## self.__apiClient = SafeBrowsingAPIClient(self.__apiKey,
75 ## parent=self)
76 # TODO: switch these after debugging is finished
77 self.__apiClient = SafeBrowsingAPIClient(self.__apiKey,
78 parent=self,
79 fairUse=False)
80
81 self.__enabled = (
82 Preferences.getWebBrowser("SafeBrowsingEnabled") and
83 bool(self.__apiKey))
84
85 def isEnabled(self):
86 """
87 Public method to check, if safe browsing is enabled.
88
89 @return flag indicating the enabled state
90 @rtype bool
91 """
92 return self.__enabled
93
94 def close(self):
95 """
96 Public method to close the safe browsing interface.
97 """
98 self.__cache.close()
99
100 def fairUseDelayExpired(self):
101 """
102 Public method to check, if the fair use wait period has expired.
103
104 @return flag indicating expiration
105 @rtype bool
106 """
107 return self.__enabled and self.__apiClient.fairUseDelayExpired()
108
109 def updateHashPrefixCache(self):
110 """
111 Public method to load or update the locally cached threat lists.
112
113 @return flag indicating success and an error message
114 @rtype tuple of (bool, str)
115 """
116 if not self.__enabled:
117 return False, self.tr("Safe Browsing is disabled.")
118
119 if not self.__apiClient.fairUseDelayExpired():
120 return False, \
121 self.tr("The fair use wait period has not expired yet.")
122
123 # step 1: remove expired hashes
124 self.__cache.cleanupFullHashes()
125
126 # step 2: update threat lists
127 threatListsForRemove = {}
128 for threatList, clientState in self.__cache.getThreatLists():
129 threatListsForRemove[repr(threatList)] = threatList
130 threatLists = self.__apiClient.getThreatLists()
131 for entry in threatLists:
132 threatList = ThreatList.fromApiEntry(entry)
133 if self.__platforms is None or \
134 threatList.platformType in self.__platforms:
135 self.__cache.addThreatList(threatList)
136 key = repr(threatList)
137 if key in threatListsForRemove:
138 del threatListsForRemove[key]
139 for threatList in threatListsForRemove.values():
140 self.__cache.deleteHashPrefixList(threatList)
141 self.__cache.deleteThreatList(threatList)
142 del threatListsForRemove
143
144 # step 3: update threats
145 threatLists = self.__cache.getThreatLists()
146 clientStates = {}
147 for threatList, clientState in threatLists:
148 clientStates[threatList.asTuple()] = clientState
149 threatsUpdateResponses = \
150 self.__apiClient.getThreatsUpdate(clientStates)
151 for response in threatsUpdateResponses:
152 responseThreatList = ThreatList.fromApiEntry(response)
153 if response["responseType"] == "FULL_UPDATE":
154 self.__cache.deleteHashPrefixList(responseThreatList)
155 for removal in response.get("removals", []):
156 self.__cache.removeHashPrefixIndices(
157 responseThreatList, removal["rawIndices"]["indices"])
158 for addition in response.get("additions", []):
159 hashPrefixList = HashPrefixList(
160 addition["rawHashes"]["prefixSize"],
161 base64.b64decode(addition["rawHashes"]["rawHashes"]))
162 self.__cache.populateHashPrefixList(responseThreatList,
163 hashPrefixList)
164 expectedChecksum = base64.b64decode(response["checksum"]["sha256"])
165 if self.__verifyThreatListChecksum(responseThreatList,
166 expectedChecksum):
167 self.__cache.updateThreatListClientState(
168 responseThreatList, response["newClientState"])
169 else:
170 return False, \
171 self.tr("Local cache checksum does not match the server."
172 " Consider cleaning the cache. Threat update has"
173 " been aborted.")
174
175 return True, ""
176
177 def __verifyThreatListChecksum(self, threatList, remoteChecksum):
178 """
179 Private method to verify the local checksum of a threat list with the
180 checksum of the safe browsing server.
181 """
182 localChecksum = self.__cache.hashPrefixListChecksum(threatList)
183 return remoteChecksum == localChecksum
184
185 def fullCacheCleanup(self):
186 """
187 Public method to clean up the cache completely.
188 """
189 self.__cache.prepareCacheDb()
190
191 def showSafeBrowsingDialog(self):
192 """
193 Public slot to show the safe browsing management dialog.
194 """
195 if self.__gsbDialog is None:
196 from WebBrowser.WebBrowserWindow import WebBrowserWindow
197 from .SafeBrowsingDialog import SafeBrowsingDialog
198 self.__gsbDialog = SafeBrowsingDialog(
199 self, parent=WebBrowserWindow.mainWindow())
200
201 self.__gsbDialog.show()

eric ide

mercurial