File indexing completed on 2024-04-28 05:36:02
0001 /* 0002 SPDX-FileCopyrightText: 2005 Jean-Remy Falleri <jr.falleri@laposte.net> 0003 SPDX-FileCopyrightText: 2005-2007 Kevin Ottens <ervin@kde.org> 0004 SPDX-FileCopyrightText: 2007 Alexis Ménard <darktears31@gmail.com> 0005 SPDX-FileCopyrightText: 2011, 2014 Lukas Tinkl <ltinkl@redhat.com> 0006 0007 SPDX-License-Identifier: LGPL-2.0-only 0008 */ 0009 0010 #include "soliduiserver.h" 0011 #include "config-X11.h" 0012 #include "soliduiserver_debug.h" 0013 0014 #include <QDBusInterface> 0015 #include <QDBusReply> 0016 #include <QDebug> 0017 #include <QIcon> 0018 0019 #include <KLocalizedString> 0020 #include <KPluginFactory> 0021 #include <KUserTimestamp> 0022 0023 #include <kpassworddialog.h> 0024 #include <kwallet.h> 0025 #include <kwindowsystem.h> 0026 #if HAVE_X11 0027 #include <KX11Extras> 0028 #endif 0029 0030 // solid specific includes 0031 #include <solid/device.h> 0032 #include <solid/deviceinterface.h> 0033 #include <solid/devicenotifier.h> 0034 #include <solid/predicate.h> 0035 #include <solid/storagevolume.h> 0036 0037 K_PLUGIN_CLASS_WITH_JSON(SolidUiServer, "soliduiserver.json") 0038 0039 SolidUiServer::SolidUiServer(QObject *parent, const QList<QVariant> &) 0040 : KDEDModule(parent) 0041 { 0042 } 0043 0044 SolidUiServer::~SolidUiServer() 0045 { 0046 } 0047 0048 void SolidUiServer::showPassphraseDialog(const QString &udi, const QString &returnService, const QString &returnObject, uint wId, const QString &appId) 0049 { 0050 if (m_idToPassphraseDialog.contains(returnService + ':' + udi)) { 0051 KPasswordDialog *dialog = m_idToPassphraseDialog[returnService + ':' + udi]; 0052 dialog->activateWindow(); 0053 return; 0054 } 0055 0056 Solid::Device device(udi); 0057 0058 KPasswordDialog *dialog = new KPasswordDialog(nullptr, KPasswordDialog::ShowKeepPassword); 0059 0060 QString label = device.vendor(); 0061 if (!label.isEmpty()) 0062 label += ' '; 0063 label += device.product(); 0064 0065 dialog->setPrompt(i18n("'%1' needs a password to be accessed. Please enter a password.", label)); 0066 dialog->setIcon(QIcon::fromTheme(device.icon())); 0067 dialog->setProperty("soliduiserver.udi", udi); 0068 dialog->setProperty("soliduiserver.returnService", returnService); 0069 dialog->setProperty("soliduiserver.returnObject", returnObject); 0070 0071 QString uuid; 0072 if (device.is<Solid::StorageVolume>()) 0073 uuid = device.as<Solid::StorageVolume>()->uuid(); 0074 0075 // read the password from wallet and prefill it to the dialog 0076 if (!uuid.isEmpty()) { 0077 dialog->setProperty("soliduiserver.uuid", uuid); 0078 0079 KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), (WId)wId); 0080 const QString folderName = QString::fromLatin1("SolidLuks"); 0081 if (wallet && wallet->hasFolder(folderName)) { 0082 wallet->setFolder(folderName); 0083 QString savedPassword; 0084 if (wallet->readPassword(uuid, savedPassword) == 0) { 0085 dialog->setKeepPassword(true); 0086 dialog->setPassword(savedPassword); 0087 } 0088 wallet->closeWallet(wallet->walletName(), false); 0089 } 0090 delete wallet; 0091 } 0092 0093 connect(dialog, &KPasswordDialog::gotPassword, this, &SolidUiServer::onPassphraseDialogCompleted); 0094 connect(dialog, &KPasswordDialog::rejected, this, &SolidUiServer::onPassphraseDialogRejected); 0095 0096 m_idToPassphraseDialog[returnService + ':' + udi] = dialog; 0097 0098 reparentDialog(dialog, (WId)wId, appId, true); 0099 dialog->show(); 0100 } 0101 0102 void SolidUiServer::onPassphraseDialogCompleted(const QString &pass, bool keep) 0103 { 0104 KPasswordDialog *dialog = qobject_cast<KPasswordDialog *>(sender()); 0105 0106 if (dialog) { 0107 QString returnService = dialog->property("soliduiserver.returnService").toString(); 0108 QString returnObject = dialog->property("soliduiserver.returnObject").toString(); 0109 QDBusInterface returnIface(returnService, returnObject); 0110 0111 QDBusReply<void> reply = returnIface.call(QStringLiteral("passphraseReply"), pass); 0112 0113 QString udi = dialog->property("soliduiserver.udi").toString(); 0114 m_idToPassphraseDialog.remove(returnService + ':' + udi); 0115 0116 if (!reply.isValid()) { 0117 qCWarning(SOLIDUISERVER_DEBUG) << "Impossible to send the passphrase to the application, D-Bus said: " << reply.error().name() << ", " 0118 << reply.error().message() << Qt::endl; 0119 return; // don't save into wallet if an error occurs 0120 } 0121 0122 if (keep) { // save the password into the wallet 0123 KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), 0); 0124 if (wallet) { 0125 const QString folderName = QString::fromLatin1("SolidLuks"); 0126 const QString uuid = dialog->property("soliduiserver.uuid").toString(); 0127 if (!wallet->hasFolder(folderName)) 0128 wallet->createFolder(folderName); 0129 if (wallet->setFolder(folderName)) 0130 wallet->writePassword(uuid, pass); 0131 wallet->closeWallet(wallet->walletName(), false); 0132 delete wallet; 0133 } 0134 } 0135 } 0136 } 0137 0138 void SolidUiServer::onPassphraseDialogRejected() 0139 { 0140 onPassphraseDialogCompleted(QString(), false); 0141 } 0142 0143 void SolidUiServer::reparentDialog(QWidget *dialog, WId wId, const QString &appId, bool modal) 0144 { 0145 Q_UNUSED(appId); 0146 // Code borrowed from kwalletd 0147 0148 dialog->setAttribute(Qt::WA_NativeWindow, true); 0149 KWindowSystem::setMainWindow(dialog->windowHandle(), wId); // correct, set dialog parent 0150 0151 #if HAVE_X11 0152 if (KWindowSystem::isPlatformX11()) { 0153 if (modal) { 0154 KX11Extras::setState(dialog->winId(), NET::Modal); 0155 } else { 0156 KX11Extras::clearState(dialog->winId(), NET::Modal); 0157 } 0158 } 0159 #endif 0160 0161 // allow dialog activation even if it interrupts, better than trying hacks 0162 // with keeping the dialog on top or on all desktops 0163 KUserTimestamp::updateUserTimestamp(); 0164 } 0165 0166 #include "soliduiserver.moc"