src/eric7/WebBrowser/SafeBrowsing/SafeBrowsingCache.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9473
3f23dbf37dbe
--- a/src/eric7/WebBrowser/SafeBrowsing/SafeBrowsingCache.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/WebBrowser/SafeBrowsing/SafeBrowsingCache.py	Wed Jul 13 14:55:47 2022 +0200
@@ -17,7 +17,11 @@
 import os
 
 from PyQt6.QtCore import (
-    QObject, QByteArray, QCryptographicHash, QCoreApplication, QEventLoop
+    QObject,
+    QByteArray,
+    QCryptographicHash,
+    QCoreApplication,
+    QEventLoop,
 )
 from PyQt6.QtSql import QSql, QSqlDatabase, QSqlQuery
 
@@ -28,6 +32,7 @@
     """
     Class implementing a cache for Google Safe Browsing.
     """
+
     create_threat_list_stmt = """
         CREATE TABLE threat_list
         (threat_type character varying(128) NOT NULL,
@@ -39,7 +44,7 @@
         )
     """
     drop_threat_list_stmt = """DROP TABLE IF EXISTS threat_list"""
-    
+
     create_full_hashes_stmt = """
         CREATE TABLE full_hash
         (value BLOB NOT NULL,
@@ -54,7 +59,7 @@
         )
     """
     drop_full_hashes_stmt = """DROP TABLE IF EXISTS full_hash"""
-    
+
     create_hash_prefix_stmt = """
         CREATE TABLE hash_prefix
         (value BLOB NOT NULL,
@@ -72,49 +77,49 @@
         )
     """
     drop_hash_prefix_stmt = """DROP TABLE IF EXISTS hash_prefix"""
-    
+
     create_full_hash_cue_idx = """
         CREATE INDEX idx_hash_prefix_cue ON hash_prefix (cue)
     """
     drop_full_hash_cue_idx = """DROP INDEX IF EXISTS idx_hash_prefix_cue"""
-    
+
     create_full_hash_expires_idx = """
         CREATE INDEX idx_full_hash_expires_at ON full_hash (expires_at)
     """
     drop_full_hash_expires_idx = """
         DROP INDEX IF EXISTS idx_full_hash_expires_at
     """
-    
+
     create_full_hash_value_idx = """
         CREATE INDEX idx_full_hash_value ON full_hash (value)
     """
     drop_full_hash_value_idx = """DROP INDEX IF EXISTS idx_full_hash_value"""
-    
+
     maxProcessEventsTime = 500
-    
+
     def __init__(self, dbPath, parent=None):
         """
         Constructor
-        
+
         @param dbPath path to store the cache DB into
         @type str
         @param parent reference to the parent object
         @type QObject
         """
         super().__init__(parent)
-        
+
         self.__connectionName = "SafeBrowsingCache"
-        
+
         if not os.path.exists(dbPath):
             os.makedirs(dbPath)
-        
+
         self.__dbFileName = os.path.join(dbPath, "SafeBrowsingCache.db")
         preparationNeeded = not os.path.exists(self.__dbFileName)
-        
+
         self.__openCacheDb()
         if preparationNeeded:
             self.prepareCacheDb()
-    
+
     def close(self):
         """
         Public method to close the database.
@@ -122,11 +127,11 @@
         if QSqlDatabase.database(self.__connectionName).isOpen():
             QSqlDatabase.database(self.__connectionName).close()
             QSqlDatabase.removeDatabase(self.__connectionName)
-    
+
     def __openCacheDb(self):
         """
         Private method to open the cache database.
-        
+
         @return flag indicating the open state
         @rtype bool
         """
@@ -141,7 +146,7 @@
         else:
             opened = True
         return opened
-    
+
     def prepareCacheDb(self):
         """
         Public method to prepare the cache database.
@@ -169,12 +174,12 @@
         finally:
             del query
             db.commit()
-    
+
     def lookupFullHashes(self, hashValues):
         """
         Public method to get a list of threat lists and expiration flag
         for the given hashes if a hash is blacklisted.
-        
+
         @param hashValues list of hash values to look up
         @type list of bytes
         @return list of tuples containing the threat list info and the
@@ -187,42 +192,42 @@
             FROM full_hash WHERE value IN ({0})
         """
         output = []
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
             try:
                 query = QSqlQuery(db)
-                query.prepare(
-                    queryStr.format(",".join(["?"] * len(hashValues))))
+                query.prepare(queryStr.format(",".join(["?"] * len(hashValues))))
                 for hashValue in hashValues:
                     query.addBindValue(
                         QByteArray(hashValue),
-                        QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary)
-                
+                        QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary,
+                    )
+
                 query.exec()
