Falkon Develop
Cross-platform Qt-based web browser
fcm_plugin.cpp
Go to the documentation of this file.
1/* ============================================================
2* FlashCookieManager plugin for Falkon
3* Copyright (C) 2014-2018 S. Razi Alavizadeh <s.r.alavizadeh@gmail.com>
4* Copyright (C) 2017-2018 David Rosca <nowrep@gmail.com>
5*
6* This program is free software: you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation, either version 3 of the License, or
9* (at your option) any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with this program. If not, see <http://www.gnu.org/licenses/>.
18* ============================================================ */
19#include "fcm_plugin.h"
20#include "browserwindow.h"
21#include "pluginproxy.h"
22#include "mainapplication.h"
23#include "fcm_dialog.h"
25#include "tabbedwebview.h"
26#include "fcm_notification.h"
27#include "datapaths.h"
28#include "../config.h"
29#include "statusbar.h"
30#include "navigationbar.h"
31
32#include <QTimer>
33#include <QSettings>
34#include <QDir>
35#include <QMenu>
36
37#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
38#include <QProcessEnvironment>
39#endif
40
41const int refreshInterval = 60 * 1000;
42
44{
45 Q_OBJECT
46public:
47 explicit FCM_Button(QObject *parent = nullptr)
49 {
50 }
51
52 QString id() const override
53 {
54 return QSL("fcm-icon");
55 }
56
57 QString name() const override
58 {
59 return tr("Flash Cookie Manager button");
60 }
61};
62
64 : QObject()
65{
66}
67
68void FCM_Plugin::init(InitState state, const QString &settingsPath)
69{
70 m_settingsPath = settingsPath;
71
72 connect(mApp->plugins(), &PluginProxy::mainWindowCreated, this, &FCM_Plugin::mainWindowCreated);
73 connect(mApp->plugins(), &PluginProxy::mainWindowDeleted, this, &FCM_Plugin::mainWindowDeleted);
74
75 m_timer = new QTimer(this);
76 m_timer->setInterval(refreshInterval);
77 connect(m_timer, &QTimer::timeout, this, &FCM_Plugin::autoRefresh);
78
79 // start timer if needed
80 startStopTimer();
81
82 if (state == StartupInitState && readSettings().value(QL1S("deleteAllOnStartExit")).toBool()) {
83 loadFlashCookies();
84
85 removeAllButWhitelisted();
86 }
87
88 if (state == LateInitState) {
89 const auto windows = mApp->windows();
90 for (BrowserWindow* window : windows) {
91 mainWindowCreated(window);
92 }
93 }
94}
95
97{
98 if (m_fcmDialog) {
99 m_fcmDialog->close();
100 }
101
102 if (mApp->isClosing() && readSettings().value(QL1S("deleteAllOnStartExit")).toBool()) {
103 removeAllButWhitelisted();
104 }
105
106 const auto windows = mApp->windows();
107 for (BrowserWindow* window : windows) {
108 mainWindowDeleted(window);
109 }
110
111 delete m_fcmDialog;
112}
113
115{
116 return (QString::fromLatin1(Qz::VERSION) == QLatin1String(FALKON_VERSION));
117}
118
119void FCM_Plugin::showSettings(QWidget* parent)
120{
121 Q_UNUSED(parent)
122
123 showFlashCookieManager();
124 m_fcmDialog->showPage(2);
125}
126
128{
129 auto* showFCM = new QAction(QIcon(QSL(":/flashcookiemanager/data/flash-cookie-manager.png")), tr("Flash Cookie Manager"), menu);
130 connect(showFCM, &QAction::triggered, this, &FCM_Plugin::showFlashCookieManager);
131 menu->addAction(showFCM);
132}
133
134void FCM_Plugin::setFlashCookies(const QList<FlashCookie> &flashCookies)
135{
136 m_flashCookies = flashCookies;
137}
138
139QList<FlashCookie> FCM_Plugin::flashCookies()
140{
141 if (m_flashCookies.isEmpty()) {
142 loadFlashCookies();
143 }
144 return m_flashCookies;
145}
146
148{
149 return m_newCookiesList;
150}
151
153{
154 m_newCookiesList.clear();
155}
156
158{
159 m_flashCookies.clear();
160}
161
162bool FCM_Plugin::isBlacklisted(const FlashCookie &flashCookie)
163{
164 return readSettings().value(QL1S("flashCookiesBlacklist")).toStringList().contains(flashCookie.origin);
165}
166
167bool FCM_Plugin::isWhitelisted(const FlashCookie &flashCookie)
168{
169 return readSettings().value(QL1S("flashCookiesWhitelist")).toStringList().contains(flashCookie.origin);
170}
171
172void FCM_Plugin::removeAllButWhitelisted()
173{
174 for (const FlashCookie &flashCookie : std::as_const(m_flashCookies)) {
175 if (isWhitelisted(flashCookie)) {
176 continue;
177 }
178
179 removeCookie(flashCookie);
180 }
181}
182
183QString FCM_Plugin::sharedObjectDirName() const
184{
185 if (flashPlayerDataPath().contains(QL1S("macromedia"), Qt::CaseInsensitive) ||
186 !flashPlayerDataPath().contains(QL1S("/.gnash"), Qt::CaseInsensitive)) {
187 return QLatin1String(QL1S("/#SharedObjects/"));
188 }
189 else {
190 return QLatin1String(QL1S("/SharedObjects/"));
191 }
192}
193
195{
196 return DataPaths::currentProfilePath() + QSL("/Pepper Data/Shockwave Flash/WritableRoot/");
197}
198
199QVariantHash FCM_Plugin::readSettings() const
200{
201 if (m_settingsHash.isEmpty()) {
202 m_settingsHash.insert(QL1S("autoMode"), QVariant(false));
203 m_settingsHash.insert(QL1S("deleteAllOnStartExit"), QVariant(false));
204 m_settingsHash.insert(QL1S("notification"), QVariant(false));
205 m_settingsHash.insert(QL1S("flashCookiesWhitelist"), QVariant());
206 m_settingsHash.insert(QL1S("flashCookiesBlacklist"), QVariant());
207
208 QSettings settings(m_settingsPath + QL1S("/extensions.ini"), QSettings::IniFormat);
209 settings.beginGroup(QL1S("FlashCookieManager"));
210 QVariantHash::iterator i = m_settingsHash.begin();
211 while (i != m_settingsHash.end()) {
212 *i = settings.value(i.key(), i.value());
213 ++i;
214 }
215
216 settings.endGroup();
217 }
218
219 return m_settingsHash;
220}
221
222void FCM_Plugin::writeSettings(const QVariantHash &hashSettings)
223{
224 m_settingsHash = hashSettings;
225
226 QSettings settings(m_settingsPath + QL1S(QL1S("/extensions.ini")), QSettings::IniFormat);
227 settings.beginGroup(QL1S("FlashCookieManager"));
228 QVariantHash::const_iterator i = m_settingsHash.constBegin();
229 while (i != m_settingsHash.constEnd()) {
230 settings.setValue(i.key(), i.value());
231 ++i;
232 }
233
234 settings.endGroup();
235
236 startStopTimer();
237}
238
239void FCM_Plugin::removeCookie(const FlashCookie &flashCookie)
240{
241 if (m_flashCookies.contains(flashCookie)) {
242 m_flashCookies.removeOne(flashCookie);
243 if (QFile(flashCookie.path + QL1C('/') + flashCookie.name).remove()) {
244 QDir dir(flashCookie.path);
245 dir.rmpath(flashCookie.path);
246 }
247 }
248}
249
250void FCM_Plugin::autoRefresh()
251{
252 if (m_fcmDialog && m_fcmDialog->isVisible()) {
253 return;
254 }
255
256 QList<FlashCookie> oldflashCookies = m_flashCookies;
257 loadFlashCookies();
258 QStringList newCookieList;
259
260 for (const FlashCookie &flashCookie : std::as_const(m_flashCookies)) {
261 if (isBlacklisted(flashCookie)) {
262 removeCookie(flashCookie);
263 continue;
264 }
265
266 if (isWhitelisted(flashCookie)) {
267 continue;
268 }
269
270 bool newCookie = true;
271 for (const FlashCookie &oldFlashCookie : std::as_const(oldflashCookies)) {
272 if (QString(oldFlashCookie.path + oldFlashCookie.name) ==
273 QString(flashCookie.path + flashCookie.name)) {
274 newCookie = false;
275 break;
276 }
277 }
278
279 if (newCookie) {
280 newCookieList << flashCookie.path + QL1C('/') + flashCookie.name;
281 }
282 }
283
284 if (!newCookieList.isEmpty() && readSettings().value(QL1S("notification")).toBool()) {
285 m_newCookiesList << newCookieList;
286 BrowserWindow* window = mApp->getWindow();
287 if (!window) {
288 return;
289 }
290 TabbedWebView* weView = window->weView();
291 if (!weView) {
292 return;
293 }
294
295 auto* notif = new FCM_Notification(this, newCookieList.size());
296 weView->addNotification(notif);
297 }
298}
299
300void FCM_Plugin::showFlashCookieManager()
301{
302 if (!m_fcmDialog) {
303 m_fcmDialog = new FCM_Dialog(this);
304 }
305
306 m_fcmDialog->refreshView();
307 m_fcmDialog->showPage(0);
308 m_fcmDialog->show();
309 m_fcmDialog->raise();
310}
311
312void FCM_Plugin::mainWindowCreated(BrowserWindow *window)
313{
314 window->statusBar()->addButton(createStatusBarIcon(window));
315 window->navigationBar()->addToolButton(createStatusBarIcon(window));
316}
317
318void FCM_Plugin::mainWindowDeleted(BrowserWindow *window)
319{
320 if (!window) {
321 return;
322 }
323
324 if (m_fcmDialog && m_fcmDialog->parent() == window) {
325 m_fcmDialog->setParent(nullptr);
326 }
327
328 window->statusBar()->removeButton(m_statusBarIcons.value(window));
329 window->navigationBar()->removeToolButton(m_statusBarIcons.value(window));
330
331 delete m_statusBarIcons.value(window);
332 m_statusBarIcons.remove(window);
333}
334
335void FCM_Plugin::startStopTimer()
336{
337 if (readSettings().value(QL1S("autoMode")).toBool()) {
338 if (!m_timer->isActive()) {
339 if (m_flashCookies.isEmpty()) {
340 loadFlashCookies();
341 }
342
343 m_timer->start();
344 }
345 }
346 else {
347 m_timer->stop();
348 }
349}
350
351AbstractButtonInterface* FCM_Plugin::createStatusBarIcon(BrowserWindow* mainWindow)
352{
353 if (m_statusBarIcons.contains(mainWindow)) {
354 return m_statusBarIcons.value(mainWindow);
355 }
356
357 auto* icon = new FCM_Button(this);
358 icon->setIcon(QIcon(QSL(":/flashcookiemanager/data/flash-cookie-manager.png")));
359 icon->setTitle(tr("Flash Cookie Manager"));
360 icon->setToolTip(tr("Show Flash Cookie Manager"));
361 connect(icon, &AbstractButtonInterface::clicked, this, &FCM_Plugin::showFlashCookieManager);
362
363 m_statusBarIcons.insert(mainWindow, icon);
364
365 return icon;
366}
367
368void FCM_Plugin::loadFlashCookies()
369{
370 m_flashCookies.clear();
371 loadFlashCookies(flashPlayerDataPath());
372}
373
374void FCM_Plugin::loadFlashCookies(QString path)
375{
376 QDir solDir(path);
377 QStringList entryList = solDir.entryList();
378 entryList.removeAll(QL1S("."));
379 entryList.removeAll(QL1S(".."));
380
381 for (QString entry : std::as_const(entryList)) {
382 if (path.endsWith(QL1S("#SharedObjects")) && entry == QL1S("#AppContainer")) {
383 // specific to IE and Windows
384 continue;
385 }
386
387 path.replace(QL1C('\\'), QL1C('/'));
388 QFileInfo entryInfo(path + QL1C('/') + entry);
389 if (entryInfo.isDir()) {
390 loadFlashCookies(entryInfo.filePath());
391 }
392 else if (entryInfo.isFile() && entryInfo.suffix() == QL1S("sol")) {
393 insertFlashCookie(entryInfo.filePath());
394 }
395 }
396}
397
398void FCM_Plugin::insertFlashCookie(const QString &path)
399{
400 QFile solFile(path);
401 if (!solFile.open(QFile::ReadOnly)) {
402 return;
403 }
404
405 QByteArray file = solFile.readAll();
406 for (int i = 0; i < file.size(); ++i) {
407 if (!((file.at(i) >= 'a' && file.at(i) <= 'z') || (file.at(i) >= 'A' && file.at(i) <= 'Z') ||
408 (file.at(i) >= '0' && file.at(i) <= '9'))) {
409 file[i] = ' ';
410 }
411 }
412
413 QString fileStr = QString(QString::fromUtf8(file));
414 fileStr = fileStr.split(QL1C('.'), Qt::SkipEmptyParts).join(QL1S("\n"));
415
416 QFileInfo solFileInfo(solFile);
417
418 FlashCookie flashCookie;
419 flashCookie.contents = fileStr;
420 flashCookie.name = solFileInfo.fileName();
421 flashCookie.path = solFileInfo.canonicalPath();
422 flashCookie.size = (int)solFile.size();
423 flashCookie.lastModification = solFileInfo.lastModified();
424 flashCookie.origin = extractOriginFrom(path);
425
426 m_flashCookies << flashCookie;
427}
428
429QString FCM_Plugin::extractOriginFrom(const QString &path)
430{
431 QString origin = path;
432 if (path.startsWith(flashPlayerDataPath() + sharedObjectDirName())) {
433 origin.remove(flashPlayerDataPath() + sharedObjectDirName());
434 if (origin.indexOf(QL1C('/')) != -1) {
435 origin.remove(0, origin.indexOf(QL1C('/')) + 1);
436 }
437 }
438 else if (path.startsWith(flashPlayerDataPath() + QL1S("/macromedia.com/support/flashplayer/sys/"))) {
439 origin.remove(flashPlayerDataPath() + QL1S("/macromedia.com/support/flashplayer/sys/"));
440 if (origin == QL1S("settings.sol")) {
441 return tr("!default");
442 }
443 else if (origin.startsWith(QL1C('#'))) {
444 origin.remove(0, 1);
445 }
446 }
447 else {
448 origin.clear();
449 }
450
451 int index = origin.indexOf(QL1C('/'));
452 if (index == -1) {
453 return tr("!other");
454 }
455 origin.remove(index, origin.size());
456 if (origin == QL1S("localhost") || origin == QL1S("local")) {
457 origin = QL1S("!localhost");
458 }
459
460 return origin;
461}
462
463#include "fcm_plugin.moc"
void clicked(AbstractButtonInterface::ClickController *controller)
NavigationBar * navigationBar() const
StatusBar * statusBar() const
TabbedWebView * weView() const
static QString currentProfilePath()
Definition: datapaths.cpp:95
FCM_Button(QObject *parent=nullptr)
Definition: fcm_plugin.cpp:47
QString name() const override
Definition: fcm_plugin.cpp:57
QString id() const override
Definition: fcm_plugin.cpp:52
void unload() override
Definition: fcm_plugin.cpp:96
bool testPlugin() override
Definition: fcm_plugin.cpp:114
void clearCache()
Definition: fcm_plugin.cpp:157
void init(InitState state, const QString &settingsPath) override
Definition: fcm_plugin.cpp:68
QStringList newCookiesList()
Definition: fcm_plugin.cpp:147
QVariantHash readSettings() const
Definition: fcm_plugin.cpp:199
void clearNewOrigins()
Definition: fcm_plugin.cpp:152
void showSettings(QWidget *parent) override
Definition: fcm_plugin.cpp:119
void populateExtensionsMenu(QMenu *menu) override
Definition: fcm_plugin.cpp:127
void removeCookie(const FlashCookie &flashCookie)
Definition: fcm_plugin.cpp:239
QString flashPlayerDataPath() const
Definition: fcm_plugin.cpp:194
QList< FlashCookie > flashCookies()
Definition: fcm_plugin.cpp:139
void setFlashCookies(const QList< FlashCookie > &flashCookies)
Definition: fcm_plugin.cpp:134
void writeSettings(const QVariantHash &hashSettings)
Definition: fcm_plugin.cpp:222
void removeToolButton(AbstractButtonInterface *button)
void addToolButton(AbstractButtonInterface *button)
void mainWindowDeleted(BrowserWindow *window)
void mainWindowCreated(BrowserWindow *window)
void addButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:217
void removeButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:235
void addNotification(QWidget *notif)
Definition: webview.cpp:286
const int refreshInterval
Definition: fcm_plugin.cpp:41
#define mApp
int value(const QColor &c)
Definition: colors.cpp:238
FALKON_EXPORT const char * VERSION
Definition: qzcommon.cpp:26
i
Definition: i18n.py:23
State state
#define QL1S(x)
Definition: qzcommon.h:44
#define QL1C(x)
Definition: qzcommon.h:48
#define QSL(x)
Definition: qzcommon.h:40