diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml index 9b53ff35..115a73c4 100644 --- a/resources/qml/UserProfile.qml +++ b/resources/qml/UserProfile.qml @@ -14,7 +14,7 @@ ApplicationWindow{ height: 650 width: 420 modality: Qt.WindowModal - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter palette: colors Connections{ diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp index 5069ff9d..8c230887 100644 --- a/src/DeviceVerificationFlow.cpp +++ b/src/DeviceVerificationFlow.cpp @@ -8,24 +8,31 @@ #include #include -#include - static constexpr int TIMEOUT = 2 * 60 * 1000; // 2 minutes namespace msgs = mtx::events::msg; -DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow::Type flow_type) +DeviceVerificationFlow::DeviceVerificationFlow(QObject *, + DeviceVerificationFlow::Type flow_type, + TimelineModel *model) : type(flow_type) + , model_(model) { timeout = new QTimer(this); timeout->setSingleShot(true); this->sas = olm::client()->sas_init(); this->isMacVerified = false; - connect(this->model_, - &TimelineModel::updateFlowEventId, - this, - [this](std::string event_id) { this->relation.in_reply_to.event_id = event_id; }); + if (model) { + connect(this->model_, + &TimelineModel::updateFlowEventId, + this, + [this](std::string event_id) { + this->relation.rel_type = mtx::common::RelationType::Reference; + this->relation.event_id = event_id; + this->transaction_id = event_id; + }); + } connect(timeout, &QTimer::timeout, this, [this]() { emit timedout(); @@ -42,8 +49,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; } if ((std::find(msg.key_agreement_protocols.begin(), @@ -69,8 +75,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow DeviceVerificationFlow::Error::UnknownMethod); return; } - this->acceptVerificationRequest(); this->canonical_json = nlohmann::json(msg); + this->acceptVerificationRequest(); } else { this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod); } @@ -84,8 +90,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; } if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") && @@ -116,8 +121,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; } emit verificationCanceled(); @@ -131,8 +135,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; } this->sas->set_their_key(msg.key); @@ -157,6 +160,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow } else if (this->method == DeviceVerificationFlow::Method::Decimal) { this->sasList = this->sas->generate_bytes_decimal(info); } + if (this->sender == false) { emit this->verificationRequestAccepted(this->method); this->sendVerificationKey(); @@ -181,8 +185,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; } std::string info = "MATRIX_KEY_VERIFICATION_MAC" + this->toClient.to_string() + @@ -227,12 +230,11 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - // this is just a workaround - this->relation.in_reply_to.event_id = - msg.relates_to.value().in_reply_to.event_id; - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; + else { + this->deviceId = QString::fromStdString(msg.from_device); + } } this->startVerificationRequest(); }); @@ -245,8 +247,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow if (msg.transaction_id.value() != this->transaction_id) return; } else if (msg.relates_to.has_value()) { - if (msg.relates_to.value().in_reply_to.event_id != - this->relation.in_reply_to.event_id) + if (msg.relates_to.value().event_id != this->relation.event_id) return; } this->acceptDevice(); @@ -297,12 +298,6 @@ DeviceVerificationFlow::getSasList() return this->sasList; } -void -DeviceVerificationFlow::setModel(TimelineModel *&model) -{ - this->model_ = model; -} - void DeviceVerificationFlow::setTransactionId(QString transaction_id_) { @@ -351,15 +346,17 @@ DeviceVerificationFlow::setType(Type type) void DeviceVerificationFlow::setSender(bool sender_) { - this->sender = sender_; - this->transaction_id = http::client()->generate_txn_id(); + this->sender = sender_; + if (this->sender) + this->transaction_id = http::client()->generate_txn_id(); } void DeviceVerificationFlow::setEventId(std::string event_id) { - this->relation.in_reply_to.event_id = event_id; - this->transaction_id = event_id; + this->relation.rel_type = mtx::common::RelationType::Reference; + this->relation.event_id = event_id; + this->transaction_id = event_id; } //! accepts a verification @@ -476,7 +473,8 @@ DeviceVerificationFlow::startVerificationRequest() static_cast(err->status_code)); }); } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) { - req.relates_to = this->relation; + req.relates_to = this->relation; + this->canonical_json = nlohmann::json(req); (model_)->sendMessage(req); } } @@ -562,6 +560,7 @@ DeviceVerificationFlow::cancelVerification(DeviceVerificationFlow::Error error_c } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) { req.relates_to = this->relation; (model_)->sendMessage(req); + this->deleteLater(); } // TODO : Handle Blocking user better diff --git a/src/DeviceVerificationFlow.h b/src/DeviceVerificationFlow.h index 1ad3b1d0..4c3e5171 100644 --- a/src/DeviceVerificationFlow.h +++ b/src/DeviceVerificationFlow.h @@ -52,7 +52,8 @@ public: DeviceVerificationFlow( QObject *parent = nullptr, - DeviceVerificationFlow::Type = DeviceVerificationFlow::Type::ToDevice); + DeviceVerificationFlow::Type = DeviceVerificationFlow::Type::ToDevice, + TimelineModel *model = nullptr); // getters QString getTransactionId(); QString getUserId(); @@ -62,7 +63,6 @@ public: std::vector getSasList(); bool getSender(); // setters - void setModel(TimelineModel *&model); void setTransactionId(QString transaction_id_); void setUserId(QString userID); void setDeviceId(QString deviceID); @@ -127,5 +127,5 @@ private: std::optional room_id; std::optional event_id; TimelineModel *model_; - mtx::common::ReplyRelatesTo relation; + mtx::common::ReactionRelatesTo relation; }; diff --git a/src/Olm.cpp b/src/Olm.cpp index ff6ea2f4..48439fa3 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -211,10 +211,15 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id, // relations shouldn't be encrypted... mtx::common::ReplyRelatesTo relation; + mtx::common::ReactionRelatesTo r_relation; + if (body["content"].contains("m.relates_to") && body["content"]["m.relates_to"].contains("m.in_reply_to")) { relation = body["content"]["m.relates_to"]; body["content"].erase("m.relates_to"); + } else if (body["content"]["m.relates_to"].contains("event_id")) { + r_relation = body["content"]["m.relates_to"]; + body["content"].erase("m.relates_to"); } // Always check before for existence. @@ -223,12 +228,13 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id, // Prepare the m.room.encrypted event. msg::Encrypted data; - data.ciphertext = std::string((char *)payload.data(), payload.size()); - data.sender_key = olm::client()->identity_keys().curve25519; - data.session_id = res.data.session_id; - data.device_id = device_id; - data.algorithm = MEGOLM_ALGO; - data.relates_to = relation; + data.ciphertext = std::string((char *)payload.data(), payload.size()); + data.sender_key = olm::client()->identity_keys().curve25519; + data.session_id = res.data.session_id; + data.device_id = device_id; + data.algorithm = MEGOLM_ALGO; + data.relates_to = relation; + data.r_relates_to = r_relation; auto message_index = olm_outbound_group_session_message_index(res.session); nhlog::crypto()->debug("next message_index {}", message_index); diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp index 208b20e2..b210e157 100644 --- a/src/timeline/EventStore.cpp +++ b/src/timeline/EventStore.cpp @@ -95,8 +95,8 @@ EventStore::EventStore(std::string room_id, QObject *) room_id_, txn_id, e.content, - [this, txn_id](const mtx::responses::EventId &event_id, - mtx::http::RequestErr err) { + [this, txn_id, e](const mtx::responses::EventId &event_id, + mtx::http::RequestErr err) { if (err) { const int status_code = static_cast(err->status_code); @@ -108,7 +108,21 @@ EventStore::EventStore(std::string room_id, QObject *) emit messageFailed(txn_id); return; } + emit messageSent(txn_id, event_id.event_id.to_string()); + if constexpr (mtx::events::message_content_to_type< + decltype(e.content)> == + mtx::events::EventType::RoomEncrypted) { + auto event = + decryptEvent({room_id_, e.event_id}, e); + if (auto dec = + std::get_if>(event)) { + emit updateFlowEventId( + event_id.event_id.to_string()); + } + } }); }, event->data); @@ -318,12 +332,12 @@ EventStore::reactions(const std::string &event_id) if (auto reaction = std::get_if>( related_event)) { - auto &agg = aggregation[reaction->content.relates_to.key]; + auto &agg = aggregation[reaction->content.relates_to.key.value()]; if (agg.count == 0) { Reaction temp{}; temp.key_ = - QString::fromStdString(reaction->content.relates_to.key); + QString::fromStdString(reaction->content.relates_to.key.value()); reactions.push_back(temp); } diff --git a/src/timeline/EventStore.h b/src/timeline/EventStore.h index 28d46e90..55a66f49 100644 --- a/src/timeline/EventStore.h +++ b/src/timeline/EventStore.h @@ -100,6 +100,7 @@ signals: void messageFailed(std::string txn_id); void startDMVerification( mtx::events::RoomEvent &msg); + void updateFlowEventId(std::string event_id); public slots: void addPending(mtx::events::collections::TimelineEvents event); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 809fe382..dc5eb8cc 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -22,8 +22,6 @@ #include "Utils.h" #include "dialogs/RawMessage.h" -#include - Q_DECLARE_METATYPE(QModelIndex) namespace std { @@ -237,6 +235,9 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj [this](mtx::events::RoomEvent msg) { ChatPage::instance()->recievedRoomDeviceVerificationRequest(msg, this); }); + connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) { + this->updateFlowEventId(event_id); + }); } QHash @@ -814,7 +815,6 @@ TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent msg) json doc = { {"type", to_string(msg.type)}, {"content", json(msg.content)}, {"room_id", room_id}}; - std::cout << doc.dump(2) << std::endl; try { // Check if we have already an outbound megolm session then we can use. @@ -1095,7 +1095,6 @@ struct SendMessageVisitor void operator()(const mtx::events::RoomEvent &msg) { - emit model_->updateFlowEventId(msg.event_id); model_->sendEncryptedMessage(msg); } void operator()(const mtx::events::RoomEvent &msg) diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index c16e09d1..fb4a094e 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -194,13 +194,12 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin [this](const mtx::events::RoomEvent &message, TimelineModel *model) { if (!(this->dvList->exist(QString::fromStdString(message.event_id)))) { - auto flow = - new DeviceVerificationFlow(this, DeviceVerificationFlow::Type::RoomMsg); + auto flow = new DeviceVerificationFlow( + this, DeviceVerificationFlow::Type::RoomMsg, model); if (std::find(message.content.methods.begin(), message.content.methods.end(), mtx::events::msg::VerificationMethods::SASv1) != message.content.methods.end()) { - flow->setModel(model); flow->setEventId(message.event_id); emit newDeviceVerificationRequest( std::move(flow), @@ -241,42 +240,48 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin &ChatPage::recievedDeviceVerificationStart, this, [this](const mtx::events::msg::KeyVerificationStart &msg, std::string sender) { - if (!(this->dvList->exist(QString::fromStdString(msg.transaction_id.value())))) { - auto flow = new DeviceVerificationFlow(this); - flow->canonical_json = nlohmann::json(msg); - if ((std::find(msg.key_agreement_protocols.begin(), - msg.key_agreement_protocols.end(), - "curve25519-hkdf-sha256") != - msg.key_agreement_protocols.end()) && - (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") != - msg.hashes.end()) && - (std::find(msg.message_authentication_codes.begin(), - msg.message_authentication_codes.end(), - "hmac-sha256") != - msg.message_authentication_codes.end())) { - if (std::find(msg.short_authentication_string.begin(), - msg.short_authentication_string.end(), - mtx::events::msg::SASMethods::Emoji) != - msg.short_authentication_string.end()) { - flow->setMethod(DeviceVerificationFlow::Method::Emoji); - } else if (std::find(msg.short_authentication_string.begin(), + if (msg.transaction_id.has_value()) { + if (!(this->dvList->exist( + QString::fromStdString(msg.transaction_id.value())))) { + auto flow = new DeviceVerificationFlow(this); + flow->canonical_json = nlohmann::json(msg); + if ((std::find(msg.key_agreement_protocols.begin(), + msg.key_agreement_protocols.end(), + "curve25519-hkdf-sha256") != + msg.key_agreement_protocols.end()) && + (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") != + msg.hashes.end()) && + (std::find(msg.message_authentication_codes.begin(), + msg.message_authentication_codes.end(), + "hmac-sha256") != + msg.message_authentication_codes.end())) { + if (std::find(msg.short_authentication_string.begin(), + msg.short_authentication_string.end(), + mtx::events::msg::SASMethods::Emoji) != + msg.short_authentication_string.end()) { + flow->setMethod( + DeviceVerificationFlow::Method::Emoji); + } else if (std::find( + msg.short_authentication_string.begin(), msg.short_authentication_string.end(), mtx::events::msg::SASMethods::Decimal) != - msg.short_authentication_string.end()) { - flow->setMethod(DeviceVerificationFlow::Method::Decimal); + msg.short_authentication_string.end()) { + flow->setMethod( + DeviceVerificationFlow::Method::Decimal); + } else { + flow->cancelVerification( + DeviceVerificationFlow::Error::UnknownMethod); + return; + } + emit newDeviceVerificationRequest( + std::move(flow), + QString::fromStdString(msg.transaction_id.value()), + QString::fromStdString(sender), + QString::fromStdString(msg.from_device)); } else { flow->cancelVerification( DeviceVerificationFlow::Error::UnknownMethod); - return; } - emit newDeviceVerificationRequest( - std::move(flow), - QString::fromStdString(msg.transaction_id.value()), - QString::fromStdString(sender), - QString::fromStdString(msg.from_device)); - } else { - flow->cancelVerification( - DeviceVerificationFlow::Error::UnknownMethod); } } }); diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp index 1eaa9d27..87eae001 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp @@ -211,8 +211,9 @@ UserProfile::createFlow(bool isVerifyUser) << std::endl; if (this->roomid_.toStdString() == room_id) { auto newflow = new DeviceVerificationFlow( - this, DeviceVerificationFlow::Type::RoomMsg); - newflow->setModel(this->model); + this, + DeviceVerificationFlow::Type::RoomMsg, + this->model); return (std::move(newflow)); } else { std::cout << "FOUND A ENCRYPTED ROOM BUT CURRENTLY "