Tue, 11 Aug 2015 19:49:05 +0200
Continued adding code for a Flash cookie manager.
--- a/Helpviewer/FlashCookieManager/FlashCookieManager.py Mon Aug 10 19:54:54 2015 +0200 +++ b/Helpviewer/FlashCookieManager/FlashCookieManager.py Tue Aug 11 19:49:05 2015 +0200 @@ -19,6 +19,7 @@ from PyQt5.QtCore import QObject, QTimer, QDir, QFileInfo, QFile from .FlashCookie import FlashCookie +from .FlashCookieReader import FlashCookieReader, FlashCookieReaderError import Helpviewer.HelpWindow @@ -259,7 +260,7 @@ @param path Flash cookies path @type str """ - if path.endswith(("#SharedObjects", "#AppContainer")): + if path.endswith("#AppContainer"): # specific to IE and Windows return @@ -286,15 +287,16 @@ if not solFile.open(QFile.ReadOnly): return - # TODO: dissect the flash cookie (see gnash s2x.py for example) - data = bytearray(solFile.readAll()) - for i in range(len(data)): - if not ((data[i] >= ord("a") and data[i] <= ord("z")) or - (data[i] >= ord("A") and data[i] <= ord("Z")) or - (data[i] >= ord("0") and data[i] <= ord("9"))): - data[i] = 32 - dataStr = str(data, "utf-8", "replace") - dataStr = "\n".join([s for s in dataStr.split(".") if s]) + 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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Helpviewer/FlashCookieManager/FlashCookieManagerDialog.py Tue Aug 11 19:49:05 2015 +0200 @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to manage the flash cookies. +""" + +from PyQt5.QtCore import pyqtSlot, Qt, QPoint, QTimer +from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QApplication + +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): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_blackList_itemSelectionChanged(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_removeWhiteButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_addWhiteButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_removeBlackButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_addBlackButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot(str) + def on_filterEdit_textChanged(self, p0): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) + def on_cookiesList_currentItemChanged(self, current, previous): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_cookiesList_itemSelectionChanged(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot(QPoint) + def __cookiesListContextMenuRequested(self, point): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_reloadButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_removeAllButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_removeButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + 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(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, cookie.name + suffix) + itm.setData(0, Qt.UserRole, cookie) + + counter += 1 + if counter > 100: + QApplication.processEvents() + counter = 0 + + 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"))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Helpviewer/FlashCookieManager/FlashCookieManagerDialog.ui Tue Aug 11 19:49:05 2015 +0200 @@ -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>450</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 Cookies</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>
--- a/Helpviewer/FlashCookieManager/FlashCookieReader.py Mon Aug 10 19:54:54 2015 +0200 +++ b/Helpviewer/FlashCookieManager/FlashCookieReader.py Tue Aug 11 19:49:05 2015 +0200 @@ -106,7 +106,11 @@ sLenData = self.__data.read(4) lenData, = struct.unpack(">L", sLenData) # unsigned long, big-endian if lenSolData != lenData + 6: - print("Warning: data length doesn't match.") + 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( @@ -168,7 +172,7 @@ value = "Infinity" elif b == b"\xFF\xF0\x00\x00\x00\x00\x00\x00": value = "-Infinity" - elif value == b"\x7F\xF8\x00\x00\x00\x00\x00\x00": + elif b == b"\x7F\xF8\x00\x00\x00\x00\x00\x00": value = "NaN" else: value, = struct.unpack(">d", b) # double, big-endian @@ -425,3 +429,39 @@ "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)
--- a/Helpviewer/FlashCookieManager/FlashCookieUtilities.py Mon Aug 10 19:54:54 2015 +0200 +++ b/Helpviewer/FlashCookieManager/FlashCookieUtilities.py Tue Aug 11 19:49:05 2015 +0200 @@ -25,7 +25,7 @@ @rtype str """ # On Microsoft Windows NT 5.x and 6.x, they are stored in: - # %APPDATA%\Macromedia\Flash Player\#SharedObjects\ + # %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/
--- a/eric6.e4p Mon Aug 10 19:54:54 2015 +0200 +++ b/eric6.e4p Tue Aug 11 19:49:05 2015 +0200 @@ -314,6 +314,7 @@ <Source>Helpviewer/Feeds/__init__.py</Source> <Source>Helpviewer/FlashCookieManager/FlashCookie.py</Source> <Source>Helpviewer/FlashCookieManager/FlashCookieManager.py</Source> + <Source>Helpviewer/FlashCookieManager/FlashCookieManagerDialog.py</Source> <Source>Helpviewer/FlashCookieManager/FlashCookieNotification.py</Source> <Source>Helpviewer/FlashCookieManager/FlashCookieReader.py</Source> <Source>Helpviewer/FlashCookieManager/FlashCookieUtilities.py</Source> @@ -1309,6 +1310,7 @@ <Form>Helpviewer/Feeds/FeedEditDialog.ui</Form> <Form>Helpviewer/Feeds/FeedsDialog.ui</Form> <Form>Helpviewer/Feeds/FeedsManager.ui</Form> + <Form>Helpviewer/FlashCookieManager/FlashCookieManagerDialog.ui</Form> <Form>Helpviewer/GreaseMonkey/GreaseMonkeyAddScriptDialog.ui</Form> <Form>Helpviewer/GreaseMonkey/GreaseMonkeyConfiguration/GreaseMonkeyConfigurationDialog.ui</Form> <Form>Helpviewer/GreaseMonkey/GreaseMonkeyConfiguration/GreaseMonkeyConfigurationScriptInfoDialog.ui</Form>