From 69d797fe51d57a373ee56f67124fe0a239790716 Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 18 Mar 2023 02:50:04 +0300 Subject: [PATCH] showing the button for encryption if there is at least one omemo key, trust summary update calculations --- core/handlers/rosterhandler.cpp | 30 +++++++----- core/handlers/rosterhandler.h | 3 ++ core/handlers/trusthandler.cpp | 86 ++++++++++++++++++++++++++++----- core/handlers/trusthandler.h | 4 ++ shared/trustsummary.cpp | 10 +++- shared/trustsummary.h | 3 ++ ui/models/contact.cpp | 12 +++-- ui/models/contact.h | 1 + ui/widgets/chat.cpp | 24 ++++----- 9 files changed, 134 insertions(+), 39 deletions(-) diff --git a/core/handlers/rosterhandler.cpp b/core/handlers/rosterhandler.cpp index ceaab2d..2e59971 100644 --- a/core/handlers/rosterhandler.cpp +++ b/core/handlers/rosterhandler.cpp @@ -39,6 +39,10 @@ void Core::RosterHandler::initialize() { connect(acc->bm, &QXmppBookmarkManager::bookmarksReceived, this, &RosterHandler::bookmarksReceived); connect(acc, &Account::pepSupportChanged, this, &RosterHandler::onPepSupportedChanged); + +#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0) + connect(acc->th, &TrustHandler::trustLevelsChanged, this, &RosterHandler::onTrustChanged); +#endif } Core::RosterHandler::~RosterHandler() { @@ -214,10 +218,13 @@ void Core::RosterHandler::onContactGroupAdded(const QString& group) { if (contact->groupsCount() == 1) { // not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway } - + QMap cData({ {"name", contact->getName()}, {"state", QVariant::fromValue(contact->getSubscriptionState())}, +#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0) + {"trust", QVariant::fromValue(acc->th->getSummary(contact->jid))}, +#endif {"encryption", contact->isEncryptionEnabled()} }); addToGroup(contact->jid, group); @@ -229,7 +236,7 @@ void Core::RosterHandler::onContactGroupRemoved(const QString& group) { if (contact->groupsCount() == 0) { // not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway } - + emit acc->removeContact(contact->jid, group); removeFromGroup(contact->jid, group); } @@ -246,12 +253,14 @@ void Core::RosterHandler::onContactEncryptionChanged(bool value) { void Core::RosterHandler::onContactSubscriptionStateChanged(Shared::SubscriptionState cstate) { Contact* contact = static_cast(sender()); - QMap cData({ - {"state", QVariant::fromValue(cstate)}, - }); - emit acc->changeContact(contact->jid, cData); + emit acc->changeContact(contact->jid, {{"state", QVariant::fromValue(cstate)}}); } +void Core::RosterHandler::onTrustChanged(const QString& jid, const Shared::TrustSummary& trust) { + emit acc->changeContact(jid, {{"trust", QVariant::fromValue(trust)}}); +} + + void Core::RosterHandler::addToGroup(const QString& jid, const QString& group) { std::map>::iterator gItr = groups.find(group); if (gItr == groups.end()) { @@ -296,18 +305,18 @@ Core::RosterItem * Core::RosterHandler::getRosterItem(const QString& jid) { Core::Conference * Core::RosterHandler::getConference(const QString& jid) { Conference* item = 0; std::map::const_iterator coitr = conferences.find(jid.toLower()); - if (coitr != conferences.end()) { + if (coitr != conferences.end()) item = coitr->second; - } + return item; } Core::Contact * Core::RosterHandler::getContact(const QString& jid) { Contact* item = 0; std::map::const_iterator citr = contacts.find(jid.toLower()); - if (citr != contacts.end()) { + if (citr != contacts.end()) item = citr->second; - } + return item; } @@ -527,7 +536,6 @@ void Core::RosterHandler::handleOffline() { } } - void Core::RosterHandler::onPepSupportedChanged(Shared::Support support) { if (support == Shared::Support::supported) { for (const std::pair& pair : contacts) { diff --git a/core/handlers/rosterhandler.h b/core/handlers/rosterhandler.h index 63f291c..61f3d7a 100644 --- a/core/handlers/rosterhandler.h +++ b/core/handlers/rosterhandler.h @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -75,6 +77,7 @@ private slots: void onRosterItemAdded(const QString& bareJid); void onRosterItemChanged(const QString& bareJid); void onRosterItemRemoved(const QString& bareJid); + void onTrustChanged(const QString& jid, const Shared::TrustSummary& trust); void onMucRoomAdded(QXmppMucRoom* room); void onMucJoinedChanged(bool joined); diff --git a/core/handlers/trusthandler.cpp b/core/handlers/trusthandler.cpp index 35e1bc6..c866d6f 100644 --- a/core/handlers/trusthandler.cpp +++ b/core/handlers/trusthandler.cpp @@ -79,7 +79,25 @@ Core::TrustHandler::KeyCache * Core::TrustHandler::createNewCache(const QString& QXmppTask Core::TrustHandler::resetAll(const QString& encryption) { securityPolicies->removeRecord(encryption); ownKeys->removeRecord(encryption); - getCache(encryption)->drop(); + std::map::const_iterator itr = keysByProtocol.find(encryption); + if (itr == keysByProtocol.end()) + return Core::makeReadyTask(); + + KeyCache* cache = itr->second; + std::map keys = cache->readAll(); + cache->drop(); + + for (const std::pair& pair : keys) { + bool empty = true; + for (const std::pair& trust : pair.second) { + if (trust.second != Shared::TrustLevel::undecided) { + empty = false; + break; + } + } + if (!empty) + emit trustLevelsChanged(pair.first, getSummary(pair.first)); + } return Core::makeReadyTask(); } @@ -109,6 +127,7 @@ QXmppTask>> Core::TrustHandler::s QHash> modifiedKeys; Shared::TrustLevel oldLevel = convert(oldTrustLevel); Shared::TrustLevel newLevel = convert(newTrustLevel); + std::set modifiedJids; KeyCache* cache = getCache(encryption); for (const QString& keyOwnerJid : keyOwnerJids) { Keys map = cache->getRecord(keyOwnerJid); @@ -118,13 +137,16 @@ QXmppTask>> Core::TrustHandler::s if (current == oldLevel) { current = newLevel; modifiedKeys[encryption].insert(keyOwnerJid, pair.first); + modifiedJids.insert(keyOwnerJid); ++count; } } - if (count > 0) { + if (count > 0) cache->changeRecord(keyOwnerJid, map); - } } + for (const QString& jid : modifiedJids) + emit trustLevelsChanged(jid, getSummary(jid)); + return Core::makeReadyTask(std::move(modifiedKeys)); } @@ -135,6 +157,7 @@ QXmppTask>> Core::TrustHandler::s { QHash> modifiedKeys; Shared::TrustLevel level = convert(trustLevel); + std::set modifiedJids; KeyCache* cache = getCache(encryption); for (MultySB::const_iterator itr = keyIds.begin(), end = keyIds.end(); itr != end; ++itr) { @@ -150,14 +173,20 @@ QXmppTask>> Core::TrustHandler::s } if (changed) { modifiedKeys[encryption].insert(keyOwnerJid, keyId); + modifiedJids.insert(keyOwnerJid); cache->changeRecord(keyOwnerJid, map); } } catch (const DataBase::NotFound& e) { Keys map({{keyId, level}}); modifiedKeys[encryption].insert(keyOwnerJid, keyId); + modifiedJids.insert(keyOwnerJid); cache->addRecord(keyOwnerJid, map); } } + + for (const QString& jid : modifiedJids) + emit trustLevelsChanged(jid, getSummary(jid)); + return Core::makeReadyTask(std::move(modifiedKeys)); } @@ -220,12 +249,41 @@ QXmppTask>> Core::Trust } QXmppTask Core::TrustHandler::removeKeys(const QString& encryption) { - getCache(encryption)->drop(); + std::map::const_iterator itr = keysByProtocol.find(encryption); + if (itr == keysByProtocol.end()) + return Core::makeReadyTask(); + + KeyCache* cache = itr->second; + std::map keys = cache->readAll(); + cache->drop(); + + for (const std::pair& pair : keys) { + bool empty = true; + for (const std::pair& trust : pair.second) { + if (trust.second != Shared::TrustLevel::undecided) { + empty = false; + break; + } + } + if (!empty) + emit trustLevelsChanged(pair.first, getSummary(pair.first)); + } + return Core::makeReadyTask(); } QXmppTask Core::TrustHandler::removeKeys(const QString& encryption, const QString& keyOwnerJid) { - getCache(encryption)->removeRecord(keyOwnerJid); + std::map::const_iterator itr = keysByProtocol.find(encryption); + if (itr == keysByProtocol.end()) + return Core::makeReadyTask(); + + KeyCache* cache = itr->second; + try { + cache->removeRecord(keyOwnerJid); + emit trustLevelsChanged(keyOwnerJid, getSummary(keyOwnerJid)); //TODO there is a probability of notification without the actial change + } catch (const DataBase::NotFound& e) {} //if the movin entry was empty or if it consisted of Undecided keys + + return Core::makeReadyTask(); } @@ -236,14 +294,15 @@ QXmppTask Core::TrustHandler::removeKeys(const QString& encryption, const KeyCache* cache = getCache(encryption); std::map data = cache->readAll(); - bool changed = false; + std::set modifiedJids; + for (std::map::iterator cItr = data.begin(), cEnd = data.end(); cItr != cEnd; /*no increment*/) { Keys& byOwner = cItr->second; for (Keys::const_iterator itr = byOwner.begin(), end = byOwner.end(); itr != end; /*no increment*/) { const QByteArray& keyId = itr->first; if (set.erase(keyId)) { byOwner.erase(itr++); - changed = true; + modifiedJids.insert(cItr->first); } else ++itr; } @@ -252,8 +311,12 @@ QXmppTask Core::TrustHandler::removeKeys(const QString& encryption, const else ++cItr; } - if (changed) + if (modifiedJids.size() > 0) { cache->replaceAll(data); + } + + for (const QString& jid : modifiedJids) + emit trustLevelsChanged(jid, getSummary(jid)); return Core::makeReadyTask(); } @@ -278,11 +341,12 @@ QXmppTask Core::TrustHandler::addKeys( result.first->second = level; } - if (had) { + if (had) cache->changeRecord(keyOwnerJid, data); - } else { + else cache->addRecord(keyOwnerJid, data); - } + + emit trustLevelsChanged(keyOwnerJid, getSummary(keyOwnerJid)); return Core::makeReadyTask(); } diff --git a/core/handlers/trusthandler.h b/core/handlers/trusthandler.h index d21e0c3..98d7f1e 100644 --- a/core/handlers/trusthandler.h +++ b/core/handlers/trusthandler.h @@ -32,6 +32,10 @@ public: TrustHandler(Account* account); ~TrustHandler(); +signals: + void trustLevelsChanged(const QString& jid, const Shared::TrustSummary& summary) const; + +public: typedef QMultiHash MultySB; typedef QHash HashSM; typedef const QList& CLSR; diff --git a/shared/trustsummary.cpp b/shared/trustsummary.cpp index 33a3873..eae98bf 100644 --- a/shared/trustsummary.cpp +++ b/shared/trustsummary.cpp @@ -138,7 +138,7 @@ bool Shared::TrustSummary::hasTrustedKeys(Shared::EncryptionProtocol protocol) c } bool Shared::TrustSummary::hasUntrustedKeys(Shared::EncryptionProtocol protocol) const { - Data::const_iterator itr = data.find(protocol); + Data::const_iterator itr = data.find(protocol); if (itr == data.end()) return false; @@ -149,3 +149,11 @@ bool Shared::TrustSummary::hasUntrustedKeys(Shared::EncryptionProtocol protocol) return false; } + +bool Shared::TrustSummary::operator==(const Shared::TrustSummary& other) { + return data == other.data; +} + +bool Shared::TrustSummary::operator!=(const Shared::TrustSummary& other) { + return data != other.data; +} diff --git a/shared/trustsummary.h b/shared/trustsummary.h index 7c79978..e663a9d 100644 --- a/shared/trustsummary.h +++ b/shared/trustsummary.h @@ -30,6 +30,9 @@ class TrustSummary { public: TrustSummary(); + bool operator == (const TrustSummary& other); + bool operator != (const TrustSummary& other); + void set(EncryptionProtocol protocol, TrustLevel level, uint8_t amount); uint8_t increment(EncryptionProtocol protocol, TrustLevel level); uint8_t decrement(EncryptionProtocol protocol, TrustLevel level); diff --git a/ui/models/contact.cpp b/ui/models/contact.cpp index b963421..8d6def9 100644 --- a/ui/models/contact.cpp +++ b/ui/models/contact.cpp @@ -206,10 +206,10 @@ Shared::TrustSummary Models::Contact::getTrust() const { } void Models::Contact::setTrust(const Shared::TrustSummary& p_trust) { - //if (trust != p_trust) { + if (trust != p_trust) { trust = p_trust; changed(8); - //} + } } @@ -245,7 +245,11 @@ QString Models::Contact::getDisplayedName() const { } void Models::Contact::handleRecconnect() { - if (getMessagesCount() > 0) { + if (getMessagesCount() > 0) feed->requestLatestMessages(); - } } + +bool Models::Contact::hasKeys(Shared::EncryptionProtocol protocol) const { + return trust.hasKeys(protocol); +} + diff --git a/ui/models/contact.h b/ui/models/contact.h index 36802cb..e7d767d 100644 --- a/ui/models/contact.h +++ b/ui/models/contact.h @@ -59,6 +59,7 @@ public: QString getStatus() const; QString getDisplayedName() const override; Shared::TrustSummary getTrust() const; + bool hasKeys(Shared::EncryptionProtocol protocol) const; void handleRecconnect(); //this is a special method Models::Roster calls when reconnect happens diff --git a/ui/widgets/chat.cpp b/ui/widgets/chat.cpp index 052d83d..607fab4 100644 --- a/ui/widgets/chat.cpp +++ b/ui/widgets/chat.cpp @@ -17,6 +17,7 @@ */ #include "chat.h" +#include "ui_conversation.h" Chat::Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent): Conversation(false, acc, p_contact, p_contact->getJid(), "", parent), @@ -28,14 +29,14 @@ Chat::Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent): setAvatar(p_contact->getAvatarPath()); connect(contact, &Models::Contact::childChanged, this, &Chat::onContactChanged); + if (p_contact->hasKeys(Shared::EncryptionProtocol::omemo2)) + m_ui->encryptionButton->setVisible(true); } Chat::~Chat() -{ -} +{} -void Chat::onContactChanged(Models::Item* item, int row, int col) -{ +void Chat::onContactChanged(Models::Item* item, int row, int col) { if (item == contact) { switch (col) { case 0: @@ -50,19 +51,20 @@ void Chat::onContactChanged(Models::Item* item, int row, int col) case 7: setAvatar(contact->getAvatarPath()); break; + case 8: + m_ui->encryptionButton->setVisible(contact->hasKeys(Shared::EncryptionProtocol::omemo2)); + break; } } } -void Chat::updateState() -{ +void Chat::updateState() { Shared::Availability av = contact->getAvailability(); statusIcon->setPixmap(Shared::availabilityIcon(av, true).pixmap(40)); statusIcon->setToolTip(Shared::Global::getName(av)); } -Shared::Message Chat::createMessage() const -{ +Shared::Message Chat::createMessage() const { Shared::Message msg = Conversation::createMessage(); msg.setType(Shared::Message::chat); msg.setFrom(account->getFullJid()); @@ -71,14 +73,12 @@ Shared::Message Chat::createMessage() const return msg; } -void Chat::onMessage(const Shared::Message& data) -{ +void Chat::onMessage(const Shared::Message& data){ Conversation::onMessage(data); if (!data.getOutgoing()) { const QString& res = data.getPenPalResource(); - if (res.size() > 0) { + if (res.size() > 0) setPalResource(res); - } } }