Fri, 19 Feb 2016 19:55:56 +0100
Continued porting the web browser.
- added the Flash Cookies manager
--- a/Preferences/__init__.py Fri Feb 19 19:55:27 2016 +0100 +++ b/Preferences/__init__.py Fri Feb 19 19:55:56 2016 +0100 @@ -55,9 +55,12 @@ ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \ OthersBrowserFlag, AllBrowsersFlag -from Helpviewer.FlashCookieManager.FlashCookieUtilities import \ - flashDataPathForOS - +try: + from Helpviewer.FlashCookieManager.FlashCookieUtilities import \ + flashDataPathForOS +except ImportError: + from WebBrowser.FlashCookieManager.FlashCookieUtilities import \ + flashDataPathForOS class Prefs(object): """ @@ -1022,6 +1025,13 @@ "WebSearchKeywords": [], # array of two tuples (keyword, # search engine name) "SearchLanguage": QLocale().language(), + # Flash Cookie Manager + "FlashCookiesDeleteOnStartExit": False, + "FlashCookieAutoRefresh": False, + "FlashCookieNotify": False, + "FlashCookiesWhitelist": [], + "FlashCookiesBlacklist": [], + "FlashCookiesDataPath": flashDataPathForOS(), } @classmethod @@ -2672,7 +2682,7 @@ ## elif key in ["DownloadManagerDownloads"]: ## # return a list of tuples of (URL, save location, done flag, page url) ## downloads = [] -## length = prefClass.settings.beginReadArray("Help/" + key) +## length = prefClass.settings.beginReadArray("WebBrowser/" + key) ## for index in range(length): ## prefClass.settings.setArrayIndex(index) ## url = prefClass.settings.value("URL") @@ -2687,7 +2697,7 @@ ## elif key == "RssFeeds": ## # return a list of tuples of (URL, title, icon) ## feeds = [] -## length = prefClass.settings.beginReadArray("Help/" + key) +## length = prefClass.settings.beginReadArray("WebBrowser/" + key) ## for index in range(length): ## prefClass.settings.setArrayIndex(index) ## url = prefClass.settings.value("URL") @@ -2699,11 +2709,11 @@ ## elif key in ["SyncFtpPassword", "SyncEncryptionKey"]: ## from Utilities.crypto import pwConvert ## return pwConvert(prefClass.settings.value( -## "Help/" + key, prefClass.helpDefaults[key]), encode=False) +## "WebBrowser/" + key, prefClass.helpDefaults[key]), encode=False) ## elif key == "HelpViewerType": ## # special treatment to adjust for missing QtWebKit ## value = int(prefClass.settings.value( -## "Help/" + key, prefClass.helpDefaults[key])) +## "WebBrowser/" + key, prefClass.helpDefaults[key])) ## if QWebSettings is None: ## value = prefClass.helpDefaults[key] ## return value @@ -2748,6 +2758,8 @@ "LocalContentCanAccessFileUrls", "XSSAuditingEnabled", "ScrollAnimatorEnabled", "ErrorPageEnabled", "WarnOnMultipleClose", "WebSearchSuggestions", + "FlashCookiesDeleteOnStartExit", "FlashCookieAutoRefresh", + "FlashCookieNotify", ]: return toBool(prefClass.settings.value( "WebBrowser/" + key, prefClass.webBrowserDefaults[key])) @@ -2756,8 +2768,10 @@ ## "GreaseMonkeyDisabledScripts", "NoCacheHosts", ## "FlashCookiesWhitelist", "FlashCookiesBlacklist", ## ]: -## return toList(prefClass.settings.value( -## "Help/" + key, prefClass.helpDefaults[key])) + elif key in ["FlashCookiesWhitelist", "FlashCookiesBlacklist", + ]: + return toList(prefClass.settings.value( + "WebBrowser/" + key, prefClass.helpDefaults[key])) else: return prefClass.settings.value("WebBrowser/" + key, prefClass.webBrowserDefaults[key]) @@ -2789,7 +2803,7 @@ ## elif key == "DownloadManagerDownloads": ## # value is list of tuples of (URL, save location, done flag, page url) ## prefClass.settings.remove("Help/" + key) -## prefClass.settings.beginWriteArray("Help/" + key, len(value)) +## prefClass.settings.beginWriteArray("WebBrowser/" + key, len(value)) ## index = 0 ## for v in value: ## prefClass.settings.setArrayIndex(index) @@ -2801,7 +2815,7 @@ ## prefClass.settings.endArray() ## elif key == "RssFeeds": ## # value is list of tuples of (URL, title, icon) -## prefClass.settings.remove("Help/" + key) +## prefClass.settings.remove("WebBrowser/" + key) ## prefClass.settings.beginWriteArray("Help/" + key, len(value)) ## index = 0 ## for v in value: @@ -2814,7 +2828,7 @@ ## elif key in ["SyncFtpPassword", "SyncEncryptionKey"]: ## from Utilities.crypto import pwConvert ## prefClass.settings.setValue( -## "Help/" + key, pwConvert(value, encode=True)) +## "WebBrowser/" + key, pwConvert(value, encode=True)) else: prefClass.settings.setValue("WebBrowser/" + key, value)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookie.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the Flash cookie class. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import QDateTime + + +class FlashCookie(object): + """ + Class implementing the Flash cookie. + """ + def __init__(self): + """ + Constructor + """ + self.name = "" + self.origin = "" + self.size = 0 + self.path = "" + self.contents = "" + self.lastModified = QDateTime() + + def __eq__(self, other): + """ + Special method to compare to another Flash cookie. + + @param other reference to the other Flash cookie + @type FlashCookie + @return flag indicating equality of the two cookies + @rtype bool + """ + return (self.name == other.name and + self.path == other.path)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookieManager.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,363 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the Flash cookie manager. +""" + +from __future__ import unicode_literals + +try: + str = unicode # __IGNORE_EXCEPTION__ +except NameError: + pass + +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.__whitelist = [] # list of str +## self.__blacklist = [] # 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.getHelp("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.getHelp("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.getHelp("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.getHelp("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.getHelp("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.getHelp("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.getHelp("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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to manage the flash cookies. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSlot, Qt, QPoint, QTimer +from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QApplication, QMenu, \ + QInputDialog, QLineEdit + +from E5Gui import E5MessageBox + +from .Ui_FlashCookieManagerDialog import Ui_FlashCookieManagerDialog + +import Preferences +import UI.PixmapCache + + +class FlashCookieManagerDialog(QDialog, Ui_FlashCookieManagerDialog): + """ + Class implementing a dialog to manage the flash cookies. + """ + def __init__(self, manager, parent=None): + """ + Constructor + + @param manager reference to the Flash cookie manager object + @type FlashCookieManager + @param parent reference to the parent widget + @type QWidget + """ + super(FlashCookieManagerDialog, self).__init__(parent) + self.setupUi(self) + self.setWindowFlags(Qt.Window) + + self.cookiesList.setContextMenuPolicy(Qt.CustomContextMenu) + self.cookiesList.customContextMenuRequested.connect( + self.__cookiesListContextMenuRequested) + + self.__manager = manager + + @pyqtSlot() + def on_whiteList_itemSelectionChanged(self): + """ + Private slot handling the selection of items in the whitelist. + """ + enable = len(self.whiteList.selectedItems()) > 0 + self.removeWhiteButton.setEnabled(enable) + + @pyqtSlot() + def on_blackList_itemSelectionChanged(self): + """ + Private slot handling the selection of items in the blacklist. + """ + enable = len(self.blackList.selectedItems()) > 0 + self.removeBlackButton.setEnabled(enable) + + @pyqtSlot() + def on_removeWhiteButton_clicked(self): + """ + Private slot to remove a server from the whitelist. + """ + for itm in self.whiteList.selectedItems(): + row = self.whiteList.row(itm) + self.whiteList.takeItem(row) + del itm + + @pyqtSlot() + def on_addWhiteButton_clicked(self): + """ + Private slot to add a server to the whitelist. + """ + origin, ok = QInputDialog.getText( + self, + self.tr("Add to whitelist"), + self.tr("Origin:"), + QLineEdit.Normal) + if ok and bool(origin): + self.__addWhitelist(origin) + + def __addWhitelist(self, origin): + """ + Private method to add a cookie origin to the whitelist. + + @param origin origin to be added to the list + @type str + """ + if not origin: + return + + if len(self.blackList.findItems(origin, Qt.MatchFixedString)) > 0: + E5MessageBox.information( + self, + self.tr("Add to whitelist"), + self.tr("""The server '{0}' is already in the blacklist.""" + """ Please remove it first.""").format(origin)) + return + + if len(self.whiteList.findItems(origin, Qt.MatchFixedString)) == 0: + self.whiteList.addItem(origin) + + @pyqtSlot() + def on_removeBlackButton_clicked(self): + """ + Private slot to remove a server from the blacklist. + """ + for itm in self.blackList.selectedItems(): + row = self.blackList.row(itm) + self.blackList.takeItem(row) + del itm + + @pyqtSlot() + def on_addBlackButton_clicked(self): + """ + Private slot to add a server to the blacklist. + """ + origin, ok = QInputDialog.getText( + self, + self.tr("Add to blacklist"), + self.tr("Origin:"), + QLineEdit.Normal) + if ok and bool(origin): + self.__addBlacklist(origin) + + def __addBlacklist(self, origin): + """ + Private method to add a cookie origin to the blacklist. + + @param origin origin to be added to the list + @type str + """ + if not origin: + return + + if len(self.whiteList.findItems(origin, Qt.MatchFixedString)) > 0: + E5MessageBox.information( + self, + self.tr("Add to blacklist"), + self.tr("""The server '{0}' is already in the whitelist.""" + """ Please remove it first.""").format(origin)) + return + + if len(self.blackList.findItems(origin, Qt.MatchFixedString)) == 0: + self.blackList.addItem(origin) + + @pyqtSlot(str) + def on_filterEdit_textChanged(self, filter): + """ + Private slot to filter the cookies list. + + @param filter filter text + @type str + """ + if not filter: + # show all in collapsed state + for index in range(self.cookiesList.topLevelItemCount()): + self.cookiesList.topLevelItem(index).setHidden(False) + self.cookiesList.topLevelItem(index).setExpanded(False) + else: + # show matching in expanded state + filter = filter.lower() + for index in range(self.cookiesList.topLevelItemCount()): + txt = "." + self.cookiesList.topLevelItem(index)\ + .text(0).lower() + self.cookiesList.topLevelItem(index).setHidden( + filter not in txt) + self.cookiesList.topLevelItem(index).setExpanded(True) + + @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) + def on_cookiesList_currentItemChanged(self, current, previous): + """ + Private slot handling a change of the current cookie item. + + @param current reference to the current item + @type QTreeWidgetItem + @param previous reference to the previous item + @type QTreeWidgetItem + """ + if current is None: + self.removeButton.setEnabled(False) + return + + cookie = current.data(0, Qt.UserRole) + if cookie is None: + self.nameLabel.setText(self.tr("<no flash cookie selected>")) + self.sizeLabel.setText(self.tr("<no flash cookie selected>")) + self.originLabel.setText(self.tr("<no flash cookie selected>")) + self.modifiedLabel.setText(self.tr("<no flash cookie selected>")) + self.contentsEdit.clear() + self.pathEdit.clear() + self.removeButton.setText(self.tr("Remove Cookie Group")) + else: + suffix = "" + if cookie.path.startswith( + self.__manager.flashPlayerDataPath() + + "/macromedia.com/support/flashplayer/sys"): + suffix = self.tr(" (settings)") + self.nameLabel.setText( + self.tr("{0}{1}", "name and suffix") + .format(cookie.name, suffix)) + self.sizeLabel.setText(self.tr("{0} Byte").format(cookie.size)) + self.originLabel.setText(cookie.origin) + self.modifiedLabel.setText( + cookie.lastModified.toString("yyyy-MM-dd hh:mm:ss")) + self.contentsEdit.setPlainText(cookie.contents) + self.pathEdit.setText(cookie.path) + self.removeButton.setText(self.tr("Remove Cookie")) + self.removeButton.setEnabled(True) + + @pyqtSlot(QPoint) + def __cookiesListContextMenuRequested(self, pos): + """ + Private slot handling the cookies list context menu. + + @param pos position to show the menu at + @type QPoint + """ + itm = self.cookiesList.itemAt(pos) + if itm is None: + return + + menu = QMenu() + addBlacklistAct = menu.addAction(self.tr("Add to blacklist")) + addWhitelistAct = menu.addAction(self.tr("Add to whitelist")) + + self.cookiesList.setCurrentItem(itm) + + activatedAction = menu.exec_( + self.cookiesList.viewport().mapToGlobal(pos)) + if itm.childCount() == 0: + origin = itm.data(0, Qt.UserRole).origin + else: + origin = itm.text(0) + + if activatedAction == addBlacklistAct: + self.__addBlacklist(origin) + elif activatedAction == addWhitelistAct: + self.__addWhitelist(origin) + + @pyqtSlot() + def on_reloadButton_clicked(self): + """ + Private slot handling a press of the reload button. + """ + self.refreshView(True) + + @pyqtSlot() + def on_removeAllButton_clicked(self): + """ + Private slot to remove all cookies. + """ + ok = E5MessageBox.yesNo( + self, + self.tr("Remove All"), + self.tr("""Do you really want to delete all flash cookies on""" + """ your computer?""")) + if ok: + cookies = self.__manager.flashCookies() + for cookie in cookies: + self.__manager.removeCookie(cookie) + + self.cookiesList.clear() + self.__manager.clearNewOrigins() + self.__manager.clearCache() + + @pyqtSlot() + def on_removeButton_clicked(self): + """ + Private slot to remove one cookie or a cookie group. + """ + itm = self.cookiesList.currentItem() + if itm is None: + return + + cookie = itm.data(0, Qt.UserRole) + if cookie is None: + # remove a whole cookie group + origin = itm.text(0) + cookieList = self.__manager.flashCookies() + for fcookie in cookieList: + if fcookie.origin == origin: + self.__manager.removeCookie(fcookie) + + index = self.cookiesList.indexOfTopLevelItem(itm) + self.cookiesList.takeTopLevelItem(index) + else: + self.__manager.removeCookie(cookie) + parent = itm.parent() + index = parent.indexOfChild(itm) + parent.takeChild(index) + + if parent.childCount() == 0: + # remove origin item as well + index = self.cookiesList.indexOfTopLevelItem(parent) + self.cookiesList.takeTopLevelItem(index) + del parent + del itm + + def refreshView(self, forceReload=False): + """ + Public method to refresh the dialog view. + + @param forceReload flag indicating to reload the cookies + @type bool + """ + blocked = self.filterEdit.blockSignals(True) + self.filterEdit.clear() + self.contentsEdit.clear() + self.filterEdit.blockSignals(blocked) + + if forceReload: + self.__manager.clearCache() + self.__manager.clearNewOrigins() + + QTimer.singleShot(0, self.__refreshCookiesList) + QTimer.singleShot(0, self.__refreshFilterLists) + + def showPage(self, index): + """ + Public method to display a given page. + + @param index index of the page to be shown + @type int + """ + self.cookiesTabWidget.setCurrentIndex(index) + + @pyqtSlot() + def __refreshCookiesList(self): + """ + Private slot to refresh the cookies list. + """ + QApplication.setOverrideCursor(Qt.WaitCursor) + + cookies = self.__manager.flashCookies() + self.cookiesList.clear() + + counter = 0 + originDict = {} + for cookie in cookies: + cookieOrigin = cookie.origin + if cookieOrigin.startswith("."): + cookieOrigin = cookieOrigin[1:] + + if cookieOrigin in originDict: + itm = QTreeWidgetItem(originDict[cookieOrigin]) + else: + newParent = QTreeWidgetItem(self.cookiesList) + newParent.setText(0, cookieOrigin) + newParent.setIcon(0, UI.PixmapCache.getIcon("dirOpen.png")) + self.cookiesList.addTopLevelItem(newParent) + originDict[cookieOrigin] = newParent + + itm = QTreeWidgetItem(newParent) + + suffix = "" + if cookie.path.startswith( + self.__manager.flashPlayerDataPath() + + "/macromedia.com/support/flashplayer/sys"): + suffix = self.tr(" (settings)") + + if cookie.path + "/" + cookie.name in \ + self.__manager.newCookiesList(): + suffix += self.tr(" [new]") + font = itm.font(0) + font.setBold(True) + itm.setFont(font) + itm.parent().setExpanded(True) + + itm.setText(0, self.tr("{0}{1}", "name and suffix").format( + cookie.name, suffix)) + itm.setData(0, Qt.UserRole, cookie) + + counter += 1 + if counter > 100: + QApplication.processEvents() + counter = 0 + + self.removeAllButton.setEnabled( + self.cookiesList.topLevelItemCount() > 0) + self.removeButton.setEnabled(False) + + QApplication.restoreOverrideCursor() + + @pyqtSlot() + def __refreshFilterLists(self): + """ + Private slot to refresh the white and black lists. + """ + self.whiteList.clear() + self.blackList.clear() + + self.whiteList.addItems(Preferences.getHelp("FlashCookiesWhitelist")) + self.blackList.addItems(Preferences.getHelp("FlashCookiesBlacklist")) + + self.on_whiteList_itemSelectionChanged() + self.on_blackList_itemSelectionChanged() + + def closeEvent(self, evt): + """ + Protected method to handle the close event. + + @param evt reference to the close event + @type QCloseEvent + """ + self.__manager.clearNewOrigins() + + whiteList = [] + for row in range(self.whiteList.count()): + whiteList.append(self.whiteList.item(row).text()) + + blackList = [] + for row in range(self.blackList.count()): + blackList.append(self.blackList.item(row).text()) + + Preferences.setHelp("FlashCookiesWhitelist", whiteList) + Preferences.setHelp("FlashCookiesBlacklist", blackList) + + evt.accept()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookieManagerDialog.ui Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,478 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>FlashCookieManagerDialog</class> + <widget class="QDialog" name="FlashCookieManagerDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>550</width> + <height>500</height> + </rect> + </property> + <property name="windowTitle"> + <string>Flash Cookie Management</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="cookiesTabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Stored Flash Cookies</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Filter:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="filterEdit"> + <property name="toolTip"> + <string>Enter cookie filter string</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QLabel" name="label_24"> + <property name="text"> + <string>Stored Flash Cookies:</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QTreeWidget" name="cookiesList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <column> + <property name="text"> + <string>Origin</string> + </property> + </column> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>158</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="reloadButton"> + <property name="toolTip"> + <string>Press to reload Flash cookies from disk</string> + </property> + <property name="text"> + <string>Reload</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Name:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="nameLabel"> + <property name="text"> + <string><no flash cookie selected></string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelSize_2"> + <property name="text"> + <string>Size:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="sizeLabel"> + <property name="text"> + <string><no flash cookie selected></string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Origin:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="originLabel"> + <property name="text"> + <string><no flash cookie selected></string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_22"> + <property name="text"> + <string>Last Modified:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="modifiedLabel"> + <property name="text"> + <string><no flash cookie selected></string> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Contents:</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QPlainTextEdit" name="contentsEdit"> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + <property name="lineWrapMode"> + <enum>QPlainTextEdit::NoWrap</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Path:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="pathEdit"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="removeAllButton"> + <property name="toolTip"> + <string>Press to remove all flash cookies</string> + </property> + <property name="text"> + <string>Remove All Cookies</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeButton"> + <property name="toolTip"> + <string>Press to remove selected flash cookies</string> + </property> + <property name="text"> + <string>Remove Cookie</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Flash Cookies Lists</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string><b>Flash cookie whitelist</b></string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string><b>Flash cookie blacklist</b></string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Flash cookies from these origins will not be deleted automatically. (Also detection of them will not be notified to user.)</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Flash cookies from these origins will be deleted without any notification.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QListWidget" name="whiteList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QListWidget" name="blackList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="removeWhiteButton"> + <property name="toolTip"> + <string>Press to remove selected origins from the whitelist</string> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addWhiteButton"> + <property name="toolTip"> + <string>Press to add an origin to the whitelist</string> + </property> + <property name="text"> + <string>Add...</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="3" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="removeBlackButton"> + <property name="toolTip"> + <string>Press to remove selected origins from the blacklist</string> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addBlackButton"> + <property name="toolTip"> + <string>Press to add an origin to the blacklist</string> + </property> + <property name="text"> + <string>Add...</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>cookiesTabWidget</tabstop> + <tabstop>filterEdit</tabstop> + <tabstop>cookiesList</tabstop> + <tabstop>reloadButton</tabstop> + <tabstop>contentsEdit</tabstop> + <tabstop>pathEdit</tabstop> + <tabstop>removeAllButton</tabstop> + <tabstop>removeButton</tabstop> + <tabstop>whiteList</tabstop> + <tabstop>removeWhiteButton</tabstop> + <tabstop>addWhiteButton</tabstop> + <tabstop>blackList</tabstop> + <tabstop>removeBlackButton</tabstop> + <tabstop>addBlackButton</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>FlashCookieManagerDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>FlashCookieManagerDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookieNotification.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the feature permission bar widget. +""" + +from __future__ import unicode_literals + +from PyQt5.QtWidgets import QLabel, QHBoxLayout, QPushButton + +from E5Gui.E5AnimatedWidget import E5AnimatedWidget + +import UI.PixmapCache + + +class FlashCookieNotification(E5AnimatedWidget): + """ + Class implementing the feature permission bar widget. + """ + DefaultHeight = 30 + + def __init__(self, view, manager, noCookies): + """ + Constructor + + @param view reference to the web view + @type WebBrowserView + @param manager reference to the Flash cookie manager object + @type FlashCookieManager + @param noCookies number of newly detected Flash cookies + @type int + """ + super(FlashCookieNotification, self).__init__(parent=view) + + self.__manager = manager + + if noCookies == 1: + msg = self.tr("A new flash cookie was detected.") + else: + msg = self.tr("{0} new flash cookies were detected.")\ + .format(noCookies) + self.setAutoFillBackground(True) + self.__layout = QHBoxLayout() + self.setLayout(self.__layout) + self.__layout.setContentsMargins(9, 0, 0, 0) + self.__iconLabel = QLabel(self) + self.__iconLabel.setPixmap(UI.PixmapCache.getPixmap("flashCookie.png")) + self.__layout.addWidget(self.__iconLabel) + self.__messageLabel = QLabel(msg, self) + self.__layout.addWidget(self.__messageLabel) + self.__viewButton = QPushButton(self.tr("View"), self) + self.__layout.addWidget(self.__viewButton) + self.__layout.addStretch() + self.__discardButton = QPushButton(UI.PixmapCache.getIcon("close.png"), + "", self) + self.__layout.addWidget(self.__discardButton) + + self.__viewButton.clicked.connect(manager.showFlashCookieManagerDialog) + self.__viewButton.clicked.connect(self.hide) + self.__discardButton.clicked.connect(self.hide) + + self.resize(view.width(), self.height()) + self.startAnimation()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookieReader.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,474 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a class to read flash cookies. +""" + +# +# Note: The code is based on s2x.py +# + +from __future__ import unicode_literals + +import struct +import io + +from PyQt5.QtCore import QDateTime + + +class FlashCookieReaderError(Exception): + """ + Class containing data of a reader error. + """ + def __init__(self, msg): + """ + Constructor + + @param msg error message + @type str + """ + self.msg = msg + + +class FlashCookieReader(object): + """ + Class implementing a reader for flash cookies (*.sol files). + """ + Number = b'\x00' + Boolean = b'\x01' + String = b'\x02' + ObjObj = b'\x03' + Null = b'\x05' + Undef = b'\x06' + ObjArr = b'\x08' + ObjDate = b'\x0B' + ObjM = b'\x0D' + ObjXml = b'\x0F' + ObjCc = b'\x10' + + EpochCorrectionMsecs = 31 * 24 * 60 * 60 * 1000 + # Flash Epoch starts at 1969-12-01 + + def __init__(self): + """ + Constructor + """ + self.__result = {} + # dictionary with element name as key and tuple of + # type and value as value + self.__data = None + self.__parsed = False + + def setBytes(self, solData): + """ + Public method to set the contents of a sol file to be parsed. + + @param solData contents of the file + @type bytes + """ + self.__data = io.BytesIO(solData) + + def setFileName(self, solFilename): + """ + Public method to set the name of a sol file to be parsed. + + @param solFilename name of the sol file + @type str + """ + self.__data = open(solFilename, "rb") + + def setFile(self, solFile): + """ + Public method to set an open sol file to be parsed. + + @param solFile sol file to be parsed + @type io.FileIO + """ + self.__data = solFile + + def parse(self): + """ + Public method to parse the sol file. + + @exception FlashCookieReaderError raised when encountering a parse + issue + """ + if self.__data is None: + return + + self.__data.seek(0, 2) + lenSolData = self.__data.tell() + self.__data.seek(0) + self.__data.read(2) + sLenData = self.__data.read(4) + lenData, = struct.unpack(">L", sLenData) # unsigned long, big-endian + if lenSolData != lenData + 6: + raise FlashCookieReaderError( + "Flash cookie data lengths don't match\n" + " file length: {0}\n" + " data length: {1}" + .format(lenSolData - 6, lenData)) + sDataType = self.__data.read(4).decode("utf-8") # 'TCSO' + if sDataType != "TCSO": + raise FlashCookieReaderError( + "Flash cookie type is not 'TCSO'; found '{0}'." + .format(sDataType)) + self.__data.read(6) + lenSolName, = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + solName = self.__data.read(lenSolName) + solName = solName.decode("utf-8", "replace") + self.__result["SolName"] = ("string", solName) + self.__data.read(4) + while self.__data.tell() < lenSolData: + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + variableName = self.__data.read(lenVariableName) + variableName = variableName.decode("utf-8", "replace") + variableType = self.__data.read(1) + if len(variableType): + if variableType == self.Number: + self.__parseNumber(variableName, self.__result) + elif variableType == self.Boolean: + self.__parseBoolean(variableName, self.__result) + elif variableType == self.String: + self.__parseString(variableName, self.__result) + elif variableType == self.ObjObj: + self.__parseObject(variableName, self.__result) + elif variableType == self.ObjArr: + self.__parseArray(variableName, self.__result) + elif variableType == self.ObjDate: + self.__parseDate(variableName, self.__result) + elif variableType == self.ObjXml: + self.__parseXml(variableName, self.__result) + elif variableType == self.ObjCc: + self.__parseOcc(variableName, self.__result) + elif variableType == self.ObjM: + self.__parseOjm(variableName, self.__result) + elif variableType == self.Null: + self.__parseNull(variableName, self.__result) + elif variableType == self.Undef: + self.__parseUndefined(variableName, self.__result) + else: + raise FlashCookieReaderError( + "Unexpected Data Type: " + hex(ord(variableType))) + self.__data.read(1) # '\x00' + self.__data.close() + self.__parsed = True + + def __parseNumber(self, variableName, parent): + """ + Private method to parse a number. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + b = self.__data.read(8) + if b == b"\x7F\xF0\x00\x00\x00\x00\x00\x00": + value = "Infinity" + elif b == b"\xFF\xF0\x00\x00\x00\x00\x00\x00": + value = "-Infinity" + elif b == b"\x7F\xF8\x00\x00\x00\x00\x00\x00": + value = "NaN" + else: + value, = struct.unpack(">d", b) # double, big-endian + value = str(value) + parent[variableName] = ("number", value) + + def __parseBoolean(self, variableName, parent): + """ + Private method to parse a boolean. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + b = self.__data.read(1) + if b == b"\x00": + value = "False" + elif b == b"\x01": + value = "True" + else: + # boolean value error; default to True + value = "True" + parent[variableName] = ("boolean", value) + + def __parseString(self, variableName, parent): + """ + Private method to parse a string. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + lenStr, = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + b = self.__data.read(lenStr) + value = b.decode("utf-8", "replace") + parent[variableName] = ("string", value) + + def __parseDate(self, variableName, parent): + """ + Private method to parse a date. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + msec, = struct.unpack(">d", self.__data.read(8)) + # double, big-endian + # DateObject: Milliseconds Count From Dec. 1, 1969 + msec -= self.EpochCorrectionMsecs # correct for Unix epoch + minOffset, = struct.unpack(">h", self.__data.read(2)) + # short, big-endian + offset = minOffset // 60 # offset in hours + # Timezone: UTC + Offset + value = QDateTime() + value.setMSecsSinceEpoch(msec) + value.setOffsetFromUtc(offset * 3600) + parent[variableName] = ("date", + value.toString("yyyy-MM-dd HH:mm:ss t")) + + def __parseXml(self, variableName, parent): + """ + Private method to parse XML. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + lenCData, = struct.unpack(">L", self.__data.read(4)) + # unsigned long, big-endian + cData = self.__data.read(lenCData) + value = cData.decode("utf-8", "replace") + parent[variableName] = ("xml", value) + + def __parseOjm(self, variableName, parent): + """ + Private method to parse an m_object. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + parent[variableName] = ("m_object", "") + + def __parseNull(self, variableName, parent): + """ + Private method to parse a null object. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + parent[variableName] = ("null", "") + + def __parseUndefined(self, variableName, parent): + """ + Private method to parse an undefined object. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + """ + parent[variableName] = ("undefined", "") + + def __parseObject(self, variableName, parent): + """ + Private method to parse an object. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + @exception FlashCookieReaderError raised when an issue with the cookie + file is found + """ + value = {} + parent[variableName] = ("object", value) + + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + while lenVariableName != 0: + variableName = self.__data.read(lenVariableName) + variableName = variableName.decode("utf-8", "replace") + variableType = self.__data.read(1) + if variableType == self.Number: + self.__parseNumber(variableName, value) + elif variableType == self.Boolean: + self.__parseBoolean(variableName, value) + elif variableType == self.String: + self.__parseString(variableName, value) + elif variableType == self.ObjObj: + self.__parseObject(variableName, value) + elif variableType == self.ObjArr: + self.__parseArray(variableName, value) + elif variableType == self.ObjDate: + self.__parseDate(variableName, value) + elif variableType == self.ObjXml: + self.__parseXml(variableName, value) + elif variableType == self.ObjCc: + self.__parseOcc(variableName, value) + elif variableType == self.ObjM: + self.__parseOjm(variableName, value) + elif variableType == self.Null: + self.__parseNull(variableName, value) + elif variableType == self.Undef: + self.__parseUndefined(variableName, value) + else: + raise FlashCookieReaderError( + "Unexpected Data Type: " + hex(ord(variableType))) + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + self.__data.read(1) # '\x09' + + def __parseArray(self, variableName, parent): + """ + Private method to parse an array. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + @exception FlashCookieReaderError raised when an issue with the cookie + file is found + """ + arrayLength, = struct.unpack(">L", self.__data.read(4)) + # unsigned long, big-endian + + value = {} + parent[variableName] = ("array; length={0}".format(arrayLength), value) + + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + while lenVariableName != 0: + variableName = self.__data.read(lenVariableName) + variableName = variableName.decode("utf-8", "replace") + variableType = self.__data.read(1) + if variableType == self.Number: + self.__parseNumber(variableName, value) + elif variableType == self.Boolean: + self.__parseBoolean(variableName, value) + elif variableType == self.String: + self.__parseString(variableName, value) + elif variableType == self.ObjObj: + self.__parseObject(variableName, value) + elif variableType == self.ObjArr: + self.__parseArray(variableName, value) + elif variableType == self.ObjDate: + self.__parseDate(variableName, value) + elif variableType == self.ObjXml: + self.__parseXml(variableName, value) + elif variableType == self.ObjCc: + self.__parseOcc(variableName, value) + elif variableType == self.ObjM: + self.__parseOjm(variableName, value) + elif variableType == self.Null: + self.__parseNull(variableName, value) + elif variableType == self.Undef: + self.__parseUndefined(variableName, value) + else: + raise FlashCookieReaderError( + "Unexpected Data Type: " + hex(ord(variableType))) + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + self.__data.read(1) # '\x09' + + def __parseOcc(self, variableName, parent): + """ + Private method to parse a c_object. + + @param variableName name of the variable to be parsed + @type str + @param parent reference to the dictionary to insert the result into + @type dict + @exception FlashCookieReaderError raised when an issue with the cookie + file is found + """ + lenCname = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + cname = self.__data.read(lenCname) + cname = cname.decode("utf-8", "replace") + + value = {} + parent[variableName] = ("c_object; cname={0}".format(cname), value) + + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + # unsigned short, big-endian + while lenVariableName != 0: + variableName = self.__data.read(lenVariableName) + variableName = variableName.decode("utf-8", "replace") + variableType = self.__data.read(1) + if variableType == self.Number: + self.__parseNumber(variableName, value) + elif variableType == self.Boolean: + self.__parseBoolean(variableName, value) + elif variableType == self.String: + self.__parseString(variableName, value) + elif variableType == self.ObjObj: + self.__parseObject(variableName, value) + elif variableType == self.ObjArr: + self.__parseArray(variableName, value) + elif variableType == self.ObjDate: + self.__parseDate(variableName, value) + elif variableType == self.ObjXml: + self.__parseXml(variableName, value) + elif variableType == self.ObjCc: + self.__parseOcc(variableName, value) + elif variableType == self.ObjM: + self.__parseOjm(variableName, value) + elif variableType == self.Null: + self.__parseNull(variableName, value) + elif variableType == self.Undef: + self.__parseUndefined(variableName, value) + else: + raise FlashCookieReaderError( + "Unexpected Data Type: " + hex(ord(variableType))) + lenVariableName, = struct.unpack(">H", self.__data.read(2)) + self.__data.read(1) # '\x09' + + def toString(self, indent=0, parent=None): + """ + Public method to convert the parsed cookie to a string representation. + + @param indent indentation level + @type int + @param parent reference to the dictionary to be converted + @type dict + @return string representation of the cookie + @rtype str + """ + indentStr = " " * indent + strArr = [] + + if parent is None: + parent = self.__result + + if not parent: + return "" + + for variableName in sorted(parent.keys()): + variableType, value = parent[variableName] + if isinstance(value, dict): + resultStr = self.toString(indent + 1, value) + if resultStr: + strArr.append("{0}{1}:\n{2}" + .format(indentStr, variableName, resultStr)) + else: + strArr.append("{0}{1}:" + .format(indentStr, variableName)) + else: + strArr.append("{0}{1}: {2}" + .format(indentStr, variableName, value)) + + return "\n".join(strArr)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/FlashCookieUtilities.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing some utility functions. +""" + +from __future__ import unicode_literals + +import os + +from PyQt5.QtCore import QProcessEnvironment + +import Globals + + +def flashDataPathForOS(): + """ + Function to determine the OS dependent path where Flash cookies + are stored. + + @return Flash data path + @rtype str + """ + # On Microsoft Windows NT 5.x and 6.x, they are stored in: + # %APPDATA%\Macromedia\Flash Player\#SharedObjects\ + # %APPDATA%\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys\ + # On Mac OS X, they are stored in: + # ~/Library/Preferences/Macromedia/Flash Player/#SharedObjects/ + # ~/Library/Preferences/Macromedia/Flash Player/macromedia.com/support/⏎ + # flashplayer/sys/ + # On Linux or Unix, they are stored in: + # ~/.macromedia/Flash_Player/#SharedObjects/ + # ~/.macromedia/Flash_Player/macromedia.com/support/flashplayer/sys/ + # For Linux and Unix systems, if the open-source Gnash plugin is being used + # instead of the official Adobe Flash, they will instead be found at: + # ~/.gnash/SharedObjects/ + + flashPath = "" + + if Globals.isWindowsPlatform(): + appData = QProcessEnvironment.systemEnvironment().value("APPDATA") + appData = appData.replace("\\", "/") + flashPath = appData + "/Macromedia/Flash Player" + elif Globals.isMacPlatform(): + flashPath = os.path.expanduser( + "~/Library/Preferences/Macromedia/Flash Player") + else: + if os.path.exists(os.path.expanduser("~/.macromedia")): + flashPath = os.path.expanduser("~/.macromedia/Flash_Player") + elif os.path.exists(os.path.expanduser("~/.gnash")): + flashPath = os.path.expanduser("~/.gnash") + + return flashPath
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/FlashCookieManager/__init__.py Fri Feb 19 19:55:56 2016 +0100 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the Flash cookie manager and associated objects. +"""
--- a/WebBrowser/Passwords/PasswordManager.py Fri Feb 19 19:55:27 2016 +0100 +++ b/WebBrowser/Passwords/PasswordManager.py Fri Feb 19 19:55:56 2016 +0100 @@ -381,7 +381,6 @@ if not self.__loaded: self.__load() - # TODO: change this to include postData progress = E5ProgressDialog( self.tr("Re-encoding saved passwords..."), None, 0, len(self.__logins) + len(self.__loginForms),
--- a/WebBrowser/WebBrowserWindow.py Fri Feb 19 19:55:27 2016 +0100 +++ b/WebBrowser/WebBrowserWindow.py Fri Feb 19 19:55:56 2016 +0100 @@ -97,7 +97,7 @@ ## _greaseMonkeyManager = None _notification = None _featurePermissionManager = None -## _flashCookieManager = None + _flashCookieManager = None def __init__(self, home, path, parent, name, fromEric=False, initShortcutsOnly=False, searchWord=None, @@ -1282,21 +1282,20 @@ ## self.__showCookiesConfiguration) ## self.__actions.append(self.cookiesAct) - # TODO: Flash Cookies -## self.flashCookiesAct = E5Action( -## self.tr('Flash Cookies'), -## UI.PixmapCache.getIcon("flashCookie.png"), -## self.tr('&Flash Cookies...'), 0, 0, self, 'webbrowser_flash_cookies') -## self.flashCookiesAct.setStatusTip(self.tr( -## 'Manage flash cookies')) -## self.flashCookiesAct.setWhatsThis(self.tr( -## """<b>Flash Cookies</b>""" -## """<p>Show a dialog to manage the flash cookies.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.flashCookiesAct.triggered.connect( -## self.__showFlashCookiesManagement) -## self.__actions.append(self.flashCookiesAct) + self.flashCookiesAct = E5Action( + self.tr('Flash Cookies'), + UI.PixmapCache.getIcon("flashCookie.png"), + self.tr('&Flash Cookies...'), 0, 0, self, 'webbrowser_flash_cookies') + self.flashCookiesAct.setStatusTip(self.tr( + 'Manage flash cookies')) + self.flashCookiesAct.setWhatsThis(self.tr( + """<b>Flash Cookies</b>""" + """<p>Show a dialog to manage the flash cookies.</p>""" + )) + if not self.__initShortcutsOnly: + self.flashCookiesAct.triggered.connect( + self.__showFlashCookiesManagement) + self.__actions.append(self.flashCookiesAct) # TODO: Offline Storage ## self.offlineStorageAct = E5Action( @@ -1856,7 +1855,7 @@ menu.addAction(self.prefAct) ## menu.addAction(self.acceptedLanguagesAct) ## menu.addAction(self.cookiesAct) -## menu.addAction(self.flashCookiesAct) + menu.addAction(self.flashCookiesAct) ## menu.addAction(self.offlineStorageAct) ## menu.addAction(self.personalDataAct) ## menu.addAction(self.greaseMonkeyAct) @@ -1996,7 +1995,7 @@ settingstb.addAction(self.prefAct) ## settingstb.addAction(self.acceptedLanguagesAct) ## settingstb.addAction(self.cookiesAct) -## settingstb.addAction(self.flashCookiesAct) + settingstb.addAction(self.flashCookiesAct) ## settingstb.addAction(self.offlineStorageAct) ## settingstb.addAction(self.personalDataAct) ## settingstb.addAction(self.greaseMonkeyAct) @@ -2849,11 +2848,11 @@ ## dlg = CookiesConfigurationDialog(self) ## dlg.exec_() -## def __showFlashCookiesManagement(self): -## """ -## Private slot to show the flash cookies management dialog. -## """ -## self.flashCookieManager().showFlashCookieManagerDialog() + def __showFlashCookiesManagement(self): + """ + Private slot to show the flash cookies management dialog. + """ + self.flashCookieManager().showFlashCookieManagerDialog() ## def __showOfflineStorageConfiguration(self): ## """ @@ -3323,20 +3322,8 @@ ## for securityOrigin in QWebSecurityOrigin.allOrigins(): ## for database in securityOrigin.databases(): ## QWebDatabase.removeDatabase(database) - # TODO: Flash Cookie Manager -## if flashCookies: -## from .HelpLanguagesDialog import HelpLanguagesDialog -## languages = Preferences.toList( -## Preferences.Prefs.settings.value( -## "Help/AcceptLanguages", -## HelpLanguagesDialog.defaultAcceptLanguages())) -## if languages: -## language = languages[0] -## langCode = language.split("[")[1][:2] -## self.newTab( -## "http://www.macromedia.com/support/documentation/" -## "{0}/flashplayer/help/settings_manager07.html".format( -## langCode)) + if flashCookies: + self.flashCookieManager().removeAllCookies() if zoomValues: ZoomManager.instance().clear() @@ -3603,21 +3590,21 @@ return cls._featurePermissionManager -## @classmethod -## def flashCookieManager(cls): -## """ -## Class method to get a reference to the flash cookies manager. -## -## @return reference to the flash cookies manager -## @rtype FlashCookieManager -## """ -## if cls._flashCookieManager is None: -## from .FlashCookieManager.FlashCookieManager import \ -## FlashCookieManager -## cls._flashCookieManager = FlashCookieManager() -## -## return cls._flashCookieManager -## + @classmethod + def flashCookieManager(cls): + """ + Class method to get a reference to the flash cookies manager. + + @return reference to the flash cookies manager + @rtype FlashCookieManager + """ + if cls._flashCookieManager is None: + from .FlashCookieManager.FlashCookieManager import \ + FlashCookieManager + cls._flashCookieManager = FlashCookieManager() + + return cls._flashCookieManager + @classmethod def mainWindow(cls): """
--- a/eric6.e4p Fri Feb 19 19:55:27 2016 +0100 +++ b/eric6.e4p Fri Feb 19 19:55:56 2016 +0100 @@ -1293,6 +1293,13 @@ <Source>WebBrowser/FeaturePermissions/FeaturePermissionManager.py</Source> <Source>WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py</Source> <Source>WebBrowser/FeaturePermissions/__init__.py</Source> + <Source>WebBrowser/FlashCookieManager/FlashCookie.py</Source> + <Source>WebBrowser/FlashCookieManager/FlashCookieManager.py</Source> + <Source>WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py</Source> + <Source>WebBrowser/FlashCookieManager/FlashCookieNotification.py</Source> + <Source>WebBrowser/FlashCookieManager/FlashCookieReader.py</Source> + <Source>WebBrowser/FlashCookieManager/FlashCookieUtilities.py</Source> + <Source>WebBrowser/FlashCookieManager/__init__.py</Source> <Source>WebBrowser/History/HistoryCompleter.py</Source> <Source>WebBrowser/History/HistoryDialog.py</Source> <Source>WebBrowser/History/HistoryFilterModel.py</Source> @@ -1753,6 +1760,7 @@ <Form>WebBrowser/Bookmarks/BookmarksDialog.ui</Form> <Form>WebBrowser/Bookmarks/BookmarksImportDialog.ui</Form> <Form>WebBrowser/FeaturePermissions/FeaturePermissionsDialog.ui</Form> + <Form>WebBrowser/FlashCookieManager/FlashCookieManagerDialog.ui</Form> <Form>WebBrowser/History/HistoryDialog.ui</Form> <Form>WebBrowser/OpenSearch/OpenSearchDialog.ui</Form> <Form>WebBrowser/OpenSearch/OpenSearchEditDialog.ui</Form>