Wed, 01 Jan 2020 11:57:23 +0100
Updated copyright for 2020.
# -*- coding: utf-8 -*- # Copyright (c) 2015 - 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the Flash cookie manager. """ import shutil from PyQt5.QtCore import QObject, QTimer, QDir, QFileInfo, QFile from .FlashCookie import FlashCookie from .FlashCookieReader import FlashCookieReader, FlashCookieReaderError import WebBrowser.WebBrowserWindow import Preferences class FlashCookieManager(QObject): """ Class implementing the Flash cookie manager object. """ RefreshInterval = 60 * 1000 def __init__(self, parent=None): """ Constructor @param parent reference to the parent object @type QObject """ super(FlashCookieManager, self).__init__(parent) self.__flashCookieManagerDialog = None self.__flashCookies = [] # list of FlashCookie self.__newCookiesList = [] # list of str self.__timer = QTimer(self) self.__timer.setInterval(FlashCookieManager.RefreshInterval) self.__timer.timeout.connect(self.__autoRefresh) # start the timer if needed self.__startStopTimer() if Preferences.getWebBrowser("FlashCookiesDeleteOnStartExit"): self.__loadFlashCookies() self.__removeAllButWhitelisted() def shutdown(self): """ Public method to perform shutdown actions. """ if self.__flashCookieManagerDialog is not None: self.__flashCookieManagerDialog.close() if Preferences.getWebBrowser("FlashCookiesDeleteOnStartExit"): self.__removeAllButWhitelisted() def setFlashCookies(self, cookies): """ Public method to set the list of cached Flash cookies. @param cookies list of Flash cookies to store @type list of FlashCookie """ self.__flashCookies = cookies[:] def flashCookies(self): """ Public method to get the list of cached Flash cookies. @return list of Flash cookies @rtype list of FlashCookie """ if not self.__flashCookies: self.__loadFlashCookies() return self.__flashCookies[:] def newCookiesList(self): """ Public method to get the list of newly detected Flash cookies. @return list of newly detected Flash cookies @rtype list of str """ return self.__newCookiesList[:] def clearNewOrigins(self): """ Public method to clear the list of newly detected Flash cookies. """ self.__newCookiesList = [] def clearCache(self): """ Public method to clear the list of cached Flash cookies. """ self.__flashCookies = [] def __isBlacklisted(self, cookie): """ Private method to check for a blacklisted cookie. @param cookie Flash cookie to be tested @type FlashCookie @return flag indicating a blacklisted cookie @rtype bool """ return ( cookie.origin in Preferences.getWebBrowser("FlashCookiesBlacklist") ) def __isWhitelisted(self, cookie): """ Private method to check for a whitelisted cookie. @param cookie Flash cookie to be tested @type FlashCookie @return flag indicating a whitelisted cookie @rtype bool """ return ( cookie.origin in Preferences.getWebBrowser("FlashCookiesWhitelist") ) def __removeAllButWhitelisted(self): """ Private method to remove all non-whitelisted cookies. """ for cookie in self.__flashCookies[:]: if not self.__isWhitelisted(cookie): self.removeCookie(cookie) def removeAllCookies(self): """ Public method to remove all flash cookies. """ for cookie in self.__flashCookies[:]: self.removeCookie(cookie) self.clearNewOrigins() self.clearCache() def __sharedObjectDirName(self): """ Private slot to determine the path of the shared data objects. @return path of the shared data objects @rtype str """ if ( "macromedia" in self.flashPlayerDataPath().lower() or "/.gnash" not in self.flashPlayerDataPath().lower() ): return "/#SharedObjects/" else: return "/SharedObjects/" def flashPlayerDataPath(self): """ Public method to get the Flash Player data path. @return Flash Player data path @rtype str """ return Preferences.getWebBrowser("FlashCookiesDataPath") def preferencesChanged(self): """ Public slot to handle a change of preferences. """ self.__startStopTimer() def removeCookie(self, cookie): """ Public method to remove a cookie of the list of cached cookies. @param cookie Flash cookie to be removed @type FlashCookie """ if cookie in self.__flashCookies: self.__flashCookies.remove(cookie) shutil.rmtree(cookie.path, True) def __autoRefresh(self): """ Private slot to refresh the list of cookies. """ if ( self.__flashCookieManagerDialog and self.__flashCookieManagerDialog.isVisible() ): return oldFlashCookies = self.__flashCookies[:] self.__loadFlashCookies() newCookieList = [] for cookie in self.__flashCookies[:]: if self.__isBlacklisted(cookie): self.removeCookie(cookie) continue if self.__isWhitelisted(cookie): continue newCookie = True for oldCookie in oldFlashCookies: if (oldCookie.path + oldCookie.name == cookie.path + cookie.name): newCookie = False break if newCookie: newCookieList.append(cookie.path + "/" + cookie.name) if newCookieList and Preferences.getWebBrowser("FlashCookieNotify"): self.__newCookiesList.extend(newCookieList) win = WebBrowser.WebBrowserWindow.WebBrowserWindow.mainWindow() if win is None: return view = win.currentBrowser() if view is None: return from .FlashCookieNotification import FlashCookieNotification notification = FlashCookieNotification( view, self, len(newCookieList)) notification.show() def showFlashCookieManagerDialog(self): """ Public method to show the Flash cookies management dialog. """ if self.__flashCookieManagerDialog is None: from .FlashCookieManagerDialog import FlashCookieManagerDialog self.__flashCookieManagerDialog = FlashCookieManagerDialog(self) self.__flashCookieManagerDialog.refreshView() self.__flashCookieManagerDialog.showPage(0) self.__flashCookieManagerDialog.show() self.__flashCookieManagerDialog.raise_() def __startStopTimer(self): """ Private slot to start or stop the auto refresh timer. """ if Preferences.getWebBrowser("FlashCookieAutoRefresh"): if not self.__timer.isActive(): if not bool(self.__flashCookies): self.__loadFlashCookies() self.__timer.start() else: self.__timer.stop() def __loadFlashCookies(self): """ Private slot to load the Flash cookies to be cached. """ self.__flashCookies = [] self.__loadFlashCookiesFromPath(self.flashPlayerDataPath()) def __loadFlashCookiesFromPath(self, path): """ Private slot to load the Flash cookies from a path. @param path Flash cookies path @type str """ if path.endswith("#AppContainer"): # specific to IE and Windows return path = path.replace("\\", "/") solDir = QDir(path) entryList = solDir.entryList() for entry in entryList: if entry == "." or entry == "..": continue entryInfo = QFileInfo(path + "/" + entry) if entryInfo.isDir(): self.__loadFlashCookiesFromPath(entryInfo.filePath()) else: self.__insertFlashCookie(entryInfo.filePath()) def __insertFlashCookie(self, path): """ Private method to insert a Flash cookie into the cache. @param path Flash cookies path @type str """ solFile = QFile(path) if not solFile.open(QFile.ReadOnly): return dataStr = "" data = bytes(solFile.readAll()) if data: try: reader = FlashCookieReader() reader.setBytes(data) reader.parse() dataStr = reader.toString() except FlashCookieReaderError as err: dataStr = err.msg solFileInfo = QFileInfo(solFile) cookie = FlashCookie() cookie.contents = dataStr cookie.name = solFileInfo.fileName() cookie.path = solFileInfo.canonicalPath() cookie.size = int(solFile.size()) cookie.lastModified = solFileInfo.lastModified() cookie.origin = self.__extractOriginFrom(path) self.__flashCookies.append(cookie) def __extractOriginFrom(self, path): """ Private method to extract the cookie origin given its file name. @param path file name of the cookie file @type str @return cookie origin @rtype str """ origin = path if path.startswith( self.flashPlayerDataPath() + self.__sharedObjectDirName()): origin = origin.replace( self.flashPlayerDataPath() + self.__sharedObjectDirName(), "") if "/" in origin: origin = origin.split("/", 1)[1] elif path.startswith( self.flashPlayerDataPath() + "/macromedia.com/support/flashplayer/sys/"): origin = origin.replace( self.flashPlayerDataPath() + "/macromedia.com/support/flashplayer/sys/", "") if origin == "settings.sol": return self.tr("!default") elif origin.startswith("#"): origin = origin[1:] else: origin = "" index = origin.find("/") if index == -1: return self.tr("!other") origin = origin[:index] if origin in ["localhost", "local"]: origin = "!localhost" return origin