File indexing completed on 2024-05-19 05:00:54
0001 /* 0002 kcookiesmanagement.cpp - Cookies manager 0003 0004 SPDX-FileCopyrightText: 2000-2001 Marco Pinelli <pinmc@orion.it> 0005 SPDX-FileCopyrightText: 2000-2001 Dawit Alemayehu <adawit@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 // Own 0011 #include "kcookiesmanagement.h" 0012 0013 // Qt 0014 #include <QDBusConnection> 0015 #include <QDBusInterface> 0016 #include <QDBusReply> 0017 #include <QPushButton> 0018 #include <QDateTime> 0019 #include <QLocale> 0020 #include <QApplication> 0021 0022 // KDE 0023 #include <KLocalizedString> 0024 #include <KMessageBox> 0025 0026 // Local 0027 #include "kcookiesmain.h" 0028 #include "kcookiespolicies.h" 0029 #include "interfaces/browser.h" 0030 #include "interfaces/cookiejar.h" 0031 0032 using namespace KonqInterfaces; 0033 0034 QString tolerantFromAce(const QByteArray &_domain); 0035 0036 struct CookieProp { 0037 QNetworkCookie cookie; 0038 QString host; 0039 bool allLoaded; 0040 0041 QString expireDate() const { 0042 QDateTime expDate = cookie.expirationDate(); 0043 if (expDate.isValid()) { 0044 return QLocale().toString(expDate, QLocale::ShortFormat); 0045 } else { 0046 return i18n("End of session"); 0047 } 0048 } 0049 0050 QString secure() const { 0051 return i18n(cookie.isSecure() ? "Yes" : "No"); 0052 } 0053 }; 0054 0055 CookieListViewItem::CookieListViewItem(QTreeWidget *parent, const QString &dom) 0056 : QTreeWidgetItem(parent) 0057 { 0058 init(nullptr, dom); 0059 } 0060 0061 CookieListViewItem::CookieListViewItem(QTreeWidgetItem *parent, CookieProp *cookie) 0062 : QTreeWidgetItem(parent) 0063 { 0064 init(cookie); 0065 } 0066 0067 CookieListViewItem::~CookieListViewItem() 0068 { 0069 delete mCookie; 0070 } 0071 0072 void CookieListViewItem::init(CookieProp *cookie, const QString &domain, bool cookieLoaded) 0073 { 0074 mCookie = cookie; 0075 mDomain = domain; 0076 mCookiesLoaded = cookieLoaded; 0077 0078 if (mCookie) { 0079 if (mDomain.isEmpty()) { 0080 setText(0, tolerantFromAce(mCookie->host.toLatin1())); 0081 } else { 0082 setText(0, tolerantFromAce(mDomain.toLatin1())); 0083 } 0084 setText(1, mCookie->cookie.name()); 0085 } else { 0086 QString siteName; 0087 if (mDomain.startsWith(QLatin1Char('.'))) { 0088 siteName = mDomain.mid(1); 0089 } else { 0090 siteName = mDomain; 0091 } 0092 setText(0, tolerantFromAce(siteName.toLatin1())); 0093 } 0094 } 0095 0096 CookieProp *CookieListViewItem::leaveCookie() 0097 { 0098 CookieProp *ret = mCookie; 0099 mCookie = nullptr; 0100 return ret; 0101 } 0102 0103 KCookiesManagement::KCookiesManagement(QObject *parent, const KPluginMetaData &md, const QVariantList &) 0104 : KCModule(parent, md) 0105 , mDeleteAllFlag(false) 0106 , mMainWidget(qobject_cast<QWidget*>(parent)) 0107 { 0108 mUi.setupUi(widget()); 0109 mUi.searchLineEdit->setTreeWidget(mUi.cookiesTreeWidget); 0110 mUi.cookiesTreeWidget->setColumnWidth(0, 150); 0111 0112 connect(mUi.deleteButton, &QAbstractButton::clicked, this, &KCookiesManagement::deleteCurrent); 0113 connect(mUi.deleteAllButton, &QAbstractButton::clicked, this, &KCookiesManagement::deleteAll); 0114 connect(mUi.reloadButton, &QAbstractButton::clicked, this, &KCookiesManagement::reload); 0115 connect(mUi.cookiesTreeWidget, &QTreeWidget::itemExpanded, this, &KCookiesManagement::listCookiesForDomain); 0116 connect(mUi.cookiesTreeWidget, &QTreeWidget::currentItemChanged, this, &KCookiesManagement::updateForItem); 0117 connect(mUi.cookiesTreeWidget, &QTreeWidget::itemDoubleClicked, this, &KCookiesManagement::showConfigPolicyDialog); 0118 connect(mUi.configPolicyButton, &QAbstractButton::clicked, this, &KCookiesManagement::showConfigPolicyDialog); 0119 } 0120 0121 KCookiesManagement::~KCookiesManagement() 0122 { 0123 } 0124 0125 void KCookiesManagement::load() 0126 { 0127 defaults(); 0128 } 0129 0130 void KCookiesManagement::save() 0131 { 0132 Browser *browser = Browser::browser(qApp); 0133 CookieJar *jar = browser ? browser->cookieJar() : nullptr; 0134 0135 // If delete all cookies was requested! 0136 if (mDeleteAllFlag) { 0137 if (jar) { 0138 jar->removeAllCookies(); 0139 } 0140 mDeleteAllFlag = false; // deleted[Cookies|Domains] have been cleared yet 0141 } 0142 0143 if (!mDeletedDomains.isEmpty()) { 0144 if (jar) { 0145 for (const QString &d :mDeletedDomains) { 0146 jar->removeCookiesWithDomain(d); 0147 } 0148 } 0149 mDeletedDomains.clear(); 0150 } 0151 0152 // Individual cookies were deleted... 0153 if (jar) { 0154 for (auto it = mDeletedCookies.constBegin(); it != mDeletedCookies.constEnd(); ++it) { 0155 CookiePropList list = it.value(); 0156 QVector<QNetworkCookie> toDelete; 0157 std::transform(list.constBegin(), list.constEnd(), std::back_inserter(toDelete), [](CookieProp* p){return p->cookie;}); 0158 jar->removeCookies(toDelete); 0159 } 0160 } 0161 mDeletedCookies.clear(); 0162 setNeedsSave(false); 0163 } 0164 0165 void KCookiesManagement::defaults() 0166 { 0167 reset(); 0168 reload(); 0169 } 0170 0171 void KCookiesManagement::reset(bool deleteAll) 0172 { 0173 if (!deleteAll) { 0174 mDeleteAllFlag = false; 0175 } 0176 0177 clearCookieDetails(); 0178 mDeletedDomains.clear(); 0179 mDeletedCookies.clear(); 0180 0181 mUi.cookiesTreeWidget->clear(); 0182 mUi.deleteButton->setEnabled(false); 0183 mUi.deleteAllButton->setEnabled(false); 0184 mUi.configPolicyButton->setEnabled(false); 0185 } 0186 0187 void KCookiesManagement::clearCookieDetails() 0188 { 0189 mUi.nameLineEdit->clear(); 0190 mUi.valueLineEdit->clear(); 0191 mUi.domainLineEdit->clear(); 0192 mUi.pathLineEdit->clear(); 0193 mUi.expiresLineEdit->clear(); 0194 mUi.secureLineEdit->clear(); 0195 } 0196 0197 QSet<QNetworkCookie> KCookiesManagement::getCookies() 0198 { 0199 Browser *browser = Browser::browser(qApp); 0200 CookieJar *jar = browser ? browser->cookieJar() : nullptr; 0201 if (!jar) { 0202 return {}; 0203 } 0204 return jar->cookies(); 0205 } 0206 0207 void KCookiesManagement::reload() 0208 { 0209 0210 if (mUi.cookiesTreeWidget->topLevelItemCount() > 0) { 0211 reset(); 0212 } 0213 0214 CookieSet cookies = getCookies(); 0215 QStringList domains; 0216 std::transform(cookies.constBegin(), cookies.constEnd(), std::back_inserter(domains), [](const QNetworkCookie &c){return c.domain();}); 0217 0218 CookieListViewItem *dom; 0219 for (const QString &domain : domains) { 0220 const QString siteName = (domain.startsWith(QLatin1Char('.')) ? domain.mid(1) : domain); 0221 if (mUi.cookiesTreeWidget->findItems(siteName, Qt::MatchFixedString).isEmpty()) { 0222 dom = new CookieListViewItem(mUi.cookiesTreeWidget, domain); 0223 dom->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 0224 } 0225 } 0226 0227 // are there any cookies? 0228 mUi.deleteAllButton->setEnabled(mUi.cookiesTreeWidget->topLevelItemCount() > 0); 0229 mUi.cookiesTreeWidget->sortItems(0, Qt::AscendingOrder); 0230 setNeedsSave(false); 0231 } 0232 0233 Q_DECLARE_METATYPE(QList<int>) 0234 0235 void KCookiesManagement::listCookiesForDomain(QTreeWidgetItem *item) 0236 { 0237 CookieListViewItem *cookieDom = static_cast<CookieListViewItem *>(item); 0238 if (!cookieDom || cookieDom->cookiesLoaded()) { 0239 return; 0240 } 0241 0242 QStringList cookiesString; 0243 // Always check for cookies in both "foo.bar" and ".foo.bar" domains... 0244 const QStringList domains{cookieDom->domain(), QLatin1String(".") + cookieDom->domain()}; 0245 CookieSet cookies = getCookies(); 0246 QList<QNetworkCookie> filteredCookies; 0247 auto filter = [domains](const QNetworkCookie &c){return domains.contains(c.domain());}; 0248 std::copy_if(cookies.constBegin(), cookies.constEnd(), std::back_inserter(filteredCookies), filter); 0249 for (const QNetworkCookie &c : filteredCookies) { 0250 CookieProp *details = new CookieProp; 0251 details->cookie.setDomain(c.domain()); 0252 details->cookie.setPath(c.path()); 0253 details->cookie.setName(c.name()); 0254 details->host = c.domain(); 0255 if (details->host.startsWith('.')) { 0256 details->host.remove(0, 1); 0257 } 0258 details->allLoaded = false; 0259 new CookieListViewItem(item, details); 0260 } 0261 0262 if (!filteredCookies.isEmpty()) { 0263 static_cast<CookieListViewItem *>(item)->setCookiesLoaded(); 0264 mUi.searchLineEdit->updateSearch(); 0265 } 0266 } 0267 0268 bool KCookiesManagement::cookieDetails(CookieProp *cookie) 0269 { 0270 CookieSet cookies = getCookies(); 0271 const QStringList domains{cookie->cookie.domain(), QLatin1String(".") + cookie->cookie.domain()}; 0272 auto filter = [cookie, domains](const QNetworkCookie &c){ 0273 return domains.contains(c.domain()) && c.path() == cookie->cookie.path() && c.name() == cookie->cookie.name(); 0274 }; 0275 auto it = std::find_if(cookies.constBegin(), cookies.constEnd(), filter); 0276 if (it == cookies.constEnd()) { 0277 return false; 0278 } 0279 cookie->cookie = *it; 0280 cookie->allLoaded = true; 0281 return true; 0282 } 0283 0284 void KCookiesManagement::updateForItem(QTreeWidgetItem *item) 0285 { 0286 if (item) { 0287 CookieListViewItem *cookieItem = static_cast<CookieListViewItem *>(item); 0288 CookieProp *cookie = cookieItem->cookie(); 0289 0290 if (cookie) { 0291 if (cookie->allLoaded || cookieDetails(cookie)) { 0292 mUi.nameLineEdit->setText(cookie->cookie.name()); 0293 mUi.valueLineEdit->setText(cookie->cookie.value()); 0294 mUi.domainLineEdit->setText(cookie->cookie.domain()); 0295 mUi.pathLineEdit->setText(cookie->cookie.path()); 0296 mUi.expiresLineEdit->setText(cookie->expireDate()); 0297 mUi.secureLineEdit->setText(cookie->secure()); 0298 } 0299 0300 mUi.configPolicyButton->setEnabled(false); 0301 } else { 0302 clearCookieDetails(); 0303 mUi.configPolicyButton->setEnabled(true); 0304 } 0305 } else { 0306 mUi.configPolicyButton->setEnabled(false); 0307 } 0308 mUi.deleteButton->setEnabled(item != nullptr); 0309 } 0310 0311 void KCookiesManagement::showConfigPolicyDialog() 0312 { 0313 // Get current item 0314 CookieListViewItem *item = static_cast<CookieListViewItem *>(mUi.cookiesTreeWidget->currentItem()); 0315 Q_ASSERT(item); // the button is disabled otherwise 0316 0317 if (item) { 0318 KCookiesMain *mainDlg = qobject_cast<KCookiesMain *>(mMainWidget); 0319 // must be present or something is really wrong. 0320 Q_ASSERT(mainDlg); 0321 0322 KCookiesPolicies *policyDlg = mainDlg->policyDlg(); 0323 // must be present unless someone rewrote the widget in which case 0324 // this needs to be re-written as well. 0325 Q_ASSERT(policyDlg); 0326 0327 policyDlg->setPolicy(item->domain()); 0328 } 0329 } 0330 0331 void KCookiesManagement::deleteCurrent() 0332 { 0333 QTreeWidgetItem *currentItem = mUi.cookiesTreeWidget->currentItem(); 0334 Q_ASSERT(currentItem); // the button is disabled otherwise 0335 CookieListViewItem *item = static_cast<CookieListViewItem *>(currentItem); 0336 if (item->cookie()) { 0337 CookieListViewItem *parent = static_cast<CookieListViewItem *>(item->parent()); 0338 CookiePropList list = mDeletedCookies.value(parent->domain()); 0339 list.append(item->leaveCookie()); 0340 mDeletedCookies.insert(parent->domain(), list); 0341 delete item; 0342 if (parent->childCount() == 0) { 0343 delete parent; 0344 } 0345 } else { 0346 mDeletedDomains.append(item->domain()); 0347 delete item; 0348 } 0349 0350 currentItem = mUi.cookiesTreeWidget->currentItem(); 0351 if (currentItem) { 0352 mUi.cookiesTreeWidget->setCurrentItem(currentItem); 0353 } else { 0354 clearCookieDetails(); 0355 } 0356 0357 mUi.deleteAllButton->setEnabled(mUi.cookiesTreeWidget->topLevelItemCount() > 0); 0358 0359 setNeedsSave(true); 0360 } 0361 0362 void KCookiesManagement::deleteAll() 0363 { 0364 mDeleteAllFlag = true; 0365 reset(true); 0366 setNeedsSave(true); 0367 }