Sun, 09 Aug 2015 17:18:21 +0200
Started adding code for a Flash cookie manager.
--- a/Globals/compatibility_fixes.py Sun Aug 09 17:01:36 2015 +0200 +++ b/Globals/compatibility_fixes.py Sun Aug 09 17:18:21 2015 +0200 @@ -10,7 +10,7 @@ should throw a NotImplementedError exception. """ -import __builtin__ +import __builtin__ # __IGNORE_EXCEPTION__ import codecs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Helpviewer/FlashCookieManager/FlashCookie.py Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 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/Helpviewer/FlashCookieManager/FlashCookieManager.py Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,348 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 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 + +import Helpviewer.HelpWindow + +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 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 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 __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 = Helpviewer.HelpWindow.HelpWindow.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(("#SharedObjects", "#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 + + # 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]) + + 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/Helpviewer/FlashCookieManager/FlashCookieNotification.py Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 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 QWebView + @param 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/Helpviewer/FlashCookieManager/FlashCookieUtilities.py Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 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/Helpviewer/FlashCookieManager/__init__.py Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the Flash cookie manager and associated objects. +"""
--- a/Helpviewer/HelpWindow.py Sun Aug 09 17:01:36 2015 +0200 +++ b/Helpviewer/HelpWindow.py Sun Aug 09 17:18:21 2015 +0200 @@ -89,6 +89,7 @@ _greaseMonkeyManager = None _notification = None _featurePermissionManager = None + _flashCookieManager = None def __init__(self, home, path, parent, name, fromEric=False, initShortcutsOnly=False, searchWord=None): @@ -287,11 +288,17 @@ self.__previewer = None self.__shutdownCalled = False + self.flashCookieManager() + if self.useQtHelp: QTimer.singleShot(0, self.__lookForNewDocumentation) if self.__searchWord is not None: QTimer.singleShot(0, self.__searchForWord) + self.__lastActiveWindow = None + e5App().focusChanged[QWidget, QWidget].connect( + self.__appFocusChanged) + QTimer.singleShot(0, syncMgr.loadSettings) def __del__(self): @@ -2230,6 +2237,8 @@ self.__virusTotal.close() + self.flashCookieManager().shutdown() + self.searchEdit.openSearchManager().close() if self.useQtHelp: @@ -3301,6 +3310,21 @@ return cls._featurePermissionManager @classmethod + def flashCookieManager(cls): + """ + Class method to get a reference to the flash cookies manager. + + @return reference to the feature permission manager + @rtype FlashCookieManager + """ + if cls._flashCookieManager is None: + from .FlashCookieManager.FlashCookieManager import \ + FlashCookieManager + cls._flashCookieManager = FlashCookieManager() + + return cls._flashCookieManager + + @classmethod def mainWindow(cls): """ Class method to get a reference to the main window. @@ -3321,6 +3345,28 @@ """ return cls.helpwindows + def __appFocusChanged(self, old, now): + """ + Private slot to handle a change of the focus. + + @param old reference to the widget, that lost focus (QWidget or None) + @param now reference to the widget having the focus (QWidget or None) + """ + if isinstance(now, HelpWindow): + self.__lastActiveWindow = now + + def getWindow(self): + """ + Public method to get a reference to the most recent active help window. + + @return reference to most recent help window + @rtype HelpWindow + """ + if self.__lastActiveWindow: + return self.__lastActiveWindow + + return self.mainWindow() + def openSearchManager(self): """ Public method to get a reference to the opensearch manager object.
--- a/Preferences/ConfigurationDialog.py Sun Aug 09 17:01:36 2015 +0200 +++ b/Preferences/ConfigurationDialog.py Sun Aug 09 17:18:21 2015 +0200 @@ -59,7 +59,7 @@ """ return self.__pageName - +# TODO: add page for Flash Cookie Manager class ConfigurationWidget(QWidget): """ Class implementing a dialog for the configuration of eric6. @@ -287,6 +287,10 @@ [self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None], + "helpFlashCookieManagerPage": + [self.tr("Flash Cookie Manager"), + "flashCookie16.png", + "HelpFlashCookieManagerPage", "0helpPage", None], "helpViewersPage": [self.tr("Help Viewers"), "preferences-helpviewers.png", @@ -357,6 +361,10 @@ [self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None], + "helpFlashCookieManagerPage": + [self.tr("Flash Cookie Manager"), + "flashCookie16.png", + "HelpFlashCookieManagerPage", "0helpPage", None], "helpVirusTotalPage": [self.tr("VirusTotal Interface"), "virustotal.png", "HelpVirusTotalPage", "0helpPage", None],
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Preferences/ConfigurationPages/HelpFlashCookieManagerPage.py Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the Flash Cookies Manager configuration page. +""" + +from PyQt5.QtCore import pyqtSlot + +from E5Gui.E5Completers import E5DirCompleter +from E5Gui import E5FileDialog + +from .ConfigurationPageBase import ConfigurationPageBase +from .Ui_HelpFlashCookieManagerPage import Ui_HelpFlashCookieManagerPage + +import Preferences +import Utilities +import UI.PixmapCache + + +class HelpFlashCookieManagerPage(ConfigurationPageBase, + Ui_HelpFlashCookieManagerPage): + """ + Class implementing the Flash Cookies Manager configuration page. + """ + def __init__(self): + """ + Constructor + """ + super(HelpFlashCookieManagerPage, self).__init__() + self.setupUi(self) + self.setObjectName("HelpFlashCookieManagerPage") + + self.flashDataPathButton.setIcon(UI.PixmapCache.getIcon("open.png")) + + self.flashDataPathCompleter = E5DirCompleter(self.flashDataPathEdit) + + # set initial values + self.flashDataPathEdit.setText( + Preferences.getHelp("FlashCookiesDataPath")) + self.autoModeGroup.setChecked( + Preferences.getHelp("FlashCookieAutoRefresh")) + self.notificationGroup.setChecked( + Preferences.getHelp("FlashCookieNotify")) + self.deleteGroup.setChecked( + Preferences.getHelp("FlashCookiesDeleteOnStartExit")) + + def save(self): + """ + Public slot to save the Flash Cookies Manager configuration. + """ + Preferences.setHelp("FlashCookiesDataPath", + self.flashDataPathEdit.text()) + Preferences.setHelp("FlashCookieAutoRefresh", + self.autoModeGroup.isChecked()) + Preferences.setHelp("FlashCookieNotify", + self.notificationGroup.isChecked()) + Preferences.setHelp("FlashCookiesDeleteOnStartExit", + self.deleteGroup.isChecked()) + + @pyqtSlot() + def on_flashDataPathButton_clicked(self): + """ + Private slot to handle the flash data path selection. + """ + path = E5FileDialog.getExistingDirectory( + self, + self.tr("Select Flash Cookies Data Path"), + self.flashDataPathEdit.text(), + E5FileDialog.Options(E5FileDialog.ShowDirsOnly)) + + if path: + self.flashDataPathEdit.setText(Utilities.toNativeSeparators(path)) + + +def create(dlg): + """ + Module function to create the configuration page. + + @param dlg reference to the configuration dialog + @return reference to the instantiated page (ConfigurationPageBase) + """ + page = HelpFlashCookieManagerPage() + return page
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Preferences/ConfigurationPages/HelpFlashCookieManagerPage.ui Sun Aug 09 17:18:21 2015 +0200 @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HelpFlashCookieManagerPage</class> + <widget class="QWidget" name="HelpFlashCookieManagerPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>588</width> + <height>419</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="headerLabel"> + <property name="text"> + <string><b>Configure Flash Cookies Manager</b></string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line9"> + <property name="frameShape"> + <enum>QFrame::HLine</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Flash Data Path</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLineEdit" name="flashDataPathEdit"/> + </item> + <item row="0" column="1"> + <widget class="QToolButton" name="flashDataPathButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string><b>Note</b>: You should select the directory that contains #SharedObject as a subfolder.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="autoModeGroup"> + <property name="toolTip"> + <string>Select to activate auto mode</string> + </property> + <property name="title"> + <string>Auto Mode Enabled</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="autoModeLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>The flash data directory will be checked regularly. and flash cookies in blacklist will be deleted automatically.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="notificationGroup"> + <property name="toolTip"> + <string>Select to show a notification upon detection of new flash cookies</string> + </property> + <property name="title"> + <string>Notifications enabled</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="notificationLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>User will be notified for every new flash cookie that is not in blacklist and whitelist.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="deleteGroup"> + <property name="toolTip"> + <string>Select to delete all flash cookies on startup and shutdown</string> + </property> + <property name="title"> + <string>Delete</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="deleteLabel"> + <property name="text"> + <string>Delete all flash cookies on exit/start (except those are in whitelist)</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="label_19"> + <property name="text"> + <string><p><b>Note:</b> These settings are just applied to flash cookies.</p></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>39</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <tabstops> + <tabstop>flashDataPathEdit</tabstop> + <tabstop>flashDataPathButton</tabstop> + <tabstop>autoModeGroup</tabstop> + <tabstop>notificationGroup</tabstop> + <tabstop>deleteGroup</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- a/Preferences/__init__.py Sun Aug 09 17:01:36 2015 +0200 +++ b/Preferences/__init__.py Sun Aug 09 17:18:21 2015 +0200 @@ -48,6 +48,9 @@ ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \ OthersBrowserFlag, AllBrowsersFlag +from Helpviewer.FlashCookieManager.FlashCookieUtilities import \ + flashDataPathForOS + class Prefs(object): """ @@ -889,6 +892,13 @@ "PimSpecial3": "", "PimSpecial4": "", "GreaseMonkeyDisabledScripts": [], + # Flash Cookie Manager + "FlashCookiesDeleteOnStartExit": False, + "FlashCookieAutoRefresh": False, + "FlashCookieNotify": False, + "FlashCookiesWhitelist": [], + "FlashCookiesBlacklist": [], + "FlashCookiesDataPath": flashDataPathForOS(), } @classmethod @@ -2411,13 +2421,17 @@ "SyncHistory", "SyncPasswords", "SyncUserAgents", "SyncSpeedDial", "SyncEncryptData", "SyncEncryptPasswordsOnly", - "WarnOnMultipleClose", "ClickToFlashEnabled" + "WarnOnMultipleClose", "ClickToFlashEnabled", + "FlashCookiesDeleteOnStartExit", "FlashCookieAutoRefresh", + "FlashCookieNotify", ]: return toBool(prefClass.settings.value( "Help/" + key, prefClass.helpDefaults[key])) elif key in ["AdBlockSubscriptions", "AdBlockExceptions", "ClickToFlashWhitelist", "SendRefererWhitelist", - "GreaseMonkeyDisabledScripts", "NoCacheHosts"]: + "GreaseMonkeyDisabledScripts", "NoCacheHosts", + "FlashCookiesWhitelist", "FlashCookiesBlacklist", + ]: return toList(prefClass.settings.value( "Help/" + key, prefClass.helpDefaults[key])) else:
--- a/eric6.e4p Sun Aug 09 17:01:36 2015 +0200 +++ b/eric6.e4p Sun Aug 09 17:18:21 2015 +0200 @@ -26,6 +26,46 @@ <Source>DataViews/PyCoverageDialog.py</Source> <Source>DataViews/PyProfileDialog.py</Source> <Source>DataViews/__init__.py</Source> + <Source>DebugClients/Python/AsyncFile.py</Source> + <Source>DebugClients/Python/AsyncIO.py</Source> + <Source>DebugClients/Python/DCTestResult.py</Source> + <Source>DebugClients/Python/DebugBase.py</Source> + <Source>DebugClients/Python/DebugClient.py</Source> + <Source>DebugClients/Python/DebugClientBase.py</Source> + <Source>DebugClients/Python/DebugClientCapabilities.py</Source> + <Source>DebugClients/Python/DebugClientThreads.py</Source> + <Source>DebugClients/Python/DebugConfig.py</Source> + <Source>DebugClients/Python/DebugProtocol.py</Source> + <Source>DebugClients/Python/DebugThread.py</Source> + <Source>DebugClients/Python/FlexCompleter.py</Source> + <Source>DebugClients/Python/PyProfile.py</Source> + <Source>DebugClients/Python/__init__.py</Source> + <Source>DebugClients/Python/coverage/__init__.py</Source> + <Source>DebugClients/Python/coverage/__main__.py</Source> + <Source>DebugClients/Python/coverage/annotate.py</Source> + <Source>DebugClients/Python/coverage/backward.py</Source> + <Source>DebugClients/Python/coverage/bytecode.py</Source> + <Source>DebugClients/Python/coverage/cmdline.py</Source> + <Source>DebugClients/Python/coverage/codeunit.py</Source> + <Source>DebugClients/Python/coverage/collector.py</Source> + <Source>DebugClients/Python/coverage/config.py</Source> + <Source>DebugClients/Python/coverage/control.py</Source> + <Source>DebugClients/Python/coverage/data.py</Source> + <Source>DebugClients/Python/coverage/debug.py</Source> + <Source>DebugClients/Python/coverage/execfile.py</Source> + <Source>DebugClients/Python/coverage/files.py</Source> + <Source>DebugClients/Python/coverage/html.py</Source> + <Source>DebugClients/Python/coverage/misc.py</Source> + <Source>DebugClients/Python/coverage/parser.py</Source> + <Source>DebugClients/Python/coverage/phystokens.py</Source> + <Source>DebugClients/Python/coverage/report.py</Source> + <Source>DebugClients/Python/coverage/results.py</Source> + <Source>DebugClients/Python/coverage/summary.py</Source> + <Source>DebugClients/Python/coverage/templite.py</Source> + <Source>DebugClients/Python/coverage/version.py</Source> + <Source>DebugClients/Python/coverage/xmlreport.py</Source> + <Source>DebugClients/Python/eric6dbgstub.py</Source> + <Source>DebugClients/Python/getpass.py</Source> <Source>DebugClients/Python3/AsyncFile.py</Source> <Source>DebugClients/Python3/AsyncIO.py</Source> <Source>DebugClients/Python3/DCTestResult.py</Source> @@ -66,46 +106,6 @@ <Source>DebugClients/Python3/coverage/xmlreport.py</Source> <Source>DebugClients/Python3/eric6dbgstub.py</Source> <Source>DebugClients/Python3/getpass.py</Source> - <Source>DebugClients/Python/AsyncFile.py</Source> - <Source>DebugClients/Python/AsyncIO.py</Source> - <Source>DebugClients/Python/DCTestResult.py</Source> - <Source>DebugClients/Python/DebugBase.py</Source> - <Source>DebugClients/Python/DebugClient.py</Source> - <Source>DebugClients/Python/DebugClientBase.py</Source> - <Source>DebugClients/Python/DebugClientCapabilities.py</Source> - <Source>DebugClients/Python/DebugClientThreads.py</Source> - <Source>DebugClients/Python/DebugConfig.py</Source> - <Source>DebugClients/Python/DebugProtocol.py</Source> - <Source>DebugClients/Python/DebugThread.py</Source> - <Source>DebugClients/Python/FlexCompleter.py</Source> - <Source>DebugClients/Python/PyProfile.py</Source> - <Source>DebugClients/Python/__init__.py</Source> - <Source>DebugClients/Python/coverage/__init__.py</Source> - <Source>DebugClients/Python/coverage/__main__.py</Source> - <Source>DebugClients/Python/coverage/annotate.py</Source> - <Source>DebugClients/Python/coverage/backward.py</Source> - <Source>DebugClients/Python/coverage/bytecode.py</Source> - <Source>DebugClients/Python/coverage/cmdline.py</Source> - <Source>DebugClients/Python/coverage/codeunit.py</Source> - <Source>DebugClients/Python/coverage/collector.py</Source> - <Source>DebugClients/Python/coverage/config.py</Source> - <Source>DebugClients/Python/coverage/control.py</Source> - <Source>DebugClients/Python/coverage/data.py</Source> - <Source>DebugClients/Python/coverage/debug.py</Source> - <Source>DebugClients/Python/coverage/execfile.py</Source> - <Source>DebugClients/Python/coverage/files.py</Source> - <Source>DebugClients/Python/coverage/html.py</Source> - <Source>DebugClients/Python/coverage/misc.py</Source> - <Source>DebugClients/Python/coverage/parser.py</Source> - <Source>DebugClients/Python/coverage/phystokens.py</Source> - <Source>DebugClients/Python/coverage/report.py</Source> - <Source>DebugClients/Python/coverage/results.py</Source> - <Source>DebugClients/Python/coverage/summary.py</Source> - <Source>DebugClients/Python/coverage/templite.py</Source> - <Source>DebugClients/Python/coverage/version.py</Source> - <Source>DebugClients/Python/coverage/xmlreport.py</Source> - <Source>DebugClients/Python/eric6dbgstub.py</Source> - <Source>DebugClients/Python/getpass.py</Source> <Source>DebugClients/Ruby/AsyncFile.rb</Source> <Source>DebugClients/Ruby/AsyncIO.rb</Source> <Source>DebugClients/Ruby/Completer.rb</Source> @@ -312,6 +312,11 @@ <Source>Helpviewer/Feeds/FeedsDialog.py</Source> <Source>Helpviewer/Feeds/FeedsManager.py</Source> <Source>Helpviewer/Feeds/__init__.py</Source> + <Source>Helpviewer/FlashCookieManager/FlashCookie.py</Source> + <Source>Helpviewer/FlashCookieManager/FlashCookieManager.py</Source> + <Source>Helpviewer/FlashCookieManager/FlashCookieNotification.py</Source> + <Source>Helpviewer/FlashCookieManager/FlashCookieUtilities.py</Source> + <Source>Helpviewer/FlashCookieManager/__init__.py</Source> <Source>Helpviewer/GreaseMonkey/GreaseMonkeyAddScriptDialog.py</Source> <Source>Helpviewer/GreaseMonkey/GreaseMonkeyConfiguration/GreaseMonkeyConfigurationDialog.py</Source> <Source>Helpviewer/GreaseMonkey/GreaseMonkeyConfiguration/GreaseMonkeyConfigurationListDelegate.py</Source> @@ -766,6 +771,7 @@ <Source>Preferences/ConfigurationPages/GraphicsPage.py</Source> <Source>Preferences/ConfigurationPages/HelpAppearancePage.py</Source> <Source>Preferences/ConfigurationPages/HelpDocumentationPage.py</Source> + <Source>Preferences/ConfigurationPages/HelpFlashCookieManagerPage.py</Source> <Source>Preferences/ConfigurationPages/HelpInterfacePage.py</Source> <Source>Preferences/ConfigurationPages/HelpViewersPage.py</Source> <Source>Preferences/ConfigurationPages/HelpVirusTotalPage.py</Source> @@ -1285,7 +1291,6 @@ <Form>E5Network/E5SslCertificatesInfoDialog.ui</Form> <Form>E5Network/E5SslCertificatesInfoWidget.ui</Form> <Form>Graphics/UMLSceneSizeDialog.ui</Form> - <Form>Helpviewer/FeaturePermissions/FeaturePermissionsDialog.ui</Form> <Form>Helpviewer/AdBlock/AdBlockDialog.ui</Form> <Form>Helpviewer/AdBlock/AdBlockExceptionsDialog.ui</Form> <Form>Helpviewer/Bookmarks/AddBookmarkDialog.ui</Form> @@ -1299,6 +1304,7 @@ <Form>Helpviewer/Download/DownloadAskActionDialog.ui</Form> <Form>Helpviewer/Download/DownloadItem.ui</Form> <Form>Helpviewer/Download/DownloadManager.ui</Form> + <Form>Helpviewer/FeaturePermissions/FeaturePermissionsDialog.ui</Form> <Form>Helpviewer/Feeds/FeedEditDialog.ui</Form> <Form>Helpviewer/Feeds/FeedsDialog.ui</Form> <Form>Helpviewer/Feeds/FeedsManager.ui</Form> @@ -1514,6 +1520,7 @@ <Form>Preferences/ConfigurationPages/GraphicsPage.ui</Form> <Form>Preferences/ConfigurationPages/HelpAppearancePage.ui</Form> <Form>Preferences/ConfigurationPages/HelpDocumentationPage.ui</Form> + <Form>Preferences/ConfigurationPages/HelpFlashCookieManagerPage.ui</Form> <Form>Preferences/ConfigurationPages/HelpInterfacePage.ui</Form> <Form>Preferences/ConfigurationPages/HelpViewersPage.ui</Form> <Form>Preferences/ConfigurationPages/HelpVirusTotalPage.ui</Form> @@ -1632,14 +1639,14 @@ <Interfaces/> <Others> <Other>.hgignore</Other> + <Other>APIs/Python/zope-2.10.7.api</Other> + <Other>APIs/Python/zope-2.11.2.api</Other> + <Other>APIs/Python/zope-3.3.1.api</Other> <Other>APIs/Python3/PyQt4.bas</Other> <Other>APIs/Python3/PyQt5.bas</Other> <Other>APIs/Python3/QScintilla2.bas</Other> <Other>APIs/Python3/eric6.api</Other> <Other>APIs/Python3/eric6.bas</Other> - <Other>APIs/Python/zope-2.10.7.api</Other> - <Other>APIs/Python/zope-2.11.2.api</Other> - <Other>APIs/Python/zope-3.3.1.api</Other> <Other>APIs/QSS/qss.api</Other> <Other>APIs/Ruby/Ruby-1.8.7.api</Other> <Other>APIs/Ruby/Ruby-1.8.7.bas</Other> @@ -1650,10 +1657,10 @@ <Other>CSSs</Other> <Other>CodeTemplates</Other> <Other>DTDs</Other> + <Other>DebugClients/Python/coverage/doc</Other> + <Other>DebugClients/Python/coverage/htmlfiles</Other> <Other>DebugClients/Python3/coverage/doc</Other> <Other>DebugClients/Python3/coverage/htmlfiles</Other> - <Other>DebugClients/Python/coverage/doc</Other> - <Other>DebugClients/Python/coverage/htmlfiles</Other> <Other>DesignerTemplates</Other> <Other>Dictionaries</Other> <Other>Documentation/Help</Other>