-                
-                while query.next():             # __IGNORE_WARNING_M523__
+
+                while query.next():  # __IGNORE_WARNING_M523__
                     threatType = query.value(0)
                     platformType = query.value(1)
                     threatEntryType = query.value(2)
                     hasExpired = bool(query.value(3))
-                    threatList = ThreatList(threatType, platformType,
-                                            threatEntryType)
+                    threatList = ThreatList(threatType, platformType, threatEntryType)
                     output.append((threatList, hasExpired))
                     QCoreApplication.processEvents(
                         QEventLoop.ProcessEventsFlag.AllEvents,
-                        self.maxProcessEventsTime)
+                        self.maxProcessEventsTime,
+                    )
                 del query
             finally:
                 db.commit()
-        
+
         return output
-    
+
     def lookupHashPrefix(self, prefixes):
         """
         Public method to look up hash prefixes in the local cache.
-        
+
         @param prefixes list of hash prefixes to look up
         @type list of bytes
         @return list of tuples containing the threat list, full hash and
@@ -235,42 +240,40 @@
             FROM hash_prefix WHERE cue IN ({0})
         """
         output = []
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
             try:
                 query = QSqlQuery(db)
-                query.prepare(
-                    queryStr.format(",".join(["?"] * len(prefixes))))
+                query.prepare(queryStr.format(",".join(["?"] * len(prefixes))))
                 for prefix in prefixes:
                     query.addBindValue(prefix)
-                
+
                 query.exec()
-                
-                while query.next():             # __IGNORE_WARNING_M523__
+
+                while query.next():  # __IGNORE_WARNING_M523__
                     fullHash = bytes(query.value(0))
                     threatType = query.value(1)
                     platformType = query.value(2)
                     threatEntryType = query.value(3)
                     negativeCacheExpired = bool(query.value(4))
-                    threatList = ThreatList(threatType, platformType,
-                                            threatEntryType)
+                    threatList = ThreatList(threatType, platformType, threatEntryType)
                     output.append((threatList, fullHash, negativeCacheExpired))
                     QCoreApplication.processEvents(
                         QEventLoop.ProcessEventsFlag.AllEvents,
-                        self.maxProcessEventsTime)
+                        self.maxProcessEventsTime,
+                    )
                 del query
             finally:
                 db.commit()
-        
+
         return output
-    
-    def storeFullHash(self, threatList, hashValue, cacheDuration,
-                      malwareThreatType):
+
+    def storeFullHash(self, threatList, hashValue, cacheDuration, malwareThreatType):
         """
         Public method to store full hash data in the cache database.
-        
+
         @param threatList threat list info object
         @type ThreatList
         @param hashValue hash to be stored
@@ -287,15 +290,15 @@
             VALUES
                 (?, ?, ?, ?, ?, current_timestamp)
         """
-        updateQueryStr = (
-            """
+        updateQueryStr = """
             UPDATE full_hash SET
             expires_at=datetime(current_timestamp, '+{0} SECONDS')
             WHERE value=? AND threat_type=? AND platform_type=? AND
             threat_entry_type=?
-            """.format(int(cacheDuration))
+            """.format(
+            int(cacheDuration)
         )
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -304,19 +307,21 @@
                 query.prepare(insertQueryStr)
                 query.addBindValue(
                     QByteArray(hashValue),
-                    QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary)
+                    QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary,
+                )
                 query.addBindValue(threatList.threatType)
                 query.addBindValue(threatList.platformType)
                 query.addBindValue(threatList.threatEntryType)
                 query.addBindValue(malwareThreatType)
                 query.exec()
                 del query
-                
+
                 query = QSqlQuery(db)
                 query.prepare(updateQueryStr)
                 query.addBindValue(
                     QByteArray(hashValue),
-                    QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary)
+                    QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary,
+                )
                 query.addBindValue(threatList.threatType)
                 query.addBindValue(threatList.platformType)
                 query.addBindValue(threatList.threatEntryType)
@@ -324,11 +329,11 @@
                 del query
             finally:
                 db.commit()
-    
+
     def deleteHashPrefixList(self, threatList):
         """
         Public method to delete hash prefixes for a given threat list.
-        
+
         @param threatList threat list info object
         @type ThreatList
         """
@@ -336,7 +341,7 @@
             DELETE FROM hash_prefix
                 WHERE threat_type=? AND platform_type=? AND threat_entry_type=?
         """
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -350,22 +355,22 @@
                 del query
             finally:
                 db.commit()
-    
+
     def cleanupFullHashes(self, keepExpiredFor=43200):
         """
         Public method to clean up full hash entries expired more than the
         given time.
