showing the button for encryption if there is at least one omemo key, trust summary update calculations

This commit is contained in:
Blue 2023-03-18 02:50:04 +03:00
parent 4f295fee3c
commit 69d797fe51
Signed by: blue
GPG Key ID: 9B203B252A63EE38
9 changed files with 134 additions and 39 deletions

View File

@ -39,6 +39,10 @@ void Core::RosterHandler::initialize() {
connect(acc->bm, &QXmppBookmarkManager::bookmarksReceived, this, &RosterHandler::bookmarksReceived); connect(acc->bm, &QXmppBookmarkManager::bookmarksReceived, this, &RosterHandler::bookmarksReceived);
connect(acc, &Account::pepSupportChanged, this, &RosterHandler::onPepSupportedChanged); 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() { Core::RosterHandler::~RosterHandler() {
@ -214,10 +218,13 @@ void Core::RosterHandler::onContactGroupAdded(const QString& group) {
if (contact->groupsCount() == 1) { if (contact->groupsCount() == 1) {
// not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway // not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway
} }
QMap<QString, QVariant> cData({ QMap<QString, QVariant> cData({
{"name", contact->getName()}, {"name", contact->getName()},
{"state", QVariant::fromValue(contact->getSubscriptionState())}, {"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()} {"encryption", contact->isEncryptionEnabled()}
}); });
addToGroup(contact->jid, group); addToGroup(contact->jid, group);
@ -229,7 +236,7 @@ void Core::RosterHandler::onContactGroupRemoved(const QString& group) {
if (contact->groupsCount() == 0) { if (contact->groupsCount() == 0) {
// not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway // 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); emit acc->removeContact(contact->jid, group);
removeFromGroup(contact->jid, group); removeFromGroup(contact->jid, group);
} }
@ -246,12 +253,14 @@ void Core::RosterHandler::onContactEncryptionChanged(bool value) {
void Core::RosterHandler::onContactSubscriptionStateChanged(Shared::SubscriptionState cstate) { void Core::RosterHandler::onContactSubscriptionStateChanged(Shared::SubscriptionState cstate) {
Contact* contact = static_cast<Contact*>(sender()); Contact* contact = static_cast<Contact*>(sender());
QMap<QString, QVariant> cData({ emit acc->changeContact(contact->jid, {{"state", QVariant::fromValue(cstate)}});
{"state", QVariant::fromValue(cstate)},
});
emit acc->changeContact(contact->jid, cData);
} }
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) { void Core::RosterHandler::addToGroup(const QString& jid, const QString& group) {
std::map<QString, std::set<QString>>::iterator gItr = groups.find(group); std::map<QString, std::set<QString>>::iterator gItr = groups.find(group);
if (gItr == groups.end()) { if (gItr == groups.end()) {
@ -296,18 +305,18 @@ Core::RosterItem * Core::RosterHandler::getRosterItem(const QString& jid) {
Core::Conference * Core::RosterHandler::getConference(const QString& jid) { Core::Conference * Core::RosterHandler::getConference(const QString& jid) {
Conference* item = 0; Conference* item = 0;
std::map<QString, Conference*>::const_iterator coitr = conferences.find(jid.toLower()); std::map<QString, Conference*>::const_iterator coitr = conferences.find(jid.toLower());
if (coitr != conferences.end()) { if (coitr != conferences.end())
item = coitr->second; item = coitr->second;
}
return item; return item;
} }
Core::Contact * Core::RosterHandler::getContact(const QString& jid) { Core::Contact * Core::RosterHandler::getContact(const QString& jid) {
Contact* item = 0; Contact* item = 0;
std::map<QString, Contact*>::const_iterator citr = contacts.find(jid.toLower()); std::map<QString, Contact*>::const_iterator citr = contacts.find(jid.toLower());
if (citr != contacts.end()) { if (citr != contacts.end())
item = citr->second; item = citr->second;
}
return item; return item;
} }
@ -527,7 +536,6 @@ void Core::RosterHandler::handleOffline() {
} }
} }
void Core::RosterHandler::onPepSupportedChanged(Shared::Support support) { void Core::RosterHandler::onPepSupportedChanged(Shared::Support support) {
if (support == Shared::Support::supported) { if (support == Shared::Support::supported) {
for (const std::pair<const QString, Contact*>& pair : contacts) { for (const std::pair<const QString, Contact*>& pair : contacts) {

View File

@ -34,6 +34,8 @@
#include <shared/enums.h> #include <shared/enums.h>
#include <shared/message.h> #include <shared/message.h>
#include <shared/trustsummary.h>
#include <core/contact.h> #include <core/contact.h>
#include <core/conference.h> #include <core/conference.h>
#include <core/delayManager/manager.h> #include <core/delayManager/manager.h>
@ -75,6 +77,7 @@ private slots:
void onRosterItemAdded(const QString& bareJid); void onRosterItemAdded(const QString& bareJid);
void onRosterItemChanged(const QString& bareJid); void onRosterItemChanged(const QString& bareJid);
void onRosterItemRemoved(const QString& bareJid); void onRosterItemRemoved(const QString& bareJid);
void onTrustChanged(const QString& jid, const Shared::TrustSummary& trust);
void onMucRoomAdded(QXmppMucRoom* room); void onMucRoomAdded(QXmppMucRoom* room);
void onMucJoinedChanged(bool joined); void onMucJoinedChanged(bool joined);

View File

@ -79,7 +79,25 @@ Core::TrustHandler::KeyCache * Core::TrustHandler::createNewCache(const QString&
QXmppTask<void> Core::TrustHandler::resetAll(const QString& encryption) { QXmppTask<void> Core::TrustHandler::resetAll(const QString& encryption) {
securityPolicies->removeRecord(encryption); securityPolicies->removeRecord(encryption);
ownKeys->removeRecord(encryption); ownKeys->removeRecord(encryption);
getCache(encryption)->drop(); std::map<QString, KeyCache*>::const_iterator itr = keysByProtocol.find(encryption);
if (itr == keysByProtocol.end())
return Core::makeReadyTask();
KeyCache* cache = itr->second;
std::map<QString, Keys> keys = cache->readAll();
cache->drop();
for (const std::pair<const QString, Keys>& pair : keys) {
bool empty = true;
for (const std::pair<const QByteArray, Shared::TrustLevel>& trust : pair.second) {
if (trust.second != Shared::TrustLevel::undecided) {
empty = false;
break;
}
}
if (!empty)
emit trustLevelsChanged(pair.first, getSummary(pair.first));
}
return Core::makeReadyTask(); return Core::makeReadyTask();
} }
@ -109,6 +127,7 @@ QXmppTask<QHash<QString, QMultiHash<QString, QByteArray>>> Core::TrustHandler::s
QHash<QString, QMultiHash<QString, QByteArray>> modifiedKeys; QHash<QString, QMultiHash<QString, QByteArray>> modifiedKeys;
Shared::TrustLevel oldLevel = convert(oldTrustLevel); Shared::TrustLevel oldLevel = convert(oldTrustLevel);
Shared::TrustLevel newLevel = convert(newTrustLevel); Shared::TrustLevel newLevel = convert(newTrustLevel);
std::set<QString> modifiedJids;
KeyCache* cache = getCache(encryption); KeyCache* cache = getCache(encryption);
for (const QString& keyOwnerJid : keyOwnerJids) { for (const QString& keyOwnerJid : keyOwnerJids) {
Keys map = cache->getRecord(keyOwnerJid); Keys map = cache->getRecord(keyOwnerJid);
@ -118,13 +137,16 @@ QXmppTask<QHash<QString, QMultiHash<QString, QByteArray>>> Core::TrustHandler::s
if (current == oldLevel) { if (current == oldLevel) {
current = newLevel; current = newLevel;
modifiedKeys[encryption].insert(keyOwnerJid, pair.first); modifiedKeys[encryption].insert(keyOwnerJid, pair.first);
modifiedJids.insert(keyOwnerJid);
++count; ++count;
} }
} }
if (count > 0) { if (count > 0)
cache->changeRecord(keyOwnerJid, map); cache->changeRecord(keyOwnerJid, map);
}
} }
for (const QString& jid : modifiedJids)
emit trustLevelsChanged(jid, getSummary(jid));
return Core::makeReadyTask(std::move(modifiedKeys)); return Core::makeReadyTask(std::move(modifiedKeys));
} }
@ -135,6 +157,7 @@ QXmppTask<QHash<QString, QMultiHash<QString, QByteArray>>> Core::TrustHandler::s
{ {
QHash<QString, QMultiHash<QString, QByteArray>> modifiedKeys; QHash<QString, QMultiHash<QString, QByteArray>> modifiedKeys;
Shared::TrustLevel level = convert(trustLevel); Shared::TrustLevel level = convert(trustLevel);
std::set<QString> modifiedJids;
KeyCache* cache = getCache(encryption); KeyCache* cache = getCache(encryption);
for (MultySB::const_iterator itr = keyIds.begin(), end = keyIds.end(); itr != end; ++itr) { for (MultySB::const_iterator itr = keyIds.begin(), end = keyIds.end(); itr != end; ++itr) {
@ -150,14 +173,20 @@ QXmppTask<QHash<QString, QMultiHash<QString, QByteArray>>> Core::TrustHandler::s
} }
if (changed) { if (changed) {
modifiedKeys[encryption].insert(keyOwnerJid, keyId); modifiedKeys[encryption].insert(keyOwnerJid, keyId);
modifiedJids.insert(keyOwnerJid);
cache->changeRecord(keyOwnerJid, map); cache->changeRecord(keyOwnerJid, map);
} }
} catch (const DataBase::NotFound& e) { } catch (const DataBase::NotFound& e) {
Keys map({{keyId, level}}); Keys map({{keyId, level}});
modifiedKeys[encryption].insert(keyOwnerJid, keyId); modifiedKeys[encryption].insert(keyOwnerJid, keyId);
modifiedJids.insert(keyOwnerJid);
cache->addRecord(keyOwnerJid, map); cache->addRecord(keyOwnerJid, map);
} }
} }
for (const QString& jid : modifiedJids)
emit trustLevelsChanged(jid, getSummary(jid));
return Core::makeReadyTask(std::move(modifiedKeys)); return Core::makeReadyTask(std::move(modifiedKeys));
} }
@ -220,12 +249,41 @@ QXmppTask<QHash<QXmpp::TrustLevel, QMultiHash<QString, QByteArray>>> Core::Trust
} }
QXmppTask<void> Core::TrustHandler::removeKeys(const QString& encryption) { QXmppTask<void> Core::TrustHandler::removeKeys(const QString& encryption) {
getCache(encryption)->drop(); std::map<QString, KeyCache*>::const_iterator itr = keysByProtocol.find(encryption);
if (itr == keysByProtocol.end())
return Core::makeReadyTask();
KeyCache* cache = itr->second;
std::map<QString, Keys> keys = cache->readAll();
cache->drop();
for (const std::pair<const QString, Keys>& pair : keys) {
bool empty = true;
for (const std::pair<const QByteArray, Shared::TrustLevel>& trust : pair.second) {
if (trust.second != Shared::TrustLevel::undecided) {
empty = false;
break;
}
}
if (!empty)
emit trustLevelsChanged(pair.first, getSummary(pair.first));
}
return Core::makeReadyTask(); return Core::makeReadyTask();
} }
QXmppTask<void> Core::TrustHandler::removeKeys(const QString& encryption, const QString& keyOwnerJid) { QXmppTask<void> Core::TrustHandler::removeKeys(const QString& encryption, const QString& keyOwnerJid) {
getCache(encryption)->removeRecord(keyOwnerJid); std::map<QString, KeyCache*>::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(); return Core::makeReadyTask();
} }
@ -236,14 +294,15 @@ QXmppTask<void> Core::TrustHandler::removeKeys(const QString& encryption, const
KeyCache* cache = getCache(encryption); KeyCache* cache = getCache(encryption);
std::map<QString, Keys> data = cache->readAll(); std::map<QString, Keys> data = cache->readAll();
bool changed = false; std::set<QString> modifiedJids;
for (std::map<QString, Keys>::iterator cItr = data.begin(), cEnd = data.end(); cItr != cEnd; /*no increment*/) { for (std::map<QString, Keys>::iterator cItr = data.begin(), cEnd = data.end(); cItr != cEnd; /*no increment*/) {
Keys& byOwner = cItr->second; Keys& byOwner = cItr->second;
for (Keys::const_iterator itr = byOwner.begin(), end = byOwner.end(); itr != end; /*no increment*/) { for (Keys::const_iterator itr = byOwner.begin(), end = byOwner.end(); itr != end; /*no increment*/) {
const QByteArray& keyId = itr->first; const QByteArray& keyId = itr->first;
if (set.erase(keyId)) { if (set.erase(keyId)) {
byOwner.erase(itr++); byOwner.erase(itr++);
changed = true; modifiedJids.insert(cItr->first);
} else } else
++itr; ++itr;
} }
@ -252,8 +311,12 @@ QXmppTask<void> Core::TrustHandler::removeKeys(const QString& encryption, const
else else
++cItr; ++cItr;
} }
if (changed) if (modifiedJids.size() > 0) {
cache->replaceAll(data); cache->replaceAll(data);
}
for (const QString& jid : modifiedJids)
emit trustLevelsChanged(jid, getSummary(jid));
return Core::makeReadyTask(); return Core::makeReadyTask();
} }
@ -278,11 +341,12 @@ QXmppTask<void> Core::TrustHandler::addKeys(
result.first->second = level; result.first->second = level;
} }
if (had) { if (had)
cache->changeRecord(keyOwnerJid, data); cache->changeRecord(keyOwnerJid, data);
} else { else
cache->addRecord(keyOwnerJid, data); cache->addRecord(keyOwnerJid, data);
}
emit trustLevelsChanged(keyOwnerJid, getSummary(keyOwnerJid));
return Core::makeReadyTask(); return Core::makeReadyTask();
} }

View File

@ -32,6 +32,10 @@ public:
TrustHandler(Account* account); TrustHandler(Account* account);
~TrustHandler(); ~TrustHandler();
signals:
void trustLevelsChanged(const QString& jid, const Shared::TrustSummary& summary) const;
public:
typedef QMultiHash<QString, QByteArray> MultySB; typedef QMultiHash<QString, QByteArray> MultySB;
typedef QHash<QString, MultySB> HashSM; typedef QHash<QString, MultySB> HashSM;
typedef const QList<QString>& CLSR; typedef const QList<QString>& CLSR;

View File

@ -138,7 +138,7 @@ bool Shared::TrustSummary::hasTrustedKeys(Shared::EncryptionProtocol protocol) c
} }
bool Shared::TrustSummary::hasUntrustedKeys(Shared::EncryptionProtocol protocol) const { 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()) if (itr == data.end())
return false; return false;
@ -149,3 +149,11 @@ bool Shared::TrustSummary::hasUntrustedKeys(Shared::EncryptionProtocol protocol)
return false; 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;
}

