Helpviewer/CookieJar/CookieJar.py

changeset 0
de9c2efb9d02
child 7
c679fb30c8f3
diff -r 000000000000 -r de9c2efb9d02 Helpviewer/CookieJar/CookieJar.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helpviewer/CookieJar/CookieJar.py	Mon Dec 28 16:03:33 2009 +0000
@@ -0,0 +1,492 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a QNetworkCookieJar subclass with various accept policies.
+"""
+
+import os
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from PyQt4.QtNetwork import QNetworkCookieJar, QNetworkCookie
+from PyQt4.QtWebKit import QWebSettings
+
+from Utilities.AutoSaver import AutoSaver
+import Utilities
+import Preferences
+
+class CookieJar(QNetworkCookieJar):
+    """
+    Class implementing a QNetworkCookieJar subclass with various accept policies.
+    
+    @signal cookiesChanged() emitted after the cookies have been changed
+    """
+    JAR_VERSION = 23
+    
+    AcceptAlways                    = 0
+    AcceptNever                     = 1
+    AcceptOnlyFromSitesNavigatedTo  = 2
+
+    KeepUntilExpire     = 0
+    KeepUntilExit       = 1
+    KeepUntilTimeLimit  = 2
+    
+    Allow           = 0
+    Block           = 1
+    AllowForSession = 2
+    
+    def __init__(self, parent = None):
+        """
+        Constructor
+        
+        @param parent reference to the parent object (QObject)
+        """
+        QNetworkCookieJar.__init__(self, parent)
+        
+        self.__loaded = False
+        self.__acceptCookies = self.AcceptOnlyFromSitesNavigatedTo
+        self.__saveTimer = AutoSaver(self, self.save)
+        
+        self.__cookiesFile = os.path.join(Utilities.getConfigDir(), 
+                                          "browser", "cookies.ini")
+    
+    def saveCookies(self, cookiesList):
+        """
+        Public method to save the cookies.
+        
+        @param cookiesList list of cookies to be saved
+        @return saved cookies as a byte array (QByteArray)
+        """
+        data = QByteArray()
+        stream = QDataStream(data, QIODevice.WriteOnly)
+        stream.writeUInt16(self.JAR_VERSION)
+        stream.writeUInt32(len(cookiesList))
+        for cookie in cookiesList:
+            stream << cookie.toRawForm()
+        
+        return data
+    
+    def loadCookies(self, cookies):
+        """
+        Public method to restore the saved cookies.
+        
+        @param cookies byte array containing the saved cookies (QByteArray)
+        @return list of cookies
+        """
+        if cookies.isEmpty():
+            return []
+        
+        cookiesList = []
+        data = QByteArray(cookies)
+        stream = QDataStream(data, QIODevice.ReadOnly)
+        
+        version = stream.readUInt16()
+        if version != self.JAR_VERSION:
+            return []
+        
+        noCookies = stream.readUInt32()
+        
+        rawCookie = QByteArray()
+        while not stream.atEnd():
+            stream >> rawCookie
+            newCookies = QNetworkCookie.parseCookies(rawCookie)
+            for newCookie in newCookies:
+                cookiesList.append(newCookie)
+        
+        return cookiesList
+    
+    def close(self):
+        """
+        Public slot to close the cookie jar.
+        """
+        if self.__loaded and self.__keepCookies == self.KeepUntilExit:
+            self.clear()
+        self.__saveTimer.saveIfNeccessary()
+    
+    def clear(self):
+        """
+        Public method to clear all cookies.
+        """
+        if not self.__loaded:
+            self.load()
+        
+        self.setAllCookies([])
+        self.__saveTimer.changeOccurred()
+        self.emit(SIGNAL("cookiesChanged()"))
+    
+    def load(self):
+        """
+        Public method to load the cookies.
+        """
+        if self.__loaded:
+            return
+        
+        cookieSettings = QSettings(self.__cookiesFile, QSettings.IniFormat)
+        
+        # load cookies
+        cookies = cookieSettings.value("Cookies")
+        if cookies.isValid():
+            cookiesList = self.loadCookies(cookies.toByteArray())
+        else:
+            cookiesList = []
+        self.setAllCookies(cookiesList)
+        
+        # load exceptions
+        self.__exceptionsBlock = \
+            cookieSettings.value("Exceptions/block").toStringList()
+        self.__exceptionsAllow = \
+            cookieSettings.value("Exceptions/allow").toStringList()
+        self.__exceptionsAllowForSession = \
+            cookieSettings.value("Exceptions/allowForSession").toStringList()
+        self.__exceptionsBlock.sort()
+        self.__exceptionsAllow.sort()
+        self.__exceptionsAllowForSession.sort()
+        
+        self.__acceptCookies = Preferences.getHelp("AcceptCookies")
+        self.__keepCookies = Preferences.getHelp("KeepCookiesUntil")
+        if self.__keepCookies == self.KeepUntilExit:
+            self.setAllCookies([])
+        
+        self.__filterTrackingCookies = Preferences.getHelp("FilterTrackingCookies")
+        
+        self.__loaded = True
+        self.emit(SIGNAL("cookiesChanged()"))
+    
+    def save(self):
+        """
+        Public method to save the cookies.
+        """
+        if not self.__loaded:
+            return
+        
+        self.__purgeOldCookies()
+        
+        cookieSettings = QSettings(self.__cookiesFile, QSettings.IniFormat)
+        
+        cookiesList = self.allCookies()
+        for index in range(len(cookiesList) -1, -1, -1):
+            if cookiesList[index].isSessionCookie():
+                del cookiesList[index]
+        cookies = self.saveCookies(cookiesList)
+        
+        cookieSettings.setValue("Cookies", 
+                                QVariant(cookies))
+        cookieSettings.setValue("Exceptions/block", 
+                                QVariant(self.__exceptionsBlock))
+        cookieSettings.setValue("Exceptions/allow", 
+                                QVariant(self.__exceptionsAllow))
+        cookieSettings.setValue("Exceptions/allowForSession", 
+                                QVariant(self.__exceptionsAllowForSession))
+        
+        Preferences.setHelp("AcceptCookies", self.__acceptCookies)
+        Preferences.setHelp("KeepCookiesUntil", self.__keepCookies)
+        Preferences.setHelp("FilterTrackingCookies", int(self.__filterTrackingCookies))
+    
+    def __purgeOldCookies(self):
+        """
+        Private method to purge old cookies
+        """
+        cookies = self.allCookies()
+        if len(cookies) == 0:
+            return
+        
+        oldCount = len(cookies)
+        now = QDateTime.currentDateTime()
+        for index in range(len(cookies) - 1, -1, -1):
+            if not cookies[index].isSessionCookie() and \
+               cookies[index].expirationDate() < now:
+                del cookies[index]
+        if oldCount == len(cookies):
+            return
+        self.setAllCookies(cookies)
+        self.emit(SIGNAL("cookiesChanged()"))
+    
+    def cookiesForUrl(self, url):
+        """
+        Public method to get the cookies for a URL.
+        
+        @param url URL to get cookies for (QUrl)
+        @return list of cookies (list of QNetworkCookie)
+        """
+        if not self.__loaded:
+            self.load()
+        
+        globalSettings = QWebSettings.globalSettings()
+        if globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled):
+            return []
+        
+        return QNetworkCookieJar.cookiesForUrl(self, url)
+    
+    def setCookiesFromUrl(self, cookieList, url):
+        """
+        Public method to set cookies for a URL.
+        
+        @param cookieList list of cookies to set (list of QNetworkCookie)
+        @param url url to set cookies for (QUrl)
+        @return flag indicating cookies were set (boolean)
+        """
+        if not self.__loaded:
+            self.load()
+        
+        globalSettings = QWebSettings.globalSettings()
+        if globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled):
+            return False
+        
+        host = url.host()
+        eBlock = self.__isOnDomainList(self.__exceptionsBlock, host)
+        eAllow = not eBlock and \
+                 self.__isOnDomainList(self.__exceptionsAllow, host)
+        eAllowSession = not eBlock and \
+                        not eAllow and \
+                        self.__isOnDomainList(self.__exceptionsAllowForSession, host)
+        
+        addedCookies = False
+        acceptInitially = self.__acceptCookies != self.AcceptNever
+        if (acceptInitially and not eBlock) or \
+           (not acceptInitially and (eAllow or eAllowSession)):
+            # url domain == cookie domain
+            soon = QDateTime.currentDateTime()
+            soon = soon.addDays(90)
+            for cookie in cookieList:
+                lst = []
+                if not (self.__filterTrackingCookies and \
+                        cookie.name().startsWith("__utm")):
+                    if eAllowSession:
+                        cookie.setExpirationDate(QDateTime())
+                    if self.__keepCookies == self.KeepUntilTimeLimit and \
+                       not cookie.isSessionCookie and \
+                       cookie.expirationDate() > soon:
+                        cookie.setExpirationDate(soon)
+                    lst.append(cookie)
+                    if QNetworkCookieJar.setCookiesFromUrl(self, lst, url):
+                        addedCookies = True
+                    elif self.__acceptCookies == self.AcceptAlways:
+                        # force it in if wanted
+                        cookies = self.allCookies()
+                        for ocookie in cookies[:]:
+                            # does the cookie exist already?
+                            if cookie.name() == ocookie.name() and \
+                               cookie.domain() == ocookie.domain() and \
+                               cookie.path() == ocookie.path():
+                                # found a match
+                                cookies.remove(ocookie)
+                        
+                        cookies.append(cookie)
+                        self.setAllCookies(cookies)
+                        addedCookies = True
+        
+        if addedCookies:
+            self.__saveTimer.changeOccurred()
+            self.emit(SIGNAL("cookiesChanged()"))
+        
+        return addedCookies
+    
+    def acceptPolicy(self):
+        """
+        Public method to get the accept policy.
+        
+        @return current accept policy
+        """
+        if not self.__loaded:
+            self.load()
+        return self.__acceptCookies
+    
+    def setAcceptPolicy(self, policy):
+        """
+        Public method to set the accept policy.
+        
+        @param policy accept policy to be set
+        """
+        if not self.__loaded:
+            self.load()
+        if policy > self.AcceptOnlyFromSitesNavigatedTo:
+            return
+        if policy == self.__acceptCookies:
+            return
+        self.__acceptCookies = policy
+        self.__saveTimer.changeOccurred()
+    
+    def keepPolicy(self):
+        """
+        Private method to get the keep policy.
+        """
+        if not self.__loaded:
+            self.load()
+        return self.__keepCookies
+    
+    def setKeepPolicy(self, policy):
+        """
+        Public method to set the keep policy.
+        
+        @param policy keep policy to be set
+        """
+        if not self.__loaded:
+            self.load()
+        if policy > self.KeepUntilTimeLimit:
+            return
+        if policy == self.__keepCookies:
+            return
+        self.__keepCookies = policy
+        self.__saveTimer.changeOccurred()
+    
+    def blockedCookies(self):
+        """
+        Public method to return the blocked cookies.
+        
+        @return list of blocked cookies (list of strings)
+        """
+        if not self.__loaded:
+            self.load()
+        return self.__exceptionsBlock
+    
+    def allowedCookies(self):
+        """
+        Public method to return the allowed cookies.
+        
+        @return list of allowed cookies (list of strings)
+        """
+        if not self.__loaded:
+            self.load()
+        return self.__exceptionsAllow
+    
+    def allowForSessionCookies(self):
+        """
+        Public method to return the allowed session cookies.
+        
+        @return list of allowed session cookies (list of strings)
+        """
+        if not self.__loaded:
+            self.load()
+        return self.__exceptionsAllowForSession
+    
+    def setBlockedCookies(self, list_):
+        """
+        Public method to set the list of blocked cookies.
+        
+        @param list_ list of blocked cookies (list of strings)
+        """
+        if not self.__loaded:
+            self.load()
+        self.__exceptionsBlock = list_[:]
+        self.__exceptionsBlock.sort()
+        self.__applyRules()
+        self.__saveTimer.changeOccurred()
+    
+    def setAllowedCookies(self, list_):
+        """
+        Public method to set the list of allowed cookies.
+        
+        @param list_ list of allowed cookies (list of strings)
+        """
+        if not self.__loaded:
+            self.load()
+        self.__exceptionsAllow = list_[:]
+        self.__exceptionsAllow.sort()
+        self.__applyRules()
+        self.__saveTimer.changeOccurred()
+    
+    def setAllowForSessionCookies(self, list_):
+        """
+        Public method to set the list of allowed session cookies.
+        
+        @param list_ list of allowed session cookies (list of strings)
+        """
+        if not self.__loaded:
+            self.load()
+        self.__exceptionsAllowForSession = list_[:]
+        self.__exceptionsAllowForSession.sort()
+        self.__applyRules()
+        self.__saveTimer.changeOccurred()
+    
+    def filterTrackingCookies(self):
+        """
+        Public method to get the filter tracking cookies flag.
+        
+        @return filter tracking cookies flag (boolean)
+        """
+        return self.__filterTrackingCookies
+    
+    def setFilterTrackingCookies(self, filterTrackingCookies):
+        """
+        Public method to set the filter tracking cookies flag.
+        
+        @param filterTrackingCookies filter tracking cookies flag (boolean)
+        """
+        self.__filterTrackingCookies = filterTrackingCookies
+    
+    def __isOnDomainList(self, rules, domain):
+        """
+        Private method to check, if either the rule matches the domain exactly
+        or the domain ends with ".rule".
+        
+        @param rules list of rules (list of strings)
+        @param domain domain name to check (string)
+        @return flag indicating a match (boolean)
+        """
+        for rule in rules:
+            if rule.startswith("."):
+                if domain.endswith(rule):
+                    return True
+                
+                withoutDot = rule[1:]
+                if domain == withoutDot:
+                    return True
+            else:
+                domainEnding = domain[-(len(rule) + 1):]
+                if domainEnding and \
+                   domainEnding[0] == "." and \
+                   domain.endswith(rule):
+                    return True
+                
+                if rule == domain:
+                    return True
+        
+        return False
+    
+    def __applyRules(self):
+        """
+        Private method to apply the cookie rules.
+        """
+        cookiesList = self.allCookies()
+        changed = False
+        
+        for index in range(len(cookiesList) - 1, -1, -1):
+            cookie = cookiesList[index]
+            if self.__isOnDomainList(self.__exceptionsBlock, cookie.domain()):
+                del cookiesList[index]
+                changed = True
+            elif self.__isOnDomainList(self.__exceptionsAllowForSession, cookie.domain()):
+                cookie.setExpirationDate(QDateTime())
+                changed = True
+        
+        if changed:
+            self.setAllCookies(cookiesList)
+            self.__saveTimer.changeOccurred()
+            self.emit(SIGNAL("cookiesChanged()"))
+    
+    def cookies(self):
+        """
+        Public method to get the cookies of the cookie jar.
+        
+        @return list of all cookies (list of QNetworkCookie)
+        """
+        if not self.__loaded:
+            self.load()
+        
+        return self.allCookies()
+    
+    def setCookies(self, cookies):
+        """
+        Public method to set all cookies.
+        
+        @param cookies list of cookies to be set (list of QNetworkCookie)
+        """
+        if not self.__loaded:
+            self.load()
+        
+        self.setAllCookies(cookies)
+        self.__saveTimer.changeOccurred()
+        self.emit(SIGNAL("cookiesChanged()"))

eric ide

mercurial