WebBrowser/CookieJar/CookieJar.py

branch
QtWebEngine
changeset 4845
2d22ff71c005
parent 4631
5c1a96925da4
child 4886
b56735d36159
equal deleted inserted replaced
4840:69ee7965ba27 4845:2d22ff71c005
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a QNetworkCookieJar subclass with various accept policies.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13
14 from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSettings
15 from PyQt5.QtNetwork import QNetworkCookieJar, QNetworkCookie
16
17 from WebBrowser.WebBrowserWindow import WebBrowserWindow
18
19 from Utilities.AutoSaver import AutoSaver
20 import Utilities
21 import Preferences
22
23
24 class CookieJar(QNetworkCookieJar):
25 """
26 Class implementing a QNetworkCookieJar subclass with various accept
27 policies.
28
29 @signal cookiesChanged() emitted after the cookies have been changed
30 """
31 cookiesChanged = pyqtSignal()
32
33 AcceptAlways = 0
34 AcceptNever = 1
35 AcceptOnlyFromSitesNavigatedTo = 2
36 AcceptMax = 2
37
38 KeepUntilExpire = 0
39 KeepUntilExit = 1
40 KeepMax = 1
41
42 Allow = 0
43 Block = 1
44 AllowForSession = 2
45
46 def __init__(self, parent=None):
47 """
48 Constructor
49
50 @param parent reference to the parent object (QObject)
51 """
52 super(CookieJar, self).__init__(parent)
53
54 self.__loaded = False
55 self.__acceptCookies = self.AcceptOnlyFromSitesNavigatedTo
56 self.__saveTimer = AutoSaver(self, self.__save)
57
58 self.__cookies = []
59
60 self.__cookiesFile = os.path.join(Utilities.getConfigDir(),
61 "web_browser", "cookies.ini")
62 self.__load()
63
64 # TODO: Qt 5.6
65 ## self.__store = WebBrowserWindow.webProfile.cookieStore()
66 ## self.__store.cookieAdded.connect(self.__cookieAdded)
67 ## self.__store.cookieRemoved.connect(self.__cookieRemoved)
68
69 def close(self):
70 """
71 Public slot to close the cookie jar.
72 """
73 if not self.__loaded:
74 self.__load()
75
76 if self.__keepCookies == self.KeepUntilExit:
77 self.clear()
78 self.__saveTimer.saveIfNeccessary()
79
80 def clear(self):
81 """
82 Public method to clear all cookies.
83 """
84 if not self.__loaded:
85 self.__load()
86
87 self.__cookies = []
88 # TODO: Qt 5.6
89 ## self.__store.deleteAllCookies()
90 self.cookiesChanged.emit()
91
92 def removeCookies(self, cookies):
93 """
94 Public method to remove a cookie.
95
96 @param cookies list of cookies to be removed
97 @type list of QNetworkCookie
98 """
99 wasBlocked = self.blockSignals(True)
100 # TODO: Qt 5.6
101 ## for cookie in cookies:
102 ## self.__store.deleteCookie(cookie)
103 self.blockSignals(wasBlocked)
104
105 self.cookiesChanged.emit()
106
107 def __load(self):
108 """
109 Private method to load the cookies settings.
110 """
111 if self.__loaded:
112 return
113
114 cookieSettings = QSettings(self.__cookiesFile, QSettings.IniFormat)
115
116 # load exceptions
117 self.__exceptionsBlock = Preferences.toList(
118 cookieSettings.value("Exceptions/block"))
119 self.__exceptionsAllow = Preferences.toList(
120 cookieSettings.value("Exceptions/allow"))
121 self.__exceptionsAllowForSession = Preferences.toList(
122 cookieSettings.value("Exceptions/allowForSession"))
123 self.__exceptionsBlock.sort()
124 self.__exceptionsAllow.sort()
125 self.__exceptionsAllowForSession.sort()
126
127 self.__acceptCookies = Preferences.getWebBrowser("AcceptCookies")
128 self.__keepCookies = Preferences.getWebBrowser("KeepCookiesUntil")
129 if self.__keepCookies == self.KeepUntilExit:
130 self.clear()
131
132 self.__filterTrackingCookies = Preferences.toBool(
133 Preferences.getWebBrowser("FilterTrackingCookies"))
134
135 self.__loaded = True
136 self.cookiesChanged.emit()
137
138 def __save(self):
139 """
140 Private method to save the cookies settings.
141 """
142 if not self.__loaded:
143 return
144
145 cookieSettings = QSettings(self.__cookiesFile, QSettings.IniFormat)
146
147 cookieSettings.setValue("Exceptions/block", self.__exceptionsBlock)
148 cookieSettings.setValue("Exceptions/allow", self.__exceptionsAllow)
149 cookieSettings.setValue("Exceptions/allowForSession",
150 self.__exceptionsAllowForSession)
151
152 Preferences.setWebBrowser("AcceptCookies", self.__acceptCookies)
153 Preferences.setWebBrowser("KeepCookiesUntil", self.__keepCookies)
154 Preferences.setWebBrowser("FilterTrackingCookies",
155 self.__filterTrackingCookies)
156
157 @pyqtSlot(QNetworkCookie)
158 def __cookieAdded(self, cookie):
159 """
160 Private slot handling the addition of a cookie.
161
162 @param cookie cookie which was added
163 @type QNetworkCookie
164 """
165 if self.__rejectCookie(cookie, cookie.domain()):
166 # TODO: Qt 5.6
167 ## self.__store.deleteCookie(cookie)
168 return
169
170 self.__cookies.append(cookie)
171 self.cookiesChanged.emit()
172
173 @pyqtSlot(QNetworkCookie)
174 def __cookieRemoved(self, cookie):
175 """
176 Private slot handling the removal of a cookie.
177
178 @param cookie cookie which was removed
179 @type QNetworkCookie
180 """
181 if cookie in self.__cookies:
182 self.__cookies.remove(cookie)
183 self.cookiesChanged.emit()
184
185 def __rejectCookie(self, cookie, cookieDomain):
186 """
187 Public method to test, if a cookie shall be rejected.
188
189 @param cookie cookie to be tested
190 @type QNetworkCookie
191 @param cookieDomain domain of the cookie
192 @type str
193 @return flag indicating the cookie shall be rejected
194 @rtype bool
195 """
196 if not self.__loaded:
197 self.__load()
198
199 eBlock = self.__isOnDomainList(self.__exceptionsBlock, cookieDomain)
200 eAllow = not eBlock and \
201 self.__isOnDomainList(self.__exceptionsAllow, cookieDomain)
202 eAllowSession = not eBlock and \
203 not eAllow and \
204 self.__isOnDomainList(
205 self.__exceptionsAllowForSession, cookieDomain)
206
207 if self.__acceptCookies == self.AcceptNever:
208 if not eAllow and not eAllowSession:
209 return True
210
211 if self.__acceptCookies == self.AcceptAlways:
212 if eBlock:
213 return True
214
215 if self.__acceptCookies == self.AcceptOnlyFromSitesNavigatedTo:
216 url = WebBrowserWindow.mainWindow().getWindow().currentBrowser()\
217 .url()
218 if url.isValid():
219 host = url.host()
220 else:
221 host = ""
222 if not self.__matchDomain(cookieDomain, host):
223 return True
224
225 if self.__filterTrackingCookies and cookie.name().startsWith(b"__utm"):
226 return True
227
228 return False
229
230 def acceptPolicy(self):
231 """
232 Public method to get the accept policy.
233
234 @return current accept policy
235 """
236 if not self.__loaded:
237 self.__load()
238
239 return self.__acceptCookies
240
241 def setAcceptPolicy(self, policy):
242 """
243 Public method to set the accept policy.
244
245 @param policy accept policy to be set
246 """
247 if not self.__loaded:
248 self.__load()
249
250 if policy > self.AcceptMax:
251 return
252 if policy == self.__acceptCookies:
253 return
254
255 self.__acceptCookies = policy
256 self.__saveTimer.changeOccurred()
257
258 def keepPolicy(self):
259 """
260 Public method to get the keep policy.
261
262 @return keep policy
263 """
264 if not self.__loaded:
265 self.__load()
266
267 return self.__keepCookies
268
269 def setKeepPolicy(self, policy):
270 """
271 Public method to set the keep policy.
272
273 @param policy keep policy to be set
274 """
275 if not self.__loaded:
276 self.__load()
277
278 if policy > self.KeepMax:
279 return
280 if policy == self.__keepCookies:
281 return
282
283 self.__keepCookies = policy
284 self.__saveTimer.changeOccurred()
285
286 def blockedCookies(self):
287 """
288 Public method to return the list of blocked domains.
289
290 @return list of blocked domains (list of strings)
291 """
292 if not self.__loaded:
293 self.__load()
294
295 return self.__exceptionsBlock
296
297 def allowedCookies(self):
298 """
299 Public method to return the list of allowed domains.
300
301 @return list of allowed domains (list of strings)
302 """
303 if not self.__loaded:
304 self.__load()
305
306 return self.__exceptionsAllow
307
308 def allowForSessionCookies(self):
309 """
310 Public method to return the list of allowed session cookie domains.
311
312 @return list of allowed session cookie domains (list of strings)
313 """
314 if not self.__loaded:
315 self.__load()
316
317 return self.__exceptionsAllowForSession
318
319 def setBlockedCookies(self, list_):
320 """
321 Public method to set the list of blocked domains.
322
323 @param list_ list of blocked domains (list of strings)
324 """
325 if not self.__loaded:
326 self.__load()
327
328 self.__exceptionsBlock = list_[:]
329 self.__exceptionsBlock.sort()
330 self.__saveTimer.changeOccurred()
331
332 def setAllowedCookies(self, list_):
333 """
334 Public method to set the list of allowed domains.
335
336 @param list_ list of allowed domains (list of strings)
337 """
338 if not self.__loaded:
339 self.__load()
340
341 self.__exceptionsAllow = list_[:]
342 self.__exceptionsAllow.sort()
343 self.__saveTimer.changeOccurred()
344
345 def setAllowForSessionCookies(self, list_):
346 """
347 Public method to set the list of allowed session cookie domains.
348
349 @param list_ list of allowed session cookie domains (list of strings)
350 """
351 if not self.__loaded:
352 self.__load()
353
354 self.__exceptionsAllowForSession = list_[:]
355 self.__exceptionsAllowForSession.sort()
356 self.__saveTimer.changeOccurred()
357
358 def filterTrackingCookies(self):
359 """
360 Public method to get the filter tracking cookies flag.
361
362 @return filter tracking cookies flag (boolean)
363 """
364 return self.__filterTrackingCookies
365
366 def setFilterTrackingCookies(self, filterTrackingCookies):
367 """
368 Public method to set the filter tracking cookies flag.
369
370 @param filterTrackingCookies filter tracking cookies flag (boolean)
371 """
372 self.__filterTrackingCookies = filterTrackingCookies
373
374 def __isOnDomainList(self, rules, domain):
375 """
376 Private method to check, if either the rule matches the domain exactly
377 or the domain ends with ".rule".
378
379 @param rules list of rules (list of strings)
380 @param domain domain name to check (string)
381 @return flag indicating a match (boolean)
382 """
383 for rule in rules:
384 if rule.startswith("."):
385 if domain.endswith(rule):
386 return True
387
388 withoutDot = rule[1:]
389 if domain == withoutDot:
390 return True
391 else:
392 domainEnding = domain[-(len(rule) + 1):]
393 if domainEnding and \
394 domainEnding[0] == "." and \
395 domain.endswith(rule):
396 return True
397
398 if rule == domain:
399 return True
400
401 return False
402
403 def __matchDomain(self, cookieDomain, siteDomain):
404 """
405 Private method to check, if a URLs host matches a cookie domain
406 according to RFC 6265.
407
408 @param cookieDomain domain of the cookie
409 @type str
410 @param siteDomain domain or host of an URL
411 @type str
412 @return flag indicating a match
413 @rtype bool
414 """
415 if cookieDomain.startswith("."):
416 cookieDomain = cookieDomain[1:]
417 if siteDomain.startswith("."):
418 siteDomain = siteDomain[1:]
419
420 if cookieDomain == siteDomain:
421 return True
422
423 if not siteDomain.endswith(cookieDomain):
424 return False
425
426 index = siteDomain.find(cookieDomain)
427 return index > 0 and siteDomain[index - 1] == "."
428
429 def cookies(self):
430 """
431 Public method to get the cookies of the cookie jar.
432
433 @return list of all cookies (list of QNetworkCookie)
434 """
435 return self.__cookies

eric ide

mercurial