Falkon Develop
Cross-platform Qt-based web browser
cookiejar.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2010-2017 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "cookiejar.h"
19#include "mainapplication.h"
20#include "datapaths.h"
21#include "autosaver.h"
22#include "settings.h"
23#include "qztools.h"
24#include "sitesettingsmanager.h"
25#include "sqldatabase.h"
26
27#include <QNetworkCookie>
28#include <QWebEngineProfile>
29#include <QWebEngineSettings>
30#include <QDateTime>
31
32//#define COOKIE_DEBUG
33
34CookieJar::CookieJar(QObject* parent)
35 : QObject(parent)
36 , m_client(mApp->webProfile()->cookieStore())
37{
39 m_client->loadAllCookies();
40
41 m_client->setCookieFilter(std::bind(&CookieJar::cookieFilter, this, std::placeholders::_1));
42
43 connect(m_client, &QWebEngineCookieStore::cookieAdded, this, &CookieJar::slotCookieAdded);
44 connect(m_client, &QWebEngineCookieStore::cookieRemoved, this, &CookieJar::slotCookieRemoved);
45}
46
48{
49 m_client->setCookieFilter(nullptr);
50}
51
53{
54 Settings settings;
55 settings.beginGroup(QSL("Cookie-Settings"));
56 m_allowCookies = settings.value(QSL("allowCookies"), true).toBool();
57 m_filterThirdParty = settings.value(QSL("filterThirdPartyCookies"), false).toBool();
58 m_filterTrackingCookie = settings.value(QSL("filterTrackingCookie"), false).toBool();
59 settings.endGroup();
60}
61
63{
64 m_allowCookies = allow;
65}
66
67void CookieJar::deleteCookie(const QNetworkCookie &cookie)
68{
69 m_client->deleteCookie(cookie);
70}
71
72QVector<QNetworkCookie> CookieJar::getAllCookies() const
73{
74 return m_cookies;
75}
76
77void CookieJar::deleteAllCookies(bool deleteAll)
78{
79 QStringList whitelist;
80 QSqlDatabase db = SqlDatabase::instance()->database();
81 QString sqlColumn = mApp->siteSettingsManager()->optionToSqlColumn(SiteSettingsManager::poAllowCookies);
82 QString sqlTable = mApp->siteSettingsManager()->sqlTable();
83
84 QSqlQuery query(SqlDatabase::instance()->database());
85 query.prepare(QSL("SELECT server FROM %1 WHERE %2=?").arg(sqlTable, sqlColumn));
86 query.addBindValue(SiteSettingsManager::Allow);
87 query.exec();
88
89 while (query.next()) {
90 QString server = query.value(0).toString();
91 whitelist.append(server);
92 }
93
94 if (deleteAll || whitelist.isEmpty()) {
95 m_client->deleteAllCookies();
96 return;
97 }
98
99 for (const QNetworkCookie &cookie : std::as_const(m_cookies)) {
100 if (!listMatchesDomain(whitelist, cookie.domain())) {
101 m_client->deleteCookie(cookie);
102 }
103 }
104}
105
106bool CookieJar::matchDomain(QString cookieDomain, QString siteDomain) const
107{
108 // According to RFC 6265
109
110 // Remove leading dot
111 if (cookieDomain.startsWith(QLatin1Char('.'))) {
112 cookieDomain.remove(0, 1);
113 }
114
115 if (siteDomain.startsWith(QLatin1Char('.'))) {
116 siteDomain.remove(0, 1);
117 }
118
119 return QzTools::matchDomain(cookieDomain, siteDomain);
120}
121
122bool CookieJar::listMatchesDomain(const QStringList &list, const QString &cookieDomain) const
123{
124 for (const QString &d : list) {
125 if (matchDomain(d, cookieDomain)) {
126 return true;
127 }
128 }
129
130 return false;
131}
132
133void CookieJar::slotCookieAdded(const QNetworkCookie &cookie)
134{
135 if (rejectCookie(QString(), cookie, cookie.domain())) {
136 m_client->deleteCookie(cookie);
137 return;
138 }
139
140 m_cookies.append(cookie);
141 Q_EMIT cookieAdded(cookie);
142}
143
144void CookieJar::slotCookieRemoved(const QNetworkCookie &cookie)
145{
146 if (m_cookies.removeOne(cookie))
147 Q_EMIT cookieRemoved(cookie);
148}
149
150bool CookieJar::cookieFilter(const QWebEngineCookieStore::FilterRequest &request) const
151{
152 auto result = mApp->siteSettingsManager()->getPermission(SiteSettingsManager::poAllowCookies, request.origin);
153 if (result == SiteSettingsManager::Default) {
154 result = mApp->siteSettingsManager()->getDefaultPermission(SiteSettingsManager::poAllowCookies);
155 }
156
157 if (!m_allowCookies && (result != SiteSettingsManager::Allow)) {
158#ifdef COOKIE_DEBUG
159 qDebug() << "Cookies not allowed" << request.origin;
160#endif
161 return false;
162 }
163
164 if (m_allowCookies && (result == SiteSettingsManager::Deny)) {
165#ifdef COOKIE_DEBUG
166 qDebug() << "Cookies denied" << request.origin;
167#endif
168 return false;
169 }
170
171 if (m_filterThirdParty && request.thirdParty) {
172#ifdef COOKIE_DEBUG
173 qDebug() << "thirdParty" << request.firstPartyUrl << request.origin;
174#endif
175 return false;
176 }
177
178 return true;
179}
180
181bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie, const QString &cookieDomain) const
182{
183 Q_UNUSED(domain)
184
185 auto result = mApp->siteSettingsManager()->getPermission(SiteSettingsManager::poAllowCookies, cookieDomain);
186 if (result == SiteSettingsManager::Default) {
187 result = mApp->siteSettingsManager()->getDefaultPermission(SiteSettingsManager::poAllowCookies);
188 }
189
190 if (!m_allowCookies && (result != SiteSettingsManager::Allow)) {
191#ifdef COOKIE_DEBUG
192 qDebug() << "Cookies not allowed" << cookie;
193#endif
194 return false;
195 }
196
197 if (m_allowCookies && (result == SiteSettingsManager::Deny)) {
198#ifdef COOKIE_DEBUG
199 qDebug() << "Cookies denied" << cookie;
200#endif
201 return false;
202 }
203
204#ifdef QTWEBENGINE_DISABLED
205 if (m_filterThirdParty) {
206 bool result = matchDomain(cookieDomain, domain);
207 if (!result) {
208#ifdef COOKIE_DEBUG
209 qDebug() << "purged for domain mismatch" << cookie << cookieDomain << domain;
210#endif
211 return true;
212 }
213 }
214#endif
215
216 if (m_filterTrackingCookie && cookie.name().startsWith("__utm")) {
217#ifdef COOKIE_DEBUG
218 qDebug() << "purged as tracking " << cookie;
219#endif
220 return true;
221 }
222
223 return false;
224}
static bool matchDomain(const QString &pattern, const QString &domain)
Definition: qztools.cpp:737
void beginGroup(const QString &prefix)
Definition: settings.cpp:79
void endGroup()
Definition: settings.cpp:84
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:74
static SqlDatabase * instance()
QSqlDatabase database()
#define mApp
#define QSL(x)
Definition: qzcommon.h:40