diff --git a/CHANGELOG.md b/CHANGELOG.md index 7107e26..a36da73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - deactivated accounts now don't appear in combobox of "Add contact" and "Join conference" dialogues - all of the expandable roster items now get saved between launches - settings file on the disk is not rewritten every roster element expansion or collapse +- removed unnecessary own vcard request at sturtup (used to do it to discover my own avatar) ### New features - Now you can enable tray icon from settings! diff --git a/core/account.cpp b/core/account.cpp index c3203b4..1c3314f 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -18,6 +18,7 @@ #include "account.h" #include + #include using namespace Core; @@ -44,12 +45,13 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& network(p_net), passwordType(Shared::AccountPassword::plain), lastError(Error::none), - pepSupport(false), + pepSupport(Shared::Support::unknown), active(p_active), notReadyPassword(false), mh(new MessageHandler(this)), rh(new RosterHandler(this)), - vh(new VCardHandler(this)) + vh(new VCardHandler(this)), + dh(new DiscoveryHandler(this)) { config.setUser(p_login); config.setDomain(p_server); @@ -79,9 +81,6 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& QObject::connect(um, &QXmppUploadRequestManager::slotReceived, mh, &MessageHandler::onUploadSlotReceived); QObject::connect(um, &QXmppUploadRequestManager::requestFailed, mh, &MessageHandler::onUploadSlotRequestFailed); - QObject::connect(dm, &QXmppDiscoveryManager::itemsReceived, this, &Account::onDiscoveryItemsReceived); - QObject::connect(dm, &QXmppDiscoveryManager::infoReceived, this, &Account::onDiscoveryInfoReceived); - QObject::connect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onUploadFileComplete); QObject::connect(network, &NetworkAccess::downloadFileComplete, mh, &MessageHandler::onDownloadFileComplete); QObject::connect(network, &NetworkAccess::loadFileError, mh, &MessageHandler::onLoadFileError); @@ -93,8 +92,6 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& QObject::connect(reconnectTimer, &QTimer::timeout, this, &Account::onReconnectTimer); if (name == "Test") { - qDebug() << "Presence capabilities: " << presence.capabilityNode(); - QXmppLogger* logger = new QXmppLogger(this); logger->setLoggingType(QXmppLogger::SignalLogging); client.setLogger(logger); @@ -263,9 +260,8 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence) if (jid == getBareJid()) { if (resource == getResource()) { emit availabilityChanged(static_cast(p_presence.availableStatusType())); - } else { - vh->handleOtherPresenceOfMyAccountChange(p_presence); } + vh->handlePresenceOfMyAccountChange(p_presence); } else { RosterItem* item = rh->getRosterItem(jid); if (item != 0) { @@ -574,104 +570,6 @@ void Core::Account::setRoomJoined(const QString& jid, bool joined) conf->setJoined(joined); } -void Core::Account::onDiscoveryItemsReceived(const QXmppDiscoveryIq& items) -{ - if (items.from() == getServer()) { - std::set needToRequest; - qDebug() << "Server items list received for account " << name << ":"; - for (QXmppDiscoveryIq::Item item : items.items()) { - QString jid = item.jid(); - if (jid != getServer()) { - qDebug() << " Node" << jid; - needToRequest.insert(jid); - } else { - qDebug() << " " << item.node().toStdString().c_str(); - } - } - - for (const QString& jid : needToRequest) { - dm->requestInfo(jid); - } - } -} - -void Core::Account::onDiscoveryInfoReceived(const QXmppDiscoveryIq& info) -{ - QString from = info.from(); - if (from == getServer()) { - bool enableCC = false; - qDebug() << "Server info received for account" << name; - QStringList features = info.features(); - qDebug() << "List of supported features of the server " << getServer() << ":"; - for (const QString& feature : features) { - qDebug() << " " << feature.toStdString().c_str(); - if (feature == "urn:xmpp:carbons:2") { - enableCC = true; - } - } - - if (enableCC) { - qDebug() << "Enabling carbon copies for account" << name; - cm->setCarbonsEnabled(true); - } - - qDebug() << "Requesting account" << name << "capabilities"; - dm->requestInfo(getBareJid()); - } else if (from == getBareJid()) { - qDebug() << "Received capabilities for account" << name << ":"; - QList identities = info.identities(); - bool pepSupported = false; - for (const QXmppDiscoveryIq::Identity& identity : identities) { - QString type = identity.type(); - QString category = identity.category(); - qDebug() << " " << category << type; - if (type == "pep" && category == "pubsub") { - pepSupported = true; - } - } - rh->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported); - } else { - qDebug() << "Received info for account" << name << "about" << from; - QString node = info.queryNode(); - if (!node.isEmpty()) { - QStringList feats = info.features(); - std::set identities; - std::set features(feats.begin(), feats.end()); - QList idents = info.identities(); - for (const QXmppDiscoveryIq::Identity& ident : idents) { - Shared::Identity identity; - identity.category = ident.category(); - identity.language = ident.language(); - identity.name = ident.name(); - identity.type = ident.type(); - identities.insert(identity); - - qDebug() << " " << identity.name << identity.category << identity.type; - } - for (const QString& feat : features) { - qDebug() << " " << feat; - } - emit infoDiscovered(from, node, identities, features); - } else { - Contact* cont = rh->getContact(from); - if (cont != nullptr) { - qDebug() << "Received info for account" << name << "about" << from; - QList identities = info.identities(); - bool pepSupported = false; - for (const QXmppDiscoveryIq::Identity& identity : identities) { - QString type = identity.type(); - QString category = identity.category(); - qDebug() << " " << category << type; - if (type == "pep" && category == "pubsub") { - pepSupported = true; - } - } - cont->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported); - } - } - } -} - void Core::Account::discoverInfo(const QString& address, const QString& node) { if (state == Shared::ConnectionState::connected) { dm->requestInfo(address, node); @@ -682,8 +580,17 @@ void Core::Account::discoverInfo(const QString& address, const QString& node) { } } +void Core::Account::setPepSupport(Shared::Support support) +{ + if (support != pepSupport) { + pepSupport = support; + emit pepSupportChanged(pepSupport); + } +} + void Core::Account::handleDisconnection() { + setPepSupport(Shared::Support::unknown); cm->setCarbonsEnabled(false); rh->handleOffline(); vh->handleOffline(); diff --git a/core/account.h b/core/account.h index a409490..0ce39e5 100644 --- a/core/account.h +++ b/core/account.h @@ -52,6 +52,7 @@ #include "handlers/messagehandler.h" #include "handlers/rosterhandler.h" #include "handlers/vcardhandler.h" +#include "handlers/discoveryhandler.h" namespace Core { @@ -62,6 +63,7 @@ class Account : public QObject friend class MessageHandler; friend class RosterHandler; friend class VCardHandler; + friend class DiscoveryHandler; public: enum class Error { authentication, @@ -156,6 +158,7 @@ signals: void uploadFileError(const QString& jid, const QString& messageId, const QString& error); void needPassword(); void infoDiscovered(const QString& address, const QString& node, const std::set& identities, const std::set& features); + void pepSupportChanged(Shared::Support support); private: QString name; @@ -179,13 +182,14 @@ private: NetworkAccess* network; Shared::AccountPassword passwordType; Error lastError; - bool pepSupport; + Shared::Support pepSupport; bool active; bool notReadyPassword; MessageHandler* mh; RosterHandler* rh; VCardHandler* vh; + DiscoveryHandler* dh; private slots: void onClientStateChange(QXmppClient::State state); @@ -199,13 +203,12 @@ private slots: void onMamLog(QXmppLogger::MessageType type, const QString &msg); - void onDiscoveryItemsReceived (const QXmppDiscoveryIq& items); - void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info); void onContactHistoryResponse(const std::list& list, bool last); private: void handleDisconnection(); void onReconnectTimer(); + void setPepSupport(Shared::Support support); }; } diff --git a/core/handlers/CMakeLists.txt b/core/handlers/CMakeLists.txt index fb67953..255d7fa 100644 --- a/core/handlers/CMakeLists.txt +++ b/core/handlers/CMakeLists.txt @@ -5,4 +5,6 @@ target_sources(squawk PRIVATE rosterhandler.h vcardhandler.cpp vcardhandler.h + discoveryhandler.cpp + discoveryhandler.h ) diff --git a/core/handlers/discoveryhandler.cpp b/core/handlers/discoveryhandler.cpp new file mode 100644 index 0000000..e562e68 --- /dev/null +++ b/core/handlers/discoveryhandler.cpp @@ -0,0 +1,135 @@ +// 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 "discoveryhandler.h" +#include "core/account.h" + +#include + +Core::DiscoveryHandler::DiscoveryHandler(Core::Account* account): + QObject(), + acc(account) +{ + QObject::connect(acc->dm, &QXmppDiscoveryManager::itemsReceived, this, &DiscoveryHandler::onItemsReceived); + QObject::connect(acc->dm, &QXmppDiscoveryManager::infoReceived, this, &DiscoveryHandler::onInfoReceived); + + acc->dm->setClientType("pc"); + acc->dm->setClientCategory("client"); + acc->dm->setClientName(qApp->applicationDisplayName() + " " + qApp->applicationVersion()); + acc->dm->setClientCapabilitiesNode("https://git.macaw.me/blue/squawk"); +} + +void Core::DiscoveryHandler::onItemsReceived(const QXmppDiscoveryIq& items) +{ + QString server = acc->getServer(); + if (items.from() == server) { + std::set needToRequest; + qDebug() << "Server items list received for account " << acc->getName() << ":"; + for (QXmppDiscoveryIq::Item item : items.items()) { + QString jid = item.jid(); + if (jid != server) { + qDebug() << " Node" << jid; + needToRequest.insert(jid); + } else { + qDebug() << " " << item.node().toStdString().c_str(); + } + } + + for (const QString& jid : needToRequest) { + acc->dm->requestInfo(jid); + } + } +} + +void Core::DiscoveryHandler::onInfoReceived(const QXmppDiscoveryIq& info) +{ + QString from = info.from(); + QString server = acc->getServer(); + QString accName = acc->getName(); + QString bareJid = acc->getBareJid(); + if (from == server) { + bool enableCC = false; + qDebug() << "Server info received for account" << accName; + QStringList features = info.features(); + qDebug() << "List of supported features of the server " << server << ":"; + for (const QString& feature : features) { + qDebug() << " " << feature.toStdString().c_str(); + if (feature == "urn:xmpp:carbons:2") { + enableCC = true; + } + } + + if (enableCC) { + qDebug() << "Enabling carbon copies for account" << accName; + acc->cm->setCarbonsEnabled(true); + } + + qDebug() << "Requesting account" << accName << "capabilities"; + acc->dm->requestInfo(bareJid); + } else if (from == bareJid) { + qDebug() << "Received capabilities for account" << accName << ":"; + QList identities = info.identities(); + bool pepSupported = false; + for (const QXmppDiscoveryIq::Identity& identity : identities) { + QString type = identity.type(); + QString category = identity.category(); + qDebug() << " " << category << type; + if (type == "pep" && category == "pubsub") { + pepSupported = true; + } + } + acc->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported); + } else { + qDebug() << "Received info for account" << accName << "about" << from; + QString node = info.queryNode(); + if (!node.isEmpty()) { + QStringList feats = info.features(); + std::set identities; + std::set features(feats.begin(), feats.end()); + QList idents = info.identities(); + for (const QXmppDiscoveryIq::Identity& ident : idents) { + Shared::Identity identity; + identity.category = ident.category(); + identity.language = ident.language(); + identity.name = ident.name(); + identity.type = ident.type(); + identities.insert(identity); + + qDebug() << " " << identity.name << identity.category << identity.type; + } + for (const QString& feat : features) { + qDebug() << " " << feat; + } + emit acc->infoDiscovered(from, node, identities, features); + } else { + Contact* cont = acc->rh->getContact(from); + if (cont != nullptr) { + qDebug() << "Received info for account" << accName << "about" << from; + QList identities = info.identities(); + bool pepSupported = false; + for (const QXmppDiscoveryIq::Identity& identity : identities) { + QString type = identity.type(); + QString category = identity.category(); + qDebug() << " " << category << type; + if (type == "pep" && category == "pubsub") { + pepSupported = true; + } + } + cont->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported); + } + } + } +} diff --git a/core/handlers/discoveryhandler.h b/core/handlers/discoveryhandler.h new file mode 100644 index 0000000..3129219 --- /dev/null +++ b/core/handlers/discoveryhandler.h @@ -0,0 +1,45 @@ +// 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 . + +#ifndef CORE_DISCOVERYHANDLER_H +#define CORE_DISCOVERYHANDLER_H + +#include + +#include +#include + +namespace Core { +class Account; + +class DiscoveryHandler : public QObject +{ + Q_OBJECT +public: + DiscoveryHandler(Account* account); + ~DiscoveryHandler(); + +private slots: + void onItemsReceived (const QXmppDiscoveryIq& items); + void onInfoReceived (const QXmppDiscoveryIq& info); + +private: + Account* acc; +}; + +} + +#endif // CORE_DISCOVERYHANDLER_H diff --git a/core/handlers/rosterhandler.cpp b/core/handlers/rosterhandler.cpp index 748f0f7..1a61440 100644 --- a/core/handlers/rosterhandler.cpp +++ b/core/handlers/rosterhandler.cpp @@ -26,8 +26,7 @@ Core::RosterHandler::RosterHandler(Core::Account* account): conferences(), groups(), queuedContacts(), - outOfRosterContacts(), - pepSupport(Shared::Support::unknown) + outOfRosterContacts() { connect(acc->rm, &QXmppRosterManager::rosterReceived, this, &RosterHandler::onRosterReceived); connect(acc->rm, &QXmppRosterManager::itemAdded, this, &RosterHandler::onRosterItemAdded); @@ -37,6 +36,8 @@ Core::RosterHandler::RosterHandler(Core::Account* account): connect(acc->mm, &QXmppMucManager::roomAdded, this, &RosterHandler::onMucRoomAdded); connect(acc->bm, &QXmppBookmarkManager::bookmarksReceived, this, &RosterHandler::bookmarksReceived); + + connect(acc, &Account::pepSupportChanged, this, &RosterHandler::onPepSupportedChanged); } Core::RosterHandler::~RosterHandler() @@ -52,8 +53,6 @@ Core::RosterHandler::~RosterHandler() void Core::RosterHandler::onRosterReceived() { - acc->requestVCard(acc->getBareJid()); //TODO need to make sure server actually supports vCards - QStringList bj = acc->rm->getRosterBareJids(); for (int i = 0; i < bj.size(); ++i) { const QString& jid = bj[i]; @@ -111,7 +110,7 @@ void Core::RosterHandler::addedAccount(const QString& jid) if (grCount == 0) { emit acc->addContact(jid, "", cData); } - if (pepSupport == Shared::Support::supported) { + if (acc->pepSupport == Shared::Support::supported) { acc->dm->requestInfo(jid); //acc->dm->requestItems(jid); } @@ -592,20 +591,15 @@ void Core::RosterHandler::handleOffline() pair.second->clearArchiveRequests(); pair.second->downgradeDatabaseState(); } - setPepSupport(Shared::Support::unknown); } -void Core::RosterHandler::setPepSupport(Shared::Support support) +void Core::RosterHandler::onPepSupportedChanged(Shared::Support support) { - if (pepSupport != support) { - pepSupport = support; - - if (pepSupport == Shared::Support::supported) { - for (const std::pair& pair : contacts) { - if (pair.second->getPepSupport() == Shared::Support::unknown) { - acc->dm->requestInfo(pair.first); - } + if (support == Shared::Support::supported) { + for (const std::pair& pair : contacts) { + if (pair.second->getPepSupport() == Shared::Support::unknown) { + acc->dm->requestInfo(pair.first); } } } diff --git a/core/handlers/rosterhandler.h b/core/handlers/rosterhandler.h index 7be38e1..6a56b15 100644 --- a/core/handlers/rosterhandler.h +++ b/core/handlers/rosterhandler.h @@ -65,7 +65,6 @@ public: void storeConferences(); void clearConferences(); - void setPepSupport(Shared::Support support); private slots: void onRosterReceived(); @@ -89,6 +88,7 @@ private slots: void onContactNameChanged(const QString& name); void onContactSubscriptionStateChanged(Shared::SubscriptionState state); void onContactAvatarChanged(Shared::Avatar, const QString& path); + void onPepSupportedChanged(Shared::Support support); private: void addNewRoom(const QString& jid, const QString& nick, const QString& roomName, bool autoJoin); @@ -109,7 +109,6 @@ private: std::map> groups; std::map queuedContacts; std::set outOfRosterContacts; - Shared::Support pepSupport; }; } diff --git a/core/handlers/vcardhandler.cpp b/core/handlers/vcardhandler.cpp index 2a8d65c..24cb6ee 100644 --- a/core/handlers/vcardhandler.cpp +++ b/core/handlers/vcardhandler.cpp @@ -228,7 +228,7 @@ void Core::VCardHandler::requestVCard(const QString& jid) } } -void Core::VCardHandler::handleOtherPresenceOfMyAccountChange(const QXmppPresence& p_presence) +void Core::VCardHandler::handlePresenceOfMyAccountChange(const QXmppPresence& p_presence) { if (!ownVCardRequestInProgress) { switch (p_presence.vCardUpdateType()) { diff --git a/core/handlers/vcardhandler.h b/core/handlers/vcardhandler.h index 4febb69..ee61d0a 100644 --- a/core/handlers/vcardhandler.h +++ b/core/handlers/vcardhandler.h @@ -44,7 +44,7 @@ public: void handleOffline(); void requestVCard(const QString& jid); - void handleOtherPresenceOfMyAccountChange(const QXmppPresence& p_presence); + void handlePresenceOfMyAccountChange(const QXmppPresence& p_presence); void uploadVCard(const Shared::VCard& card); QString getAvatarPath() const;