File indexing completed on 2024-04-21 05:01:41
0001 /* 0002 This is the wallet manager of Smb4K. 0003 0004 SPDX-FileCopyrightText: 2008-2022 Alexander Reinholdt <alexander.reinholdt@kdemail.net> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 // application specific includes 0009 #include "smb4kwalletmanager.h" 0010 #include "smb4kauthinfo.h" 0011 #include "smb4kglobal.h" 0012 #include "smb4khomesshareshandler.h" 0013 #include "smb4khost.h" 0014 #include "smb4knotification.h" 0015 #include "smb4ksettings.h" 0016 #include "smb4kshare.h" 0017 0018 // Qt includes 0019 #include <QApplication> 0020 #include <QPointer> 0021 0022 // KDE includes 0023 #include <KWallet> 0024 0025 using namespace Smb4KGlobal; 0026 0027 class Smb4KWalletManagerPrivate 0028 { 0029 public: 0030 KWallet::Wallet *wallet; 0031 }; 0032 0033 class Smb4KWalletManagerStatic 0034 { 0035 public: 0036 Smb4KWalletManager instance; 0037 }; 0038 0039 Q_GLOBAL_STATIC(Smb4KWalletManagerStatic, p); 0040 0041 Smb4KWalletManager::Smb4KWalletManager(QObject *parent) 0042 : QObject(parent) 0043 , d(new Smb4KWalletManagerPrivate) 0044 { 0045 d->wallet = nullptr; 0046 } 0047 0048 Smb4KWalletManager::~Smb4KWalletManager() 0049 { 0050 } 0051 0052 Smb4KWalletManager *Smb4KWalletManager::self() 0053 { 0054 return &p->instance; 0055 } 0056 0057 void Smb4KWalletManager::readLoginCredentials(const NetworkItemPtr &networkItem) 0058 { 0059 if (networkItem) { 0060 if (networkItem->type() == Host || networkItem->type() == Share) { 0061 Smb4KAuthInfo authInfo; 0062 0063 if (networkItem->type() == Share) { 0064 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0065 0066 if (share->isHomesShare()) { 0067 authInfo.setUrl(share->homeUrl()); 0068 } else { 0069 authInfo.setUrl(share->url()); 0070 } 0071 0072 // 0073 // Read the credentials for the share. Fall back to the URL of the 0074 // host, if no credentials for the share could be found. 0075 // 0076 if (!read(&authInfo)) { 0077 authInfo.setUrl(share->url().adjusted(QUrl::RemovePath | QUrl::StripTrailingSlash)); 0078 (void)read(&authInfo); 0079 } 0080 } else { 0081 authInfo.setUrl(networkItem->url()); 0082 (void)read(&authInfo); 0083 } 0084 0085 QUrl url = networkItem->url(); 0086 0087 url.setUserName(authInfo.userName()); 0088 url.setPassword(authInfo.password()); 0089 0090 networkItem->setUrl(url); 0091 } 0092 } 0093 } 0094 0095 void Smb4KWalletManager::readLoginCredentials(Smb4KAuthInfo *authInfo) 0096 { 0097 if (authInfo) { 0098 if (authInfo->type() == Host || authInfo->type() == Share) { 0099 (void)read(authInfo); 0100 } 0101 } 0102 } 0103 0104 void Smb4KWalletManager::writeLoginCredentials(const NetworkItemPtr &networkItem) 0105 { 0106 if (networkItem) { 0107 if (networkItem->type() == Host || networkItem->type() == Share) { 0108 Smb4KAuthInfo authInfo; 0109 0110 if (networkItem->type() == Share) { 0111 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0112 0113 if (share->isHomesShare()) { 0114 authInfo.setUrl(share->homeUrl()); 0115 } else { 0116 authInfo.setUrl(share->url()); 0117 } 0118 } else { 0119 authInfo.setUrl(networkItem->url()); 0120 } 0121 0122 write(&authInfo); 0123 } else if (networkItem->type() == UnknownNetworkItem) { 0124 Smb4KAuthInfo authInfo; 0125 authInfo.setUserName(networkItem->url().userName()); 0126 authInfo.setPassword(networkItem->url().password()); 0127 write(&authInfo); 0128 } 0129 } 0130 } 0131 0132 void Smb4KWalletManager::writeLoginCredentials(Smb4KAuthInfo *authInfo) 0133 { 0134 if (authInfo) { 0135 if (authInfo->type() == Host || authInfo->type() == Share || authInfo->type() == UnknownNetworkItem) { 0136 write(authInfo); 0137 } 0138 } 0139 } 0140 0141 void Smb4KWalletManager::writeLoginCredentialsList(const QList<Smb4KAuthInfo *> &list) 0142 { 0143 // 0144 // For the sake of simplicity, clear all wallet entries 0145 // 0146 clear(); 0147 0148 // 0149 // Write the new list to the wallet 0150 // 0151 for (Smb4KAuthInfo *authInfo : list) { 0152 write(authInfo); 0153 } 0154 } 0155 0156 QList<Smb4KAuthInfo *> Smb4KWalletManager::loginCredentialsList() 0157 { 0158 QList<Smb4KAuthInfo *> entries; 0159 0160 if (init()) { 0161 bool ok = false; 0162 QMap<QString, QMap<QString, QString>> allWalletEntries = d->wallet->mapList(&ok); 0163 0164 if (ok) { 0165 QMapIterator<QString, QMap<QString, QString>> it(allWalletEntries); 0166 0167 while (it.hasNext()) { 0168 it.next(); 0169 0170 Smb4KAuthInfo *authInfo = new Smb4KAuthInfo(); 0171 0172 if (it.key() == QStringLiteral("DEFAULT_LOGIN")) { 0173 authInfo->setUserName(it.value().value(QStringLiteral("Login"))); 0174 authInfo->setPassword(it.value().value(QStringLiteral("Password"))); 0175 } else { 0176 QUrl url(it.key(), QUrl::TolerantMode); 0177 authInfo->setUrl(url); 0178 authInfo->setUserName(it.value().value(QStringLiteral("Login"))); 0179 authInfo->setPassword(it.value().value(QStringLiteral("Password"))); 0180 } 0181 0182 entries << authInfo; 0183 } 0184 } 0185 } 0186 0187 return entries; 0188 } 0189 0190 bool Smb4KWalletManager::useWalletSystem() const 0191 { 0192 return (KWallet::Wallet::isEnabled() && Smb4KSettings::useWallet()); 0193 } 0194 0195 bool Smb4KWalletManager::hasDefaultCredentials() 0196 { 0197 if (init()) { 0198 if (d->wallet->hasEntry(QStringLiteral("DEFAULT_LOGIN"))) { 0199 return true; 0200 } 0201 } 0202 0203 return false; 0204 } 0205 0206 bool Smb4KWalletManager::init() 0207 { 0208 if (useWalletSystem()) { 0209 // 0210 // Get a pointer to the wallet, if we do not have one yet 0211 // 0212 if (!d->wallet) { 0213 // 0214 // Open the wallet synchronously. 0215 // 0216 d->wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), QApplication::activeWindow() ? QApplication::activeWindow()->winId() : 0); 0217 0218 // 0219 // Check if the wallet was opened successfully. Set the 0220 // right folder in case it was. 0221 // 0222 if (d->wallet) { 0223 if (d->wallet->isOpen()) { 0224 if (!d->wallet->hasFolder(QStringLiteral("Smb4K"))) { 0225 d->wallet->createFolder(QStringLiteral("Smb4K")); 0226 d->wallet->setFolder(QStringLiteral("Smb4K")); 0227 } else { 0228 d->wallet->setFolder(QStringLiteral("Smb4K")); 0229 } 0230 } else { 0231 Smb4KNotification::credentialsNotAccessible(); 0232 } 0233 } else { 0234 delete d->wallet; 0235 d->wallet = nullptr; 0236 0237 Smb4KNotification::openingWalletFailed(KWallet::Wallet::NetworkWallet()); 0238 } 0239 } 0240 } else { 0241 if (d->wallet) { 0242 // 0243 // Close the wallet, if Smb4K is the only application that 0244 // is using it. Thus, use force=false, otherwise it will definitely 0245 // be closed. 0246 // 0247 d->wallet->closeWallet(KWallet::Wallet::NetworkWallet(), false); 0248 0249 // 0250 // Delete the wallet and set it to 0. 0251 // 0252 delete d->wallet; 0253 d->wallet = nullptr; 0254 } 0255 } 0256 0257 Q_EMIT initialized(); 0258 0259 return (d->wallet && d->wallet->isOpen()); 0260 } 0261 0262 bool Smb4KWalletManager::read(Smb4KAuthInfo *authInfo) 0263 { 0264 bool success = false; 0265 0266 if (init()) { 0267 if (authInfo->type() != Smb4KGlobal::UnknownNetworkItem) { 0268 // 0269 // Get the string representation of the URL 0270 // 0271 QString itemUrlString; 0272 QString testString = authInfo->url().toString(QUrl::RemoveUserInfo | QUrl::RemovePort); 0273 0274 // 0275 // Check if an entry exists for the given URL. If not, try to 0276 // get the correct string / key by a case insensitive comparision. 0277 // 0278 if (!d->wallet->hasEntry(testString)) { 0279 // 0280 // Get all keys of the saved login credentials 0281 // 0282 QStringList walletEntries = d->wallet->entryList(); 0283 0284 // 0285 // Find the correct key for these login credentials 0286 // 0287 for (const QString &entry : qAsConst(walletEntries)) { 0288 if (QString::compare(entry, testString, Qt::CaseInsensitive) == 0) { 0289 itemUrlString = entry; 0290 break; 0291 } 0292 } 0293 } else { 0294 itemUrlString = testString; 0295 } 0296 0297 // 0298 // Read the login credentials from the wallet. Use the default login 0299 // as fallback. 0300 // 0301 if (!itemUrlString.isEmpty()) { 0302 QMap<QString, QString> credentials; 0303 0304 if (d->wallet->readMap(itemUrlString, credentials) == 0) { 0305 authInfo->setUserName(credentials.value(QStringLiteral("Login"))); 0306 authInfo->setPassword(credentials.value(QStringLiteral("Password"))); 0307 success = true; 0308 } 0309 } else { 0310 if (Smb4KSettings::useDefaultLogin()) { 0311 QMap<QString, QString> credentials; 0312 0313 if (d->wallet->readMap(QStringLiteral("DEFAULT_LOGIN"), credentials) == 0) { 0314 authInfo->setUserName(credentials.value(QStringLiteral("Login"))); 0315 authInfo->setPassword(credentials.value(QStringLiteral("Password"))); 0316 success = true; 0317 } 0318 } 0319 } 0320 } else { 0321 if (Smb4KSettings::useDefaultLogin()) { 0322 QMap<QString, QString> credentials; 0323 0324 if (d->wallet->readMap(QStringLiteral("DEFAULT_LOGIN"), credentials) == 0) { 0325 authInfo->setUserName(credentials.value(QStringLiteral("Login"))); 0326 authInfo->setPassword(credentials.value(QStringLiteral("Password"))); 0327 success = true; 0328 } 0329 } 0330 } 0331 } 0332 0333 return success; 0334 } 0335 0336 void Smb4KWalletManager::write(Smb4KAuthInfo *authInfo) 0337 { 0338 if (init()) { 0339 // 0340 // Get the key for the wallet entry 0341 // 0342 QString key; 0343 0344 if (authInfo->type() != UnknownNetworkItem) { 0345 key = authInfo->url().toString(QUrl::RemoveUserInfo | QUrl::RemovePort); 0346 } else { 0347 key = QStringLiteral("DEFAULT_LOGIN"); 0348 } 0349 0350 // 0351 // Write the credentials to the wallet. 0352 // 0353 if (!authInfo->userName().isEmpty() /* allow empty passwords */) { 0354 QMap<QString, QString> credentials; 0355 credentials.insert(QStringLiteral("Login"), authInfo->userName()); 0356 credentials.insert(QStringLiteral("Password"), authInfo->password()); 0357 0358 if (d->wallet->writeMap(key, credentials) == 0) { 0359 d->wallet->sync(); 0360 } 0361 } 0362 0363 Q_EMIT credentialsUpdated(authInfo->url()); 0364 } 0365 } 0366 0367 void Smb4KWalletManager::clear() 0368 { 0369 if (init()) { 0370 // 0371 // Get the list of wallet entries 0372 // 0373 QStringList entryList = d->wallet->entryList(); 0374 0375 // 0376 // Remove all wallet entries 0377 // 0378 for (const QString &entry : qAsConst(entryList)) { 0379 d->wallet->removeEntry(entry); 0380 } 0381 0382 d->wallet->sync(); 0383 0384 Q_EMIT credentialsUpdated(QUrl()); 0385 } 0386 }