View File

@ -30,6 +30,9 @@ class TrustSummary {
public: public:
TrustSummary(); TrustSummary();
bool operator == (const TrustSummary& other);
bool operator != (const TrustSummary& other);
void set(EncryptionProtocol protocol, TrustLevel level, uint8_t amount); void set(EncryptionProtocol protocol, TrustLevel level, uint8_t amount);
uint8_t increment(EncryptionProtocol protocol, TrustLevel level); uint8_t increment(EncryptionProtocol protocol, TrustLevel level);
uint8_t decrement(EncryptionProtocol protocol, TrustLevel level); uint8_t decrement(EncryptionProtocol protocol, TrustLevel level);

View File

@ -206,10 +206,10 @@ Shared::TrustSummary Models::Contact::getTrust() const {
} }
void Models::Contact::setTrust(const Shared::TrustSummary& p_trust) { void Models::Contact::setTrust(const Shared::TrustSummary& p_trust) {
//if (trust != p_trust) { if (trust != p_trust) {
trust = p_trust; trust = p_trust;
changed(8); changed(8);
//} }
} }
@ -245,7 +245,11 @@ QString Models::Contact::getDisplayedName() const {
} }
void Models::Contact::handleRecconnect() { void Models::Contact::handleRecconnect() {
if (getMessagesCount() > 0) { if (getMessagesCount() > 0)
feed->requestLatestMessages(); feed->requestLatestMessages();
}
} }
bool Models::Contact::hasKeys(Shared::EncryptionProtocol protocol) const {
return trust.hasKeys(protocol);
}

