File indexing completed on 2024-05-12 15:41:56
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 0019 // KDE 0020 #include <KLocalizedString> 0021 #include <KMessageBox> 0022 #include <QDateTime> 0023 #include <QLocale> 0024 // Local 0025 #include "kcookiesmain.h" 0026 #include "kcookiespolicies.h" 0027 0028 QString tolerantFromAce(const QByteArray &_domain); 0029 0030 struct CookieProp { 0031 QString host; 0032 QString name; 0033 QString value; 0034 QString domain; 0035 QString path; 0036 QString expireDate; 0037 QString secure; 0038 bool allLoaded; 0039 }; 0040 0041 CookieListViewItem::CookieListViewItem(QTreeWidget *parent, const QString &dom) 0042 : QTreeWidgetItem(parent) 0043 { 0044 init(nullptr, dom); 0045 } 0046 0047 CookieListViewItem::CookieListViewItem(QTreeWidgetItem *parent, CookieProp *cookie) 0048 : QTreeWidgetItem(parent) 0049 { 0050 init(cookie); 0051 } 0052 0053 CookieListViewItem::~CookieListViewItem() 0054 { 0055 delete mCookie; 0056 } 0057 0058 void CookieListViewItem::init(CookieProp *cookie, const QString &domain, bool cookieLoaded) 0059 { 0060 mCookie = cookie; 0061 mDomain = domain; 0062 mCookiesLoaded = cookieLoaded; 0063 0064 if (mCookie) { 0065 if (mDomain.isEmpty()) { 0066 setText(0, tolerantFromAce(mCookie->host.toLatin1())); 0067 } else { 0068 setText(0, tolerantFromAce(mDomain.toLatin1())); 0069 } 0070 setText(1, mCookie->name); 0071 } else { 0072 QString siteName; 0073 if (mDomain.startsWith(QLatin1Char('.'))) { 0074 siteName = mDomain.mid(1); 0075 } else { 0076 siteName = mDomain; 0077 } 0078 setText(0, tolerantFromAce(siteName.toLatin1())); 0079 } 0080 } 0081 0082 CookieProp *CookieListViewItem::leaveCookie() 0083 { 0084 CookieProp *ret = mCookie; 0085 mCookie = nullptr; 0086 return ret; 0087 } 0088 0089 KCookiesManagement::KCookiesManagement(QWidget *parent, const QVariantList &args) 0090 : KCModule(parent, args) 0091 , mDeleteAllFlag(false) 0092 , mMainWidget(parent) 0093 { 0094 mUi.setupUi(this); 0095 mUi.searchLineEdit->setTreeWidget(mUi.cookiesTreeWidget); 0096 mUi.cookiesTreeWidget->setColumnWidth(0, 150); 0097 0098 connect(mUi.deleteButton, &QAbstractButton::clicked, this, &KCookiesManagement::deleteCurrent); 0099 connect(mUi.deleteAllButton, &QAbstractButton::clicked, this, &KCookiesManagement::deleteAll); 0100 connect(mUi.reloadButton, &QAbstractButton::clicked, this, &KCookiesManagement::reload); 0101 connect(mUi.cookiesTreeWidget, &QTreeWidget::itemExpanded, this, &KCookiesManagement::listCookiesForDomain); 0102 connect(mUi.cookiesTreeWidget, &QTreeWidget::currentItemChanged, this, &KCookiesManagement::updateForItem); 0103 connect(mUi.cookiesTreeWidget, &QTreeWidget::itemDoubleClicked, this, &KCookiesManagement::showConfigPolicyDialog); 0104 connect(mUi.configPolicyButton, &QAbstractButton::clicked, this, &KCookiesManagement::showConfigPolicyDialog); 0105 } 0106 0107 KCookiesManagement::~KCookiesManagement() 0108 { 0109 } 0110 0111 void KCookiesManagement::load() 0112 { 0113 defaults(); 0114 } 0115 0116 void KCookiesManagement::save() 0117 { 0118 // If delete all cookies was requested! 0119 if (mDeleteAllFlag) { 0120 QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), 0121 QStringLiteral("/modules/kcookiejar"), 0122 QStringLiteral("org.kde.KCookieServer"), 0123 QDBusConnection::sessionBus()); 0124 QDBusReply<void> reply = kded.call(QStringLiteral("deleteAllCookies")); 0125 if (!reply.isValid()) { 0126 const QString title = i18n("D-Bus Communication Error"); 0127 const QString message = i18n("Unable to delete all the cookies as requested."); 0128 KMessageBox::error(this, message, title); 0129 return; 0130 } 0131 mDeleteAllFlag = false; // deleted[Cookies|Domains] have been cleared yet 0132 } 0133 0134 // Certain groups of cookies were deleted... 0135 QMutableStringListIterator it(mDeletedDomains); 0136 while (it.hasNext()) { 0137 QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), 0138 QStringLiteral("/modules/kcookiejar"), 0139 QStringLiteral("org.kde.KCookieServer"), 0140 QDBusConnection::sessionBus()); 0141 QDBusReply<void> reply = kded.call(QStringLiteral("deleteCookiesFromDomain"), (it.next())); 0142 if (!reply.isValid()) { 0143 const QString title = i18n("D-Bus Communication Error"); 0144 const QString message = i18n("Unable to delete cookies as requested."); 0145 KMessageBox::error(this, message, title); 0146 return; 0147 } 0148 it.remove(); 0149 } 0150 0151 // Individual cookies were deleted... 0152 bool success = true; // Maybe we can go on... 0153 QMutableHashIterator<QString, CookiePropList> cookiesDom(mDeletedCookies); 0154 while (cookiesDom.hasNext()) { 0155 cookiesDom.next(); 0156 CookiePropList list = cookiesDom.value(); 0157 for (auto it = list.begin(); it < list.end(); ++it) { 0158 CookieProp *cookie = *it; 0159 QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), 0160 QStringLiteral("/modules/kcookiejar"), 0161 QStringLiteral("org.kde.KCookieServer"), 0162 QDBusConnection::sessionBus()); 0163 QDBusReply<void> reply = kded.call(QStringLiteral("deleteCookie"), cookie->domain, cookie->host, cookie->path, cookie->name); 0164 if (!reply.isValid()) { 0165 success = false; 0166 break; 0167 } 0168 0169 list.removeOne(cookie); 0170 } 0171 0172 if (!success) { 0173 break; 0174 } 0175 0176 mDeletedCookies.remove(cookiesDom.key()); 0177 } 0178 0179 Q_EMIT changed(false); 0180 } 0181 0182 void KCookiesManagement::defaults() 0183 { 0184 reset(); 0185 reload(); 0186 } 0187 0188 void KCookiesManagement::reset(bool deleteAll) 0189 { 0190 if (!deleteAll) { 0191 mDeleteAllFlag = false; 0192 } 0193 0194 clearCookieDetails(); 0195 mDeletedDomains.clear(); 0196 mDeletedCookies.clear(); 0197 0198 mUi.cookiesTreeWidget->clear(); 0199 mUi.deleteButton->setEnabled(false); 0200 mUi.deleteAllButton->setEnabled(false); 0201 mUi.configPolicyButton->setEnabled(false); 0202 } 0203 0204 void KCookiesManagement::clearCookieDetails() 0205 { 0206 mUi.nameLineEdit->clear(); 0207 mUi.valueLineEdit->clear(); 0208 mUi.domainLineEdit->clear(); 0209 mUi.pathLineEdit->clear(); 0210 mUi.expiresLineEdit->clear(); 0211 mUi.secureLineEdit->clear(); 0212 } 0213 0214 QString KCookiesManagement::quickHelp() const 0215 { 0216 return i18n("<h1>Cookie Management Quick Help</h1>"); 0217 } 0218 0219 void KCookiesManagement::reload() 0220 { 0221 QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), 0222 QStringLiteral("/modules/kcookiejar"), 0223 QStringLiteral("org.kde.KCookieServer"), 0224 QDBusConnection::sessionBus()); 0225 QDBusReply<QStringList> reply = kded.call(QStringLiteral("findDomains")); 0226 0227 if (!reply.isValid()) { 0228 const QString title = i18n("Information Lookup Failure"); 0229 const QString message = i18n( 0230 "Unable to retrieve information about the " 0231 "cookies stored on your computer."); 0232 KMessageBox::error(this, message, title); 0233 return; 0234 } 0235 0236 if (mUi.cookiesTreeWidget->topLevelItemCount() > 0) { 0237 reset(); 0238 } 0239 0240 CookieListViewItem *dom; 0241 const QStringList domains(reply.value()); 0242 for (const QString &domain : domains) { 0243 const QString siteName = (domain.startsWith(QLatin1Char('.')) ? domain.mid(1) : domain); 0244 if (mUi.cookiesTreeWidget->findItems(siteName, Qt::MatchFixedString).isEmpty()) { 0245 dom = new CookieListViewItem(mUi.cookiesTreeWidget, domain); 0246 dom->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 0247 } 0248 } 0249 0250 // are there any cookies? 0251 mUi.deleteAllButton->setEnabled(mUi.cookiesTreeWidget->topLevelItemCount() > 0); 0252 mUi.cookiesTreeWidget->sortItems(0, Qt::AscendingOrder); 0253 Q_EMIT changed(false); 0254 } 0255 0256 Q_DECLARE_METATYPE(QList<int>) 0257 0258 void KCookiesManagement::listCookiesForDomain(QTreeWidgetItem *item) 0259 { 0260 CookieListViewItem *cookieDom = static_cast<CookieListViewItem *>(item); 0261 if (!cookieDom || cookieDom->cookiesLoaded()) { 0262 return; 0263 } 0264 0265 QStringList cookies; 0266 const QList<int> fields{0, 1, 2, 3}; 0267 // Always check for cookies in both "foo.bar" and ".foo.bar" domains... 0268 const QString domain = cookieDom->domain() + QLatin1String(" .") + cookieDom->domain(); 0269 QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), 0270 QStringLiteral("/modules/kcookiejar"), 0271 QStringLiteral("org.kde.KCookieServer"), 0272 QDBusConnection::sessionBus()); 0273 QDBusReply<QStringList> reply = kded.call(QStringLiteral("findCookies"), QVariant::fromValue(fields), domain, QString(), QString(), QString()); 0274 if (reply.isValid()) { 0275 cookies.append(reply.value()); 0276 } 0277 0278 QStringListIterator it(cookies); 0279 while (it.hasNext()) { 0280 CookieProp *details = new CookieProp; 0281 details->domain = it.next(); 0282 details->path = it.next(); 0283 details->name = it.next(); 0284 details->host = it.next(); 0285 details->allLoaded = false; 0286 new CookieListViewItem(item, details); 0287 } 0288 0289 if (!cookies.isEmpty()) { 0290 static_cast<CookieListViewItem *>(item)->setCookiesLoaded(); 0291 mUi.searchLineEdit->updateSearch(); 0292 } 0293 } 0294 0295 bool KCookiesManagement::cookieDetails(CookieProp *cookie) 0296 { 0297 const QList<int> fields{4, 5, 7}; 0298 0299 QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), 0300 QStringLiteral("/modules/kcookiejar"), 0301 QStringLiteral("org.kde.KCookieServer"), 0302 QDBusConnection::sessionBus()); 0303 QDBusReply<QStringList> reply = 0304 kded.call(QStringLiteral("findCookies"), QVariant::fromValue(fields), cookie->domain, cookie->host, cookie->path, cookie->name); 0305 if (!reply.isValid()) { 0306 return false; 0307 } 0308 0309 const QStringList fieldVal = reply.value(); 0310 0311 auto c = fieldVal.cbegin(); 0312 if (c == fieldVal.cend()) { // empty list, do not crash 0313 return false; 0314 } 0315 0316 bool ok; 0317 cookie->value = *c++; 0318 qint64 tmp = (*c++).toLongLong(&ok); 0319 0320 if (!ok || tmp == 0) { 0321 cookie->expireDate = i18n("End of session"); 0322 } else { 0323 QDateTime expDate = QDateTime::fromSecsSinceEpoch(tmp); 0324 cookie->expireDate = QLocale().toString((expDate), QLocale::ShortFormat); 0325 } 0326 0327 tmp = (*c).toUInt(&ok); 0328 cookie->secure = i18n((ok && tmp) ? "Yes" : "No"); 0329 cookie->allLoaded = true; 0330 return true; 0331 } 0332 0333 void KCookiesManagement::updateForItem(QTreeWidgetItem *item) 0334 { 0335 if (item) { 0336 CookieListViewItem *cookieItem = static_cast<CookieListViewItem *>(item); 0337 CookieProp *cookie = cookieItem->cookie(); 0338 0339 if (cookie) { 0340 if (cookie->allLoaded || cookieDetails(cookie)) { 0341 mUi.nameLineEdit->setText(cookie->name); 0342 mUi.valueLineEdit->setText(cookie->value); 0343 mUi.domainLineEdit->setText(cookie->domain); 0344 mUi.pathLineEdit->setText(cookie->path); 0345 mUi.expiresLineEdit->setText(cookie->expireDate); 0346 mUi.secureLineEdit->setText(cookie->secure); 0347 } 0348 0349 mUi.configPolicyButton->setEnabled(false); 0350 } else { 0351 clearCookieDetails(); 0352 mUi.configPolicyButton->setEnabled(true); 0353 } 0354 } else { 0355 mUi.configPolicyButton->setEnabled(false); 0356 } 0357 mUi.deleteButton->setEnabled(item != nullptr); 0358 } 0359 0360 void KCookiesManagement::showConfigPolicyDialog() 0361 { 0362 // Get current item 0363 CookieListViewItem *item = static_cast<CookieListViewItem *>(mUi.cookiesTreeWidget->currentItem()); 0364 Q_ASSERT(item); // the button is disabled otherwise 0365 0366 if (item) { 0367 KCookiesMain *mainDlg = qobject_cast<KCookiesMain *>(mMainWidget); 0368 // must be present or something is really wrong. 0369 Q_ASSERT(mainDlg); 0370 0371 KCookiesPolicies *policyDlg = mainDlg->policyDlg(); 0372 // must be present unless someone rewrote the widget in which case 0373 // this needs to be re-written as well. 0374 Q_ASSERT(policyDlg); 0375 0376 policyDlg->setPolicy(item->domain()); 0377 } 0378 } 0379 0380 void KCookiesManagement::deleteCurrent() 0381 { 0382 QTreeWidgetItem *currentItem = mUi.cookiesTreeWidget->currentItem(); 0383 Q_ASSERT(currentItem); // the button is disabled otherwise 0384 CookieListViewItem *item = static_cast<CookieListViewItem *>(currentItem); 0385 if (item->cookie()) { 0386 CookieListViewItem *parent = static_cast<CookieListViewItem *>(item->parent()); 0387 CookiePropList list = mDeletedCookies.value(parent->domain()); 0388 list.append(item->leaveCookie()); 0389 mDeletedCookies.insert(parent->domain(), list); 0390 delete item; 0391 if (parent->childCount() == 0) { 0392 delete parent; 0393 } 0394 } else { 0395 mDeletedDomains.append(item->domain()); 0396 delete item; 0397 } 0398 0399 currentItem = mUi.cookiesTreeWidget->currentItem(); 0400 if (currentItem) { 0401 mUi.cookiesTreeWidget->setCurrentItem(currentItem); 0402 } else { 0403 clearCookieDetails(); 0404 } 0405 0406 mUi.deleteAllButton->setEnabled(mUi.cookiesTreeWidget->topLevelItemCount() > 0); 0407 0408 Q_EMIT changed(true); 0409 } 0410 0411 void KCookiesManagement::deleteAll() 0412 { 0413 mDeleteAllFlag = true; 0414 reset(true); 0415 Q_EMIT changed(true); 0416 } 0417 0418 #include "moc_kcookiesmanagement.cpp"