From af46ac9487caf54bb0783616af4e209b94b1cde5 Mon Sep 17 00:00:00 2001 From: Melvin Keskin Date: Sat, 11 Mar 2023 20:21:59 +0100 Subject: Fix OMEMO device list processing as specified --- src/omemo/QXmppOmemoManager_p.cpp | 51 +++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) (limited to 'src/omemo/QXmppOmemoManager_p.cpp') diff --git a/src/omemo/QXmppOmemoManager_p.cpp b/src/omemo/QXmppOmemoManager_p.cpp index 63cb5e00..c4d82e78 100644 --- a/src/omemo/QXmppOmemoManager_p.cpp +++ b/src/omemo/QXmppOmemoManager_p.cpp @@ -2650,6 +2650,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 QXmppOmemoManagerPrivate::updateContactDevices(const QString &deviceOwnerJid, const QVector &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. // @@ -3058,16 +3088,27 @@ QXmppTask ManagerPrivate::changeDeviceLabel(const QString &deviceLabel) // QXmppTask> ManagerPrivate::requestDeviceList(const QString &jid) { - auto future = pubSubManager->requestItem(jid, ns_omemo_2_devices, QXmppPubSubManager::Current); - future.then(q, [this, jid](QXmppPubSubManager::ItemResult result) mutable { + QXmppPromise> 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(jid, ns_omemo_2_devices); + future.then(q, [this, interface, jid](QXmppPubSubManager::ItemsResult result) mutable { if (const auto error = std::get_if(&result)) { warning("Device list for JID '" % jid % "' could not be retrieved: " % errorToString(*error)); + interface.finish(*error); + } else if (const auto &items = std::get>(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(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(); } // -- cgit v1.2.3