View File

@ -59,6 +59,7 @@ public:
QString getStatus() const; QString getStatus() const;
QString getDisplayedName() const override; QString getDisplayedName() const override;
Shared::TrustSummary getTrust() const; Shared::TrustSummary getTrust() const;
bool hasKeys(Shared::EncryptionProtocol protocol) const;
void handleRecconnect(); //this is a special method Models::Roster calls when reconnect happens void handleRecconnect(); //this is a special method Models::Roster calls when reconnect happens

View File

@ -17,6 +17,7 @@
*/ */
#include "chat.h" #include "chat.h"
#include "ui_conversation.h"
Chat::Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent): Chat::Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent):
Conversation(false, acc, p_contact, p_contact->getJid(), "", 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()); setAvatar(p_contact->getAvatarPath());
connect(contact, &Models::Contact::childChanged, this, &Chat::onContactChanged); connect(contact, &Models::Contact::childChanged, this, &Chat::onContactChanged);
if (p_contact->hasKeys(Shared::EncryptionProtocol::omemo2))
m_ui->encryptionButton->setVisible(true);
} }
Chat::~Chat() 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) { if (item == contact) {
switch (col) { switch (col) {
case 0: case 0:
@ -50,19 +51,20 @@ void Chat::onContactChanged(Models::Item* item, int row, int col)
case 7: case 7:
setAvatar(contact->getAvatarPath()); setAvatar(contact->getAvatarPath());
break; break;
case 8:
m_ui->encryptionButton->setVisible(contact->hasKeys(Shared::EncryptionProtocol::omemo2));
break;
} }
} }
} }
void Chat::updateState() void Chat::updateState() {
{
Shared::Availability av = contact->getAvailability(); Shared::Availability av = contact->getAvailability();
statusIcon->setPixmap(Shared::availabilityIcon(av, true).pixmap(40)); statusIcon->setPixmap(Shared::availabilityIcon(av, true).pixmap(40));
statusIcon->setToolTip(Shared::Global::getName(av)); statusIcon->setToolTip(Shared::Global::getName(av));
} }
Shared::Message Chat::createMessage() const Shared::Message Chat::createMessage() const {
{
Shared::Message msg = Conversation::createMessage(); Shared::Message msg = Conversation::createMessage();
msg.setType(Shared::Message::chat); msg.setType(Shared::Message::chat);
msg.setFrom(account->getFullJid()); msg.setFrom(account->getFullJid());
@ -71,14 +73,12 @@ Shared::Message Chat::createMessage() const
return msg; return msg;
} }
void Chat::onMessage(const Shared::Message& data) void Chat::onMessage(const Shared::Message& data){
{
Conversation::onMessage(data); Conversation::onMessage(data);
if (!data.getOutgoing()) { if (!data.getOutgoing()) {
const QString& res = data.getPenPalResource(); const QString& res = data.getPenPalResource();
if (res.size() > 0) { if (res.size() > 0)
setPalResource(res); setPalResource(res);
}
} }
} }