forked from blue/squawk
feat: omemo signal lib wip
This commit is contained in:
parent
08fe37bfb2
commit
442ad37300
34 changed files with 745 additions and 262 deletions
|
@ -4,10 +4,13 @@
|
|||
|
||||
#include "conversations.h"
|
||||
|
||||
#include "qomemo/bundle.h"
|
||||
#include "qomemo/device.h"
|
||||
#include "shared/qxmppfactories.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QXmppIq.h>
|
||||
#include <QXmppPubSubIq.h>
|
||||
|
||||
using namespace QXmpp::Omemo;
|
||||
using namespace QXmpp::Factories;
|
||||
|
@ -41,13 +44,21 @@ Variant::Conversations::deviceListToXml(const DeviceList &deviceList) {
|
|||
return element;
|
||||
}
|
||||
|
||||
DeviceList Variant::Conversations::deviceListFromXml(const QXmppElement &xml) {
|
||||
std::optional<DeviceList> Variant::Conversations::latestDeviceListFromPubSubNode(const QXmppElement &items) {
|
||||
auto item = items.firstChildElement("item");
|
||||
if (item.isNull())
|
||||
return std::nullopt;
|
||||
|
||||
auto list = item.firstChildElement("list");
|
||||
if (list.isNull())
|
||||
return std::nullopt;
|
||||
|
||||
if (!elementMatches(list, "list", "eu.siacs.conversations.axolotl"))
|
||||
return std::nullopt;
|
||||
|
||||
DeviceList result{};
|
||||
|
||||
if (!elementMatches(xml, "list", "eu.siacs.conversations.axolotl"))
|
||||
return result;
|
||||
|
||||
auto deviceElement = xml.firstChildElement("device");
|
||||
auto deviceElement = list.firstChildElement("device");
|
||||
while (!deviceElement.isNull()) {
|
||||
result.devices.push_back(deviceFromXml(deviceElement));
|
||||
deviceElement = deviceElement.nextSiblingElement("device");
|
||||
|
@ -65,7 +76,34 @@ QXmppIq Variant::Conversations::deviceListSetIq(const DeviceList &deviceList) {
|
|||
item.appendChild(deviceListToXml(deviceList));
|
||||
|
||||
auto publish = createElement("publish");
|
||||
publish.setAttribute("node", "eu.siacs.conversations.axolotl.devicelist");
|
||||
publish.setAttribute("node", getDeviceListNode());
|
||||
publish.appendChild(item);
|
||||
|
||||
auto pubSub = createElement("pubsub", "http://jabber.org/protocol/pubsub");
|
||||
pubSub.appendChild(publish);
|
||||
pubSub.appendChild(createOpenPublishOptions());
|
||||
|
||||
iq.setExtensions({ pubSub });
|
||||
|
||||
return iq;
|
||||
}
|
||||
|
||||
QString Variant::Conversations::getDeviceListNode() const {
|
||||
return "eu.siacs.conversations.axolotl.devicelist";
|
||||
}
|
||||
|
||||
QXmppIq Variant::Conversations::bundleSetIq(int deviceId, const Bundle &bundle) {
|
||||
QXmppIq iq{};
|
||||
|
||||
iq.setType(QXmppIq::Set);
|
||||
|
||||
auto item = createElement("item");
|
||||
item.appendChild(bundleToXml(bundle));
|
||||
|
||||
auto publish = createElement("publish");
|
||||
publish.setAttribute(
|
||||
"node",
|
||||
QString("eu.siacs.conversations.axolotl.bundles:%s").arg(deviceId));
|
||||
publish.appendChild(item);
|
||||
|
||||
auto pubSub = createElement("pubsub", "http://jabber.org/protocol/pubsub");
|
||||
|
@ -76,3 +114,92 @@ QXmppIq Variant::Conversations::deviceListSetIq(const DeviceList &deviceList) {
|
|||
|
||||
return iq;
|
||||
}
|
||||
|
||||
QXmppElement Variant::Conversations::bundleToXml(const Bundle &bundle) {
|
||||
auto spkNode = createElement("signedPreKeyPublic");
|
||||
spkNode.setAttribute("signedPreKeyId", QString::number(bundle.spkId));
|
||||
spkNode.setValue(bundle.spk.toBase64());
|
||||
|
||||
auto spksNode = createElement("signedPreKeySignature");
|
||||
spksNode.setValue(bundle.spks.toBase64());
|
||||
|
||||
auto ikNode = createElement("identityKey");
|
||||
ikNode.setValue(bundle.ik.toBase64());
|
||||
|
||||
auto prekeysNode = createElement("prekeys");
|
||||
for (const auto &pk : bundle.prekeys) {
|
||||
prekeysNode.appendChild(preKeyToXml(pk));
|
||||
}
|
||||
|
||||
auto result = createElement("bundle", "eu.siacs.conversations.axolotl");
|
||||
result.appendChild(spkNode);
|
||||
result.appendChild(spksNode);
|
||||
result.appendChild(ikNode);
|
||||
result.appendChild(prekeysNode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QXmppElement Variant::Conversations::preKeyToXml(const PreKey &pk) {
|
||||
auto x = createElement("preKeyPublic");
|
||||
x.setAttribute("preKeyId", QString::number(pk.id));
|
||||
x.setValue(pk.data.toBase64());
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
std::optional<PreKey> Variant::Conversations::preKeyFromXml(const QXmppElement &xml) {
|
||||
if (!elementMatches(xml, "preKeyPublic"))
|
||||
return std::nullopt;
|
||||
|
||||
auto pk = PreKey();
|
||||
pk.id = xml.attribute("preKeyId").toInt();
|
||||
pk.data = QByteArray::fromBase64Encoding(xml.value().toUtf8()).decoded;
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
std::optional<Bundle> Variant::Conversations::bundleFromXml(const QXmppElement &xml) {
|
||||
if (!elementMatches(xml, "bundle", "eu.siacs.conversations.axolotl"))
|
||||
return std::nullopt;
|
||||
|
||||
auto spkNode = xml.firstChildElement("signedPreKeyPublic");
|
||||
if (spkNode.isNull()) {
|
||||
qWarning() << "'bundle': missing 'signedPreKeyPublic'";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Bundle result{};
|
||||
|
||||
result.spk = QByteArray::fromBase64Encoding(spkNode.value().toUtf8()).decoded;
|
||||
result.spkId = spkNode.attribute("signedPreKeyId").toInt();
|
||||
|
||||
auto spksNode = xml.firstChildElement("signedPreKeySignature");
|
||||
if (spksNode.isNull()) {
|
||||
qWarning() << "'bundle': missing 'signedPreKeySignature'";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.spks = QByteArray::fromBase64Encoding(spksNode.value().toUtf8()).decoded;
|
||||
|
||||
auto ikNode = xml.firstChildElement("identityKey");
|
||||
if (ikNode.isNull()) {
|
||||
qWarning() << "'bundle': missing 'identityKey'";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.ik = QByteArray::fromBase64Encoding(ikNode.value().toUtf8()).decoded;
|
||||
|
||||
auto prekeysNode = xml.firstChildElement("prekeys");
|
||||
auto pkNode = prekeysNode.firstChildElement("preKeyPublic");
|
||||
|
||||
result.prekeys.clear();
|
||||
while (!pkNode.isNull()) {
|
||||
auto maybePk = preKeyFromXml(pkNode);
|
||||
if (maybePk)
|
||||
result.prekeys.push_back(*maybePk);
|
||||
pkNode = pkNode.nextSiblingElement("preKeyPublic");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,18 @@ namespace QXmpp::Omemo::Variant {
|
|||
QXmppElement deviceToXml(const Device &device) override;
|
||||
Device deviceFromXml(const QXmppElement &xml) override;
|
||||
|
||||
[[nodiscard]] QString getDeviceListNode() const override;
|
||||
QXmppElement deviceListToXml(const DeviceList &deviceList) override;
|
||||
DeviceList deviceListFromXml(const QXmppElement &xml) override;
|
||||
std::optional<DeviceList> latestDeviceListFromPubSubNode(const QXmppElement &items) override;
|
||||
QXmppIq deviceListSetIq(const DeviceList &deviceList) override;
|
||||
|
||||
QXmppElement preKeyToXml(const PreKey &pk) override;
|
||||
std::optional<PreKey> preKeyFromXml(const QXmppElement &xml) override;
|
||||
|
||||
QXmppElement bundleToXml(const Bundle &bundle) override;
|
||||
std::optional<Bundle> bundleFromXml(const QXmppElement &xml) override;
|
||||
|
||||
QXmppIq bundleSetIq(int deviceId, const Bundle &bundle) override;
|
||||
};
|
||||
|
||||
} // namespace QXmpp::Omemo::Variant
|
||||
|
|
|
@ -4,14 +4,17 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
class QXmppElement;
|
||||
#include <optional>
|
||||
|
||||
class QString;
|
||||
class QXmppElement;
|
||||
class QXmppIq;
|
||||
|
||||
namespace QXmpp::Omemo {
|
||||
|
||||
class PreKey;
|
||||
class Bundle;
|
||||
class Device;
|
||||
|
||||
class DeviceList;
|
||||
|
||||
namespace Variant {
|
||||
|
@ -23,9 +26,18 @@ namespace QXmpp::Omemo {
|
|||
virtual QXmppElement deviceToXml(const Device &device) = 0;
|
||||
virtual Device deviceFromXml(const QXmppElement &xml) = 0;
|
||||
|
||||
[[nodiscard]] virtual QString getDeviceListNode() const = 0;
|
||||
virtual QXmppElement deviceListToXml(const DeviceList &deviceList) = 0;
|
||||
virtual DeviceList deviceListFromXml(const QXmppElement &xml) = 0;
|
||||
virtual std::optional<DeviceList> latestDeviceListFromPubSubNode(const QXmppElement &xml) = 0;
|
||||
virtual QXmppIq deviceListSetIq(const DeviceList &deviceList) = 0;
|
||||
|
||||
virtual QXmppElement preKeyToXml(const PreKey &pk) = 0;
|
||||
virtual std::optional<PreKey> preKeyFromXml(const QXmppElement &xml) = 0;
|
||||
|
||||
virtual QXmppElement bundleToXml(const Bundle& bundle) = 0;
|
||||
virtual std::optional<Bundle> bundleFromXml(const QXmppElement& xml) = 0;
|
||||
|
||||
virtual QXmppIq bundleSetIq(int deviceId, const Bundle& bundle) = 0;
|
||||
};
|
||||
|
||||
} // namespace Variant
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue