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
|
# Trinity
|
||||||
A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Discord-like interface.
|
A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Discord-like interface.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Basic messaging capabilities
|
* Basic messaging capabilities
|
||||||
* Sending and recieving markdown messages, formatting can be disabled
|
* 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
|
* Start direct chats with other members
|
||||||
* Custom emote support
|
* 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
|
* Qt5
|
||||||
* WebEngine is also required
|
* WebEngine is also required
|
||||||
* CMark
|
* CMark
|
||||||
* libolm
|
* 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
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <vector>
|
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class MatrixCore;
|
class MatrixCore;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QSystemTrayIcon>
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
class Desktop : public QObject
|
class Desktop : public QObject {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE void showTrayIcon(const bool shouldHide) {
|
Q_INVOKABLE void showTrayIcon(const bool shouldHide) {
|
||||||
|
@ -21,7 +20,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE bool isTrayIconEnabled() {
|
Q_INVOKABLE bool isTrayIconEnabled() {
|
||||||
return icon->isVisible();;
|
return icon->isVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSystemTrayIcon* icon;
|
QSystemTrayIcon* icon;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef DIRECTORYMODEL_H
|
#ifndef DIRECTORYMODEL_H
|
||||||
#define DIRECTORYMODEL_H
|
#define DIRECTORYMODEL_H
|
||||||
|
|
||||||
|
class DirectoryModel {
|
||||||
class DirectoryModel
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
DirectoryModel();
|
DirectoryModel();
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
|
|
||||||
#include "emote.h"
|
#include "emote.h"
|
||||||
|
|
||||||
class EmoteListModel : public QAbstractListModel
|
class EmoteListModel : public QAbstractListModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
int rowCount(const QModelIndex& parent) const override;
|
int rowCount(const QModelIndex& parent) const override;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include <olm/olm.h>
|
#include <olm/olm.h>
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ class MatrixCore;
|
||||||
struct Room;
|
struct Room;
|
||||||
class Event;
|
class Event;
|
||||||
|
|
||||||
class EventModel : public QAbstractListModel
|
class EventModel : public QAbstractListModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum EventRoles {
|
enum EventRoles {
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QJsonObject>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMap>
|
#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 "emote.h"
|
||||||
#include "emotelistmodel.h"
|
#include "emotelistmodel.h"
|
||||||
#include "encryption.h"
|
#include "encryption.h"
|
||||||
|
#include "eventmodel.h"
|
||||||
|
#include "membermodel.h"
|
||||||
|
#include "room.h"
|
||||||
|
#include "roomlistmodel.h"
|
||||||
|
#include "roomlistsortmodel.h"
|
||||||
|
|
||||||
class Network;
|
class Network;
|
||||||
|
|
||||||
class MatrixCore : public QObject
|
class MatrixCore : public QObject {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString profileName MEMBER profileName CONSTANT)
|
Q_PROPERTY(QString profileName MEMBER profileName CONSTANT)
|
||||||
Q_PROPERTY(bool initialSyncComplete READ isInitialSyncComplete NOTIFY initialSyncFinished)
|
Q_PROPERTY(bool initialSyncComplete READ isInitialSyncComplete NOTIFY initialSyncFinished)
|
||||||
|
@ -39,7 +38,11 @@ public:
|
||||||
Encryption* encryption = nullptr;
|
Encryption* encryption = nullptr;
|
||||||
|
|
||||||
// account
|
// 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 login(const QString& username, const QString& password);
|
||||||
Q_INVOKABLE void logout();
|
Q_INVOKABLE void logout();
|
||||||
|
@ -94,7 +97,14 @@ public:
|
||||||
|
|
||||||
void setMarkdownEnabled(const bool enabled);
|
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;
|
OlmOutboundGroupSession* currentSession = nullptr;
|
||||||
QString currentSessionId, currentSessionKey;
|
QString currentSessionId, currentSessionKey;
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
class Room;
|
class Room;
|
||||||
|
|
||||||
class MemberModel : public QAbstractListModel
|
class MemberModel : public QAbstractListModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum EventRoles {
|
enum EventRoles {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "requestsender.h"
|
#include "requestsender.h"
|
||||||
|
@ -17,8 +17,7 @@ public:
|
||||||
QNetworkAccessManager* manager;
|
QNetworkAccessManager* manager;
|
||||||
QString homeserverURL, accessToken;
|
QString homeserverURL, accessToken;
|
||||||
|
|
||||||
template<typename Fn>
|
template<typename Fn> inline void postJSON(const QString& path, const QJsonObject object, Fn&& fn) {
|
||||||
inline void postJSON(const QString& path, const QJsonObject object, Fn&& fn) {
|
|
||||||
QNetworkRequest request(homeserverURL + path);
|
QNetworkRequest request(homeserverURL + path);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
||||||
|
@ -38,7 +37,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Fn, typename ProgressFn>
|
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);
|
QNetworkRequest request(homeserverURL + path);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
|
request.setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
|
||||||
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
||||||
|
@ -56,8 +56,7 @@ public:
|
||||||
QObject::connect(reply, &QNetworkReply::uploadProgress, progressFn);
|
QObject::connect(reply, &QNetworkReply::uploadProgress, progressFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Fn>
|
template<typename Fn> inline void post(const QString& path, Fn&& fn) {
|
||||||
inline void post(const QString& path, Fn&& fn) {
|
|
||||||
QNetworkRequest request(homeserverURL + path);
|
QNetworkRequest request(homeserverURL + path);
|
||||||
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
||||||
|
|
||||||
|
@ -90,8 +89,7 @@ public:
|
||||||
manager->put(request, jsonPost);
|
manager->put(request, jsonPost);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Fn>
|
template<typename Fn> inline void putJSON(const QString& path, const QJsonObject object, Fn&& fn) {
|
||||||
inline void putJSON(const QString& path, const QJsonObject object, Fn&& fn) {
|
|
||||||
QNetworkRequest request(homeserverURL + path);
|
QNetworkRequest request(homeserverURL + path);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
request.setRawHeader("Authorization", accessToken.toLocal8Bit());
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
#include <QObject>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class RequestSender : public QObject
|
class RequestSender : public QObject {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
RequestSender(QObject* parent = nullptr) : QObject(parent) {}
|
RequestSender(QObject* parent = nullptr) : QObject(parent) {}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QObject>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
class EncryptionInformation : public QObject {
|
class EncryptionInformation : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -12,8 +12,7 @@ public:
|
||||||
QString sessionId;
|
QString sessionId;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Event : public QObject
|
class Event : public QObject {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString sender READ getSender NOTIFY senderChanged)
|
Q_PROPERTY(QString sender READ getSender NOTIFY senderChanged)
|
||||||
Q_PROPERTY(QString msg READ getMsg NOTIFY msgChanged)
|
Q_PROPERTY(QString msg READ getMsg NOTIFY msgChanged)
|
||||||
|
@ -175,8 +174,7 @@ private:
|
||||||
QString id, displayName, avatarURL;
|
QString id, displayName, avatarURL;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Room : public QObject
|
class Room : public QObject {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString id MEMBER id NOTIFY idChanged)
|
Q_PROPERTY(QString id MEMBER id NOTIFY idChanged)
|
||||||
Q_PROPERTY(QString topic MEMBER topic NOTIFY topicChanged)
|
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 highlightCount READ getHighlightCount NOTIFY highlightCountChanged)
|
||||||
Q_PROPERTY(QString notificationCount READ getNotificationCount NOTIFY notificationCountChanged)
|
Q_PROPERTY(QString notificationCount READ getNotificationCount NOTIFY notificationCountChanged)
|
||||||
Q_PROPERTY(bool direct READ getDirect NOTIFY directChanged)
|
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)
|
Q_PROPERTY(bool encrypted READ getEncrypted NOTIFY encryptionChanged)
|
||||||
public:
|
public:
|
||||||
Room(QObject* parent = nullptr) : QObject(parent) {}
|
Room(QObject* parent = nullptr) : QObject(parent) {}
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
class Room;
|
class Room;
|
||||||
|
|
||||||
class RoomListModel : public QAbstractListModel
|
class RoomListModel : public QAbstractListModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum EventRoles {
|
enum EventRoles {
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
class RoomListSortModel : public QSortFilterProxyModel
|
class RoomListSortModel : public QSortFilterProxyModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
|
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
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
|
bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
|
||||||
|
@ -35,4 +33,3 @@ public:
|
||||||
return sourceIndex.row();
|
return sourceIndex.row();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
#include "directorymodel.h"
|
#include "directorymodel.h"
|
||||||
|
|
||||||
DirectoryModel::DirectoryModel()
|
DirectoryModel::DirectoryModel() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "encryption.h"
|
#include "encryption.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
void Encryption::createNewDeviceKeys() {
|
void Encryption::createNewDeviceKeys() {
|
||||||
initAccount();
|
initAccount();
|
||||||
|
@ -35,7 +35,6 @@ void Encryption::createNewDeviceKeys() {
|
||||||
|
|
||||||
qDebug() << "identity keys: " << (char*)identity_memory;
|
qDebug() << "identity keys: " << (char*)identity_memory;
|
||||||
qDebug() << "identity keys (parsed): " << identityKey;
|
qDebug() << "identity keys (parsed): " << identityKey;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Encryption::saveDeviceKeys() {
|
QString Encryption::saveDeviceKeys() {
|
||||||
|
@ -108,11 +107,7 @@ QString Encryption::signMessage(QString message) {
|
||||||
|
|
||||||
void* memory = malloc(length);
|
void* memory = malloc(length);
|
||||||
|
|
||||||
olm_account_sign(
|
olm_account_sign(account, message.data(), message.length(), memory, length);
|
||||||
account,
|
|
||||||
message.data(), message.length(),
|
|
||||||
memory, length
|
|
||||||
);
|
|
||||||
|
|
||||||
qDebug() << "Signed: " << (char*)memory;
|
qDebug() << "Signed: " << (char*)memory;
|
||||||
|
|
||||||
|
@ -169,7 +164,15 @@ OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::st
|
||||||
int fd = open("/dev/random", O_RDONLY);
|
int fd = open("/dev/random", O_RDONLY);
|
||||||
read(fd, memory, length);
|
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);
|
// qDebug() << "ERR: " << olm_session_last_error(outboundSession);
|
||||||
|
|
||||||
return 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 const * their_one_time_key, size_t their_one_time_key_length,
|
||||||
void * random, size_t random_length
|
void * random, size_t random_length
|
||||||
);*/
|
);*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Encryption::getSessionId(OlmSession* session) {
|
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
|
/** 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()
|
* conversation. If the id buffer is too small then olm_session_last_error()
|
||||||
* will be "OUTPUT_BUFFER_TOO_SMALL". */
|
* will be "OUTPUT_BUFFER_TOO_SMALL". */
|
||||||
olm_session_id(
|
olm_session_id(session, memory, length);
|
||||||
session,
|
|
||||||
memory, length
|
|
||||||
);
|
|
||||||
|
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +228,8 @@ OlmSession* Encryption::createInboundSession(std::string senderKey, std::string
|
||||||
void* inboundMemory = malloc(olm_session_size());
|
void* inboundMemory = malloc(olm_session_size());
|
||||||
auto inboundSession = olm_session(inboundMemory);
|
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;
|
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::vector<std::uint8_t> Encryption::decrypt(OlmSession* session, int msgType, std::string cipherText) {
|
||||||
/*std::string maxPlaintextLengthBuffer = cipherText;
|
/*std::string maxPlaintextLengthBuffer = cipherText;
|
||||||
|
|
||||||
size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType, (void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());;
|
size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType,
|
||||||
qDebug() << "THE ERROR YOU ARE LOOKING FOR " << olm_session_last_error(session);
|
(void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());; qDebug() << "THE ERROR YOU ARE LOOKING
|
||||||
if(maxPlaintextLength == olm_error())
|
FOR " << olm_session_last_error(session); if(maxPlaintextLength == olm_error()) return "";
|
||||||
return "";
|
|
||||||
|
|
||||||
char* plaintext = new char[maxPlaintextLength];
|
char* plaintext = new char[maxPlaintextLength];
|
||||||
//plaintext[maxPlaintextLength] = '\0';
|
//plaintext[maxPlaintextLength] = '\0';
|
||||||
memset(plaintext, '\0', maxPlaintextLength);
|
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] = '\0';
|
||||||
|
|
||||||
plaintext[size + 1] = '\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());
|
std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin());
|
||||||
|
|
||||||
// create the result buffer
|
// 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())
|
if (length == olm_error())
|
||||||
return {};
|
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());
|
auto tmp_buffer = std::vector<std::uint8_t>(cipherText.size());
|
||||||
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
|
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())
|
if (size == olm_error())
|
||||||
return {};
|
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());
|
std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin());
|
||||||
|
|
||||||
// create the result buffer
|
// 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())
|
if (length == olm_error())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -326,7 +329,8 @@ std::vector<std::uint8_t> Encryption::decrypt(OlmInboundGroupSession* session, s
|
||||||
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
|
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
|
||||||
|
|
||||||
uint32_t msgIndex;
|
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())
|
if (size == olm_error())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "room.h"
|
|
||||||
#include "matrixcore.h"
|
#include "matrixcore.h"
|
||||||
|
#include "room.h"
|
||||||
|
|
||||||
EventModel::EventModel(MatrixCore& matrix) : matrix(matrix) {}
|
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 <QAction>
|
||||||
#include <QMenu>
|
|
||||||
#include <QSystemTrayIcon>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QQmlComponent>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
#include <QtWebEngine/QtWebEngine>
|
#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 "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) {
|
void AppCore::addAccount(QString profileName) {
|
||||||
accounts.push_back(new MatrixCore(profileName));
|
accounts.push_back(new MatrixCore(profileName));
|
||||||
|
|
|
@ -2,19 +2,21 @@
|
||||||
|
|
||||||
#include <cmark.h>
|
#include <cmark.h>
|
||||||
|
|
||||||
|
#include "network.h"
|
||||||
|
#include <QDir>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <QMimeDatabase>
|
||||||
|
#include <QPixmap>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QPixmap>
|
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QDir>
|
|
||||||
#include <QMimeDatabase>
|
|
||||||
#include <QMimeData>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iterator>
|
#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();
|
network = new Network();
|
||||||
encryption = new Encryption();
|
encryption = new Encryption();
|
||||||
|
|
||||||
|
@ -80,39 +82,41 @@ MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent),
|
||||||
localEmoteModel.setList(&emotes);
|
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;
|
QJsonObject authObject;
|
||||||
if (!session.isEmpty()) {
|
if (!session.isEmpty()) {
|
||||||
authObject["type"] = type;
|
authObject["type"] = type;
|
||||||
authObject["session"] = session;
|
authObject["session"] = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QJsonObject registerObject {
|
const QJsonObject registerObject{{"auth", authObject}, {"username", username}, {"password", password}};
|
||||||
{"auth", authObject},
|
|
||||||
{"username", username},
|
|
||||||
{"password", password}
|
|
||||||
};
|
|
||||||
|
|
||||||
network->postJSON("/_matrix/client/r0/register?kind=user", registerObject, [this](QNetworkReply* reply) {
|
network->postJSON("/_matrix/client/r0/register?kind=user", registerObject, [this](QNetworkReply* reply) {
|
||||||
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
if (reply->error()) {
|
if (reply->error()) {
|
||||||
if (document.object().contains("flows")) {
|
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") {
|
if (stage == "m.login.recaptcha") {
|
||||||
const QJsonObject data{
|
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()},
|
{"session", document.object()["session"].toString()},
|
||||||
{"type", "m.login.recaptcha"}
|
{"type", "m.login.recaptcha"}};
|
||||||
};
|
|
||||||
|
|
||||||
emit registerFlow(data);
|
emit registerFlow(data);
|
||||||
} else if (stage == "m.login.dummy") {
|
} else if (stage == "m.login.dummy") {
|
||||||
const QJsonObject data{
|
const QJsonObject data{
|
||||||
{"session", document.object()["session"].toString()},
|
{"session", document.object()["session"].toString()}, {"type", "m.login.dummy"}};
|
||||||
{"type", "m.login.dummy"}
|
|
||||||
};
|
|
||||||
|
|
||||||
emit registerFlow(data);
|
emit registerFlow(data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -141,8 +145,7 @@ void MatrixCore::login(const QString& username, const QString& password) {
|
||||||
{"type", "m.login.password"},
|
{"type", "m.login.password"},
|
||||||
{"user", username},
|
{"user", username},
|
||||||
{"password", password},
|
{"password", password},
|
||||||
{"initial_device_display_name", "Trinity"}
|
{"initial_device_display_name", "Trinity"}};
|
||||||
};
|
|
||||||
|
|
||||||
network->postJSON("/_matrix/client/r0/login", loginObject, [this](QNetworkReply* reply) {
|
network->postJSON("/_matrix/client/r0/login", loginObject, [this](QNetworkReply* reply) {
|
||||||
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
@ -163,44 +166,37 @@ void MatrixCore::login(const QString& username, const QString& password) {
|
||||||
|
|
||||||
QJsonObject keysObject{
|
QJsonObject keysObject{
|
||||||
{"curve25519:" + document.object()["device_id"].toString(), encryption->identityKey["curve25519"]},
|
{"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{
|
QJsonObject deviceKeysObject{
|
||||||
{"user_id", document.object()["user_id"].toString()},
|
{"user_id", document.object()["user_id"].toString()},
|
||||||
{"device_id", document.object()["device_id"].toString()},
|
{"device_id", document.object()["device_id"].toString()},
|
||||||
{"algorithms", QJsonArray({"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"})},
|
{"algorithms", QJsonArray({"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"})},
|
||||||
{"keys", keysObject}
|
{"keys", keysObject}};
|
||||||
};
|
|
||||||
|
|
||||||
QJsonObject signature{
|
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 {
|
deviceKeysObject["signatures"] = QJsonObject{{document.object()["user_id"].toString(), signature}};
|
||||||
{document.object()["user_id"].toString(), signature}};
|
|
||||||
|
|
||||||
QJsonObject oneTimeKeyObject;
|
QJsonObject oneTimeKeyObject;
|
||||||
|
|
||||||
auto one_time_keys = encryption->generateOneTimeKeys(encryption->getRecommendedNumberOfOneTimeKeys());
|
auto one_time_keys = encryption->generateOneTimeKeys(encryption->getRecommendedNumberOfOneTimeKeys());
|
||||||
|
|
||||||
for (auto key : one_time_keys["curve25519"].toObject().keys()) {
|
for (auto key : one_time_keys["curve25519"].toObject().keys()) {
|
||||||
QJsonObject keyObject {
|
QJsonObject keyObject{{"key", one_time_keys["curve25519"].toObject()[key]}};
|
||||||
{"key", one_time_keys["curve25519"].toObject()[key]}
|
|
||||||
};
|
|
||||||
|
|
||||||
QJsonObject signature{
|
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 {
|
keyObject["signatures"] = QJsonObject{{document.object()["user_id"].toString(), signature}};
|
||||||
{document.object()["user_id"].toString(), signature}};
|
|
||||||
|
|
||||||
oneTimeKeyObject["signed_curve25519:" + key] = keyObject;
|
oneTimeKeyObject["signed_curve25519:" + key] = keyObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject masterKeysObject {
|
QJsonObject masterKeysObject{{"device_keys", deviceKeysObject}, {"one_time_keys", oneTimeKeyObject}};
|
||||||
{"device_keys", deviceKeysObject},
|
|
||||||
{"one_time_keys", oneTimeKeyObject}
|
|
||||||
};
|
|
||||||
|
|
||||||
// qDebug() << masterKeysObject;
|
// qDebug() << masterKeysObject;
|
||||||
|
|
||||||
|
@ -241,11 +237,10 @@ void MatrixCore::updateAccountInformation() {
|
||||||
void MatrixCore::setDisplayName(const QString& name) {
|
void MatrixCore::setDisplayName(const QString& name) {
|
||||||
displayName = name;
|
displayName = name;
|
||||||
|
|
||||||
const QJsonObject displayNameObject {
|
const QJsonObject displayNameObject{{"displayname", name}};
|
||||||
{"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();
|
emit displayNameChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -268,30 +263,49 @@ void MatrixCore::sync() {
|
||||||
// qDebug() << document.object()["device_one_time_keys_count"];
|
// qDebug() << document.object()["device_one_time_keys_count"];
|
||||||
|
|
||||||
for (auto event : document.object()["to_device"].toObject()["events"].toArray()) {
|
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 sender = event.toObject()["sender"].toString();
|
||||||
auto device_id = event.toObject()["content"].toObject()["requesting_device_id"].toString();
|
auto device_id = event.toObject()["content"].toObject()["requesting_device_id"].toString();
|
||||||
auto room_id = event.toObject()["content"].toObject()["body"].toObject()["room_id"].toString();
|
auto room_id = event.toObject()["content"].toObject()["body"].toObject()["room_id"].toString();
|
||||||
|
|
||||||
QJsonObject queryObject{
|
QJsonObject queryObject{
|
||||||
{"timeout", 10000},
|
{"timeout", 10000},
|
||||||
{"device_keys", QJsonObject{
|
{"device_keys", QJsonObject{{sender, QJsonArray({device_id})}}},
|
||||||
{sender, QJsonArray({device_id})}
|
|
||||||
}},
|
|
||||||
{"token", "string"},
|
{"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());
|
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 senderCurveKey = document.object()["device_keys"]
|
||||||
auto senderEdKey = document.object()["device_keys"].toObject()[sender].toObject()[device_id].toObject()["keys"].toObject()["ed25519:" + device_id].toString();
|
.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;
|
qDebug() << "sending keys to " << device_id;
|
||||||
|
|
||||||
createOrLoadSession();
|
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") {
|
} else if (event.toObject()["type"] == "m.room_key") {
|
||||||
qDebug() << "we recieved a new key from a user in the room :-)";
|
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") {
|
} else if (event.toObject()["type"] == "m.room.encrypted") {
|
||||||
auto curveKey = event.toObject()["content"].toObject()["ciphertext"].toObject().keys()[0];
|
auto curveKey = event.toObject()["content"].toObject()["ciphertext"].toObject().keys()[0];
|
||||||
auto senderKey = event.toObject()["content"].toObject()["sender_key"].toString();
|
auto senderKey = event.toObject()["content"].toObject()["sender_key"].toString();
|
||||||
int type = event.toObject()["content"].toObject()["ciphertext"].toObject()[curveKey].toObject()["type"].toInt();
|
int type = event.toObject()["content"]
|
||||||
auto body = event.toObject()["content"].toObject()["ciphertext"].toObject()[curveKey].toObject()["body"].toString();
|
.toObject()["ciphertext"]
|
||||||
|
.toObject()[curveKey]
|
||||||
|
.toObject()["type"]
|
||||||
|
.toInt();
|
||||||
|
auto body = event.toObject()["content"]
|
||||||
|
.toObject()["ciphertext"]
|
||||||
|
.toObject()[curveKey]
|
||||||
|
.toObject()["body"]
|
||||||
|
.toString();
|
||||||
|
|
||||||
// create a new inbound session
|
// create a new inbound session
|
||||||
auto session = encryption->createInboundSession(senderKey.toStdString(), body.toStdString());
|
auto session = encryption->createInboundSession(senderKey.toStdString(), body.toStdString());
|
||||||
|
|
||||||
auto decryptedMsg = encryption->decrypt(session, type, 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();
|
auto id = document.object()["content"].toObject()["session_id"].toString();
|
||||||
|
|
||||||
qDebug() << "NEW KEY " << id << " = " << document;
|
qDebug() << "NEW KEY " << id << " = " << document;
|
||||||
|
|
||||||
// create new inbound session, append to list
|
// 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;
|
inboundSessions[id] = sess;
|
||||||
|
|
||||||
// if we recieved a new key, let's see if we can decrypt some old messages!
|
// 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) {
|
if (event->encryptionInfo != nullptr && event->encryptionInfo->sessionId == id) {
|
||||||
auto msg = encryption->decrypt(sess, event->encryptionInfo->cipherText.toStdString());
|
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);
|
populateEvent(document.object(), event);
|
||||||
|
|
||||||
|
@ -352,7 +377,8 @@ void MatrixCore::sync() {
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
if (autofill_data) {
|
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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
|
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
|
||||||
room->setGuestDenied(true);
|
room->setGuestDenied(true);
|
||||||
|
@ -365,7 +391,8 @@ void MatrixCore::sync() {
|
||||||
roomListModel.updateRoom(room);
|
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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
|
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
|
||||||
room->setGuestDenied(true);
|
room->setGuestDenied(true);
|
||||||
|
@ -377,7 +404,8 @@ void MatrixCore::sync() {
|
||||||
roomListModel.updateRoom(room);
|
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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
|
if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") {
|
||||||
room->setGuestDenied(true);
|
room->setGuestDenied(true);
|
||||||
|
@ -386,13 +414,17 @@ void MatrixCore::sync() {
|
||||||
|
|
||||||
if (document.object().contains("url")) {
|
if (document.object().contains("url")) {
|
||||||
const QString imageId = document.object()["url"].toString().remove("mxc://");
|
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);
|
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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
for (auto user : document.object()["users"].toObject().keys()) {
|
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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
if (document.object().contains("algorithm")) {
|
if (document.object().contains("algorithm")) {
|
||||||
|
@ -428,7 +461,12 @@ void MatrixCore::sync() {
|
||||||
Room* room = createRoom(id, "Invited", false);
|
Room* room = createRoom(id, "Invited", false);
|
||||||
room->setGuestDenied(true);
|
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();
|
const QString type = event.toObject()["type"].toString();
|
||||||
|
|
||||||
if (type == "m.room.member")
|
if (type == "m.room.member")
|
||||||
|
@ -436,8 +474,11 @@ void MatrixCore::sync() {
|
||||||
else if (type == "m.room.name") {
|
else if (type == "m.room.name") {
|
||||||
room->setName(event.toObject()["content"].toObject()["name"].toString());
|
room->setName(event.toObject()["content"].toObject()["name"].toString());
|
||||||
} else if (type == "m.room.avatar") {
|
} else if (type == "m.room.avatar") {
|
||||||
const QString imageId = event.toObject()["content"].toObject()["url"].toString().remove("mxc://");
|
const QString imageId =
|
||||||
room->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
|
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);
|
roomListModel.updateRoom(room);
|
||||||
|
@ -482,7 +523,8 @@ void MatrixCore::sync() {
|
||||||
roomState->prevBatch = room.toObject()["timeline"].toObject()["prev_batch"].toString();
|
roomState->prevBatch = room.toObject()["timeline"].toObject()["prev_batch"].toString();
|
||||||
|
|
||||||
const int highlightCount = room.toObject()["unread_notifications"].toObject()["highlight_count"].toInt();
|
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()) {
|
if (highlightCount != roomState->getHighlightCount()) {
|
||||||
roomState->setNotificationCount(highlightCount);
|
roomState->setNotificationCount(highlightCount);
|
||||||
|
@ -590,7 +632,8 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
|
||||||
char* formatted = nullptr;
|
char* formatted = nullptr;
|
||||||
|
|
||||||
if (markdownEnabled) {
|
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();
|
shouldSendAsMarkdown = strlen(formatted) > 8 + message.length();
|
||||||
}
|
}
|
||||||
|
@ -601,15 +644,11 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
|
||||||
{"msgtype", "m.text"},
|
{"msgtype", "m.text"},
|
||||||
{"formatted_body", formatted},
|
{"formatted_body", formatted},
|
||||||
{"body", message},
|
{"body", message},
|
||||||
{"format", "org.matrix.custom.html"}
|
{"format", "org.matrix.custom.html"}};
|
||||||
};
|
|
||||||
|
|
||||||
e->setMsg(formatted);
|
e->setMsg(formatted);
|
||||||
} else {
|
} else {
|
||||||
messageObject = QJsonObject {
|
messageObject = QJsonObject{{"msgtype", "m.text"}, {"body", message}};
|
||||||
{"msgtype", "m.text"},
|
|
||||||
{"body", message}
|
|
||||||
};
|
|
||||||
|
|
||||||
e->setMsg(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{
|
QJsonObject trueObject{
|
||||||
{"room_id", room->getId()},
|
{"room_id", room->getId()}, {"type", "m.room.message"}, {"content", messageObject}
|
||||||
{"type", "m.room.message"},
|
|
||||||
{"content", messageObject}
|
|
||||||
/*{"keys", QJsonObject {
|
/*{"keys", QJsonObject {
|
||||||
{"ed25519", encryption->identityKey["ed25519"]}
|
{"ed25519", encryption->identityKey["ed25519"]}
|
||||||
}},
|
}},
|
||||||
|
@ -668,26 +710,39 @@ void MatrixCore::sendMessage(Room* room, const QString& message) {
|
||||||
// construct the m.room.encrypted event
|
// construct the m.room.encrypted event
|
||||||
const QJsonObject roomEncryptedObject{
|
const QJsonObject roomEncryptedObject{
|
||||||
{"algorithm", "m.megolm.v1.aes-sha2"},
|
{"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"]},
|
{"sender_key", encryption->identityKey["curve25519"]},
|
||||||
{"session_id", currentSessionId},
|
{"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();
|
// qDebug() << "reply from room send: " << reply->readAll();
|
||||||
});
|
});
|
||||||
} else {
|
} 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) {
|
void MatrixCore::removeMessage(const QString& eventId) {
|
||||||
const QJsonObject reasonObject {
|
const QJsonObject reasonObject{{"reason", ""}};
|
||||||
{"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;
|
auto& events = currentRoom->events;
|
||||||
for (int i = 0; i < events.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
if (events[i]->eventId == eventId) {
|
if (events[i]->eventId == eventId) {
|
||||||
|
@ -730,7 +785,11 @@ void MatrixCore::uploadAttachment(Room* room, const QString& path) {
|
||||||
e->setMsg(fileName);
|
e->setMsg(fileName);
|
||||||
e->setMsgType(mimeType.name().contains("image") ? "image" : "file");
|
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()) {
|
if (!reply->error()) {
|
||||||
e->setSent(true);
|
e->setSent(true);
|
||||||
|
|
||||||
|
@ -745,12 +804,15 @@ void MatrixCore::uploadAttachment(Room* room, const QString& path) {
|
||||||
{"msgtype", mimeType.name().contains("image") ? "m.image" : "m.file"},
|
{"msgtype", mimeType.name().contains("image") ? "m.image" : "m.file"},
|
||||||
{"body", fileName},
|
{"body", fileName},
|
||||||
{"url", document.object()["content_uri"].toString()},
|
{"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);
|
e->setSentProgress((double)sent / (double)total);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -761,17 +823,13 @@ void MatrixCore::startDirectChat(const QString& id) {
|
||||||
{"creation_content", QJsonObject{{"m.federate", false}}},
|
{"creation_content", QJsonObject{{"m.federate", false}}},
|
||||||
{"preset", "private_chat"},
|
{"preset", "private_chat"},
|
||||||
{"is_direct", true},
|
{"is_direct", true},
|
||||||
{"invite", QJsonArray{id}}
|
{"invite", QJsonArray{id}}};
|
||||||
};
|
|
||||||
|
|
||||||
network->postJSON("/_matrix/client/r0/createRoom", roomObject, [](QNetworkReply*) {});
|
network->postJSON("/_matrix/client/r0/createRoom", roomObject, [](QNetworkReply*) {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatrixCore::setTyping(Room* room) {
|
void MatrixCore::setTyping(Room* room) {
|
||||||
const QJsonObject typingObject {
|
const QJsonObject typingObject{{"typing", true}, {"timeout", 15000}};
|
||||||
{"typing", true},
|
|
||||||
{"timeout", 15000}
|
|
||||||
};
|
|
||||||
|
|
||||||
network->putJSON("/_matrix/client/r0/rooms/" + room->getId() + "/typing/" + userId, typingObject);
|
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) {
|
void MatrixCore::inviteToRoom(Room* room, const QString& userId) {
|
||||||
const QJsonObject inviteObject {
|
const QJsonObject inviteObject{{"user_id", userId}};
|
||||||
{"user_id", userId}
|
|
||||||
};
|
|
||||||
|
|
||||||
network->postJSON("/_matrix/client/r0/rooms/" + room->getId() + "/invite", inviteObject, [](QNetworkReply*) {});
|
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());
|
m->setDisplayName(memberJson["content"].toObject()["displayname"].toString());
|
||||||
|
|
||||||
if (!memberJson["content"].toObject()["avatar_url"].isNull()) {
|
if (!memberJson["content"].toObject()["avatar_url"].isNull()) {
|
||||||
const QString imageId = memberJson["content"].toObject()["avatar_url"].toString().remove("mxc://");
|
const QString imageId =
|
||||||
m->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale");
|
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);
|
idToMember.insert(id, m);
|
||||||
|
@ -874,7 +933,9 @@ void MatrixCore::readMessageHistory(Room* room) {
|
||||||
|
|
||||||
qDebug() << "Reading message history...";
|
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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
room->prevBatch = document.object()["end"].toString();
|
room->prevBatch = document.object()["end"].toString();
|
||||||
|
@ -973,7 +1034,6 @@ Member* MatrixCore::resolveMemberId(const QString& id) const {
|
||||||
return idToMember.value(id);
|
return idToMember.value(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Room* MatrixCore::resolveRoomId(const QString& id) const {
|
Room* MatrixCore::resolveRoomId(const QString& id) const {
|
||||||
return idToRoom.value(id);
|
return idToRoom.value(id);
|
||||||
}
|
}
|
||||||
|
@ -1009,7 +1069,9 @@ void MatrixCore::loadDirectory(const QString& homeserver) {
|
||||||
|
|
||||||
if (!roomObject["avatar_url"].isNull()) {
|
if (!roomObject["avatar_url"].isNull()) {
|
||||||
const QString imageId = roomObject["avatar_url"].toString().remove("mxc://");
|
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());
|
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()) {
|
if (!event["content"].toObject()["avatar_url"].isNull()) {
|
||||||
const QString imageId = event["content"].toObject()["avatar_url"].toString().remove("mxc://");
|
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
|
// construct m.room.key event
|
||||||
const QJsonObject roomKeyObject{
|
const QJsonObject roomKeyObject{
|
||||||
{"action", "request"},
|
{"action", "request"},
|
||||||
{"body", QJsonObject {
|
{"body",
|
||||||
|
QJsonObject{
|
||||||
{"algorithm", event["content"].toObject()["algorithm"]},
|
{"algorithm", event["content"].toObject()["algorithm"]},
|
||||||
{"room_id", room.getId()},
|
{"room_id", room.getId()},
|
||||||
{"sender_key", event["content"].toObject()["sender_key"]},
|
{"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},
|
{"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{
|
const QJsonObject sendToDeviceObject{
|
||||||
{"messages", QJsonObject {
|
{"messages",
|
||||||
{ event["sender"].toString(), QJsonObject {
|
QJsonObject{
|
||||||
{ event["content"].toObject()["device_id"].toString(), roomKeyObject}
|
{event["sender"].toString(),
|
||||||
}}
|
QJsonObject{{event["content"].toObject()["device_id"].toString(), roomKeyObject}}}}}};
|
||||||
}}
|
|
||||||
};
|
|
||||||
|
|
||||||
// qDebug() << QJsonDocument(sendToDeviceObject).toJson(QJsonDocument::Compact);
|
// 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();
|
// qDebug() << "REPLY FROM KEY REQUEST SEND: " << reply->readAll();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
auto session = inboundSessions[event["content"].toObject()["session_id"].toString()];
|
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);
|
populateEvent(document.object(), e);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
e->setMsg("** ERR: messages sent from the same device are not supported yet.");
|
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());
|
e->setAttachmentSize(event["content"].toObject()["info"].toObject()["size"].toInt());
|
||||||
|
|
||||||
if (event["content"].toObject()["info"].toObject().contains("thumbnail_url"))
|
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
|
else
|
||||||
e->setThumbnail(getMXCMediaURL(event["content"].toObject()["url"].toString()));
|
e->setThumbnail(getMXCMediaURL(event["content"].toObject()["url"].toString()));
|
||||||
|
|
||||||
|
@ -1277,22 +1344,26 @@ bool MatrixCore::getMarkdownEnabled() const {
|
||||||
return markdownEnabled;
|
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?
|
// why we would we send ourselves a key?
|
||||||
if (device_id == deviceId)
|
if (device_id == deviceId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QJsonObject claimObject{
|
QJsonObject claimObject{
|
||||||
{"timeout", 10000},
|
{"timeout", 10000}, {"one_time_keys", QJsonObject{{user_id, QJsonObject{{device_id, "signed_curve25519"}}}}}};
|
||||||
{"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());
|
const QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
std::string identityKey = senderCurveIdentity.toStdString();
|
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())
|
if (document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject().keys().empty())
|
||||||
return;
|
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);
|
auto session = encryption->beginOutboundOlmSession(identityKey, oneTimeKey);
|
||||||
|
|
||||||
// construct m.room.key event
|
// construct m.room.key event
|
||||||
const QJsonObject roomKeyObject{
|
const QJsonObject roomKeyObject{
|
||||||
{"content", QJsonObject {
|
{"content",
|
||||||
|
QJsonObject{
|
||||||
{"algorithm", "m.megolm.v1.aes-sha2"},
|
{"algorithm", "m.megolm.v1.aes-sha2"},
|
||||||
{"room_id", roomId},
|
{"room_id", roomId},
|
||||||
{"session_id", session_id},
|
{"session_id", session_id},
|
||||||
{"session_key", session_key}
|
{"session_key", session_key}}},
|
||||||
}},
|
|
||||||
{"type", "m.room_key"},
|
{"type", "m.room_key"},
|
||||||
{"keys", QJsonObject {
|
{"keys", QJsonObject{{"ed25519", encryption->identityKey["ed25519"]}}},
|
||||||
{"ed25519", encryption->identityKey["ed25519"]}
|
|
||||||
}},
|
|
||||||
{"sender", userId},
|
{"sender", userId},
|
||||||
{"sender_device", deviceId},
|
{"sender_device", deviceId},
|
||||||
{"recipient", user_id},
|
{"recipient", user_id},
|
||||||
{"recipient_keys", QJsonObject {
|
{"recipient_keys", QJsonObject{{"ed25519", senderEdIdentity}}}};
|
||||||
{"ed25519", senderEdIdentity}
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
|
|
||||||
// construct the m.room.encrypted event
|
// construct the m.room.encrypted event
|
||||||
const QJsonObject roomEncryptedObject{
|
const QJsonObject roomEncryptedObject{
|
||||||
{"algorithm", "m.olm.v1.curve25519-aes-sha2"},
|
{"algorithm", "m.olm.v1.curve25519-aes-sha2"},
|
||||||
{"ciphertext", QJsonObject {
|
{"ciphertext",
|
||||||
{identityKey.c_str(), QJsonObject {
|
QJsonObject{
|
||||||
{"body", encryption->encrypt(session, QString(QJsonDocument(roomKeyObject).toJson(QJsonDocument::Compact)).toStdString()).c_str()},
|
{identityKey.c_str(),
|
||||||
{"type", (int)olm_encrypt_message_type(session)}
|
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"]},
|
{"sender_key", encryption->identityKey["curve25519"]},
|
||||||
};
|
};
|
||||||
|
|
||||||
const QJsonObject sendToDeviceObject{
|
const QJsonObject sendToDeviceObject{
|
||||||
{"messages", QJsonObject {
|
{"messages", QJsonObject{{user_id, QJsonObject{{device_id, roomEncryptedObject}}}}}};
|
||||||
{ 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();
|
// qDebug() << "REPLY FROM KEY SEND: " << reply->readAll();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "roomlistsortmodel.h"
|
#include "roomlistsortmodel.h"
|
||||||
|
|
||||||
|
#include "membermodel.h"
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
#include "membermodel.h"
|
|
||||||
|
|
||||||
bool RoomListSortModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
|
bool RoomListSortModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
|
||||||
const QString sectionLeft = sourceModel()->data(left, RoomListModel::SectionRole).toString();
|
const QString sectionLeft = sourceModel()->data(left, RoomListModel::SectionRole).toString();
|
||||||
|
@ -29,7 +29,8 @@ bool MemberListSortModel::lessThan(const QModelIndex& left, const QModelIndex& r
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (sectionLeft == sectionRight)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue