|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the Flash cookie manager. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 try: |
|
13 str = unicode # __IGNORE_EXCEPTION__ |
|
14 except NameError: |
|
15 pass |
|
16 |
|
17 import shutil |
|
18 |
|
19 from PyQt5.QtCore import QObject, QTimer, QDir, QFileInfo, QFile |
|
20 |
|
21 from .FlashCookie import FlashCookie |
|
22 from .FlashCookieReader import FlashCookieReader, FlashCookieReaderError |
|
23 |
|
24 import WebBrowser.WebBrowserWindow |
|
25 |
|
26 import Preferences |
|
27 |
|
28 |
|
29 class FlashCookieManager(QObject): |
|
30 """ |
|
31 Class implementing the Flash cookie manager object. |
|
32 """ |
|
33 RefreshInterval = 60 * 1000 |
|
34 |
|
35 def __init__(self, parent=None): |
|
36 """ |
|
37 Constructor |
|
38 |
|
39 @param parent reference to the parent object |
|
40 @type QObject |
|
41 """ |
|
42 super(FlashCookieManager, self).__init__(parent) |
|
43 |
|
44 self.__flashCookieManagerDialog = None |
|
45 self.__flashCookies = [] # list of FlashCookie |
|
46 self.__newCookiesList = [] # list of str |
|
47 ## self.__whitelist = [] # list of str |
|
48 ## self.__blacklist = [] # list of str |
|
49 |
|
50 self.__timer = QTimer(self) |
|
51 self.__timer.setInterval(FlashCookieManager.RefreshInterval) |
|
52 self.__timer.timeout.connect(self.__autoRefresh) |
|
53 |
|
54 # start the timer if needed |
|
55 self.__startStopTimer() |
|
56 |
|
57 if Preferences.getHelp("FlashCookiesDeleteOnStartExit"): |
|
58 self.__loadFlashCookies() |
|
59 self.__removeAllButWhitelisted() |
|
60 |
|
61 def shutdown(self): |
|
62 """ |
|
63 Public method to perform shutdown actions. |
|
64 """ |
|
65 if self.__flashCookieManagerDialog is not None: |
|
66 self.__flashCookieManagerDialog.close() |
|
67 |
|
68 if Preferences.getHelp("FlashCookiesDeleteOnStartExit"): |
|
69 self.__removeAllButWhitelisted() |
|
70 |
|
71 def setFlashCookies(self, cookies): |
|
72 """ |
|
73 Public method to set the list of cached Flash cookies. |
|
74 |
|
75 @param cookies list of Flash cookies to store |
|
76 @type list of FlashCookie |
|
77 """ |
|
78 self.__flashCookies = cookies[:] |
|
79 |
|
80 def flashCookies(self): |
|
81 """ |
|
82 Public method to get the list of cached Flash cookies. |
|
83 |
|
84 @return list of Flash cookies |
|
85 @rtype list of FlashCookie |
|
86 """ |
|
87 if not self.__flashCookies: |
|
88 self.__loadFlashCookies() |
|
89 |
|
90 return self.__flashCookies[:] |
|
91 |
|
92 def newCookiesList(self): |
|
93 """ |
|
94 Public method to get the list of newly detected Flash cookies. |
|
95 |
|
96 @return list of newly detected Flash cookies |
|
97 @rtype list of str |
|
98 """ |
|
99 return self.__newCookiesList[:] |
|
100 |
|
101 def clearNewOrigins(self): |
|
102 """ |
|
103 Public method to clear the list of newly detected Flash cookies. |
|
104 """ |
|
105 self.__newCookiesList = [] |
|
106 |
|
107 def clearCache(self): |
|
108 """ |
|
109 Public method to clear the list of cached Flash cookies. |
|
110 """ |
|
111 self.__flashCookies = [] |
|
112 |
|
113 def __isBlacklisted(self, cookie): |
|
114 """ |
|
115 Private method to check for a blacklisted cookie. |
|
116 |
|
117 @param cookie Flash cookie to be tested |
|
118 @type FlashCookie |
|
119 @return flag indicating a blacklisted cookie |
|
120 @rtype bool |
|
121 """ |
|
122 return cookie.origin in Preferences.getHelp("FlashCookiesBlacklist") |
|
123 |
|
124 def __isWhitelisted(self, cookie): |
|
125 """ |
|
126 Private method to check for a whitelisted cookie. |
|
127 |
|
128 @param cookie Flash cookie to be tested |
|
129 @type FlashCookie |
|
130 @return flag indicating a whitelisted cookie |
|
131 @rtype bool |
|
132 """ |
|
133 return cookie.origin in Preferences.getHelp("FlashCookiesWhitelist") |
|
134 |
|
135 def __removeAllButWhitelisted(self): |
|
136 """ |
|
137 Private method to remove all non-whitelisted cookies. |
|
138 """ |
|
139 for cookie in self.__flashCookies[:]: |
|
140 if not self.__isWhitelisted(cookie): |
|
141 self.removeCookie(cookie) |
|
142 |
|
143 def removeAllCookies(self): |
|
144 """ |
|
145 Public method to remove all flash cookies. |
|
146 """ |
|
147 for cookie in self.__flashCookies[:]: |
|
148 self.removeCookie(cookie) |
|
149 self.clearNewOrigins() |
|
150 self.clearCache() |
|
151 |
|
152 def __sharedObjectDirName(self): |
|
153 """ |
|
154 Private slot to determine the path of the shared data objects. |
|
155 |
|
156 @return path of the shared data objects |
|
157 @rtype str |
|
158 """ |
|
159 if "macromedia" in self.flashPlayerDataPath().lower() or \ |
|
160 "/.gnash" not in self.flashPlayerDataPath().lower(): |
|
161 return "/#SharedObjects/" |
|
162 else: |
|
163 return "/SharedObjects/" |
|
164 |
|
165 def flashPlayerDataPath(self): |
|
166 """ |
|
167 Public method to get the Flash Player data path. |
|
168 |
|
169 @return Flash Player data path |
|
170 @rtype str |
|
171 """ |
|
172 return Preferences.getHelp("FlashCookiesDataPath") |
|
173 |
|
174 def preferencesChanged(self): |
|
175 """ |
|
176 Public slot to handle a change of preferences. |
|
177 """ |
|
178 self.__startStopTimer() |
|
179 |
|
180 def removeCookie(self, cookie): |
|
181 """ |
|
182 Public method to remove a cookie of the list of cached cookies. |
|
183 |
|
184 @param cookie Flash cookie to be removed |
|
185 @type FlashCookie |
|
186 """ |
|
187 if cookie in self.__flashCookies: |
|
188 self.__flashCookies.remove(cookie) |
|
189 shutil.rmtree(cookie.path, True) |
|
190 |
|
191 def __autoRefresh(self): |
|
192 """ |
|
193 Private slot to refresh the list of cookies. |
|
194 """ |
|
195 if self.__flashCookieManagerDialog and \ |
|
196 self.__flashCookieManagerDialog.isVisible(): |
|
197 return |
|
198 |
|
199 oldFlashCookies = self.__flashCookies[:] |
|
200 self.__loadFlashCookies() |
|
201 newCookieList = [] |
|
202 |
|
203 for cookie in self.__flashCookies[:]: |
|
204 if self.__isBlacklisted(cookie): |
|
205 self.removeCookie(cookie) |
|
206 continue |
|
207 |
|
208 if self.__isWhitelisted(cookie): |
|
209 continue |
|
210 |
|
211 newCookie = True |
|
212 for oldCookie in oldFlashCookies: |
|
213 if (oldCookie.path + oldCookie.name == |
|
214 cookie.path + cookie.name): |
|
215 newCookie = False |
|
216 break |
|
217 |
|
218 if newCookie: |
|
219 newCookieList.append(cookie.path + "/" + cookie.name) |
|
220 |
|
221 if newCookieList and Preferences.getHelp("FlashCookieNotify"): |
|
222 self.__newCookiesList.extend(newCookieList) |
|
223 win = WebBrowser.WebBrowserWindow.WebBrowserWindow.mainWindow() |
|
224 if win is None: |
|
225 return |
|
226 |
|
227 view = win.currentBrowser() |
|
228 if view is None: |
|
229 return |
|
230 |
|
231 from .FlashCookieNotification import FlashCookieNotification |
|
232 notification = FlashCookieNotification( |
|
233 view, self, len(newCookieList)) |
|
234 notification.show() |
|
235 |
|
236 def showFlashCookieManagerDialog(self): |
|
237 """ |
|
238 Public method to show the Flash cookies management dialog. |
|
239 """ |
|
240 if self.__flashCookieManagerDialog is None: |
|
241 from .FlashCookieManagerDialog import FlashCookieManagerDialog |
|
242 self.__flashCookieManagerDialog = FlashCookieManagerDialog(self) |
|
243 |
|
244 self.__flashCookieManagerDialog.refreshView() |
|
245 self.__flashCookieManagerDialog.showPage(0) |
|
246 self.__flashCookieManagerDialog.show() |
|
247 self.__flashCookieManagerDialog.raise_() |
|
248 |
|
249 def __startStopTimer(self): |
|
250 """ |
|
251 Private slot to start or stop the auto refresh timer. |
|
252 """ |
|
253 if Preferences.getHelp("FlashCookieAutoRefresh"): |
|
254 if not self.__timer.isActive(): |
|
255 if not bool(self.__flashCookies): |
|
256 self.__loadFlashCookies() |
|
257 |
|
258 self.__timer.start() |
|
259 else: |
|
260 self.__timer.stop() |
|
261 |
|
262 def __loadFlashCookies(self): |
|
263 """ |
|
264 Private slot to load the Flash cookies to be cached. |
|
265 """ |
|
266 self.__flashCookies = [] |
|
267 self.__loadFlashCookiesFromPath(self.flashPlayerDataPath()) |
|
268 |
|
269 def __loadFlashCookiesFromPath(self, path): |
|
270 """ |
|
271 Private slot to load the Flash cookies from a path. |
|
272 |
|
273 @param path Flash cookies path |
|
274 @type str |
|
275 """ |
|
276 if path.endswith("#AppContainer"): |
|
277 # specific to IE and Windows |
|
278 return |
|
279 |
|
280 path = path.replace("\\", "/") |
|
281 solDir = QDir(path) |
|
282 entryList = solDir.entryList() |
|
283 for entry in entryList: |
|
284 if entry == "." or entry == "..": |
|
285 continue |
|
286 entryInfo = QFileInfo(path + "/" + entry) |
|
287 if entryInfo.isDir(): |
|
288 self.__loadFlashCookiesFromPath(entryInfo.filePath()) |
|
289 else: |
|
290 self.__insertFlashCookie(entryInfo.filePath()) |
|
291 |
|
292 def __insertFlashCookie(self, path): |
|
293 """ |
|
294 Private method to insert a Flash cookie into the cache. |
|
295 |
|
296 @param path Flash cookies path |
|
297 @type str |
|
298 """ |
|
299 solFile = QFile(path) |
|
300 if not solFile.open(QFile.ReadOnly): |
|
301 return |
|
302 |
|
303 dataStr = "" |
|
304 data = bytes(solFile.readAll()) |
|
305 if data: |
|
306 try: |
|
307 reader = FlashCookieReader() |
|
308 reader.setBytes(data) |
|
309 reader.parse() |
|
310 dataStr = reader.toString() |
|
311 except FlashCookieReaderError as err: |
|
312 dataStr = err.msg |
|
313 |
|
314 solFileInfo = QFileInfo(solFile) |
|
315 |
|
316 cookie = FlashCookie() |
|
317 cookie.contents = dataStr |
|
318 cookie.name = solFileInfo.fileName() |
|
319 cookie.path = solFileInfo.canonicalPath() |
|
320 cookie.size = int(solFile.size()) |
|
321 cookie.lastModified = solFileInfo.lastModified() |
|
322 cookie.origin = self.__extractOriginFrom(path) |
|
323 |
|
324 self.__flashCookies.append(cookie) |
|
325 |
|
326 def __extractOriginFrom(self, path): |
|
327 """ |
|
328 Private method to extract the cookie origin given its file name. |
|
329 |
|
330 @param path file name of the cookie file |
|
331 @type str |
|
332 @return cookie origin |
|
333 @rtype str |
|
334 """ |
|
335 origin = path |
|
336 if path.startswith( |
|
337 self.flashPlayerDataPath() + self.__sharedObjectDirName()): |
|
338 origin = origin.replace( |
|
339 self.flashPlayerDataPath() + self.__sharedObjectDirName(), "") |
|
340 if "/" in origin: |
|
341 origin = origin.split("/", 1)[1] |
|
342 elif path.startswith( |
|
343 self.flashPlayerDataPath() + |
|
344 "/macromedia.com/support/flashplayer/sys/"): |
|
345 origin = origin.replace( |
|
346 self.flashPlayerDataPath() + |
|
347 "/macromedia.com/support/flashplayer/sys/", "") |
|
348 if origin == "settings.sol": |
|
349 return self.tr("!default") |
|
350 elif origin.startswith("#"): |
|
351 origin = origin[1:] |
|
352 else: |
|
353 origin = "" |
|
354 |
|
355 index = origin.find("/") |
|
356 if index == -1: |
|
357 return self.tr("!other") |
|
358 |
|
359 origin = origin[:index] |
|
360 if origin in ["localhost", "local"]: |
|
361 origin = "!localhost" |
|
362 |
|
363 return origin |