-        
+
         @param keepExpiredFor time period in seconds of entries to be expired
         @type int or float
         """
-        queryStr = (
-            """
+        queryStr = """
             DELETE FROM full_hash
             WHERE expires_at=datetime(current_timestamp, '{0} SECONDS')
-            """.format(int(keepExpiredFor))
+            """.format(
+            int(keepExpiredFor)
         )
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -376,12 +381,11 @@
                 del query
             finally:
                 db.commit()
-    
-    def updateHashPrefixExpiration(self, threatList, hashPrefix,
-                                   negativeCacheDuration):
+
+    def updateHashPrefixExpiration(self, threatList, hashPrefix, negativeCacheDuration):
         """
         Public method to update the hash prefix expiration time.
-        
+
         @param threatList threat list info object
         @type ThreatList
         @param hashPrefix hash prefix
@@ -390,15 +394,15 @@
             in the cache
         @type int or float
         """
-        queryStr = (
-            """
+        queryStr = """
             UPDATE hash_prefix
             SET negative_expires_at=datetime(current_timestamp, '+{0} SECONDS')
             WHERE value=? AND threat_type=? AND platform_type=? AND
             threat_entry_type=?
-            """.format(int(negativeCacheDuration))
+            """.format(
+            int(negativeCacheDuration)
         )
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -407,7 +411,8 @@
                 query.prepare(queryStr)
                 query.addBindValue(
                     QByteArray(hashPrefix),
-                    QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary)
+                    QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary,
+                )
                 query.addBindValue(threatList.threatType)
                 query.addBindValue(threatList.platformType)
                 query.addBindValue(threatList.threatEntryType)
@@ -415,11 +420,11 @@
                 del query
             finally:
                 db.commit()
-    
+
     def getThreatLists(self):
         """
         Public method to get the available threat lists.
-        
+
         @return list of available threat lists
         @rtype list of tuples of (ThreatList, str)
         """
@@ -428,37 +433,37 @@
             FROM threat_list
         """
         output = []
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
             try:
                 query = QSqlQuery(db)
                 query.prepare(queryStr)
-                
+
                 query.exec()
-                
-                while query.next():             # __IGNORE_WARNING_M523__
+
+                while query.next():  # __IGNORE_WARNING_M523__
                     threatType = query.value(0)
                     platformType = query.value(1)
                     threatEntryType = query.value(2)
                     clientState = query.value(3)
-                    threatList = ThreatList(threatType, platformType,
-                                            threatEntryType)
+                    threatList = ThreatList(threatType, platformType, threatEntryType)
                     output.append((threatList, clientState))
                     QCoreApplication.processEvents(
                         QEventLoop.ProcessEventsFlag.AllEvents,
-                        self.maxProcessEventsTime)
+                        self.maxProcessEventsTime,
+                    )
                 del query
             finally:
                 db.commit()
-        
+
         return output
-    
+
     def addThreatList(self, threatList):
         """
         Public method to add a threat list to the cache.
-        
+
         @param threatList threat list to be added
         @type ThreatList
         """
@@ -467,7 +472,7 @@
                 (threat_type, platform_type, threat_entry_type, timestamp)
             VALUES (?, ?, ?, current_timestamp)
         """
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -481,11 +486,11 @@
                 del query
             finally:
                 db.commit()
-    
+
     def deleteThreatList(self, threatList):
         """
         Public method to delete a threat list from the cache.
-        
+
         @param threatList threat list to be deleted
         @type ThreatList
         """
@@ -493,7 +498,7 @@
             DELETE FROM threat_list
                 WHERE threat_type=? AND platform_type=? AND threat_entry_type=?
         """
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -507,11 +512,11 @@
                 del query
             finally:
                 db.commit()
-    
+
     def updateThreatListClientState(self, threatList, clientState):
         """
         Public method to update the client state of a threat list.
-        
+
         @param threatList threat list to update the client state for
         @type ThreatList
         @param clientState new client state
@@ -521,7 +526,7 @@
             UPDATE threat_list SET timestamp=current_timestamp, client_state=?
             WHERE threat_type=? AND platform_type=? AND threat_entry_type=?
         """
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -536,12 +541,12 @@
                 del query
             finally:
                 db.commit()
-    
+
     def hashPrefixListChecksum(self, threatList):
         """
         Public method to calculate the SHA256 checksum for an alphabetically
         sorted concatenated list of hash prefixes.
-        
+
         @param threatList threat list to calculate checksum for
         @type ThreatList
         @return SHA256 checksum
@@ -553,38 +558,38 @@
                 ORDER BY value
         """
         checksum = None
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
-            sha256Hash = QCryptographicHash(
-                QCryptographicHash.Algorithm.Sha256)
+            sha256Hash = QCryptographicHash(QCryptographicHash.Algorithm.Sha256)
             try:
                 query = QSqlQuery(db)
                 query.prepare(queryStr)
                 query.addBindValue(threatList.threatType)
                 query.addBindValue(threatList.platformType)
                 query.addBindValue(threatList.threatEntryType)
-                
+
                 query.exec()
