File indexing completed on 2023-10-01 08:41:45
0001 /* 0002 * This file is part of telepathy-accounts-kcm 0003 * 0004 * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0019 */ 0020 0021 #include "wallet-interface.h" 0022 #include "pending-wallet.h" 0023 0024 #include "ktp-debug.h" 0025 0026 0027 class KTp::WalletInterfacePrivate : public QObject 0028 { 0029 Q_OBJECT 0030 0031 public: 0032 WalletInterfacePrivate(); 0033 void ensureWalletIsReady(); 0034 0035 QScopedPointer<KWallet::Wallet> wallet; 0036 static const QLatin1String folderName; 0037 static const QLatin1String mapsPrefix; 0038 0039 bool isOpening; 0040 0041 private Q_SLOTS: 0042 void onWalletOpened(bool success); 0043 }; 0044 0045 using KTp::WalletInterface; 0046 using KTp::WalletInterfacePrivate; 0047 0048 const QLatin1String WalletInterfacePrivate::folderName = QLatin1String("telepathy-kde"); 0049 const QLatin1String WalletInterfacePrivate::mapsPrefix = QLatin1String("maps/"); 0050 0051 void WalletInterfacePrivate::ensureWalletIsReady() 0052 { 0053 // If wallet was force-closed since last WalletInterface::openWallet(), 0054 // try to reopen it. 0055 if (!wallet || !wallet->isOpen()) { 0056 // If the wallet is not already being opened, we try to open it 0057 if (!isOpening) { 0058 isOpening = true; 0059 wallet.reset(KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), 0, KWallet::Wallet::Asynchronous)); 0060 connect(wallet.data(), SIGNAL(walletOpened(bool)), SLOT(onWalletOpened(bool))); 0061 } 0062 } 0063 } 0064 0065 0066 WalletInterfacePrivate::WalletInterfacePrivate() : 0067 wallet(nullptr), 0068 isOpening(false) 0069 { 0070 ensureWalletIsReady(); 0071 } 0072 0073 KTp::PendingWallet* WalletInterface::openWallet() 0074 { 0075 static KTp::WalletInterface s_instance; 0076 0077 s_instance.d->ensureWalletIsReady(); 0078 return new PendingWallet(&s_instance); 0079 } 0080 0081 void WalletInterfacePrivate::onWalletOpened(bool success) 0082 { 0083 if (!success) { 0084 qCWarning(KTP_COMMONINTERNALS) << "Couldn't open wallet"; 0085 } 0086 0087 disconnect(wallet.data(), SIGNAL(walletOpened(bool)), this, SLOT(onWalletOpened(bool))); 0088 isOpening = false; 0089 } 0090 0091 0092 WalletInterface::WalletInterface(): 0093 d(new WalletInterfacePrivate) 0094 { 0095 } 0096 0097 WalletInterface::~WalletInterface() 0098 { 0099 delete d; 0100 } 0101 0102 bool WalletInterface::hasPassword(const Tp::AccountPtr &account) 0103 { 0104 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0105 return false; 0106 } 0107 0108 d->wallet->setFolder(d->folderName); 0109 return d->wallet->hasEntry(account->uniqueIdentifier()); 0110 } 0111 0112 QString WalletInterface::password(const Tp::AccountPtr &account) 0113 { 0114 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0115 return QString(); 0116 } 0117 0118 d->wallet->setFolder(d->folderName); 0119 QString password; 0120 if (d->wallet->hasEntry(account->uniqueIdentifier())) { 0121 int rc = d->wallet->readPassword(account->uniqueIdentifier(), password); 0122 if (rc != 0) { 0123 password.clear(); 0124 qCWarning(KTP_COMMONINTERNALS) << "failed to read password from KWallet"; 0125 } 0126 } 0127 return password; 0128 } 0129 0130 void WalletInterface::setPassword(const Tp::AccountPtr &account, const QString &password) 0131 { 0132 if (d->wallet.isNull()) { 0133 return; 0134 } 0135 0136 if (!d->wallet->hasFolder(d->folderName)) { 0137 d->wallet->createFolder(d->folderName); 0138 } 0139 0140 d->wallet->setFolder(d->folderName); 0141 d->wallet->writePassword(account->uniqueIdentifier(), password); 0142 0143 setLastLoginFailed(account, false); 0144 0145 //sync normally happens on close, but in this case we need it to happen /now/ as it needs to be synced before the auth-client starts 0146 d->wallet->sync(); 0147 } 0148 0149 void WalletInterface::setLastLoginFailed(const Tp::AccountPtr &account, bool failed) 0150 { 0151 if (failed) { 0152 setEntry(account, QLatin1String("lastLoginFailed"), QLatin1String("true")); 0153 } else { 0154 if (hasEntry(account, QLatin1String("lastLoginFailed"))) { 0155 removeEntry(account, QLatin1String("lastLoginFailed")); 0156 } 0157 } 0158 } 0159 0160 bool WalletInterface::lastLoginFailed(const Tp::AccountPtr &account) 0161 { 0162 if (d->wallet.isNull()) { 0163 return false; 0164 } 0165 return hasEntry(account, QLatin1String("lastLoginFailed")); 0166 } 0167 0168 void WalletInterface::removePassword(const Tp::AccountPtr &account) 0169 { 0170 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0171 return; 0172 } 0173 0174 d->wallet->setFolder(d->folderName); 0175 d->wallet->removeEntry(account->uniqueIdentifier()); 0176 d->wallet->sync(); 0177 } 0178 0179 bool WalletInterface::hasEntry(const Tp::AccountPtr &account, const QString &key) 0180 { 0181 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0182 return false; 0183 } 0184 0185 d->wallet->setFolder(d->folderName); 0186 QMap< QString, QString > map; 0187 if (d->wallet->hasEntry(d->mapsPrefix + account->uniqueIdentifier())) { 0188 int rc = d->wallet->readMap(d->mapsPrefix + account->uniqueIdentifier(), map); 0189 if (rc != 0) { 0190 qCWarning(KTP_COMMONINTERNALS) << "failed to read map from KWallet (probably it is not a map)"; 0191 return false; 0192 } 0193 } 0194 return map.contains(key); 0195 } 0196 0197 QString WalletInterface::entry(const Tp::AccountPtr &account, const QString &key) 0198 { 0199 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0200 return QString(); 0201 } 0202 0203 d->wallet->setFolder(d->folderName); 0204 QString value; 0205 QMap< QString, QString > map; 0206 if (d->wallet->hasEntry(d->mapsPrefix + account->uniqueIdentifier())) { 0207 int rc = d->wallet->readMap(d->mapsPrefix + account->uniqueIdentifier(), map); 0208 if (rc != 0) { 0209 qCWarning(KTP_COMMONINTERNALS) << "failed to read map from KWallet (probably it is not a map)"; 0210 return QString(); 0211 } 0212 } 0213 return map.value(key); 0214 } 0215 0216 void WalletInterface::setEntry(const Tp::AccountPtr &account, const QString &key, const QString &value) 0217 { 0218 if (d->wallet.isNull()) { 0219 return; 0220 } 0221 0222 if (! d->wallet->hasFolder(d->folderName)) { 0223 d->wallet->createFolder(d->folderName); 0224 } 0225 0226 d->wallet->setFolder(d->folderName); 0227 QMap< QString, QString > map; 0228 if (d->wallet->hasEntry(d->mapsPrefix + account->uniqueIdentifier())) { 0229 int rc = d->wallet->readMap(d->mapsPrefix + account->uniqueIdentifier(), map); 0230 if (rc != 0) { 0231 qCWarning(KTP_COMMONINTERNALS) << "failed to read map from KWallet (probably it is not a map)"; 0232 return; 0233 } 0234 } 0235 map[key] = value; 0236 0237 d->wallet->writeMap(d->mapsPrefix + account->uniqueIdentifier(), map); 0238 //sync normally happens on close, but in this case we need it to happen /now/ as it needs to be synced before the auth-client starts 0239 d->wallet->sync(); 0240 } 0241 0242 void WalletInterface::removeEntry(const Tp::AccountPtr &account, const QString &key) 0243 { 0244 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0245 return; 0246 } 0247 0248 d->wallet->setFolder(d->folderName); 0249 QMap< QString, QString > map; 0250 if (d->wallet->hasEntry(d->mapsPrefix + account->uniqueIdentifier())) { 0251 int rc = d->wallet->readMap(d->mapsPrefix + account->uniqueIdentifier(), map); 0252 if (rc != 0) { 0253 qCWarning(KTP_COMMONINTERNALS) << "failed to read map from KWallet (probably it is not a map)"; 0254 return; 0255 } 0256 } 0257 map.remove(key); 0258 0259 if (!map.empty()) { 0260 d->wallet->writeMap(d->mapsPrefix + account->uniqueIdentifier(), map); 0261 } else { 0262 d->wallet->removeEntry(d->mapsPrefix + account->uniqueIdentifier()); 0263 } 0264 //sync normally happens on close, but in this case we need it to happen /now/ as it needs to be synced before the auth-client starts 0265 d->wallet->sync(); 0266 } 0267 0268 void WalletInterface::removeAllEntries(const Tp::AccountPtr& account) 0269 { 0270 if (d->wallet.isNull() || !d->wallet->hasFolder(d->folderName)) { 0271 return; 0272 } 0273 0274 d->wallet->setFolder(d->folderName); 0275 d->wallet->removeEntry(d->mapsPrefix + account->uniqueIdentifier()); 0276 } 0277 0278 void WalletInterface::removeAccount(const Tp::AccountPtr& account) 0279 { 0280 removePassword(account); 0281 removeAllEntries(account); 0282 } 0283 0284 bool WalletInterface::isOpen() 0285 { 0286 return (!d->wallet.isNull() && d->wallet->isOpen()); 0287 } 0288 0289 KWallet::Wallet *WalletInterface::wallet() const 0290 { 0291 return d->wallet.data(); 0292 } 0293 0294 #include "wallet-interface.moc"