squawk/core/squawk.cpp

788 lines
28 KiB
C++
Raw Normal View History

/*
* Squawk messenger.
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
*
* 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 <http://www.gnu.org/licenses/>.
*/
2019-03-29 14:54:34 +00:00
#include "squawk.h"
2019-03-30 20:13:13 +00:00
#include <QDebug>
#include <QSettings>
2019-05-29 15:05:54 +00:00
#include <QDir>
#include <QStandardPaths>
2019-03-29 14:54:34 +00:00
2024-12-13 23:53:04 +00:00
#include "utils/jammer.h"
2019-03-30 20:13:13 +00:00
Core::Squawk::Squawk(QObject* parent):
2019-03-29 14:54:34 +00:00
QObject(parent),
accounts(),
amap(),
state(Shared::Availability::offline),
network(),
isInitialized(false),
#ifdef WITH_KWALLET
kwallet(),
#endif
clientCache()
2019-03-29 14:54:34 +00:00
{
connect(&network, &NetworkAccess::loadFileProgress, this, &Squawk::fileProgress);
connect(&network, &NetworkAccess::loadFileError, this, &Squawk::fileError);
connect(&network, &NetworkAccess::downloadFileComplete, this, &Squawk::fileDownloadComplete);
connect(&network, &NetworkAccess::uploadFileComplete, this, &Squawk::fileUploadComplete);
#ifdef WITH_KWALLET
if (kwallet.supportState() == PSE::KWallet::success) {
connect(&kwallet, &PSE::KWallet::opened, this, &Squawk::onWalletOpened);
connect(&kwallet, &PSE::KWallet::rejectPassword, this, &Squawk::onWalletRejectPassword);
connect(&kwallet, &PSE::KWallet::responsePassword, this, &Squawk::responsePassword);
Shared::Global::setSupported("KWallet", true);
}
#endif
2019-03-29 14:54:34 +00:00
}
Core::Squawk::~Squawk() {
2019-03-30 20:13:13 +00:00
Accounts::const_iterator itr = accounts.begin();
Accounts::const_iterator end = accounts.end();
for (; itr != end; ++itr) {
delete (*itr);
2019-03-30 20:13:13 +00:00
}
}
void Core::Squawk::onWalletOpened(bool success) {
qDebug() << "KWallet opened: " << success;
}
void Core::Squawk::stop() {
qDebug("Stopping squawk core..");
network.stop();
clientCache.close();
if (isInitialized) {
QSettings settings;
settings.beginGroup("core");
settings.beginWriteArray("accounts");
for (std::deque<Account*>::size_type i = 0; i < accounts.size(); ++i) {
settings.setArrayIndex(i);
Account* acc = accounts[i];
Shared::AccountPassword ap = acc->getPasswordType();
QString password;
switch (ap) {
case Shared::AccountPassword::plain:
password = acc->getPassword();
break;
case Shared::AccountPassword::jammed:
2024-12-13 23:53:04 +00:00
password = Jammer::encrypt(acc->getPassword(), passwordHash);
break;
default:
break;
}
2024-12-13 23:53:04 +00:00
qDebug() << "Saving password for" << acc->getName() << password;
settings.setValue("name", acc->getName());
settings.setValue("server", acc->getServer());
settings.setValue("login", acc->getLogin());
settings.setValue("password", password);
settings.setValue("resource", acc->getResource());
settings.setValue("passwordType", static_cast<int>(ap));
settings.setValue("active", acc->getActive());
}
settings.endArray();
settings.endGroup();
settings.sync();
}
emit quit();
}
void Core::Squawk::start() {
qDebug("Starting squawk core..");
readSettings();
isInitialized = true;
network.start();
clientCache.open();
2019-03-30 20:13:13 +00:00
}
2019-03-29 14:54:34 +00:00
void Core::Squawk::newAccountRequest(const QMap<QString, QVariant>& map) {
2019-03-30 20:13:13 +00:00
QString name = map.value("name").toString();
QString login = map.value("login").toString();
QString server = map.value("server").toString();
QString password = map.value("password").toString();
QString resource = map.value("resource").toString();
int passwordType = map.value("passwordType").toInt();
bool active = map.value("active").toBool();
2019-03-30 20:13:13 +00:00
addAccount(login, server, password, name, resource, active, Shared::Global::fromInt<Shared::AccountPassword>(passwordType));
2019-03-30 20:13:13 +00:00
}
void Core::Squawk::addAccount(
const QString& login,
const QString& server,
const QString& password,
const QString& name,
const QString& resource,
bool active,
Shared::AccountPassword passwordType)
2019-03-30 20:13:13 +00:00
{
2022-04-13 19:02:48 +00:00
if (amap.count(name) > 0) {
qDebug() << "An attempt to add account" << name << "but an account with such name already exist, ignoring";
return;
}
Account* acc = new Account(login, server, password, name, active, &network);
acc->setResource(resource);
acc->setPasswordType(passwordType);
2019-03-30 20:13:13 +00:00
accounts.push_back(acc);
amap.insert(std::make_pair(name, acc));
connect(acc, &Account::connectionStateChanged, this, &Squawk::onAccountConnectionStateChanged);
connect(acc, &Account::changed, this, &Squawk::onAccountChanged);
connect(acc, &Account::error, this, &Squawk::onAccountError);
connect(acc, &Account::needPassword, this, &Squawk::onAccountNeedPassword);
connect(acc, &Account::availabilityChanged, this, &Squawk::onAccountAvailabilityChanged);
connect(acc, &Account::addContact, this, &Squawk::onAccountAddContact);
connect(acc, &Account::addGroup, this, &Squawk::onAccountAddGroup);
connect(acc, &Account::removeGroup, this, &Squawk::onAccountRemoveGroup);
connect(acc, qOverload<const QString&, const QString&>(&Account::removeContact),
this, qOverload<const QString&, const QString&>(&Squawk::onAccountRemoveContact));
connect(acc, qOverload<const QString&>(&Account::removeContact),
this, qOverload<const QString&>(&Squawk::onAccountRemoveContact));
connect(acc, &Account::changeContact, this, &Squawk::onAccountChangeContact);
connect(acc, &Account::addPresence, this, &Squawk::onAccountAddPresence);
connect(acc, &Account::removePresence, this, &Squawk::onAccountRemovePresence);
connect(acc, &Account::message, this, &Squawk::onAccountMessage);
connect(acc, &Account::changeMessage, this, &Squawk::onAccountChangeMessage);
connect(acc, &Account::responseArchive, this, &Squawk::onAccountResponseArchive);
connect(acc, &Account::addRoom, this, &Squawk::onAccountAddRoom);
connect(acc, &Account::changeRoom, this, &Squawk::onAccountChangeRoom);
connect(acc, &Account::removeRoom, this, &Squawk::onAccountRemoveRoom);
connect(acc, &Account::addRoomParticipant, this, &Squawk::onAccountAddRoomPresence);
connect(acc, &Account::changeRoomParticipant, this, &Squawk::onAccountChangeRoomPresence);
connect(acc, &Account::removeRoomParticipant, this, &Squawk::onAccountRemoveRoomPresence);
connect(acc, &Account::infoReady, this, &Squawk::responseInfo);
connect(acc, &Account::uploadFileError, this, &Squawk::onAccountUploadFileError);
connect(acc, &Account::infoDiscovered, this, &Squawk::onAccountInfoDiscovered);
2019-03-30 20:13:13 +00:00
QMap<QString, QVariant> map = {
{"login", login},
{"server", server},
{"name", name},
{"password", password},
{"resource", resource},
{"state", QVariant::fromValue(Shared::ConnectionState::disconnected)},
{"offline", QVariant::fromValue(Shared::Availability::offline)},
{"error", ""},
{"avatarPath", acc->getAvatarPath()},
{"passwordType", QVariant::fromValue(passwordType)},
{"active", active}
2019-03-30 20:13:13 +00:00
};
2019-03-30 20:13:13 +00:00
emit newAccount(map);
switch (passwordType) {
case Shared::AccountPassword::alwaysAsk:
case Shared::AccountPassword::kwallet:
if (password == "")
2022-04-13 19:02:48 +00:00
acc->invalidatePassword();
break;
default:
break;
}
if (state != Shared::Availability::offline) {
acc->setAvailability(state);
if (acc->getActive())
acc->connect();
}
2019-03-29 14:54:34 +00:00
}
void Core::Squawk::changeState(Shared::Availability p_state) {
if (state != p_state) {
for (std::deque<Account*>::iterator itr = accounts.begin(), end = accounts.end(); itr != end; ++itr) {
Account* acc = *itr;
acc->setAvailability(p_state);
if (state == Shared::Availability::offline && acc->getActive())
acc->connect();
}
state = p_state;
emit stateChanged(p_state);
}
}
void Core::Squawk::connectAccount(const QString& account) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to connect non existing account, skipping");
return;
}
itr->second->setActive(true);
if (state != Shared::Availability::offline)
itr->second->connect();
}
void Core::Squawk::disconnectAccount(const QString& account) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to connect non existing account, skipping");
return;
}
itr->second->setActive(false);
2019-04-02 15:46:18 +00:00
itr->second->disconnect();
}
void Core::Squawk::onAccountConnectionStateChanged(Shared::ConnectionState p_state) {
Account* acc = static_cast<Account*>(sender());
QMap<QString, QVariant> changes = {
{"state", QVariant::fromValue(p_state)}
};
if (acc->getLastError() == Account::Error::none)
changes.insert("error", "");
emit changeAccount(acc->getName(), changes);
#ifdef WITH_KWALLET
2020-08-07 23:33:03 +00:00
if (p_state == Shared::ConnectionState::connected) {
if (acc->getPasswordType() == Shared::AccountPassword::kwallet && kwallet.supportState() == PSE::KWallet::success) {
kwallet.requestWritePassword(acc->getName(), acc->getPassword(), true);
}
}
#endif
}
void Core::Squawk::onAccountAddContact(const QString& jid, const QString& group, const QMap<QString, QVariant>& data) {
2019-04-03 21:23:51 +00:00
Account* acc = static_cast<Account*>(sender());
emit addContact(acc->getName(), jid, group, data);
2019-04-03 21:23:51 +00:00
}
void Core::Squawk::onAccountAddGroup(const QString& name) {
2019-04-03 21:23:51 +00:00
Account* acc = static_cast<Account*>(sender());
emit addGroup(acc->getName(), name);
}
void Core::Squawk::onAccountRemoveGroup(const QString& name) {
2019-04-03 21:23:51 +00:00
Account* acc = static_cast<Account*>(sender());
emit removeGroup(acc->getName(), name);
}
2019-04-06 10:14:32 +00:00
void Core::Squawk::onAccountChangeContact(const QString& jid, const QMap<QString, QVariant>& data) {
2019-04-06 10:14:32 +00:00
Account* acc = static_cast<Account*>(sender());
emit changeContact(acc->getName(), jid, data);
2019-04-06 10:14:32 +00:00
}
void Core::Squawk::onAccountRemoveContact(const QString& jid) {
2019-04-06 10:14:32 +00:00
Account* acc = static_cast<Account*>(sender());
emit removeContact(acc->getName(), jid);
}
void Core::Squawk::onAccountRemoveContact(const QString& jid, const QString& group) {
2019-04-06 10:14:32 +00:00
Account* acc = static_cast<Account*>(sender());
emit removeContact(acc->getName(), jid, group);
}
2019-04-07 14:02:41 +00:00
void Core::Squawk::onAccountAddPresence(const QString& jid, const QString& name, const QMap<QString, QVariant>& data) {
2019-04-07 14:02:41 +00:00
Account* acc = static_cast<Account*>(sender());
emit addPresence(acc->getName(), jid, name, data);
//it's equal if a MUC sends its status with presence of the same jid (ex: muc@srv.im/muc@srv.im), it's not a client, so, no need to request
if (jid != name) {
const Shared::ClientId& id = data["client"].value<Shared::ClientId>();
if (!id.valid())
return;
if (!clientCache.checkClient(id))
acc->discoverInfo(jid + "/" + name, id.getId());
}
}
void Core::Squawk::onAccountInfoDiscovered(
const QString& address,
const QString& node,
const std::set<Shared::Identity>& identities,
const std::set<QString>& features)
{
Account* acc = static_cast<Account*>(sender());
if (!clientCache.registerClientInfo(address, node, identities, features)) {
qDebug() << "Account" << acc->getName() << "received an ill-formed client discovery response from" << address << "about" << node;
}
2019-04-07 14:02:41 +00:00
}
void Core::Squawk::onAccountRemovePresence(const QString& jid, const QString& name) {
2019-04-07 14:02:41 +00:00
Account* acc = static_cast<Account*>(sender());
emit removePresence(acc->getName(), jid, name);
}
void Core::Squawk::onAccountAvailabilityChanged(Shared::Availability state) {
Account* acc = static_cast<Account*>(sender());
emit changeAccount(acc->getName(), {{"availability", QVariant::fromValue(state)}});
}
2019-04-09 22:01:25 +00:00
void Core::Squawk::onAccountChanged(const QMap<QString, QVariant>& data) {
Account* acc = static_cast<Account*>(sender());
emit changeAccount(acc->getName(), data);
}
void Core::Squawk::onAccountMessage(const Shared::Message& data) {
2019-04-09 22:01:25 +00:00
Account* acc = static_cast<Account*>(sender());
emit accountMessage(acc->getName(), data);
}
2019-04-10 20:53:42 +00:00
void Core::Squawk::sendMessage(const QString& account, const Shared::Message& data) {
2019-04-10 20:53:42 +00:00
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to send a message with non existing account" << account << ", skipping";
2019-04-10 20:53:42 +00:00
return;
}
itr->second->sendMessage(data);
}
2019-04-13 20:38:20 +00:00
void Core::Squawk::replaceMessage(const QString& account, const QString& originalId, const Shared::Message& data) {
2022-03-28 20:25:33 +00:00
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to replace a message with non existing account" << account << ", skipping";
return;
}
itr->second->replaceMessage(originalId, data);
}
void Core::Squawk::resendMessage(const QString& account, const QString& jid, const QString& id) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to resend a message with non existing account" << account << ", skipping";
return;
}
itr->second->resendMessage(jid, id);
}
void Core::Squawk::requestArchive(const QString& account, const QString& jid, int count, const QString& before) {
2019-04-13 20:38:20 +00:00
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to request an archive of non existing account, skipping");
return;
}
itr->second->requestArchive(jid, count, before);
2019-04-13 20:38:20 +00:00
}
void Core::Squawk::onAccountResponseArchive(const QString& jid, const std::list<Shared::Message>& list, bool last) {
Account* acc = static_cast<Account*>(sender());
emit responseArchive(acc->getName(), jid, list, last);
}
void Core::Squawk::modifyAccountRequest(const QString& name, const QMap<QString, QVariant>& map) {
AccountsMap::const_iterator itr = amap.find(name);
if (itr == amap.end()) {
qDebug("An attempt to modify non existing account, skipping");
return;
}
Core::Account* acc = itr->second;
Shared::ConnectionState st = acc->getState();
QMap<QString, QVariant>::const_iterator mItr;
bool needToReconnect = false;
bool wentReconnecting = false;
mItr = map.find("login");
if (mItr != map.end()) {
needToReconnect = acc->getLogin() != mItr->toString();
}
if (!needToReconnect) {
mItr = map.find("password");
if (mItr != map.end()) {
needToReconnect = acc->getPassword() != mItr->toString();
}
}
if (!needToReconnect) {
mItr = map.find("server");
if (mItr != map.end()) {
needToReconnect = acc->getServer() != mItr->toString();
}
}
if (!needToReconnect) {
mItr = map.find("resource");
if (mItr != map.end()) {
needToReconnect = acc->getResource() != mItr->toString();
}
}
bool activeChanged = false;
mItr = map.find("active");
if (mItr == map.end() || mItr->toBool() == acc->getActive()) {
if (needToReconnect && st != Shared::ConnectionState::disconnected) {
acc->reconnect();
wentReconnecting = true;
}
} else {
acc->setActive(mItr->toBool());
activeChanged = true;
}
mItr = map.find("login");
if (mItr != map.end())
acc->setLogin(mItr->toString());
mItr = map.find("password");
if (mItr != map.end())
acc->setPassword(mItr->toString());
mItr = map.find("resource");
if (mItr != map.end())
acc->setResource(mItr->toString());
mItr = map.find("server");
if (mItr != map.end())
acc->setServer(mItr->toString());
mItr = map.find("passwordType");
if (mItr != map.end())
acc->setPasswordType(Shared::Global::fromInt<Shared::AccountPassword>(mItr->toInt()));
#ifdef WITH_KWALLET
if (acc->getPasswordType() == Shared::AccountPassword::kwallet
&& kwallet.supportState() == PSE::KWallet::success
&& !needToReconnect
) {
kwallet.requestWritePassword(acc->getName(), acc->getPassword(), true);
}
#endif
if (state != Shared::Availability::offline) {
if (activeChanged && acc->getActive())
acc->connect();
else if (!wentReconnecting && acc->getActive() && acc->getLastError() == Account::Error::authentication)
acc->connect();
}
emit changeAccount(name, map);
}
void Core::Squawk::onAccountError(const QString& text) {
Account* acc = static_cast<Account*>(sender());
emit changeAccount(acc->getName(), {{"error", text}});
if (acc->getLastError() == Account::Error::authentication)
emit requestPassword(acc->getName(), true);
}
2019-05-29 15:05:54 +00:00
void Core::Squawk::removeAccountRequest(const QString& name) {
2019-05-29 15:05:54 +00:00
AccountsMap::const_iterator itr = amap.find(name);
if (itr == amap.end()) {
qDebug() << "An attempt to remove non existing account " << name << " from core, skipping";
return;
}
Account* acc = itr->second;
if (acc->getState() != Shared::ConnectionState::disconnected)
2019-05-30 09:36:21 +00:00
acc->disconnect();
2019-05-29 15:05:54 +00:00
for (Accounts::const_iterator aItr = accounts.begin(); aItr != accounts.end(); ++aItr) {
if (*aItr == acc) {
accounts.erase(aItr);
break;
}
}
amap.erase(itr);
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
path += "/" + name;
QDir dir(path);
dir.removeRecursively();
emit removeAccount(name);
2019-05-30 09:36:21 +00:00
acc->deleteLater();
2019-05-29 15:05:54 +00:00
}
void Core::Squawk::subscribeContact(const QString& account, const QString& jid, const QString& reason) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to subscribe to the contact with non existing account, skipping");
return;
}
itr->second->subscribeToContact(jid, reason);
}
void Core::Squawk::unsubscribeContact(const QString& account, const QString& jid, const QString& reason) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to subscribe to the contact with non existing account, skipping");
return;
}
itr->second->unsubscribeFromContact(jid, reason);
}
2019-06-14 16:36:04 +00:00
void Core::Squawk::removeContactRequest(const QString& account, const QString& jid) {
2019-06-14 16:36:04 +00:00
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to remove contact from non existing account, skipping");
return;
}
itr->second->removeContactRequest(jid);
}
void Core::Squawk::addContactRequest(const QString& account, const QString& jid, const QString& name, const QSet<QString>& groups) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to add contact to a non existing account, skipping");
return;
}
itr->second->addContactRequest(jid, name, groups);
}
void Core::Squawk::onAccountAddRoom(const QString jid, const QMap<QString, QVariant>& data) {
Account* acc = static_cast<Account*>(sender());
emit addRoom(acc->getName(), jid, data);
}
void Core::Squawk::onAccountChangeRoom(const QString jid, const QMap<QString, QVariant>& data) {
Account* acc = static_cast<Account*>(sender());
emit changeRoom(acc->getName(), jid, data);
}
void Core::Squawk::onAccountRemoveRoom(const QString jid) {
Account* acc = static_cast<Account*>(sender());
emit removeRoom(acc->getName(), jid);
}
void Core::Squawk::setRoomJoined(const QString& account, const QString& jid, bool joined) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to set jouned to the room" << jid << "of non existing account" << account << ", skipping";
return;
}
itr->second->setRoomJoined(jid, joined);
}
void Core::Squawk::setRoomAutoJoin(const QString& account, const QString& jid, bool joined) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to set autoJoin to the room" << jid << "of non existing account" << account << ", skipping";
return;
}
itr->second->setRoomAutoJoin(jid, joined);
}
2023-11-05 01:12:15 +00:00
void Core::Squawk::setContactEncryption(const QString& account, const QString& jid, Shared::EncryptionProtocol value) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to set encryption to the contact" << jid << "of non existing account" << account << ", skipping";
return;
}
itr->second->setContactEncryption(jid, value);
}
void Core::Squawk::onAccountAddRoomPresence(const QString& jid, const QString& nick, const QMap<QString, QVariant>& data) {
Account* acc = static_cast<Account*>(sender());
emit addRoomParticipant(acc->getName(), jid, nick, data);
}
void Core::Squawk::onAccountChangeRoomPresence(const QString& jid, const QString& nick, const QMap<QString, QVariant>& data) {
Account* acc = static_cast<Account*>(sender());
emit changeRoomParticipant(acc->getName(), jid, nick, data);
}
void Core::Squawk::onAccountRemoveRoomPresence(const QString& jid, const QString& nick) {
Account* acc = static_cast<Account*>(sender());
emit removeRoomParticipant(acc->getName(), jid, nick);
}
void Core::Squawk::onAccountChangeMessage(const QString& jid, const QString& id, const QMap<QString, QVariant>& data) {
Account* acc = static_cast<Account*>(sender());
emit changeMessage(acc->getName(), jid, id, data);
}
void Core::Squawk::removeRoomRequest(const QString& account, const QString& jid) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to remove the room" << jid << "of non existing account" << account << ", skipping";
return;
}
itr->second->removeRoomRequest(jid);
}
2019-09-04 16:38:52 +00:00
void Core::Squawk::addRoomRequest(const QString& account, const QString& jid, const QString& nick, const QString& password, bool autoJoin) {
2019-09-04 16:38:52 +00:00
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to add the room" << jid << "to non existing account" << account << ", skipping";
return;
}
itr->second->addRoomRequest(jid, nick, password, autoJoin);
}
void Core::Squawk::fileDownloadRequest(const QString& url) {
network.downladFile(url);
}
void Core::Squawk::addContactToGroupRequest(const QString& account, const QString& jid, const QString& groupName) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to add contact" << jid << "of non existing account" << account << "to the group" << groupName << ", skipping";
return;
}
itr->second->addContactToGroupRequest(jid, groupName);
}
void Core::Squawk::removeContactFromGroupRequest(const QString& account, const QString& jid, const QString& groupName) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to add contact" << jid << "of non existing account" << account << "to the group" << groupName << ", skipping";
return;
}
itr->second->removeContactFromGroupRequest(jid, groupName);
}
void Core::Squawk::renameContactRequest(const QString& account, const QString& jid, const QString& newName) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to rename contact" << jid << "of non existing account" << account << ", skipping";
return;
}
itr->second->renameContactRequest(jid, newName);
}
void Core::Squawk::requestInfo(const QString& account, const QString& jid) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to request info about" << jid << "of non existing account" << account << ", skipping";
return;
}
itr->second->requestInfo(jid);
}
void Core::Squawk::updateInfo(const QString& account, const Shared::Info& info) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to update info to non existing account" << account << ", skipping";
return;
}
itr->second->updateInfo(info);
}
void Core::Squawk::readSettings() {
QSettings settings;
settings.beginGroup("core");
int size = settings.beginReadArray("accounts");
for (int i = 0; i < size; ++i) {
settings.setArrayIndex(i);
Shared::AccountPassword passwordType =
Shared::Global::fromInt<Shared::AccountPassword>(
settings.value("passwordType", static_cast<int>(Shared::AccountPassword::plain)).toInt()
);
QString name = settings.value("name").toString();
QString password = settings.value("password", "").toString();
2024-12-13 23:53:04 +00:00
if (passwordType == Shared::AccountPassword::jammed)
password = Jammer::decrypt(password, passwordHash);
addAccount(
settings.value("login").toString(),
settings.value("server").toString(),
password,
name,
settings.value("resource").toString(),
settings.value("active").toBool(),
passwordType
);
}
settings.endArray();
settings.endGroup();
qDebug() << "Squawk core is ready";
emit ready();
}
void Core::Squawk::onAccountNeedPassword() {
Account* acc = static_cast<Account*>(sender());
switch (acc->getPasswordType()) {
case Shared::AccountPassword::alwaysAsk:
emit requestPassword(acc->getName(), false);
break;
case Shared::AccountPassword::kwallet: {
#ifdef WITH_KWALLET
if (kwallet.supportState() == PSE::KWallet::success) {
kwallet.requestReadPassword(acc->getName());
} else {
#endif
emit requestPassword(acc->getName(), false);
#ifdef WITH_KWALLET
}
#endif
break;
}
default:
break; //should never happen;
}
}
void Core::Squawk::onWalletRejectPassword(const QString& login) {
emit requestPassword(login, false);
}
void Core::Squawk::responsePassword(const QString& account, const QString& password) {
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to set password to non existing account" << account << ", skipping";
return;
}
Account* acc = itr->second;
acc->setPassword(password);
emit changeAccount(account, {{"password", password}});
if (state != Shared::Availability::offline && acc->getActive())
acc->connect();
}
2021-04-13 13:27:31 +00:00
void Core::Squawk::onAccountUploadFileError(const QString& jid, const QString id, const QString& errorText) {
Account* acc = static_cast<Account*>(sender());
emit fileError({{acc->getName(), jid, id}}, errorText, true);
2021-04-13 13:27:31 +00:00
}
void Core::Squawk::onLocalPathInvalid(const QString& path) {
std::list<Shared::MessageInfo> list = network.reportPathInvalid(path);
QMap<QString, QVariant> data({{"attachPath", ""}});
for (const Shared::MessageInfo& info : list) {
AccountsMap::const_iterator itr = amap.find(info.account);
if (itr != amap.end()) {
itr->second->requestChangeMessage(info.jid, info.messageId, data);
} else {
qDebug() << "Reacting on failure to reach file" << path << "there was an attempt to change message in account" << info.account << "which doesn't exist, skipping";
}
}
}
2022-02-19 18:31:49 +00:00
void Core::Squawk::changeDownloadsPath(const QString& path) {
2022-02-19 18:31:49 +00:00
network.moveFilesDirectory(path);
}