/* * Squawk messenger. * Copyright (C) 2019 Yury Gubich * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "kwallet.h" Core::PSE::KWallet::OpenWallet Core::PSE::KWallet::openWallet = 0; Core::PSE::KWallet::NetworkWallet Core::PSE::KWallet::networkWallet = 0; Core::PSE::KWallet::DeleteWallet Core::PSE::KWallet::deleteWallet = 0; Core::PSE::KWallet::ReadPassword Core::PSE::KWallet::readPassword = 0; Core::PSE::KWallet::WritePassword Core::PSE::KWallet::writePassword = 0; Core::PSE::KWallet::HasFolder Core::PSE::KWallet::hasFolder = 0; Core::PSE::KWallet::CreateFolder Core::PSE::KWallet::createFolder = 0; Core::PSE::KWallet::SetFolder Core::PSE::KWallet::setFolder = 0; Core::PSE::KWallet::SupportState Core::PSE::KWallet::sState = Core::PSE::KWallet::initial; QLibrary Core::PSE::KWallet::lib("kwalletWrapper"); Core::PSE::KWallet::KWallet(): QObject(), cState(disconnected), everError(false), wallet(0), readRequest(), writeRequest() { if (sState == initial) { lib.load(); if (lib.isLoaded()) { openWallet = (OpenWallet) lib.resolve("openWallet"); networkWallet = (NetworkWallet) lib.resolve("networkWallet"); deleteWallet = (DeleteWallet) lib.resolve("deleteWallet"); readPassword = (ReadPassword) lib.resolve("readPassword"); writePassword = (WritePassword) lib.resolve("writePassword"); hasFolder = (HasFolder) lib.resolve("hasFolder"); createFolder = (CreateFolder) lib.resolve("createFolder"); setFolder = (SetFolder) lib.resolve("setFolder"); if (openWallet && networkWallet && deleteWallet && readPassword && writePassword ) { sState = success; } else { sState = failure; } } else { sState = failure; } } } Core::PSE::KWallet::~KWallet() { close(); } void Core::PSE::KWallet::open() { if (sState == success) { if (cState == disconnected) { QString name; networkWallet(name); wallet = openWallet(name, 0, ::KWallet::Wallet::Asynchronous); if (wallet) { cState = connecting; connect(wallet, SIGNAL(walletOpened(bool)), this, SLOT(onWalletOpened(bool))); connect(wallet, SIGNAL(walletClosed()), this, SLOT(onWalletClosed())); } else { everError = true; emit opened(false); rejectPending(); } } } } Core::PSE::KWallet::ConnectionState Core::PSE::KWallet::connectionState() { return cState; } void Core::PSE::KWallet::close() { if (sState == success) { if (cState != disconnected) { deleteWallet(wallet); wallet = 0; } rejectPending(); } } void Core::PSE::KWallet::onWalletClosed() { cState = disconnected; deleteWallet(wallet); wallet = 0; emit closed(); rejectPending(); } void Core::PSE::KWallet::onWalletOpened(bool success) { emit opened(success); if (success) { QString appName = QCoreApplication::applicationName(); if (!hasFolder(wallet, appName)) { createFolder(wallet, appName); } setFolder(wallet, appName); cState = connected; readPending(); } else { everError = true; cState = disconnected; deleteWallet(wallet); wallet = 0; rejectPending(); } } Core::PSE::KWallet::SupportState Core::PSE::KWallet::supportState() { return sState; } bool Core::PSE::KWallet::everHadError() const { return everError; } void Core::PSE::KWallet::resetEverHadError() { everError = false; } void Core::PSE::KWallet::requestReadPassword(const QString& login, bool askAgain) { if (sState == success) { readRequest.insert(login); readSwitch(askAgain); } } void Core::PSE::KWallet::requestWritePassword(const QString& login, const QString& password, bool askAgain) { if (sState == success) { std::map::iterator itr = writeRequest.find(login); if (itr == writeRequest.end()) { writeRequest.insert(std::make_pair(login, password)); } else { itr->second = password; } readSwitch(askAgain); } } void Core::PSE::KWallet::readSwitch(bool askAgain) { switch (cState) { case connected: readPending(); break; case connecting: break; case disconnected: if (!everError || askAgain) { open(); } break; } } void Core::PSE::KWallet::rejectPending() { writeRequest.clear(); std::set::const_iterator i = readRequest.begin(); while (i != readRequest.end()) { emit rejectPassword(*i); readRequest.erase(i); i = readRequest.begin(); } } void Core::PSE::KWallet::readPending() { std::map::const_iterator itr = writeRequest.begin(); while (itr != writeRequest.end()) { int result = writePassword(wallet, itr->first, itr->second); if (result == 0) { qDebug() << "Successfully saved password for user" << itr->first; } else { qDebug() << "Error writing password for user" << itr->first << ":" << result; } writeRequest.erase(itr); itr = writeRequest.begin(); } std::set::const_iterator i = readRequest.begin(); while (i != readRequest.end()) { QString password; int result = readPassword(wallet, *i, password); if (result == 0 && password.size() > 0) { //even though it's written that the error is supposed to be returned in case there were no password emit responsePassword(*i, password); //it doesn't do so. I assume empty password as a lack of password in KWallet } else { emit rejectPassword(*i); } readRequest.erase(i); i = readRequest.begin(); } }