Archived
1
Fork 0

Reformat code

This commit is contained in:
Joshua Goins 2022-08-15 21:53:56 -04:00
parent 6df6ea1523
commit d83471009f
26 changed files with 810 additions and 698 deletions

33
.clang-format Normal file
View file

@ -0,0 +1,33 @@
---
AllowShortIfStatementsOnASingleLine: Never
CompactNamespaces: 'false'
DisableFormat: 'false'
IndentCaseLabels: 'true'
IndentPPDirectives: BeforeHash
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: 'true'
SortIncludes: 'true'
SortUsingDeclarations: 'true'
SpacesInCStyleCastParentheses: 'false'
Standard: Cpp11
TabWidth: '0'
UseTab: Never
AllowShortEnumsOnASingleLine: false
BraceWrapping:
AfterEnum: true
AccessModifierOffset: -4
SpaceAfterTemplateKeyword: 'false'
AllowAllParametersOfDeclarationOnNextLine: false
AlignAfterOpenBracket: AlwaysBreak
BinPackArguments: false
BinPackParameters: false
ColumnLimit: 120
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: 'Empty'
AllowShortLambdasOnASingleLine: 'Empty'
AllowShortLoopsOnASingleLine: 'false'
SeparateDefinitionBlocks : 'Always'

8
.editorconfig Normal file
View file

@ -0,0 +1,8 @@
root = true
[*]
insert_final_newline = true
indent_style = space
indent_size = 4
tab_width = 4
max_line_length = 120

View file

