aboutsummaryrefslogtreecommitdiff
path: root/src/base/QXmppOmemoData.cpp
diff options
context:
space:
mode:
authorMelvin Keskin <melvo@olomono.de>2021-09-02 23:41:16 +0200
committerLinus Jahn <lnj@kaidan.im>2021-09-03 16:16:15 +0200
commit0623aa38f2ead734dddea4cbad899a868f01cb1e (patch)
treece6539732310386d2ba0faf7383c054a4690f3a2 /src/base/QXmppOmemoData.cpp
parent12c63eddded9f02369bd4e569f62acfdd95cc723 (diff)
downloadqxmpp-0623aa38f2ead734dddea4cbad899a868f01cb1e.tar.gz
Add QXmppOmemoElement
Co-authored-by: Germán Márquez Mejía <mancho@olomono.de>
Diffstat (limited to 'src/base/QXmppOmemoData.cpp')
-rw-r--r--src/base/QXmppOmemoData.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/base/QXmppOmemoData.cpp b/src/base/QXmppOmemoData.cpp
index 6fb2580d..fbcf8261 100644
--- a/src/base/QXmppOmemoData.cpp
+++ b/src/base/QXmppOmemoData.cpp
@@ -26,6 +26,7 @@
#include "QXmppOmemoDeviceBundle.h"
#include "QXmppOmemoDeviceElement.h"
#include "QXmppOmemoDeviceList.h"
+#include "QXmppOmemoElement.h"
#include "QXmppOmemoEnvelope.h"
#include "QXmppUtils.h"
@@ -618,3 +619,189 @@ bool QXmppOmemoEnvelope::isOmemoEnvelope(const QDomElement &element)
return element.tagName() == QStringLiteral("key") &&
element.namespaceURI() == ns_omemo_1;
}
+
+///
+/// \class QXmppOmemoElement
+///
+/// \brief The QXmppOmemoElement class represents an OMEMO element as
+/// defined by \xep{0384, OMEMO Encryption}.
+///
+/// \since QXmpp 1.5
+///
+
+class QXmppOmemoElementPrivate : public QSharedData
+{
+public:
+ uint32_t senderDeviceId = 0;
+ QByteArray payload;
+ QMultiMap<QString, QXmppOmemoEnvelope> envelopes;
+};
+
+///
+/// Constructs an OMEMO element.
+///
+QXmppOmemoElement::QXmppOmemoElement()
+ : d(new QXmppOmemoElementPrivate)
+{
+}
+
+///
+/// Constructs a copy of \a other.
+///
+/// \param other
+///
+QXmppOmemoElement::QXmppOmemoElement(const QXmppOmemoElement &other) = default;
+
+QXmppOmemoElement::~QXmppOmemoElement() = default;
+
+///
+/// Assigns \a other to this OMEMO element.
+///
+/// \param other
+///
+QXmppOmemoElement &QXmppOmemoElement::operator=(const QXmppOmemoElement &other) = default;
+
+///
+/// Returns the ID of the sender's device.
+///
+/// The ID is 0 if it is unset.
+///
+/// \return the sender's device ID
+///
+uint32_t QXmppOmemoElement::senderDeviceId() const
+{
+ return d->senderDeviceId;
+}
+
+///
+/// Sets the ID of the sender's device.
+///
+/// A valid ID must be at least 1 and at most 2^32-1.
+///
+/// \param id sender's device ID
+///
+void QXmppOmemoElement::setSenderDeviceId(const uint32_t id)
+{
+ d->senderDeviceId = id;
+}
+
+///
+/// Returns the payload which consists of the encrypted SCE envelope.
+///
+/// \return the encrypted payload
+///
+QByteArray QXmppOmemoElement::payload() const
+{
+ return d->payload;
+}
+
+///
+/// Sets the payload which consists of the encrypted SCE envelope.
+///
+/// \param payload encrypted payload
+///
+void QXmppOmemoElement::setPayload(const QByteArray &payload)
+{
+ d->payload = payload;
+}
+
+///
+/// Searches for an OMEMO envelope by its recipient JID and device ID.
+///
+/// \param recipientJid bare JID of the recipient
+/// \param recipientDeviceId ID of the recipient's device
+///
+/// \return the found OMEMO envelope
+///
+std::optional<QXmppOmemoEnvelope> QXmppOmemoElement::searchEnvelope(const QString &recipientJid, uint32_t recipientDeviceId) const
+{
+ for (auto itr = d->envelopes.constFind(recipientJid); itr != d->envelopes.constEnd() && itr.key() == recipientJid; ++itr) {
+ const auto &envelope = itr.value();
+ if (envelope.recipientDeviceId() == recipientDeviceId) {
+ return envelope;
+ }
+ }
+
+ return std::nullopt;
+}
+
+///
+/// Adds an OMEMO envelope.
+///
+/// If a full JID is passed as recipientJid, it is converted into a bare JID.
+///
+/// \see QXmppOmemoEnvelope
+///
+/// \param recipientJid bare JID of the recipient
+/// \param envelope OMEMO envelope
+///
+void QXmppOmemoElement::addEnvelope(const QString &recipientJid, QXmppOmemoEnvelope &envelope)
+{
+ d->envelopes.insert(QXmppUtils::jidToBareJid(recipientJid), envelope);
+}
+
+/// \cond
+void QXmppOmemoElement::parse(const QDomElement &element)
+{
+ const auto header = element.firstChildElement("header");
+
+ d->senderDeviceId = header.attribute("sid").toInt();
+
+ for (auto recipient = header.firstChildElement("keys");
+ !recipient.isNull();
+ recipient = recipient.nextSiblingElement("keys")) {
+ const auto recipientJid = recipient.attribute("jid");
+
+ for (auto envelope = recipient.firstChildElement("key");
+ !envelope.isNull();
+ envelope = envelope.nextSiblingElement("key")) {
+ QXmppOmemoEnvelope omemoEnvelope;
+ omemoEnvelope.parse(envelope);
+ addEnvelope(recipientJid, omemoEnvelope);
+ }
+ }
+
+ d->payload = QByteArray::fromBase64(element.firstChildElement("payload").text().toLatin1());
+}
+
+void QXmppOmemoElement::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("encrypted");
+ writer->writeAttribute("xmlns", ns_omemo_1);
+
+ writer->writeStartElement("header");
+ writer->writeAttribute("sid", QString::number(d->senderDeviceId));
+
+ const auto recipientJids = d->envelopes.uniqueKeys();
+ for (const auto &recipientJid : recipientJids) {
+ writer->writeStartElement("keys");
+ writer->writeAttribute("jid", recipientJid);
+
+ for (auto itr = d->envelopes.constFind(recipientJid); itr != d->envelopes.constEnd() && itr.key() == recipientJid; ++itr) {
+ const auto &envelope = itr.value();
+ envelope.toXml(writer);
+ }
+
+ writer->writeEndElement(); // keys
+ }
+
+ writer->writeEndElement(); // header
+
+ helperToXmlAddTextElement(writer, "payload", d->payload.toBase64());
+
+ writer->writeEndElement(); // encrypted
+}
+/// \endcond
+
+///
+/// Determines whether the given DOM element is an OMEMO element.
+///
+/// \param element DOM element being checked
+///
+/// \return true if element is an OMEMO element, otherwise false
+///
+bool QXmppOmemoElement::isOmemoElement(const QDomElement &element)
+{
+ return element.tagName() == QStringLiteral("encrypted") &&
+ element.namespaceURI() == ns_omemo_1;
+}