File indexing completed on 2024-05-12 04:57:59
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2010-2017 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "cookiejar.h" 0019 #include "mainapplication.h" 0020 #include "datapaths.h" 0021 #include "autosaver.h" 0022 #include "settings.h" 0023 #include "qztools.h" 0024 0025 #include <QNetworkCookie> 0026 #include <QWebEngineProfile> 0027 #include <QWebEngineSettings> 0028 #include <QDateTime> 0029 0030 //#define COOKIE_DEBUG 0031 0032 CookieJar::CookieJar(QObject* parent) 0033 : QObject(parent) 0034 , m_client(mApp->webProfile()->cookieStore()) 0035 { 0036 loadSettings(); 0037 m_client->loadAllCookies(); 0038 0039 m_client->setCookieFilter(std::bind(&CookieJar::cookieFilter, this, std::placeholders::_1)); 0040 0041 connect(m_client, &QWebEngineCookieStore::cookieAdded, this, &CookieJar::slotCookieAdded); 0042 connect(m_client, &QWebEngineCookieStore::cookieRemoved, this, &CookieJar::slotCookieRemoved); 0043 } 0044 0045 CookieJar::~CookieJar() 0046 { 0047 m_client->setCookieFilter(nullptr); 0048 } 0049 0050 void CookieJar::loadSettings() 0051 { 0052 Settings settings; 0053 settings.beginGroup(QSL("Cookie-Settings")); 0054 m_allowCookies = settings.value(QSL("allowCookies"), true).toBool(); 0055 m_filterThirdParty = settings.value(QSL("filterThirdPartyCookies"), false).toBool(); 0056 m_filterTrackingCookie = settings.value(QSL("filterTrackingCookie"), false).toBool(); 0057 m_whitelist = settings.value(QSL("whitelist"), QStringList()).toStringList(); 0058 m_blacklist = settings.value(QSL("blacklist"), QStringList()).toStringList(); 0059 settings.endGroup(); 0060 } 0061 0062 void CookieJar::setAllowCookies(bool allow) 0063 { 0064 m_allowCookies = allow; 0065 } 0066 0067 void CookieJar::deleteCookie(const QNetworkCookie &cookie) 0068 { 0069 m_client->deleteCookie(cookie); 0070 } 0071 0072 QVector<QNetworkCookie> CookieJar::getAllCookies() const 0073 { 0074 return m_cookies; 0075 } 0076 0077 void CookieJar::deleteAllCookies(bool deleteAll) 0078 { 0079 if (deleteAll || m_whitelist.isEmpty()) { 0080 m_client->deleteAllCookies(); 0081 return; 0082 } 0083 0084 for (const QNetworkCookie &cookie : std::as_const(m_cookies)) { 0085 if (!listMatchesDomain(m_whitelist, cookie.domain())) { 0086 m_client->deleteCookie(cookie); 0087 } 0088 } 0089 } 0090 0091 bool CookieJar::matchDomain(QString cookieDomain, QString siteDomain) const 0092 { 0093 // According to RFC 6265 0094 0095 // Remove leading dot 0096 if (cookieDomain.startsWith(QLatin1Char('.'))) { 0097 cookieDomain.remove(0, 1); 0098 } 0099 0100 if (siteDomain.startsWith(QLatin1Char('.'))) { 0101 siteDomain.remove(0, 1); 0102 } 0103 0104 return QzTools::matchDomain(cookieDomain, siteDomain); 0105 } 0106 0107 bool CookieJar::listMatchesDomain(const QStringList &list, const QString &cookieDomain) const 0108 { 0109 for (const QString &d : list) { 0110 if (matchDomain(d, cookieDomain)) { 0111 return true; 0112 } 0113 } 0114 0115 return false; 0116 } 0117 0118 void CookieJar::slotCookieAdded(const QNetworkCookie &cookie) 0119 { 0120 if (rejectCookie(QString(), cookie, cookie.domain())) { 0121 m_client->deleteCookie(cookie); 0122 return; 0123 } 0124 0125 m_cookies.append(cookie); 0126 Q_EMIT cookieAdded(cookie); 0127 } 0128 0129 void CookieJar::slotCookieRemoved(const QNetworkCookie &cookie) 0130 { 0131 if (m_cookies.removeOne(cookie)) 0132 Q_EMIT cookieRemoved(cookie); 0133 } 0134 0135 bool CookieJar::cookieFilter(const QWebEngineCookieStore::FilterRequest &request) const 0136 { 0137 if (!m_allowCookies) { 0138 bool result = listMatchesDomain(m_whitelist, request.origin.host()); 0139 if (!result) { 0140 #ifdef COOKIE_DEBUG 0141 qDebug() << "not in whitelist" << request.origin; 0142 #endif 0143 return false; 0144 } 0145 } 0146 0147 if (m_allowCookies) { 0148 bool result = listMatchesDomain(m_blacklist, request.origin.host()); 0149 if (result) { 0150 #ifdef COOKIE_DEBUG 0151 qDebug() << "found in blacklist" << request.origin.host(); 0152 #endif 0153 return false; 0154 } 0155 } 0156 0157 if (m_filterThirdParty && request.thirdParty) { 0158 #ifdef COOKIE_DEBUG 0159 qDebug() << "thirdParty" << request.firstPartyUrl << request.origin; 0160 #endif 0161 return false; 0162 } 0163 0164 return true; 0165 } 0166 0167 bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie, const QString &cookieDomain) const 0168 { 0169 Q_UNUSED(domain) 0170 0171 if (!m_allowCookies) { 0172 bool result = listMatchesDomain(m_whitelist, cookieDomain); 0173 if (!result) { 0174 #ifdef COOKIE_DEBUG 0175 qDebug() << "not in whitelist" << cookie; 0176 #endif 0177 return true; 0178 } 0179 } 0180 0181 if (m_allowCookies) { 0182 bool result = listMatchesDomain(m_blacklist, cookieDomain); 0183 if (result) { 0184 #ifdef COOKIE_DEBUG 0185 qDebug() << "found in blacklist" << cookie; 0186 #endif 0187 return true; 0188 } 0189 } 0190 0191 #ifdef QTWEBENGINE_DISABLED 0192 if (m_filterThirdParty) { 0193 bool result = matchDomain(cookieDomain, domain); 0194 if (!result) { 0195 #ifdef COOKIE_DEBUG 0196 qDebug() << "purged for domain mismatch" << cookie << cookieDomain << domain; 0197 #endif 0198 return true; 0199 } 0200 } 0201 #endif 0202 0203 if (m_filterTrackingCookie && cookie.name().startsWith("__utm")) { 0204 #ifdef COOKIE_DEBUG 0205 qDebug() << "purged as tracking " << cookie; 0206 #endif 0207 return true; 0208 } 0209 0210 return false; 0211 }