@ -1,6 +1,8 @@
# Trinity
A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Discord-like interface.
![Screenshot](misc/screenshot.png)
## Features
* Basic messaging capabilities
* Sending and recieving markdown messages, formatting can be disabled
@ -13,28 +15,18 @@ A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Di
* Start direct chats with other members
* Custom emote support
## Screenshots
![Screenshot](misc/screenshot.png)
## Installation
*Note: This is an outdated screenshot :-)*
I'm not providing any pre-built binaries yet, so you must compile from source.
## Dependencies
If you use Arch Linux, I maintain the [AUR package](https://aur.archlinux.org/packages/trinity-matrix-git).
## Building
Building Trinity is very easy, simply call CMake. Please make sure all the dependencies below are met.
### Dependencies
* Qt5
* WebEngine is also required
* CMark
* libolm
## Installation
There's no pre-compiled binaries yet, but compiling from source is easily provided you have Qt5 installed. If you use
Arch Linux, there's a [PKGBUILD available from the AUR](https://aur.archlinux.org/packages/trinity-matrix-git). Simply call it from `makepkg` or through your favorite AUR helper:
```
$ aur sync trinity-matrix-git
```
Since there's not a tagged release yet, there's only the git version available as a PKGBUILD at the moment.
## Licensing
Trinity's source code is distributed under the GPLv3 license. See the `LICENSE` file for more details.
`resources/background.jpg` shown on the login page is from Death to Stock.

View file

@ -1,8 +1,8 @@
#pragma once
#include <QObject>
#include <vector>
#include <QQmlContext>
#include <vector>
class MatrixCore;

View file

@ -1,10 +1,9 @@
#pragma once
#include <QSystemTrayIcon>
#include <QApplication>
#include <QSystemTrayIcon>
class Desktop : public QObject
{
class Desktop : public QObject {
Q_OBJECT
public:
Q_INVOKABLE void showTrayIcon(const bool shouldHide) {
@ -21,7 +20,7 @@ public:
}
Q_INVOKABLE bool isTrayIconEnabled() {
return icon->isVisible();;
return icon->isVisible();
}
QSystemTrayIcon* icon;

View file

@ -1,9 +1,7 @@
#ifndef DIRECTORYMODEL_H
#define DIRECTORYMODEL_H
class DirectoryModel
{
class DirectoryModel {
public:
DirectoryModel();
};

View file

@ -5,8 +5,7 @@
#include "emote.h"
class EmoteListModel : public QAbstractListModel
{
class EmoteListModel : public QAbstractListModel {
Q_OBJECT
public:
int rowCount(const QModelIndex& parent) const override;

View file

@ -1,7 +1,7 @@
#pragma once
#include <QString>
#include <QJsonObject>
#include <QString>
#include <olm/olm.h>

View file

@ -6,8 +6,7 @@ class MatrixCore;
struct Room;
class Event;
class EventModel : public QAbstractListModel
{
class EventModel : public QAbstractListModel {
Q_OBJECT
public:
enum EventRoles {

View file

@ -1,23 +1,22 @@
#pragma once
#include <QObject>
#include <QJsonObject>
#include <QList>
#include <QMap>
#include <QJsonObject>
#include <QObject>
#include "eventmodel.h"
#include "room.h"
#include "roomlistmodel.h"
#include "membermodel.h"
#include "roomlistsortmodel.h"
#include "emote.h"
#include "emotelistmodel.h"
#include "encryption.h"
#include "eventmodel.h"
#include "membermodel.h"
#include "room.h"
#include "roomlistmodel.h"
#include "roomlistsortmodel.h"
class Network;
class MatrixCore : public QObject
{
class MatrixCore : public QObject {
Q_OBJECT
Q_PROPERTY(QString profileName MEMBER profileName CONSTANT)
Q_PROPERTY(bool initialSyncComplete READ isInitialSyncComplete NOTIFY initialSyncFinished)
@ -39,7 +38,11 @@ public:
Encryption* encryption = nullptr;
// account
Q_INVOKABLE void registerAccount(const QString& username, const QString& password, const QString& session = "", const QString& type = "");
Q_INVOKABLE void registerAccount(
const QString& username,
const QString& password,
const QString& session = "",
const QString& type = "");
Q_INVOKABLE void login(const QString& username, const QString& password);
Q_INVOKABLE void logout();
@ -94,7 +97,14 @@ public:
void setMarkdownEnabled(const bool enabled);
void sendKeyToDevice(QString roomId, QString senderCurveIdentity, QString senderEdIdentity, QString session_id, QString session_key, QString user_id, QString device_id);
void sendKeyToDevice(
QString roomId,
QString senderCurveIdentity,
QString senderEdIdentity,
QString session_id,
QString session_key,
QString user_id,
QString device_id);
OlmOutboundGroupSession* currentSession = nullptr;
QString currentSessionId, currentSessionKey;

View file

@ -4,8 +4,7 @@
class Room;
class MemberModel : public QAbstractListModel
{
class MemberModel : public QAbstractListModel {
Q_OBJECT
public:
enum EventRoles {

View file

@ -1,9 +1,9 @@
#pragma once
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QJsonObject>
#include <QJsonDocument>
#include <QUrl>
#include "requestsender.h"
@ -17,8 +17,7 @@ public:
QNetworkAccessManager* manager;
QString homeserverURL, accessToken;
template<typename Fn>
inline void postJSON(const QString& path, const QJsonObject object, Fn&& fn) {
template<typename Fn> inline void postJSON(const QString& path, const QJsonObject object, Fn&& fn) {
QNetworkRequest request(homeserverURL + path);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
@ -38,7 +37,8 @@ public:
}
template<typename Fn, typename ProgressFn>
inline void postBinary(const QString& path, const QByteArray data, const QString mimeType, Fn&& fn, ProgressFn&& progressFn) {
inline void
postBinary(const QString& path, const QByteArray data, const QString mimeType, Fn&& fn, ProgressFn&& progressFn) {
QNetworkRequest request(homeserverURL + path);
request.setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
@ -56,8 +56,7 @@ public:
QObject::connect(reply, &QNetworkReply::uploadProgress, progressFn);
}
template<typename Fn>
inline void post(const QString& path, Fn&& fn) {
template<typename Fn> inline void post(const QString& path, Fn&& fn) {
QNetworkRequest request(homeserverURL + path);
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
@ -90,8 +89,7 @@ public:
manager->put(request, jsonPost);
}
template<typename Fn>
inline void putJSON(const QString& path, const QJsonObject object, Fn&& fn) {
template<typename Fn> inline void putJSON(const QString& path, const QJsonObject object, Fn&& fn) {
QNetworkRequest request(homeserverURL + path);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", accessToken.toLocal8Bit());

View file

@ -1,12 +1,11 @@
#pragma once
#include <functional>
#include <QObject>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
#include <functional>
class RequestSender : public QObject
{
class RequestSender : public QObject {
Q_OBJECT
public:
RequestSender(QObject* parent = nullptr) : QObject(parent) {}

View file

@ -1,9 +1,9 @@
#pragma once
#include <QObject>
#include <QString>
#include <QDateTime>
#include <QObject>
#include <QSettings>
#include <QString>
class EncryptionInformation : public QObject {
Q_OBJECT
@ -12,8 +12,7 @@ public:
QString sessionId;
};
class Event : public QObject
{
class Event : public QObject {
Q_OBJECT
Q_PROPERTY(QString sender READ getSender NOTIFY senderChanged)
Q_PROPERTY(QString msg READ getMsg NOTIFY msgChanged)
@ -175,8 +174,7 @@ private:
QString id, displayName, avatarURL;
};
class Room : public QObject
{
class Room : public QObject {
Q_OBJECT
Q_PROPERTY(QString id MEMBER id NOTIFY idChanged)
Q_PROPERTY(QString topic MEMBER topic NOTIFY topicChanged)
@ -188,7 +186,8 @@ class Room : public QObject
Q_PROPERTY(QString highlightCount READ getHighlightCount NOTIFY highlightCountChanged)
Q_PROPERTY(QString notificationCount READ getNotificationCount NOTIFY notificationCountChanged)
Q_PROPERTY(bool direct READ getDirect NOTIFY directChanged)
Q_PROPERTY(int notificationLevel READ getNotificationLevel WRITE setNotificationLevel NOTIFY notificationLevelChanged)
Q_PROPERTY(
int notificationLevel READ getNotificationLevel WRITE setNotificationLevel NOTIFY notificationLevelChanged)
Q_PROPERTY(bool encrypted READ getEncrypted NOTIFY encryptionChanged)
public:
Room(QObject* parent = nullptr) : QObject(parent) {}

View file

@ -4,8 +4,7 @@
class Room;
class RoomListModel : public QAbstractListModel
{
class RoomListModel : public QAbstractListModel {
Q_OBJECT
public:
enum EventRoles {

View file

@ -2,8 +2,7 @@
#include <QSortFilterProxyModel>
class RoomListSortModel : public QSortFilterProxyModel
{
class RoomListSortModel : public QSortFilterProxyModel {
Q_OBJECT
public:
bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
@ -19,8 +18,7 @@ public:
}
};
class MemberListSortModel : public QSortFilterProxyModel
{
class MemberListSortModel : public QSortFilterProxyModel {
Q_OBJECT
public:
bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
@ -35,4 +33,3 @@ public:
return sourceIndex.row();
}
};

View file

@ -1,6 +1,3 @@
#include "directorymodel.h"
DirectoryModel::DirectoryModel()
{
}
DirectoryModel::DirectoryModel() {}

View file

@ -1,10 +1,10 @@
#include "encryption.h"
#include <stdlib.h>
#include <QDebug>
#include <unistd.h>
#include <fcntl.h>
#include <QJsonDocument>
#include <cstring>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
void Encryption::createNewDeviceKeys() {
initAccount();
@ -35,7 +35,6 @@ void Encryption::createNewDeviceKeys() {
qDebug() << "identity keys: " << (char*)identity_memory;
qDebug() << "identity keys (parsed): " << identityKey;
}
QString Encryption::saveDeviceKeys() {
@ -108,11 +107,7 @@ QString Encryption::signMessage(QString message) {
void* memory = malloc(length);
olm_account_sign(
account,
message.data(), message.length(),
memory, length
);
olm_account_sign(account, message.data(), message.length(), memory, length);
qDebug() << "Signed: " << (char*)memory;
@ -169,7 +164,15 @@ OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::st
int fd = open("/dev/random", O_RDONLY);
read(fd, memory, length);
olm_create_outbound_session(outboundSession, account, identityKey.data(), identityKey.length(), oneTimeKey.data(), oneTimeKey.length(), (uint8_t*)memory, length);
olm_create_outbound_session(
outboundSession,
account,
identityKey.data(),
identityKey.length(),
oneTimeKey.data(),
oneTimeKey.length(),
(uint8_t*)memory,
length);
// qDebug() << "ERR: " << olm_session_last_error(outboundSession);
return outboundSession;
@ -181,7 +184,6 @@ OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::st
void const * their_one_time_key, size_t their_one_time_key_length,
void * random, size_t random_length
);*/
}
std::string Encryption::getSessionId(OlmSession* session) {
@ -192,10 +194,7 @@ std::string Encryption::getSessionId(OlmSession* session) {
/** An identifier for this session. Will be the same for both ends of the
* conversation. If the id buffer is too small then olm_session_last_error()
* will be "OUTPUT_BUFFER_TOO_SMALL". */
olm_session_id(
session,
memory, length
);
olm_session_id(session, memory, length);
return memory;
}
@ -229,7 +228,8 @@ OlmSession* Encryption::createInboundSession(std::string senderKey, std::string
void* inboundMemory = malloc(olm_session_size());
auto inboundSession = olm_session(inboundMemory);
olm_create_inbound_session_from(inboundSession, account, (void*)senderKey.c_str(), senderKey.length(), (void*)body.c_str(), body.length());
olm_create_inbound_session_from(
inboundSession, account, (void*)senderKey.c_str(), senderKey.length(), (void*)body.c_str(), body.length());
return inboundSession;
}
@ -237,15 +237,15 @@ OlmSession* Encryption::createInboundSession(std::string senderKey, std::string
std::vector<std::uint8_t> Encryption::decrypt(OlmSession* session, int msgType, std::string cipherText) {
/*std::string maxPlaintextLengthBuffer = cipherText;
size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType, (void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());;
qDebug() << "THE ERROR YOU ARE LOOKING FOR " << olm_session_last_error(session);
if(maxPlaintextLength == olm_error())
return "";
size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType,
(void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());; qDebug() << "THE ERROR YOU ARE LOOKING
FOR " << olm_session_last_error(session); if(maxPlaintextLength == olm_error()) return "";
char* plaintext = new char[maxPlaintextLength];
//plaintext[maxPlaintextLength] = '\0';
memset(plaintext, '\0', maxPlaintextLength);
int size = olm_decrypt(session, msgType, (void*)cipherText.data(), cipherText.length(), (void*)plaintext, maxPlaintextLength);
int size = olm_decrypt(session, msgType, (void*)cipherText.data(), cipherText.length(), (void*)plaintext,
maxPlaintextLength);
//plaintext[size] = '\0';
plaintext[size + 1] = '\0';
@ -257,7 +257,8 @@ std::vector<std::uint8_t> Encryption::decrypt(OlmSession* session, int msgType,
std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin());
// create the result buffer
size_t length = olm_decrypt_max_plaintext_length(session, msgType, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size());
size_t length =
olm_decrypt_max_plaintext_length(session, msgType, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size());
if (length == olm_error())
return {};
@ -267,7 +268,8 @@ std::vector<std::uint8_t> Encryption::decrypt(OlmSession* session, int msgType,
auto tmp_buffer = std::vector<std::uint8_t>(cipherText.size());
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
auto size = olm_decrypt(session, msgType, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size());
auto size =
olm_decrypt(session, msgType, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size());
if (size == olm_error())
return {};
@ -315,7 +317,8 @@ std::vector<std::uint8_t> Encryption::decrypt(OlmInboundGroupSession* session, s
std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin());
// create the result buffer
size_t length = olm_group_decrypt_max_plaintext_length(session, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size());
size_t length =
olm_group_decrypt_max_plaintext_length(session, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size());
if (length == olm_error())
return {};
@ -326,7 +329,8 @@ std::vector<std::uint8_t> Encryption::decrypt(OlmInboundGroupSession* session, s
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
uint32_t msgIndex;
auto size = olm_group_decrypt(session, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size(), &msgIndex);
auto size = olm_group_decrypt(
session, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size(), &msgIndex);
if (size == olm_error())
return {};

View file

@ -2,8 +2,8 @@
#include <QDebug>
#include "room.h"
#include "matrixcore.h"
#include "room.h"
EventModel::EventModel(MatrixCore& matrix) : matrix(matrix) {}

View file

@ -1,24 +1,24 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlComponent>
#include <QJsonArray>
#include <QAction>
#include <QMenu>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QApplication>
#include <QGuiApplication>
#include <QJsonArray>
#include <QMenu>
#include <QMessageBox>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQmlContext>
#include <QSystemTrayIcon>
#include <QtQuick/QQuickWindow>
#include <QtWebEngine/QtWebEngine>
#include "eventmodel.h"
#include "membermodel.h"
#include "matrixcore.h"
#include "network.h"
#include "desktop.h"
#include "roomlistsortmodel.h"
#include "emote.h"
#include "appcore.h"
#include "desktop.h"
#include "emote.h"
#include "eventmodel.h"
#include "matrixcore.h"
#include "membermodel.h"
#include "network.h"
#include "roomlistsortmodel.h"
void AppCore::addAccount(QString profileName) {
accounts.push_back(new MatrixCore(profileName));

View file

@ -2,19 +2,21 @@
#include <cmark.h>
#include "network.h"
#include <QDir>
#include <QJsonArray>
#include <QMimeData>
#include <QMimeDatabase>
#include <QPixmap>
#include <QRandomGenerator>
#include <QSettings>
#include <QPixmap>
#include <QStandardPaths>
#include <QDir>
#include <QMimeDatabase>
#include <QMimeData>
#include <fstream>
#include <iterator>
#include "network.h"
MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent), profileName(profileName), roomListModel(rooms), directoryListModel(publicRooms), eventModel(*this) {
MatrixCore::MatrixCore(QString profileName, QObject* parent)
: QObject(parent), profileName(profileName), roomListModel(rooms), directoryListModel(publicRooms),
eventModel(*this) {
network = new Network();
encryption = new Encryption();
@ -80,39 +82,41 @@ MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent),
localEmoteModel.setList(&emotes);
}
void MatrixCore::registerAccount(const QString &username, const QString &password, const QString& session, const QString& type) {
void MatrixCore::registerAccount(
const QString& username,
const QString& password,
const QString& session,
const QString& type) {
QJsonObject authObject;
if (!session.isEmpty()) {
authObject["type"] = type;
authObject["session"] = session;
}
const QJsonObject registerObject {
{"auth", authObject},
{"username", username},
{"password", password}
};
const QJsonObject registerObject{{"auth", authObject}, {"username", username}, {"password", password}};
network->postJSON("/_matrix/client/r0/register?kind=user", registerObject, [this](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
if (reply->error()) {
if (document.object().contains("flows")) {
const QString stage = document.object()["flows"].toArray()[0].toObject()["stages"].toArray()[0].toString();
const QString stage =
document.object()["flows"].toArray()[0].toObject()["stages"].toArray()[0].toString();
if (stage == "m.login.recaptcha") {
const QJsonObject data{
{"public_key", document.object()["params"].toObject()["m.login.recaptcha"].toObject()["public_key"].toString()},
{"public_key",
document.object()["params"]
.toObject()["m.login.recaptcha"]
.toObject()["public_key"]
.toString()},
{"session", document.object()["session"].toString()},
{"type", "m.login.recaptcha"}
};
{"type", "m.login.recaptcha"}};
emit registerFlow(data);
} else if (stage == "m.login.dummy") {
const QJsonObject data{
{"session", document.object()["session"].toString()},
{"type", "m.login.dummy"}
};
{"session", document.object()["session"].toString()}, {"type", "m.login.dummy"}};
emit registerFlow(data);
} else {
@ -141,8 +145,7 @@ void MatrixCore::login(const QString& username, const QString& password) {
{"type", "m.login.password"},
{"user", username},
{"password", password},
{"initial_device_display_name", "Trinity"}
};
{"initial_device_display_name", "Trinity"}};
network->postJSON("/_matrix/client/r0/login", loginObject, [this](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
@ -163,44 +166,37 @@ void MatrixCore::login(const QString& username, const QString& password) {
QJsonObject keysObject{
{"curve25519:" + document.object()["device_id"].toString(), encryption->identityKey["curve25519"]},
{"ed25519:" + document.object()["device_id"].toString(), encryption->identityKey["ed25519"]}
};
{"ed25519:" + document.object()["device_id"].toString(), encryption->identityKey["ed25519"]}};
QJsonObject deviceKeysObject{
{"user_id", document.object()["user_id"].toString()},
{"device_id", document.object()["device_id"].toString()},
{"algorithms", QJsonArray({"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"})},
{"keys", keysObject}
};
{"keys", keysObject}};
QJsonObject signature{
{"ed25519:" + document.object()["device_id"].toString(), encryption->signMessage(QJsonDocument(deviceKeysObject).toJson(QJsonDocument::Compact)) }};
{"ed25519:" + document.object()["device_id"].toString(),
encryption->signMessage(QJsonDocument(deviceKeysObject).toJson(QJsonDocument::Compact))}};
deviceKeysObject["signatures"] = QJsonObject {
{document.object()["user_id"].toString(), signature}};
deviceKeysObject["signatures"] = QJsonObject{{document.object()["user_id"].toString(), signature}};
QJsonObject oneTimeKeyObject;
auto one_time_keys = encryption->generateOneTimeKeys(encryption->getRecommendedNumberOfOneTimeKeys());
for (auto key : one_time_keys["curve25519"].toObject().keys()) {
QJsonObject keyObject {
{"key", one_time_keys["curve25519"].toObject()[key]}
};
QJsonObject keyObject{{"key", one_time_keys["curve25519"].toObject()[key]}};
QJsonObject signature{
{"ed25519:" + document.object()["device_id"].toString(), encryption->signMessage(QJsonDocument(keyObject).toJson(QJsonDocument::Compact)) }};
{"ed25519:" + document.object()["device_id"].toString(),
encryption->signMessage(QJsonDocument(keyObject).toJson(QJsonDocument::Compact))}};
keyObject["signatures"] = QJsonObject {
{document.object()["user_id"].toString(), signature}};
keyObject["signatures"] = QJsonObject{{document.object()["user_id"].toString(), signature}};
oneTimeKeyObject["signed_curve25519:" + key] = keyObject;
}
QJsonObject masterKeysObject {
{"device_keys", deviceKeysObject},
{"one_time_keys", oneTimeKeyObject}
};
QJsonObject masterKeysObject{{"device_keys", deviceKeysObject}, {"one_time_keys", oneTimeKeyObject}};
// qDebug() << masterKeysObject;
@ -241,11 +237,10 @@ void MatrixCore::updateAccountInformation() {
void MatrixCore::setDisplayName(const QString& name) {
displayName = name;
const QJsonObject displayNameObject {
{"displayname", name}
};
const QJsonObject displayNameObject{{"displayname", name}};
network->putJSON("/_matrix/client/r0/profile/" + userId + "/displayname", displayNameObject, [this, name](QNetworkReply* reply) {
network->putJSON(
"/_matrix/client/r0/profile/" + userId + "/displayname", displayNameObject, [this, name](QNetworkReply* reply) {
emit displayNameChanged();
});
}
@ -268,30 +263,49 @@ void MatrixCore::sync() {
// qDebug() << document.object()["device_one_time_keys_count"];
for (auto event : document.object()["to_device"].toObject()["events"].toArray()) {
if(event.toObject()["type"] == "m.room_key_request" && event.toObject()["content"].toObject()["action"] == "request") {
if (event.toObject()["type"] == "m.room_key_request" &&
event.toObject()["content"].toObject()["action"] == "request") {
auto sender = event.toObject()["sender"].toString();
auto device_id = event.toObject()["content"].toObject()["requesting_device_id"].toString();
auto room_id = event.toObject()["content"].toObject()["body"].toObject()["room_id"].toString();
QJsonObject queryObject{
{"timeout", 10000},
{"device_keys", QJsonObject{
{sender, QJsonArray({device_id})}
}},
{"device_keys", QJsonObject{{sender, QJsonArray({device_id})}}},
{"token", "string"},
};
network->postJSON("/_matrix/client/r0/keys/query", queryObject, [this, event, sender, device_id, room_id](QNetworkReply* reply) {
network->postJSON(
"/_matrix/client/r0/keys/query",
queryObject,
[this, event, sender, device_id, room_id](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
auto senderCurveKey = document.object()["device_keys"].toObject()[sender].toObject()[device_id].toObject()["keys"].toObject()["curve25519:" + device_id].toString();
auto senderEdKey = document.object()["device_keys"].toObject()[sender].toObject()[device_id].toObject()["keys"].toObject()["ed25519:" + device_id].toString();
auto senderCurveKey = document.object()["device_keys"]
.toObject()[sender]
.toObject()[device_id]
.toObject()["keys"]
.toObject()["curve25519:" + device_id]
.toString();
auto senderEdKey = document.object()["device_keys"]
.toObject()[sender]
.toObject()[device_id]
.toObject()["keys"]
.toObject()["ed25519:" + device_id]
.toString();
qDebug() << "sending keys to " << device_id;
createOrLoadSession();
sendKeyToDevice(room_id, senderCurveKey, senderEdKey, currentSessionId, currentSessionKey, sender, device_id);
sendKeyToDevice(
room_id,
senderCurveKey,
senderEdKey,
currentSessionId,
currentSessionKey,
sender,
device_id);
});
} else if (event.toObject()["type"] == "m.room_key") {
qDebug() << "we recieved a new key from a user in the room :-)";
@ -300,21 +314,31 @@ void MatrixCore::sync() {
} else if (event.toObject()["type"] == "m.room.encrypted") {
auto curveKey = event.toObject()["content"].toObject()["ciphertext"].toObject().keys()[0];
auto senderKey = event.toObject()["content"].toObject()["sender_key"].toString();
int type = event.toObject()["content"].toObject()["ciphertext"].toObject()[curveKey].toObject()["type"].toInt();
auto body = event.toObject()["content"].toObject()["ciphertext"].toObject()[curveKey].toObject()["body"].toString();
int type = event.toObject()["content"]
.toObject()["ciphertext"]
.toObject()[curveKey]
.toObject()["type"]
.toInt();
auto body = event.toObject()["content"]
.toObject()["ciphertext"]
.toObject()[curveKey]
.toObject()["body"]
.toString();
// create a new inbound session
auto session = encryption->createInboundSession(senderKey.toStdString(), body.toStdString());
auto decryptedMsg = encryption->decrypt(session, type, body.toStdString());
const QJsonDocument document = QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(decryptedMsg.data()), decryptedMsg.size()));
const QJsonDocument document = QJsonDocument::fromJson(
QByteArray(reinterpret_cast<const char*>(decryptedMsg.data()), decryptedMsg.size()));
auto id = document.object()["content"].toObject()["session_id"].toString();
qDebug() << "NEW KEY " << id << " = " << document;
// create new inbound session, append to list
auto sess = encryption->beginInboundSession(document.object()["content"].toObject()["session_key"].toString().toStdString());
auto sess = encryption->beginInboundSession(
document.object()["content"].toObject()["session_key"].toString().toStdString());
inboundSessions[id] = sess;
// if we recieved a new key, let's see if we can decrypt some old messages!
@ -324,7 +348,8 @@ void MatrixCore::sync() {
if (event->encryptionInfo != nullptr && event->encryptionInfo->sessionId == id) {
auto msg = encryption->decrypt(sess, event->encryptionInfo->cipherText.toStdString());
const QJsonDocument document = QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(msg.data()), msg.size()));
const QJsonDocument document = QJsonDocument::fromJson(
QByteArray(reinterpret_cast<const char*>(msg.data()), msg.size()));
populateEvent(document.object(), event);
@ -352,7 +377,8 @@ void MatrixCore::sync() {
settings.endGroup();
if (autofill_data) {
network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.name", [this, room](QNetworkReply* reply) {
network->get(
"/_matrix/client/r0/rooms/" + id + "/state/m.room.name", [this, room](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
room->setGuestDenied(true);
@ -365,7 +391,8 @@ void MatrixCore::sync() {
roomListModel.updateRoom(room);
});
network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.topic", [this, room](QNetworkReply* reply) {
network->get(
"/_matrix/client/r0/rooms/" + id + "/state/m.room.topic", [this, room](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
room->setGuestDenied(true);
@ -377,7 +404,8 @@ void MatrixCore::sync() {
roomListModel.updateRoom(room);
});
network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.avatar", [this, room](QNetworkReply* reply) {
network->get(
"/_matrix/client/r0/rooms/" + id + "/state/m.room.avatar", [this, room](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
room->setGuestDenied(true);
@ -386,13 +414,17 @@ void MatrixCore::sync() {
if (document.object().contains("url")) {
const QString imageId = document.object()["url"].toString().remove("mxc://");
room->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
room->setAvatar(
network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId +
"?width=64&height=64&method=scale");
}
roomListModel.updateRoom(room);
});
network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.power_levels", [this, room](QNetworkReply* reply) {
network->get(
"/_matrix/client/r0/rooms/" + id + "/state/m.room.power_levels",
[this, room](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
for (auto user : document.object()["users"].toObject().keys()) {
@ -400,7 +432,8 @@ void MatrixCore::sync() {
}
});
network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.encryption", [this, room](QNetworkReply* reply) {
network->get(
"/_matrix/client/r0/rooms/" + id + "/state/m.room.encryption", [this, room](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
if (document.object().contains("algorithm")) {
@ -428,7 +461,12 @@ void MatrixCore::sync() {
Room* room = createRoom(id, "Invited", false);
room->setGuestDenied(true);
for(auto event : document.object()["rooms"].toObject()["invite"].toObject()[id].toObject()["invite_state"].toObject()["events"].toArray()) {
for (auto event : document.object()["rooms"]
.toObject()["invite"]
.toObject()[id]
.toObject()["invite_state"]
.toObject()["events"]
.toArray()) {
const QString type = event.toObject()["type"].toString();
if (type == "m.room.member")
@ -436,8 +474,11 @@ void MatrixCore::sync() {
else if (type == "m.room.name") {
room->setName(event.toObject()["content"].toObject()["name"].toString());
} else if (type == "m.room.avatar") {
const QString imageId = event.toObject()["content"].toObject()["url"].toString().remove("mxc://");
room->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
const QString imageId =
event.toObject()["content"].toObject()["url"].toString().remove("mxc://");
room->setAvatar(
network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId +
"?width=64&height=64&method=scale");
}
roomListModel.updateRoom(room);
@ -482,7 +523,8 @@ void MatrixCore::sync() {
roomState->prevBatch = room.toObject()["timeline"].toObject()["prev_batch"].toString();
const int highlightCount = room.toObject()["unread_notifications"].toObject()["highlight_count"].toInt();
const int notificationCount = room.toObject()["unread_notifications"].toObject()["notification_count"].toInt();
const int notificationCount =
room.toObject()["unread_notifications"].toObject()["notification_count"].toInt();
if (highlightCount != roomState->getHighlightCount()) {
roomState->setNotificationCount(highlightCount);
@ -590,7 +632,8 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
char* formatted = nullptr;
if (markdownEnabled) {
formatted = cmark_markdown_to_html(message.toStdString().c_str(), message.length(), CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS);
formatted = cmark_markdown_to_html(
message.toStdString().c_str(), message.length(), CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS);
shouldSendAsMarkdown = strlen(formatted) > 8 + message.length();
}
@ -601,15 +644,11 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
{"msgtype", "m.text"},
{"formatted_body", formatted},
{"body", message},
{"format", "org.matrix.custom.html"}
};
{"format", "org.matrix.custom.html"}};
e->setMsg(formatted);
} else {
messageObject = QJsonObject {
{"msgtype", "m.text"},
{"body", message}
};
messageObject = QJsonObject{{"msgtype", "m.text"}, {"body", message}};
e->setMsg(message);
}
@ -645,19 +684,22 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
}}
};
std::string identityKey = document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("curve25519:") + device_id].toString().toStdString();
std::string identityKey =
document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("curve25519:")
+ device_id].toString().toStdString();
std::string edIdentityKey = document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("ed25519:") + device_id].toString().toStdString();
std::string edIdentityKey =
document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("ed25519:")
+ device_id].toString().toStdString();
sendKeyToDevice(room->getId(), identityKey.c_str(), edIdentityKey.c_str(), currentSessionId, currentSessionKey, user_id, device_id);
sendKeyToDevice(room->getId(), identityKey.c_str(), edIdentityKey.c_str(), currentSessionId,
currentSessionKey, user_id, device_id);
}
}
});*/
QJsonObject trueObject{
{"room_id", room->getId()},
{"type", "m.room.message"},
{"content", messageObject}
{"room_id", room->getId()}, {"type", "m.room.message"}, {"content", messageObject}
/*{"keys", QJsonObject {
{"ed25519", encryption->identityKey["ed25519"]}
}},
@ -668,26 +710,39 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
// construct the m.room.encrypted event
const QJsonObject roomEncryptedObject{
{"algorithm", "m.megolm.v1.aes-sha2"},
{"ciphertext", encryption->encryptGroup(currentSession, QString(QJsonDocument(trueObject).toJson(QJsonDocument::Compact)).toStdString()).c_str()},
{"ciphertext",
encryption
->encryptGroup(
currentSession, QString(QJsonDocument(trueObject).toJson(QJsonDocument::Compact)).toStdString())
.c_str()},
{"sender_key", encryption->identityKey["curve25519"]},
{"session_id", currentSessionId},
{"device_id", deviceId}
};
{"device_id", deviceId}};
network->putJSON("/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.encrypted/" + QRandomGenerator::global()->generate(), roomEncryptedObject, [](QNetworkReply* reply) {
network->putJSON(
"/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.encrypted/" +
QRandomGenerator::global()->generate(),
roomEncryptedObject,
[](QNetworkReply* reply) {
// qDebug() << "reply from room send: " << reply->readAll();
});
} else {
network->putJSON(QString("/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.message/") + QString::number(QRandomGenerator::global()->generate()), messageObject, onMessageFeedbackReceived);
network->putJSON(
QString("/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.message/") +
QString::number(QRandomGenerator::global()->generate()),
messageObject,
onMessageFeedbackReceived);
}
}
void MatrixCore::removeMessage(const QString& eventId) {
const QJsonObject reasonObject {
{"reason", ""}
};
const QJsonObject reasonObject{{"reason", ""}};
network->putJSON("/_matrix/client/r0/rooms/" + currentRoom->getId() + "/redact/" + eventId + "/" + QString::number(QRandomGenerator::global()->generate()), reasonObject, [this, eventId](QNetworkReply* reply) {
network->putJSON(
"/_matrix/client/r0/rooms/" + currentRoom->getId() + "/redact/" + eventId + "/" +
QString::number(QRandomGenerator::global()->generate()),
reasonObject,
[this, eventId](QNetworkReply* reply) {
auto& events = currentRoom->events;
for (int i = 0; i < events.size(); i++) {
if (events[i]->eventId == eventId) {
@ -730,7 +785,11 @@ void MatrixCore::uploadAttachment(Room* room, const QString& path) {
e->setMsg(fileName);
e->setMsgType(mimeType.name().contains("image") ? "image" : "file");
network->postBinary("/_matrix/media/r0/upload?filename=" + f.fileName(), f.readAll(), mimeType.name(), [this, mimeType, fileName, fileSize, e](QNetworkReply* reply) {
network->postBinary(
"/_matrix/media/r0/upload?filename=" + f.fileName(),
f.readAll(),
mimeType.name(),
[this, mimeType, fileName, fileSize, e](QNetworkReply* reply) {
if (!reply->error()) {
e->setSent(true);
@ -745,12 +804,15 @@ void MatrixCore::uploadAttachment(Room* room, const QString& path) {
{"msgtype", mimeType.name().contains("image") ? "m.image" : "m.file"},
{"body", fileName},
{"url", document.object()["content_uri"].toString()},
{"info", infoObject}
};
{"info", infoObject}};
network->putJSON("/_matrix/client/r0/rooms/" + currentRoom->getId() + "/send/m.room.message/" + QString::number(QRandomGenerator::global()->generate()), imageObject);
network->putJSON(
"/_matrix/client/r0/rooms/" + currentRoom->getId() + "/send/m.room.message/" +
QString::number(QRandomGenerator::global()->generate()),
imageObject);
}
}, [e](qint64 sent, qint64 total) {
},
[e](qint64 sent, qint64 total) {
e->setSentProgress((double)sent / (double)total);
});
}
@ -761,17 +823,13 @@ void MatrixCore::startDirectChat(const QString& id) {
{"creation_content", QJsonObject{{"m.federate", false}}},
{"preset", "private_chat"},
{"is_direct", true},
{"invite", QJsonArray{id}}
};
{"invite", QJsonArray{id}}};
network->postJSON("/_matrix/client/r0/createRoom", roomObject, [](QNetworkReply*) {});
}
void MatrixCore::setTyping(Room* room) {
const QJsonObject typingObject {
{"typing", true},
{"timeout", 15000}
};
const QJsonObject typingObject{{"typing", true}, {"timeout", 15000}};
network->putJSON("/_matrix/client/r0/rooms/" + room->getId() + "/typing/" + userId, typingObject);
}
@ -804,9 +862,7 @@ void MatrixCore::leaveRoom(const QString& id) {
}
void MatrixCore::inviteToRoom(Room* room, const QString& userId) {
const QJsonObject inviteObject {
{"user_id", userId}
};
const QJsonObject inviteObject{{"user_id", userId}};
network->postJSON("/_matrix/client/r0/rooms/" + room->getId() + "/invite", inviteObject, [](QNetworkReply*) {});
}
@ -843,8 +899,11 @@ void MatrixCore::updateMembers(Room* room) {
m->setDisplayName(memberJson["content"].toObject()["displayname"].toString());
if (!memberJson["content"].toObject()["avatar_url"].isNull()) {
const QString imageId = memberJson["content"].toObject()["avatar_url"].toString().remove("mxc://");
m->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
const QString imageId =
memberJson["content"].toObject()["avatar_url"].toString().remove("mxc://");
m->setAvatar(
network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId +
"?width=64&height=64&method=scale");
}
idToMember.insert(id, m);
@ -874,7 +933,9 @@ void MatrixCore::readMessageHistory(Room* room) {
qDebug() << "Reading message history...";
network->get("/_matrix/client/r0/rooms/" + room->getId() + "/messages?from=" + room->prevBatch + "&dir=b", [this, room](QNetworkReply* reply) {
network->get(
"/_matrix/client/r0/rooms/" + room->getId() + "/messages?from=" + room->prevBatch + "&dir=b",
[this, room](QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
room->prevBatch = document.object()["end"].toString();
@ -973,7 +1034,6 @@ Member* MatrixCore::resolveMemberId(const QString& id) const {
return idToMember.value(id);
}
Room* MatrixCore::resolveRoomId(const QString& id) const {
return idToRoom.value(id);
}
@ -1009,7 +1069,9 @@ void MatrixCore::loadDirectory(const QString& homeserver) {
if (!roomObject["avatar_url"].isNull()) {
const QString imageId = roomObject["avatar_url"].toString().remove("mxc://");
r->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
r->setAvatar(
network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId +
"?width=64&height=64&method=scale");
}
r->setTopic(roomObject["topic"].toString());
@ -1128,7 +1190,9 @@ void MatrixCore::consumeEvent(const QJsonObject& event, Room& room, const bool i
if (!event["content"].toObject()["avatar_url"].isNull()) {
const QString imageId = event["content"].toObject()["avatar_url"].toString().remove("mxc://");
room.setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
room.setAvatar(
network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId +
"?width=64&height=64&method=scale");
}
}
@ -1153,37 +1217,39 @@ void MatrixCore::consumeEvent(const QJsonObject& event, Room& room, const bool i
// construct m.room.key event
const QJsonObject roomKeyObject{
{"action", "request"},
{"body", QJsonObject {
{"body",
QJsonObject{
{"algorithm", event["content"].toObject()["algorithm"]},
{"room_id", room.getId()},
{"sender_key", event["content"].toObject()["sender_key"]},
{"session_id", event["content"].toObject()["session_id"]}
}},
{"session_id", event["content"].toObject()["session_id"]}}},
{"requesting_device_id", deviceId},
{"request_id", QString("lololol") + QString::number(QRandomGenerator::global()->generate())}
};
{"request_id", QString("lololol") + QString::number(QRandomGenerator::global()->generate())}};
const QJsonObject sendToDeviceObject{
{"messages", QJsonObject {
{ event["sender"].toString(), QJsonObject {
{ event["content"].toObject()["device_id"].toString(), roomKeyObject}
}}
}}
};
{"messages",
QJsonObject{
{event["sender"].toString(),
QJsonObject{{event["content"].toObject()["device_id"].toString(), roomKeyObject}}}}}};
// qDebug() << QJsonDocument(sendToDeviceObject).toJson(QJsonDocument::Compact);
network->putJSON(QString("/_matrix/client/r0/sendToDevice/m.room_key_request/") + QString::number(QRandomGenerator::global()->generate()), sendToDeviceObject, [](QNetworkReply* reply) {
network->putJSON(
QString("/_matrix/client/r0/sendToDevice/m.room_key_request/") +
QString::number(QRandomGenerator::global()->generate()),
sendToDeviceObject,
[](QNetworkReply* reply) {
// qDebug() << "REPLY FROM KEY REQUEST SEND: " << reply->readAll();
});
} else {
auto session = inboundSessions[event["content"].toObject()["session_id"].toString()];
auto msg = encryption->decrypt(session, event["content"].toObject()["ciphertext"].toString().toStdString());
auto msg =
encryption->decrypt(session, event["content"].toObject()["ciphertext"].toString().toStdString());
const QJsonDocument document = QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(msg.data()), msg.size()));
const QJsonDocument document =
QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(msg.data()), msg.size()));
populateEvent(document.object(), e);
}
} else {
e->setMsg("** ERR: messages sent from the same device are not supported yet.");
@ -1234,7 +1300,8 @@ void MatrixCore::populateEvent(const QJsonObject& event, Event* e) {
e->setAttachmentSize(event["content"].toObject()["info"].toObject()["size"].toInt());
if (event["content"].toObject()["info"].toObject().contains("thumbnail_url"))
e->setThumbnail(getMXCThumbnailURL(event["content"].toObject()["info"].toObject()["thumbnail_url"].toString()));
e->setThumbnail(
getMXCThumbnailURL(event["content"].toObject()["info"].toObject()["thumbnail_url"].toString()));
else
e->setThumbnail(getMXCMediaURL(event["content"].toObject()["url"].toString()));
@ -1277,22 +1344,26 @@ bool MatrixCore::getMarkdownEnabled() const {
return markdownEnabled;
}
void MatrixCore::sendKeyToDevice(QString roomId, QString senderCurveIdentity, QString senderEdIdentity, QString session_id, QString session_key, QString user_id, QString device_id)
{
void MatrixCore::sendKeyToDevice(
QString roomId,
QString senderCurveIdentity,
QString senderEdIdentity,
QString session_id,
QString session_key,
QString user_id,
QString device_id) {
// why we would we send ourselves a key?
if (device_id == deviceId)
return;
QJsonObject claimObject{
{"timeout", 10000},
{"one_time_keys", QJsonObject {
{user_id, QJsonObject {
{device_id, "signed_curve25519"}
}}
}}
};
{"timeout", 10000}, {"one_time_keys", QJsonObject{{user_id, QJsonObject{{device_id, "signed_curve25519"}}}}}};
network->postJSON("/_matrix/client/r0/keys/claim", claimObject, [this, device_id, user_id, senderCurveIdentity, senderEdIdentity, roomId, session_id, session_key](QNetworkReply* reply) {
network->postJSON(
"/_matrix/client/r0/keys/claim",
claimObject,
[this, device_id, user_id, senderCurveIdentity, senderEdIdentity, roomId, session_id, session_key](
QNetworkReply* reply) {
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
std::string identityKey = senderCurveIdentity.toStdString();
@ -1301,50 +1372,60 @@ void MatrixCore::sendKeyToDevice(QString roomId, QString senderCurveIdentity, QS
if (document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject().keys().empty())
return;
std::string oneTimeKey = document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject()[document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject().keys()[0]].toObject()["key"].toString().toStdString();
std::string oneTimeKey = document.object()["one_time_keys"]
.toObject()[user_id]
.toObject()[device_id]
.toObject()[document.object()["one_time_keys"]
.toObject()[user_id]
.toObject()[device_id]
.toObject()
.keys()[0]]
.toObject()["key"]
.toString()
.toStdString();
auto session = encryption->beginOutboundOlmSession(identityKey, oneTimeKey);
// construct m.room.key event
const QJsonObject roomKeyObject{
{"content", QJsonObject {
{"content",
QJsonObject{
{"algorithm", "m.megolm.v1.aes-sha2"},
{"room_id", roomId},
{"session_id", session_id},
{"session_key", session_key}
}},
{"session_key", session_key}}},
{"type", "m.room_key"},
{"keys", QJsonObject {
{"ed25519", encryption->identityKey["ed25519"]}
}},
{"keys", QJsonObject{{"ed25519", encryption->identityKey["ed25519"]}}},
{"sender", userId},
{"sender_device", deviceId},
{"recipient", user_id},
{"recipient_keys", QJsonObject {
{"ed25519", senderEdIdentity}
}}
};
{"recipient_keys", QJsonObject{{"ed25519", senderEdIdentity}}}};
// construct the m.room.encrypted event
const QJsonObject roomEncryptedObject{
{"algorithm", "m.olm.v1.curve25519-aes-sha2"},
{"ciphertext", QJsonObject {
{identityKey.c_str(), QJsonObject {
{"body", encryption->encrypt(session, QString(QJsonDocument(roomKeyObject).toJson(QJsonDocument::Compact)).toStdString()).c_str()},
{"type", (int)olm_encrypt_message_type(session)}
}}}},
{"ciphertext",
QJsonObject{
{identityKey.c_str(),
QJsonObject{
{"body",
encryption
->encrypt(
session,
QString(QJsonDocument(roomKeyObject).toJson(QJsonDocument::Compact)).toStdString())
.c_str()},
{"type", (int)olm_encrypt_message_type(session)}}}}},
{"sender_key", encryption->identityKey["curve25519"]},
};
const QJsonObject sendToDeviceObject{
{"messages", QJsonObject {
{ user_id, QJsonObject {
{ device_id, roomEncryptedObject}
}}
}}
};
{"messages", QJsonObject{{user_id, QJsonObject{{device_id, roomEncryptedObject}}}}}};
network->putJSON(QString("/_matrix/client/r0/sendToDevice/m.room.encrypted/") + QString::number(QRandomGenerator::global()->generate()), sendToDeviceObject, [](QNetworkReply* reply) {
network->putJSON(
QString("/_matrix/client/r0/sendToDevice/m.room.encrypted/") +
QString::number(QRandomGenerator::global()->generate()),
sendToDeviceObject,
[](QNetworkReply* reply) {
// qDebug() << "REPLY FROM KEY SEND: " << reply->readAll();
});
});

View file

@ -1,8 +1,8 @@
#include "roomlistsortmodel.h"
#include "membermodel.h"
#include "room.h"
#include "roomlistmodel.h"
#include "membermodel.h"
bool RoomListSortModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
const QString sectionLeft = sourceModel()->data(left, RoomListModel::SectionRole).toString();
@ -29,7 +29,8 @@ bool MemberListSortModel::lessThan(const QModelIndex& left, const QModelIndex& r
return true;
if (sectionLeft == sectionRight)
return sourceModel()->data(left, MemberModel::DisplayNameRole).toString() < sourceModel()->data(right, MemberModel::DisplayNameRole).toString();
return sourceModel()->data(left, MemberModel::DisplayNameRole).toString() <
sourceModel()->data(right, MemberModel::DisplayNameRole).toString();
return false;
}