aboutsummaryrefslogtreecommitdiff
path: root/lib/events
diff options
context:
space:
mode:
Diffstat (limited to 'lib/events')
-rw-r--r--lib/events/encryptedevent.cpp29
-rw-r--r--lib/events/encryptedevent.h66
-rw-r--r--lib/events/encryptionevent.cpp15
-rw-r--r--lib/events/event.h2
-rw-r--r--lib/events/roommessageevent.cpp37
5 files changed, 123 insertions, 26 deletions
diff --git a/lib/events/encryptedevent.cpp b/lib/events/encryptedevent.cpp
new file mode 100644
index 00000000..6942738a
--- /dev/null
+++ b/lib/events/encryptedevent.cpp
@@ -0,0 +1,29 @@
+#include "encryptedevent.h"
+#include "room.h"
+
+using namespace QMatrixClient;
+using namespace QtOlm;
+
+EncryptedEvent::EncryptedEvent(const QJsonObject &ciphertext, const QString &senderKey)
+ : RoomEvent(typeId(), matrixTypeId(),
+ { { AlgorithmKeyL , OlmV1Curve25519AesSha2AlgoKey },
+ { CiphertextKeyL , ciphertext },
+ { SenderKeyKeyL, senderKey }
+ })
+{ }
+
+EncryptedEvent::EncryptedEvent(QByteArray ciphertext, const QString &senderKey, const QString& deviceId, const QString& sessionId)
+ : RoomEvent(typeId(), matrixTypeId(),
+ { { AlgorithmKeyL , MegolmV1AesSha2AlgoKey },
+ { CiphertextKeyL , QString(ciphertext) },
+ { DeviceIdKeyL, deviceId },
+ { SenderKeyKeyL, senderKey },
+ { SessionIdKeyL, sessionId },
+ })
+{ }
+
+EncryptedEvent::EncryptedEvent(const QJsonObject &obj)
+ : RoomEvent(typeId(), obj)
+{
+ qCDebug(EVENTS) << "Encrypted event" << id();
+}
diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h
new file mode 100644
index 00000000..2f9e4422
--- /dev/null
+++ b/lib/events/encryptedevent.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include "roomevent.h"
+#include "e2ee.h"
+
+namespace QMatrixClient
+{
+ class Room;
+ /*
+ * While the specification states:
+ *
+ * "This event type is used when sending encrypted events.
+ * It can be used either within a room
+ * (in which case it will have all of the Room Event fields),
+ * or as a to-device event."
+ * "The encrypted payload can contain any message event."
+ * https://matrix.org/docs/spec/client_server/latest#id493
+ *
+ * -- for most of the cases the message event is the room message event.
+ * And even for the to-device events the context is for the room.
+ *
+ * So, to simplify integration to the timeline, EncryptedEvent is a RoomEvent inheritor.
+ * Strictly speaking though, it's not always a RoomEvent, but an Event in general.
+ * It's possible, because RoomEvent interface is similar to Event's one
+ * and doesn't add new restrictions, just provides additional features.
+ */
+ class EncryptedEvent : public RoomEvent
+ {
+ Q_GADGET
+ public:
+ DEFINE_EVENT_TYPEID("m.room.encrypted", EncryptedEvent)
+
+ /* In case with Olm, the encrypted content of the event is
+ * a map from the recipient Curve25519 identity key to ciphertext information */
+ explicit EncryptedEvent(const QJsonObject& ciphertext,
+ const QString& senderKey);
+ /* In case with Megolm, device_id and session_id are required */
+ explicit EncryptedEvent(QByteArray ciphertext,
+ const QString& senderKey,
+ const QString& deviceId,
+ const QString& sessionId);
+ explicit EncryptedEvent(const QJsonObject& obj);
+
+ QString algorithm() const
+ {
+ QString algo = content<QString>(AlgorithmKeyL);
+ if (!SupportedAlgorithms.contains(algo)) {
+ qWarning(MAIN) << "The EncryptedEvent's algorithm" << algo
+ << "is not supported";
+ }
+ return algo;
+ }
+ QByteArray ciphertext() const { return content<QString>(CiphertextKeyL).toLatin1(); }
+ QJsonObject ciphertext(const QString& identityKey) const
+ {
+ return content<QJsonObject>(CiphertextKeyL).value(identityKey).toObject();
+ }
+ QString senderKey() const { return content<QString>(SenderKeyKeyL); }
+
+ /* device_id and session_id are required with Megolm */
+ QString deviceId() const { return content<QString>(DeviceIdKeyL); }
+ QString sessionId() const { return content<QString>(SessionIdKeyL); }
+ };
+ REGISTER_EVENT_TYPE(EncryptedEvent)
+
+} // namespace QMatrixClient
diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp
index b8e2b575..ee6c92b1 100644
--- a/lib/events/encryptionevent.cpp
+++ b/lib/events/encryptionevent.cpp
@@ -7,11 +7,12 @@
#include "converters.h"
#include "logging.h"
+#include "e2ee.h"
#include <array>
static const std::array<QString, 1> encryptionStrings = { {
- QStringLiteral("m.megolm.v1.aes-sha2")
+ QMatrixClient::MegolmV1AesSha2AlgoKey
} };
namespace QMatrixClient {
@@ -36,9 +37,9 @@ using namespace QMatrixClient;
EncryptionEventContent::EncryptionEventContent(const QJsonObject& json)
: encryption(fromJson<EncryptionType>(json["algorithm"_ls]))
- , algorithm(sanitized(json["algorithm"_ls].toString()))
- , rotationPeriodMs(json["rotation_period_ms"_ls].toInt(604800000))
- , rotationPeriodMsgs(json["rotation_period_msgs"_ls].toInt(100))
+ , algorithm(sanitized(json[AlgorithmKeyL].toString()))
+ , rotationPeriodMs(json[RotationPeriodMsKeyL].toInt(604800000))
+ , rotationPeriodMsgs(json[RotationPeriodMsgsKeyL].toInt(100))
{ }
void EncryptionEventContent::fillJson(QJsonObject* o) const
@@ -47,7 +48,7 @@ void EncryptionEventContent::fillJson(QJsonObject* o) const
Q_ASSERT_X(encryption != EncryptionType::Undefined, __FUNCTION__,
"The key 'algorithm' must be explicit in EncryptionEventContent");
if (encryption != EncryptionType::Undefined)
- o->insert(QStringLiteral("algorithm"), algorithm);
- o->insert(QStringLiteral("rotation_period_ms"), rotationPeriodMs);
- o->insert(QStringLiteral("rotation_period_msgs"), rotationPeriodMsgs);
+ o->insert(AlgorithmKey, algorithm);
+ o->insert(RotationPeriodMsKey, rotationPeriodMs);
+ o->insert(RotationPeriodMsgsKey, rotationPeriodMsgs);
}
diff --git a/lib/events/event.h b/lib/events/event.h
index b3a58806..dee1c44a 100644
--- a/lib/events/event.h
+++ b/lib/events/event.h
@@ -57,11 +57,13 @@ namespace QMatrixClient
// === Standard Matrix key names and basicEventJson() ===
static const auto TypeKey = QStringLiteral("type");
+ static const auto BodyKey = QStringLiteral("body");
static const auto ContentKey = QStringLiteral("content");
static const auto EventIdKey = QStringLiteral("event_id");
static const auto UnsignedKey = QStringLiteral("unsigned");
static const auto StateKeyKey = QStringLiteral("state_key");
static const auto TypeKeyL = "type"_ls;
+ static const auto BodyKeyL = "body"_ls;
static const auto ContentKeyL = "content"_ls;
static const auto EventIdKeyL = "event_id"_ls;
static const auto UnsignedKeyL = "unsigned"_ls;
diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp
index d4b0d812..8b6cc730 100644
--- a/lib/events/roommessageevent.cpp
+++ b/lib/events/roommessageevent.cpp
@@ -30,10 +30,9 @@ using namespace EventContent;
using MsgType = RoomMessageEvent::MsgType;
-static const auto RelatesToKey = "m.relates_to"_ls;
-static const auto MsgTypeKey = "msgtype"_ls;
-static const auto BodyKey = "body"_ls;
-static const auto FormattedBodyKey = "formatted_body"_ls;
+static const auto RelatesToKeyL = "m.relates_to"_ls;
+static const auto MsgTypeKeyL = "msgtype"_ls;
+static const auto FormattedBodyKeyL = "formatted_body"_ls;
static const auto TextTypeKey = "m.text";
static const auto EmoteTypeKey = "m.emote";
@@ -50,7 +49,7 @@ TypedBase* make(const QJsonObject& json)
template <>
TypedBase* make<TextContent>(const QJsonObject& json)
{
- return json.contains(FormattedBodyKey) || json.contains(RelatesToKey)
+ return json.contains(FormattedBodyKeyL) || json.contains(RelatesToKeyL)
? new TextContent(json) : nullptr;
}
@@ -96,12 +95,12 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody,
const QString& jsonMsgType, TypedBase* content)
{
auto json = content ? content->toJson() : QJsonObject();
- if (json.contains(RelatesToKey)) {
+ if (json.contains(RelatesToKeyL)) {
if (jsonMsgType != TextTypeKey && jsonMsgType != NoticeTypeKey
&& jsonMsgType != EmoteTypeKey) {
- json.remove(RelatesToKey);
+ json.remove(RelatesToKeyL);
qCWarning(EVENTS)
- << RelatesToKey << "cannot be used in" << jsonMsgType
+ << RelatesToKeyL << "cannot be used in" << jsonMsgType
<< "messages; the relation has been stripped off";
} else {
// After the above, we know for sure that the content is TextContent
@@ -112,7 +111,7 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody,
newContentJson.insert(BodyKey, plainBody);
newContentJson.insert(TypeKey, jsonMsgType);
json.insert(QStringLiteral("m.new_content"), newContentJson);
- json[BodyKey] = "* " + plainBody;
+ json[BodyKeyL] = "* " + plainBody;
}
}
}
@@ -173,9 +172,9 @@ RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj)
if (isRedacted())
return;
const QJsonObject content = contentJson();
- if ( content.contains(MsgTypeKey) && content.contains(BodyKey) )
+ if ( content.contains(MsgTypeKeyL) && content.contains(BodyKeyL) )
{
- auto msgtype = content[MsgTypeKey].toString();
+ auto msgtype = content[MsgTypeKeyL].toString();
bool msgTypeFound = false;
for (const auto& mt: msgTypes)
if (mt.matrixType == msgtype)
@@ -205,12 +204,12 @@ RoomMessageEvent::MsgType RoomMessageEvent::msgtype() const
QString RoomMessageEvent::rawMsgtype() const
{
- return contentJson()[MsgTypeKey].toString();
+ return contentJson()[MsgTypeKeyL].toString();
}
QString RoomMessageEvent::plainBody() const
{
- return contentJson()[BodyKey].toString();
+ return contentJson()[BodyKeyL].toString();
}
QMimeType RoomMessageEvent::mimeType() const
@@ -295,7 +294,7 @@ Omittable<RelatesTo> fromJson(const QJsonValue& jv)
}
TextContent::TextContent(const QJsonObject& json)
- : relatesTo(fromJson<Omittable<RelatesTo>>(json[RelatesToKey]))
+ : relatesTo(fromJson<Omittable<RelatesTo>>(json[RelatesToKeyL]))
{
QMimeDatabase db;
static const auto PlainTextMimeType = db.mimeTypeForName("text/plain");
@@ -309,25 +308,25 @@ TextContent::TextContent(const QJsonObject& json)
if (actualJson["format"_ls].toString() == HtmlContentTypeId)
{
mimeType = HtmlMimeType;
- body = actualJson[FormattedBodyKey].toString();
+ body = actualJson[FormattedBodyKeyL].toString();
} else {
// Falling back to plain text, as there's no standard way to describe
// rich text in messages.
mimeType = PlainTextMimeType;
- body = actualJson[BodyKey].toString();
+ body = actualJson[BodyKeyL].toString();
}
}
void TextContent::fillJson(QJsonObject* json) const
{
static const auto FormatKey = QStringLiteral("format");
- static const auto RichBodyKey = QStringLiteral("formatted_body");
+ static const auto FormattedBodyKey = QStringLiteral("formatted_body");
Q_ASSERT(json);
if (mimeType.inherits("text/html"))
{
json->insert(FormatKey, HtmlContentTypeId);
- json->insert(RichBodyKey, body);
+ json->insert(FormattedBodyKey, body);
}
if (!relatesTo.omitted()) {
json->insert(QStringLiteral("m.relates_to"),
@@ -336,7 +335,7 @@ void TextContent::fillJson(QJsonObject* json) const
QJsonObject newContentJson;
if (mimeType.inherits("text/html")) {
json->insert(FormatKey, HtmlContentTypeId);
- json->insert(RichBodyKey, body);
+ json->insert(FormattedBodyKey, body);
}
json->insert(QStringLiteral("m.new_content"), newContentJson);
}