-                
-                while query.next():             # __IGNORE_WARNING_M523__
+
+                while query.next():  # __IGNORE_WARNING_M523__
                     sha256Hash.addData(query.value(0))
                     QCoreApplication.processEvents(
                         QEventLoop.ProcessEventsFlag.AllEvents,
-                        self.maxProcessEventsTime)
+                        self.maxProcessEventsTime,
+                    )
                 del query
             finally:
                 db.commit()
-            
+
             checksum = bytes(sha256Hash.result())
-        
+
         return checksum
-    
+
     def populateHashPrefixList(self, threatList, prefixes):
         """
         Public method to populate the hash prefixes for a threat list.
-        
+
         @param threatList threat list of the hash prefixes
         @type ThreatList
         @param prefixes list of hash prefixes to be inserted
@@ -596,7 +601,7 @@
                  timestamp)
                 VALUES (?, ?, ?, ?, ?, current_timestamp)
         """
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -606,7 +611,8 @@
                     query.prepare(queryStr)
                     query.addBindValue(
                         QByteArray(prefix),
-                        QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary)
+                        QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary,
+                    )
                     query.addBindValue(prefix[:4].hex())
                     query.addBindValue(threatList.threatType)
                     query.addBindValue(threatList.platformType)
@@ -615,15 +621,16 @@
                     del query
                     QCoreApplication.processEvents(
                         QEventLoop.ProcessEventsFlag.AllEvents,
-                        self.maxProcessEventsTime)
+                        self.maxProcessEventsTime,
+                    )
             finally:
                 db.commit()
-    
+
     def getHashPrefixValuesToRemove(self, threatList, indexes):
         """
         Public method to get the hash prefix values to be removed from the
         cache.
-        
+
         @param threatList threat list to remove prefixes from
         @type ThreatList
         @param indexes list of indexes of prefixes to be removed
@@ -638,7 +645,7 @@
         """
         indexes = set(indexes)
         output = []
-        
+
         db = QSqlDatabase.database(self.__connectionName)
         if db.isOpen():
             db.transaction()
@@ -648,54 +655,50 @@
                 query.addBindValue(threatList.threatType)
                 query.addBindValue(threatList.platformType)
                 query.addBindValue(threatList.threatEntryType)
-                
+
                 query.exec()
-                
+
                 index = 0
-                while query.next():         # __IGNORE_WARNING_M523__
+                while query.next():  # __IGNORE_WARNING_M523__
                     if index in indexes:
                         prefix = bytes(query.value(0))
                         output.append(prefix)
                     index += 1
                     QCoreApplication.processEvents(
                         QEventLoop.ProcessEventsFlag.AllEvents,
-                        self.maxProcessEventsTime)
+                        self.maxProcessEventsTime,
+                    )
                 del query
             finally:
                 db.commit()
-        
+
         return output
-    
+
     def removeHashPrefixIndices(self, threatList, indexes):
         """
         Public method to remove hash prefixes from the cache.
-        
+
         @param threatList threat list to delete hash prefixes of
         @type ThreatList
         @param indexes list of indexes of prefixes to be removed
         @type list of int
         """
-        queryStr = (
-            """
+        queryStr = """
             DELETE FROM hash_prefix
             WHERE threat_type=? AND platform_type=? AND
             threat_entry_type=? AND value IN ({0})
             """
-        )
         batchSize = 40
-        
-        prefixesToRemove = self.getHashPrefixValuesToRemove(
-            threatList, indexes)
+
+        prefixesToRemove = self.getHashPrefixValuesToRemove(threatList, indexes)
         if prefixesToRemove:
             db = QSqlDatabase.database(self.__connectionName)
             if db.isOpen():
                 db.transaction()
                 try:
                     for index in range(0, len(prefixesToRemove), batchSize):
-                        removeBatch = prefixesToRemove[
-                            index:(index + batchSize)
-                        ]
-                        
+                        removeBatch = prefixesToRemove[index : (index + batchSize)]
+
                         query = QSqlQuery(db)
                         query.prepare(
                             queryStr.format(",".join(["?"] * len(removeBatch)))
@@ -706,15 +709,17 @@
                         for prefix in removeBatch:
                             query.addBindValue(
                                 QByteArray(prefix),
-                                QSql.ParamTypeFlag.In |
-                                QSql.ParamTypeFlag.Binary)
+                                QSql.ParamTypeFlag.In | QSql.ParamTypeFlag.Binary,
+                            )
                         query.exec()
                         del query
                         QCoreApplication.processEvents(
                             QEventLoop.ProcessEventsFlag.AllEvents,
-                            self.maxProcessEventsTime)
+                            self.maxProcessEventsTime,
+                        )
                 finally:
                     db.commit()
 
+
 #
 # eflag: noqa = S608

eric ide

mercurial