aboutsummaryrefslogtreecommitdiff
path: root/src/omemo
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2023-03-17 17:24:52 +0100
committerLinus Jahn <lnj@kaidan.im>2023-03-17 17:24:52 +0100
commit55362b2e36f91282ccfbdd2bd5a9bba1d50c2002 (patch)
treea0d6193add779507821defb2ebe9e9f8d8405628 /src/omemo
parentd679ad1c49eeb28be2ac3a75bd7fd1a9be24d483 (diff)
parent1cf0a4aff856a1f3cab0f9750ee6b361691350a7 (diff)
downloadqxmpp-55362b2e36f91282ccfbdd2bd5a9bba1d50c2002.tar.gz
Merge branch '1.5'
Diffstat (limited to 'src/omemo')
-rw-r--r--src/omemo/QXmppOmemoManager.cpp36
-rw-r--r--src/omemo/QXmppOmemoManager_p.cpp61
-rw-r--r--src/omemo/QXmppOmemoManager_p.h1
3 files changed, 72 insertions, 26 deletions
diff --git a/src/omemo/QXmppOmemoManager.cpp b/src/omemo/QXmppOmemoManager.cpp
index 0aab152d..a3ad12bb 100644
--- a/src/omemo/QXmppOmemoManager.cpp
+++ b/src/omemo/QXmppOmemoManager.cpp
@@ -340,7 +340,7 @@ QXmppOmemoManager::~QXmppOmemoManager() = default;
///
/// This should be called after starting the client and before the login.
/// It must only be called after \c setUp() has been called once for the user
-/// during one of the past login session.
+/// during one of the past login sessions.
/// It does not need to be called if setUp() has been called during the current
/// login session.
///
@@ -1267,29 +1267,33 @@ bool Manager::handlePubSubEvent(const QDomElement &element, const QString &pubSu
switch (event.eventType()) {
// Items have been published.
case QXmppPubSubEventBase::Items: {
- const auto items = event.items();
-
// Only process items if the event notification contains one.
- // That is necessary because PubSub allows publishing without
- // items leading to notification-only events.
- if (!items.isEmpty()) {
- const auto &deviceListItem = items.constFirst();
- if (deviceListItem.id() == QXmppPubSubManager::standardItemIdToString(QXmppPubSubManager::Current)) {
- d->updateDevices(pubSubService, event.items().constFirst());
+ // That is necessary because PubSub allows publishing without items leading to
+ // notification-only events.
+ if (const auto &items = event.items(); !items.isEmpty()) {
+ // Since the usage of the item ID \c QXmppPubSubManager::Current is only RECOMMENDED
+ // by \xep{0060, Publish-Subscribe} (PubSub) but not obligatory, an appropriate
+ // contact device list is determined.
+ // In case of the own device list node, it is sctrictly processed as a recommended
+ // singleton item and changed to fit that if needed.
+ const auto isOwnDeviceListNode = d->ownBareJid() == pubSubService;
+ if (isOwnDeviceListNode) {
+ const auto &deviceListItem = items.constFirst();
+ if (deviceListItem.id() == QXmppPubSubManager::standardItemIdToString(QXmppPubSubManager::Current)) {
+ d->updateDevices(pubSubService, event.items().constFirst());
+ } else {
+ d->handleIrregularDeviceListChanges(pubSubService);
+ }
} else {
- d->handleIrregularDeviceListChanges(pubSubService);
+ d->updateContactDevices(pubSubService, items);
}
}
break;
}
- // Items have been retracted.
+ // Specific items are deleted.
case QXmppPubSubEventBase::Retract: {
- // Specific items are deleted.
- const auto &retractedItem = event.retractIds().constFirst();
- if (retractedItem == QXmppPubSubManager::standardItemIdToString(QXmppPubSubManager::Current)) {
- d->handleIrregularDeviceListChanges(pubSubService);
- }
+ d->handleIrregularDeviceListChanges(pubSubService);
}
// All items are deleted.
case QXmppPubSubEventBase::Purge:
diff --git a/src/omemo/QXmppOmemoManager_p.cpp b/src/omemo/QXmppOmemoManager_p.cpp
index 1c86d80b..bcfd8303 100644
--- a/src/omemo/QXmppOmemoManager_p.cpp
+++ b/src/omemo/QXmppOmemoManager_p.cpp
@@ -920,7 +920,7 @@ bool ManagerPrivate::updatePreKeyPairs(uint32_t count)
deviceBundle.addPublicPreKey(preKeyId, serializedPublicPreKey);
}
- this->preKeyPairs.insert(serializedPreKeyPairs);
+ preKeyPairs.insert(serializedPreKeyPairs);
omemoStorage->addPreKeyPairs(serializedPreKeyPairs);
ownDevice.latestPreKeyId = latestPreKeyId - 1 + count;
@@ -2648,6 +2648,36 @@ void ManagerPrivate::updateOwnDevicesLocally(bool isDeviceListNodeExistent, Func
}
//
+// Updates all locally stored devices of a contact.
+//
+// \param deviceOwnerJid bare JID of the devices' owner
+// \param deviceListItems PEP items that may contain a device list
+//
+// \returns a found device list item
+//
+std::optional<QXmppOmemoDeviceListItem> QXmppOmemoManagerPrivate::updateContactDevices(const QString &deviceOwnerJid, const QVector<QXmppOmemoDeviceListItem> &deviceListItems)
+{
+ if (deviceListItems.size() > 1) {
+ const auto itr = std::find_if(deviceListItems.cbegin(), deviceListItems.cend(), [=](const QXmppOmemoDeviceListItem &item) {
+ return item.id() == QXmppPubSubManager::Current;
+ });
+
+ if (itr != deviceListItems.cend()) {
+ updateDevices(deviceOwnerJid, *itr);
+ return *itr;
+ } else {
+ warning("Device list for JID '" % deviceOwnerJid % "' could not be updated because the node contains more than one item but none with the singleton node's specific ID '" % QXmppPubSubManager::standardItemIdToString(QXmppPubSubManager::Current) % "'");
+ handleIrregularDeviceListChanges(deviceOwnerJid);
+ return {};
+ }
+ }
+
+ const auto &item = deviceListItems.constFirst();
+ updateDevices(deviceOwnerJid, item);
+ return item;
+}
+
+//
// Updates all locally stored devices by a passed device list item.
//
// \param deviceOwnerJid bare JID of the devices' owner
@@ -2783,7 +2813,7 @@ void ManagerPrivate::updateDevices(const QString &deviceOwnerJid, const QXmppOme
// Publish an own correct device list if the PEP service's one is incorrect
// and the devices are already set up locally.
if (isOwnDeviceListIncorrect) {
- if (!this->devices.isEmpty()) {
+ if (!devices.isEmpty()) {
publishDeviceListItem(true, [=](bool isPublished) {
if (!isPublished) {
warning("Own device list item could not be published in order to correct the PEP service's one");
@@ -2795,7 +2825,7 @@ void ManagerPrivate::updateDevices(const QString &deviceOwnerJid, const QXmppOme
//
// Corrects the own device list on the PEP service by the locally stored
-// devices or set a contact device to be removed locally in the future.
+// devices or sets a contact device to be removed locally in the future.
//
// \param deviceOwnerJid bare JID of the devices' owner
//
@@ -2810,7 +2840,7 @@ void ManagerPrivate::handleIrregularDeviceListChanges(const QString &deviceOwner
auto future = pubSubManager->deleteOwnPepNode(ns_omemo_2_devices);
future.then(q, [=](QXmppPubSubManager::Result result) {
if (const auto error = std::get_if<QXmppError>(&result)) {
- warning("Node '" % QString(ns_omemo_2_devices) % "' of JID '" % deviceOwnerJid %
+ warning("Node '" % QString(ns_omemo_2_devices) % "' of JID '" % deviceOwnerJid %
"' could not be deleted in order to recover from an inconsistent node: " %
errorToString(*error));
} else {
@@ -2845,7 +2875,7 @@ void ManagerPrivate::handleIrregularDeviceListChanges(const QString &deviceOwner
}
});
} else {
- auto &ownerDevices = this->devices[deviceOwnerJid];
+ auto &ownerDevices = devices[deviceOwnerJid];
// Set a timestamp for locally stored contact devices being removed
// later if their device list item is removed, if their device list node
@@ -3055,16 +3085,27 @@ QXmppTask<bool> ManagerPrivate::changeDeviceLabel(const QString &deviceLabel)
//
QXmppTask<QXmppPubSubManager::ItemResult<QXmppOmemoDeviceListItem>> ManagerPrivate::requestDeviceList(const QString &jid)
{
- auto future = pubSubManager->requestItem<QXmppOmemoDeviceListItem>(jid, ns_omemo_2_devices, QXmppPubSubManager::Current);
- future.then(q, [this, jid](QXmppPubSubManager::ItemResult<QXmppOmemoDeviceListItem> result) mutable {
+ QXmppPromise<QXmppPubSubManager::ItemResult<QXmppOmemoDeviceListItem>> interface;
+
+ // Since the usage of the item ID \c QXmppPubSubManager::Current is only RECOMMENDED by
+ // \xep{0060, Publish-Subscribe} (PubSub) but not obligatory, all items are requested even if
+ // the node should contain only one item.
+ auto future = pubSubManager->requestItems<QXmppOmemoDeviceListItem>(jid, ns_omemo_2_devices);
+ future.then(q, [this, interface, jid](QXmppPubSubManager::ItemsResult<QXmppOmemoDeviceListItem> result) mutable {
if (const auto error = std::get_if<QXmppError>(&result)) {
warning("Device list for JID '" % jid % "' could not be retrieved: " % errorToString(*error));
+ interface.finish(*error);
+ } else if (const auto &items = std::get<QXmppPubSubManager::Items<QXmppOmemoDeviceListItem>>(result).items; items.isEmpty()) {
+ const auto errorMessage = "Device list for JID '" % jid % "' could not be retrieved because the node does not contain any item";
+ warning(errorMessage);
+ interface.finish(QXmppError { errorMessage });
+ } else if (const auto item = updateContactDevices(jid, items); item) {
+ interface.finish(*item);
} else {
- const auto &item = std::get<QXmppOmemoDeviceListItem>(result);
- updateDevices(jid, item);
+ interface.finish(QXmppError { "Device list for JID '" % jid % "' could not be retrieved because the node does not contain an appropriate item" });
}
});
- return future;
+ return interface.task();
}
//
diff --git a/src/omemo/QXmppOmemoManager_p.h b/src/omemo/QXmppOmemoManager_p.h
index 96f10f94..0792bdf2 100644
--- a/src/omemo/QXmppOmemoManager_p.h
+++ b/src/omemo/QXmppOmemoManager_p.h
@@ -290,6 +290,7 @@ public:
QXmppOmemoDeviceListItem deviceListItem(bool addOwnDevice = true);
template<typename Function>
void updateOwnDevicesLocally(bool isDeviceListNodeExistent, Function continuation);
+ std::optional<QXmppOmemoDeviceListItem> updateContactDevices(const QString &deviceOwnerJid, const QVector<QXmppOmemoDeviceListItem> &deviceListItems);
void updateDevices(const QString &deviceOwnerJid, const QXmppOmemoDeviceListItem &deviceListItem);
void handleIrregularDeviceListChanges(const QString &deviceOwnerJid);
template<typename Function>