Reformat code
This commit is contained in:
parent
6df6ea1523
commit
d83471009f
26 changed files with 810 additions and 698 deletions
33
.clang-format
Normal file
33
.clang-format
Normal 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
8
.editorconfig
Normal file
|
@ -0,0 +1,8 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
max_line_length = 120
|
30
README.md
30
README.md
|
@ -1,6 +1,8 @@
|
|||
# Trinity
|
||||
A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Discord-like interface.
|
||||
|
||||

|
||||
|
||||
## 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
|
||||

|
||||
## 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.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <vector>
|
||||
#include <QQmlContext>
|
||||
#include <vector>
|
||||
|
||||
class MatrixCore;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef DIRECTORYMODEL_H
|
||||
#define DIRECTORYMODEL_H
|
||||
|
||||
|
||||
class DirectoryModel
|
||||
{
|
||||
class DirectoryModel {
|
||||
public:
|
||||
DirectoryModel();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
#include <olm/olm.h>
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ class MatrixCore;
|
|||
struct Room;
|
||||
class Event;
|
||||
|
||||
class EventModel : public QAbstractListModel
|
||||
{
|
||||
class EventModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum EventRoles {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
class Room;
|
||||
|
||||
class MemberModel : public QAbstractListModel
|
||||
{
|
||||
class MemberModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum EventRoles {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
class Room;
|
||||
|
||||
class RoomListModel : public QAbstractListModel
|
||||
{
|
||||
class RoomListModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum EventRoles {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include "directorymodel.h"
|
||||
|
||||
DirectoryModel::DirectoryModel()
|
||||
{
|
||||
|
||||
}
|
||||
DirectoryModel::DirectoryModel() {}
|
||||
|
|
|
@ -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 {};
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
#include "room.h"
|
||||
#include "matrixcore.h"
|
||||
#include "room.h"
|
||||
|
||||
EventModel::EventModel(MatrixCore& matrix) : matrix(matrix) {}
|
||||
|
||||
|
|
30
src/main.cpp
30
src/main.cpp
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Reference in a new issue