File indexing completed on 2024-05-19 05:55:45
0001 /* 0002 SPDX-FileCopyrightText: 2003 George Staikos <staikos@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "../kwalletmanager_version.h" 0008 #include "konfigurator.h" 0009 0010 #include <KAuth/Action> 0011 #include <KAuth/ActionReply> 0012 #include <KAuth/ExecuteJob> 0013 #include <KConfigGroup> 0014 #include <KMessageBox> 0015 #include <KPluginFactory> 0016 #include <KWallet> 0017 #include <QInputDialog> 0018 #include <kauth_version.h> 0019 0020 #include <KAboutData> 0021 0022 #include <QDebug> 0023 #include <QCheckBox> 0024 #include <QMenu> 0025 #include <QProcess> 0026 #include <QFile> 0027 #include <QPushButton> 0028 #include <QDBusConnection> 0029 #include <QDBusInterface> 0030 #include <QDBusConnectionInterface> 0031 #include <QVBoxLayout> 0032 0033 #define KWALLETMANAGERINTERFACE "org.kde.KWallet" 0034 0035 K_PLUGIN_CLASS_WITH_JSON(KWalletConfig, "kwalletconfig.json") 0036 0037 KWalletConfig::KWalletConfig(QObject *parent, const KPluginMetaData &data) 0038 : KCModule(parent, data) 0039 , _wcw(new WalletConfigWidget(widget())) 0040 , _cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"), KConfig::NoGlobals)) 0041 { 0042 setAuthActionName(QStringLiteral("org.kde.kcontrol.kcmkwallet5.save")); 0043 auto vbox = new QVBoxLayout(widget()); 0044 vbox->setContentsMargins(0, 0, 0, 0); 0045 vbox->addWidget(_wcw); 0046 0047 connect(_wcw->_enabled, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0048 connect(_wcw->_launchManager, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0049 connect(_wcw->_autocloseManager, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0050 connect(_wcw->_autoclose, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0051 connect(_wcw->_closeIdle, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0052 connect(_wcw->_openPrompt, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0053 connect(_wcw->_screensaverLock, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0054 connect(_wcw->_localWalletSelected, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0055 connect(_wcw->_idleTime, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KWalletConfig::configChanged); 0056 connect(_wcw->_launch, &QPushButton::clicked, this, &KWalletConfig::launchManager); 0057 connect(_wcw->_newWallet, &QPushButton::clicked, this, &KWalletConfig::newNetworkWallet); 0058 connect(_wcw->_newLocalWallet, &QPushButton::clicked, this, &KWalletConfig::newLocalWallet); 0059 connect(_wcw->_localWallet, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &KWalletConfig::configChanged); 0060 connect(_wcw->_defaultWallet, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &KWalletConfig::configChanged); 0061 connect(_wcw->_accessList, &QTreeWidget::customContextMenuRequested, this, &KWalletConfig::customContextMenuRequested); 0062 connect(_wcw->_secretServiceAPI, &QCheckBox::clicked, this, &KWalletConfig::configChanged); 0063 0064 _wcw->_accessList->setAllColumnsShowFocus(true); 0065 _wcw->_accessList->setContextMenuPolicy(Qt::CustomContextMenu); 0066 updateWalletLists(); 0067 0068 if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kwalletmanager"))) { 0069 _wcw->_launch->hide(); 0070 } 0071 0072 } 0073 0074 KWalletConfig::~KWalletConfig() = default; 0075 0076 void KWalletConfig::updateWalletLists() 0077 { 0078 const QString p1(_wcw->_localWallet->currentText()); 0079 const QString p2(_wcw->_defaultWallet->currentText()); 0080 0081 _wcw->_localWallet->clear(); 0082 _wcw->_defaultWallet->clear(); 0083 0084 const QStringList wl = KWallet::Wallet::walletList(); 0085 _wcw->_localWallet->addItems(wl); 0086 _wcw->_defaultWallet->addItems(wl); 0087 0088 int index = wl.indexOf(p1); 0089 if (index != -1) { 0090 _wcw->_localWallet->setCurrentIndex(index); 0091 } 0092 0093 index = wl.indexOf(p2); 0094 if (index != -1) { 0095 _wcw->_defaultWallet->setCurrentIndex(index); 0096 } 0097 } 0098 0099 QString KWalletConfig::newWallet() 0100 { 0101 bool ok; 0102 const QString n = QInputDialog::getText(widget(), i18n("New Wallet"), 0103 i18n("Please choose a name for the new wallet:"), 0104 QLineEdit::Normal, QString(), 0105 &ok); 0106 if (!ok) { 0107 return {}; 0108 } 0109 KWallet::Wallet *w = KWallet::Wallet::openWallet(n, widget()->topLevelWidget()->winId()); 0110 if (!w) { 0111 return {}; 0112 } 0113 0114 delete w; 0115 return n; 0116 } 0117 0118 void KWalletConfig::newLocalWallet() 0119 { 0120 const QString n = newWallet(); 0121 if (n.trimmed().isEmpty()) { 0122 return; 0123 } 0124 0125 updateWalletLists(); 0126 0127 _wcw->_localWallet->setCurrentIndex(_wcw->_localWallet->findText(n)); 0128 setNeedsSave(true); 0129 } 0130 0131 void KWalletConfig::newNetworkWallet() 0132 { 0133 const QString n = newWallet(); 0134 if (n.trimmed().isEmpty()) { 0135 return; 0136 } 0137 0138 updateWalletLists(); 0139 0140 _wcw->_defaultWallet->setCurrentIndex(_wcw->_defaultWallet->findText(n)); 0141 setNeedsSave(true); 0142 } 0143 0144 void KWalletConfig::launchManager() 0145 { 0146 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kwalletmanager5"))) { 0147 QProcess::startDetached(QStringLiteral("kwalletmanager5"), QStringList(QStringLiteral("--show"))); 0148 } else { 0149 QDBusInterface kwalletd(QStringLiteral("org.kde.kwalletmanager5"), QStringLiteral("/kwalletmanager5/MainWindow_1")); 0150 kwalletd.call(QStringLiteral("show")); 0151 kwalletd.call(QStringLiteral("raise")); 0152 } 0153 } 0154 0155 void KWalletConfig::configChanged() 0156 { 0157 setNeedsSave(true); 0158 } 0159 0160 void KWalletConfig::load() 0161 { 0162 KConfigGroup config(_cfg, QStringLiteral("Wallet")); 0163 _wcw->_enabled->setChecked(config.readEntry("Enabled", true)); 0164 _wcw->_openPrompt->setChecked(config.readEntry("Prompt on Open", false)); 0165 _wcw->_launchManager->setChecked(config.readEntry("Launch Manager", false)); 0166 _wcw->_autocloseManager->setChecked(! config.readEntry("Leave Manager Open", false)); 0167 _wcw->_screensaverLock->setChecked(config.readEntry("Close on Screensaver", false)); 0168 _wcw->_autoclose->setChecked(!config.readEntry("Leave Open", true)); 0169 _wcw->_closeIdle->setChecked(config.readEntry("Close When Idle", false)); 0170 _wcw->_idleTime->setValue(config.readEntry("Idle Timeout", 10)); 0171 if (config.hasKey("Default Wallet")) { 0172 int defaultWallet_idx = _wcw->_defaultWallet->findText(config.readEntry("Default Wallet")); 0173 if (defaultWallet_idx != -1) { 0174 _wcw->_defaultWallet->setCurrentIndex(defaultWallet_idx); 0175 } else { 0176 _wcw->_defaultWallet->setCurrentIndex(0); 0177 } 0178 } else { 0179 _wcw->_defaultWallet->setCurrentIndex(0); 0180 } 0181 if (config.hasKey("Local Wallet")) { 0182 _wcw->_localWalletSelected->setChecked(!config.readEntry("Use One Wallet", false)); 0183 int localWallet_idx = _wcw->_localWallet->findText(config.readEntry("Local Wallet")); 0184 if (localWallet_idx != -1) { 0185 _wcw->_localWallet->setCurrentIndex(localWallet_idx); 0186 } else { 0187 _wcw->_localWallet->setCurrentIndex(0); 0188 } 0189 } else { 0190 _wcw->_localWalletSelected->setChecked(false); 0191 } 0192 _wcw->_accessList->clear(); 0193 KConfigGroup ad(_cfg, QStringLiteral("Auto Deny")); 0194 KConfigGroup aa(_cfg, QStringLiteral("Auto Allow")); 0195 QStringList denykeys = ad.entryMap().keys(); 0196 const QStringList keys = aa.entryMap().keys(); 0197 for (QStringList::const_iterator i = keys.begin(); i != keys.end(); ++i) { 0198 QString walletName = *i; 0199 // perform cleanup in the kwalletrc file, by removing entries that correspond to non-existent 0200 // (previously deleted, for example) wallets 0201 QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); 0202 path.append(QStringLiteral("/kwalletd/%1.kwl").arg(walletName)); 0203 if (!QFile::exists(path)) { 0204 // if the wallet no longer exists, delete the entries from the configuration file and skip to next entry 0205 KConfigGroup cfgAllow = KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group(QStringLiteral("Auto Allow")); 0206 cfgAllow.deleteEntry(walletName); 0207 0208 KConfigGroup cfgDeny = KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group(QStringLiteral("Auto Deny")); 0209 cfgDeny.deleteEntry(walletName); 0210 continue; 0211 } 0212 0213 const QStringList apps = aa.readEntry(*i, QStringList()); 0214 const QStringList denyapps = ad.readEntry(*i, QStringList()); 0215 denykeys.removeAll(walletName); 0216 auto twi = new QTreeWidgetItem(_wcw->_accessList, QStringList() << walletName); 0217 0218 for (QStringList::const_iterator j = apps.begin(), end = apps.end(); j != end; ++j) { 0219 new QTreeWidgetItem(twi, QStringList() << QString() << *j << i18n("Always Allow")); 0220 } 0221 for (QStringList::const_iterator j = denyapps.begin(), end = denyapps.end(); j != end; ++j) { 0222 new QTreeWidgetItem(twi, QStringList() << QString() << *j << i18n("Always Deny")); 0223 } 0224 } 0225 for (QStringList::const_iterator i = denykeys.constBegin(), denykeysEnd = denykeys.constEnd(); i != denykeysEnd; ++i) { 0226 const QStringList denyapps = ad.readEntry(*i, QStringList()); 0227 auto twi = new QTreeWidgetItem(_wcw->_accessList, QStringList() << *i); 0228 for (QStringList::const_iterator j = denyapps.begin(), denyappsEnd = denyapps.end(); j != denyappsEnd; ++j) { 0229 new QTreeWidgetItem(twi, QStringList() << QString() << *j << i18n("Always Deny")); 0230 } 0231 } 0232 _wcw->_accessList->header()->setSectionResizeMode(QHeaderView::ResizeToContents); 0233 0234 KConfigGroup secretsAPIConfig(_cfg, QStringLiteral("org.freedesktop.secrets")); 0235 _wcw->_secretServiceAPI->setChecked(secretsAPIConfig.readEntry("apiEnabled", true)); 0236 setNeedsSave(false); 0237 } 0238 0239 void KWalletConfig::save() 0240 { 0241 QVariantMap args; 0242 KAuth::Action action(QLatin1String("org.kde.kcontrol.kcmkwallet5.save")); 0243 action.setHelperId(QStringLiteral("org.kde.kcontrol.kcmkwallet5")); 0244 0245 widget()->window()->winId(); 0246 action.setParentWindow(widget()->window()->windowHandle()); 0247 if (!action.isValid()) { 0248 qDebug() << "There's no authAction, not saving settings"; 0249 return; 0250 } 0251 action.setArguments(args); 0252 0253 KAuth::ExecuteJob *j = action.execute(); 0254 0255 if (!j->exec()) { 0256 if (j->error() == KAuth::ActionReply::AuthorizationDeniedError) { 0257 KMessageBox::error(widget(), i18n("Permission denied."), i18n("KDE Wallet Control Module")); 0258 } else { 0259 KMessageBox::error(widget(), i18n("Error while authenticating action:\n%1", j->errorString()), i18n("KDE Wallet Control Module")); 0260 } 0261 load(); 0262 return; 0263 } 0264 0265 KConfigGroup config(_cfg, QStringLiteral("Wallet")); 0266 config.writeEntry("Enabled", _wcw->_enabled->isChecked()); 0267 config.writeEntry("Launch Manager", _wcw->_launchManager->isChecked()); 0268 config.writeEntry("Leave Manager Open", !_wcw->_autocloseManager->isChecked()); 0269 config.writeEntry("Leave Open", !_wcw->_autoclose->isChecked()); 0270 config.writeEntry("Close When Idle", _wcw->_closeIdle->isChecked()); 0271 config.writeEntry("Idle Timeout", _wcw->_idleTime->value()); 0272 config.writeEntry("Prompt on Open", _wcw->_openPrompt->isChecked()); 0273 config.writeEntry("Close on Screensaver", _wcw->_screensaverLock->isChecked()); 0274 0275 config.writeEntry("Use One Wallet", !_wcw->_localWalletSelected->isChecked()); 0276 if (_wcw->_localWalletSelected->isChecked()) { 0277 config.writeEntry("Local Wallet", _wcw->_localWallet->currentText()); 0278 } else { 0279 config.deleteEntry("Local Wallet"); 0280 } 0281 0282 if (_wcw->_defaultWallet->currentIndex() != -1) { 0283 config.writeEntry("Default Wallet", _wcw->_defaultWallet->currentText()); 0284 } else { 0285 config.deleteEntry("Default Wallet"); 0286 } 0287 0288 // FIXME: won't survive a language change 0289 _cfg->deleteGroup(QStringLiteral("Auto Allow")); 0290 _cfg->deleteGroup(QStringLiteral("Auto Deny")); 0291 config = _cfg->group(QStringLiteral("Auto Allow")); 0292 for (int i = 0; i < _wcw->_accessList->topLevelItemCount(); ++i) { 0293 QTreeWidgetItem *parentItem = _wcw->_accessList->topLevelItem(i); 0294 QStringList al; 0295 for (int j = 0; j < parentItem->childCount(); ++j) { 0296 QTreeWidgetItem *childItem = parentItem->child(j); 0297 if (childItem->text(2) == i18n("Always Allow")) { 0298 al << childItem->text(1); 0299 } 0300 } 0301 config.writeEntry(parentItem->text(0), al); 0302 } 0303 0304 config = _cfg->group(QStringLiteral("Auto Deny")); 0305 for (int i = 0; i < _wcw->_accessList->topLevelItemCount(); ++i) { 0306 QTreeWidgetItem *parentItem = _wcw->_accessList->topLevelItem(i); 0307 QStringList al; 0308 for (int j = 0; j < parentItem->childCount(); ++j) { 0309 QTreeWidgetItem *childItem = parentItem->child(j); 0310 if (childItem->text(2) == i18n("Always Deny")) { 0311 al << childItem->text(1); 0312 } 0313 } 0314 config.writeEntry(parentItem->text(0), al); 0315 } 0316 0317 KConfigGroup secretsAPIConfig(_cfg, QStringLiteral("org.freedesktop.secrets")); 0318 secretsAPIConfig.writeEntry("apiEnabled", _wcw->_secretServiceAPI->isChecked()); 0319 0320 _cfg->sync(); 0321 0322 // this restarts kwalletd if necessary 0323 QDBusInterface kwalletd(QStringLiteral("org.kde.kwalletd5"), QStringLiteral("/modules/kwalletd"), QStringLiteral(KWALLETMANAGERINTERFACE)); 0324 // if wallet was deactivated, then kwalletd will exit upon start so check 0325 // the status before invoking reconfigure 0326 if (kwalletd.isValid()) { 0327 // this will eventually make kwalletd exit upon deactivation 0328 kwalletd.call(QStringLiteral("reconfigure")); 0329 } 0330 setNeedsSave(false); 0331 } 0332 0333 void KWalletConfig::defaults() 0334 { 0335 _wcw->_enabled->setChecked(true); 0336 _wcw->_openPrompt->setChecked(false); 0337 _wcw->_launchManager->setChecked(true); 0338 _wcw->_autocloseManager->setChecked(false); 0339 _wcw->_screensaverLock->setChecked(false); 0340 _wcw->_autoclose->setChecked(true); 0341 _wcw->_closeIdle->setChecked(false); 0342 _wcw->_idleTime->setValue(10); 0343 _wcw->_defaultWallet->setCurrentIndex(0); 0344 _wcw->_localWalletSelected->setChecked(false); 0345 _wcw->_localWallet->setCurrentIndex(0); 0346 _wcw->_accessList->clear(); 0347 _wcw->_secretServiceAPI->setChecked(true); 0348 setNeedsSave(true); 0349 } 0350 0351 void KWalletConfig::customContextMenuRequested(const QPoint &pos) 0352 { 0353 QTreeWidgetItem *item = _wcw->_accessList->itemAt(pos); 0354 if (item && item->parent()) { 0355 auto m = new QMenu(widget()); 0356 m->setTitle(item->parent()->text(0)); 0357 m->addAction(i18n("&Delete"), Qt::Key_Delete, this, &KWalletConfig::deleteEntry); 0358 m->exec(_wcw->_accessList->mapToGlobal(pos)); 0359 delete m; 0360 } 0361 } 0362 0363 void KWalletConfig::deleteEntry() 0364 { 0365 QList<QTreeWidgetItem *> items = _wcw->_accessList->selectedItems(); 0366 if (items.count() == 1 && items[0]) { 0367 delete items[0]; 0368 setNeedsSave(true); 0369 } 0370 } 0371 0372 #include "konfigurator.moc" 0373 0374 #include "moc_konfigurator.cpp"