diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index e4c820f8..5170a41a 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -103,20 +103,22 @@ Page { id: deviceVerificationDialog DeviceVerification {} } + Component{ + id: deviceVerificationFlow + DeviceVerificationFlow {} + } Connections { target: timelineManager - onDeviceVerificationRequest: { - var dialog = deviceVerificationDialog.createObject(timelineRoot, {flow: deviceVerificationFlow}); + onNewDeviceVerificationRequest: { + var newFlow = deviceVerificationFlow.createObject(timelineRoot, + {userId : userId,sender: false,deviceId : deviceId,tranId:transactionId}); + deviceVerificationList.add(newFlow.tranId); + var dialog = deviceVerificationDialog.createObject(timelineRoot, + {flow: newFlow,sender: false}); dialog.show(); } } - Button { - text: "test device verification" - onClicked: timelineManager.startDummyVerification() - z: 5 - } - Label { visible: !timelineManager.timeline && !timelineManager.isInitialSync anchors.centerIn: parent diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml index c40e6765..80415a29 100644 --- a/resources/qml/UserProfile.qml +++ b/resources/qml/UserProfile.qml @@ -33,8 +33,9 @@ ApplicationWindow{ id: deviceVerificationDialog DeviceVerification {} } - DeviceVerificationFlow { + Component{ id: deviceVerificationFlow + DeviceVerificationFlow {} } background: Item{ @@ -111,10 +112,11 @@ ApplicationWindow{ id: verifyButton text:"Verify" onClicked: { - deviceVerificationFlow.userId = user_data.userId - deviceVerificationFlow.deviceId = model.deviceID + var newFlow = deviceVerificationFlow.createObject(userProfileDialog, + {userId : user_data.userId,sender: true,deviceId : model.deviceID}); + deviceVerificationList.add(newFlow.tranId); var dialog = deviceVerificationDialog.createObject(userProfileDialog, - {flow: deviceVerificationFlow,sender: true}); + {flow: newFlow,sender: true}); dialog.show(); } contentItem: Text { diff --git a/resources/qml/device-verification/DeviceVerification.qml b/resources/qml/device-verification/DeviceVerification.qml index fca360f7..ad0edeb7 100644 --- a/resources/qml/device-verification/DeviceVerification.qml +++ b/resources/qml/device-verification/DeviceVerification.qml @@ -75,7 +75,12 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignLeft text: "Cancel" - onClicked: { dialog.close(); flow.cancelVerification(); } + onClicked: { + dialog.close(); + flow.cancelVerification(); + deviceVerificationList.remove(flow.tranId); + delete flow; + } } Item { Layout.fillWidth: true @@ -127,7 +132,12 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignLeft text: "Deny" - onClicked: { dialog.close(); flow.cancelVerification(); } + onClicked: { + dialog.close(); + flow.cancelVerification(); + deviceVerificationList.remove(flow.tranId); + delete flow; + } } Item { Layout.fillWidth: true @@ -166,7 +176,12 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignLeft text: "Cancel" - onClicked: { dialog.close(); flow.cancelVerification(); } + onClicked: { + dialog.close(); + flow.cancelVerification(); + deviceVerificationList.remove(flow.tranId); + delete flow; + } } Item { Layout.fillWidth: true @@ -212,7 +227,12 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignLeft text: "They do not match!" - onClicked: { dialog.close(); flow.cancelVerification(); } + onClicked: { + dialog.close(); + flow.cancelVerification(); + deviceVerificationList.remove(flow.tranId); + delete flow; + } } Item { Layout.fillWidth: true @@ -346,7 +366,12 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignLeft text: "They do not match!" - onClicked: { dialog.close(); flow.cancelVerification(); } + onClicked: { + dialog.close(); + flow.cancelVerification(); + deviceVerificationList.remove(flow.tranId); + delete flow; + } } Item { Layout.fillWidth: true @@ -385,7 +410,12 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignLeft text: "Cancel" - onClicked: { dialog.close(); flow.cancelVerification(); } + onClicked: { + dialog.close(); + flow.cancelVerification(); + deviceVerificationList.remove(flow.tranId); + delete flow; + } } Item { Layout.fillWidth: true @@ -419,7 +449,11 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignRight text: "Close" - onClicked: dialog.close() + onClicked: { + dialog.close() + deviceVerificationList.remove(flow.tranId); + delete flow; + } } } } @@ -450,7 +484,11 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignRight text: "Close" - onClicked: dialog.close() + onClicked: { + dialog.close() + deviceVerificationList.remove(flow.tranId); + delete flow; + } } } } @@ -481,7 +519,11 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignRight text: "Close" - onClicked: dialog.close() + onClicked: { + dialog.close() + deviceVerificationList.remove(flow.tranId); + delete flow; + } } } } diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 17ea2551..aba1f75d 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -26,8 +26,8 @@ #include "Cache.h" #include "Cache_p.h" #include "ChatPage.h" -#include "EventAccessors.h" #include "DeviceVerificationFlow.h" +#include "EventAccessors.h" #include "Logging.h" #include "MainWindow.h" #include "MatrixClient.h" diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp index c6652d03..efb9882b 100644 --- a/src/DeviceVerificationFlow.cpp +++ b/src/DeviceVerificationFlow.cpp @@ -1,7 +1,7 @@ #include "DeviceVerificationFlow.h" #include "ChatPage.h" - #include "Logging.h" + #include #include // only for debugging #include @@ -13,9 +13,10 @@ namespace msgs = mtx::events::msg; DeviceVerificationFlow::DeviceVerificationFlow(QObject *) { - qRegisterMetaType(); timeout = new QTimer(this); timeout->setSingleShot(true); + if (this->sender == true) + this->transaction_id = http::client()->generate_txn_id(); connect(timeout, &QTimer::timeout, this, [this]() { emit timedout(); this->deleteLater(); @@ -73,6 +74,12 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *) timeout->start(TIMEOUT); } +QString +DeviceVerificationFlow::getTransactionId() +{ + return QString::fromStdString(this->transaction_id); +} + QString DeviceVerificationFlow::getUserId() { @@ -91,10 +98,22 @@ DeviceVerificationFlow::getMethod() return this->method; } +bool +DeviceVerificationFlow::getSender() +{ + return this->sender; +} + +void +DeviceVerificationFlow::setTransactionId(QString transaction_id_) +{ + this->transaction_id = transaction_id_.toStdString(); +} + void DeviceVerificationFlow::setUserId(QString userID) { - this->userId = userID; + this->userId = userID; this->toClient = mtx::identifiers::parse(userID.toStdString()); } @@ -110,6 +129,12 @@ DeviceVerificationFlow::setMethod(DeviceVerificationFlow::Method method_) this->method = method_; } +void +DeviceVerificationFlow::setSender(bool sender_) +{ + this->sender = sender_; +} + //! accepts a verification void DeviceVerificationFlow::acceptVerificationRequest() @@ -119,11 +144,12 @@ DeviceVerificationFlow::acceptVerificationRequest() req.transaction_id = this->transaction_id; req.method = mtx::events::msg::VerificationMethods::SASv1; - req.key_agreement_protocol = "curve25519"; + req.key_agreement_protocol = "curve25519-hkdf-sha256"; req.hash = "sha256"; - req.message_authentication_code = ""; - // req.short_authentication_string = ""; - req.commitment = ""; + req.message_authentication_code = "hkdf-hmac-sha256"; + req.short_authentication_string = {mtx::events::msg::SASMethods::Decimal, + mtx::events::msg::SASMethods::Emoji}; + req.commitment = ""; emit this->verificationRequestAccepted(this->method); @@ -132,12 +158,12 @@ DeviceVerificationFlow::acceptVerificationRequest() http::client() ->send_to_device( - "m.key.verification.accept", body, [](mtx::http::RequestErr err) { + this->transaction_id, body, [this](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to accept verification request: {} {}", err->matrix_error.error, static_cast(err->status_code)); - // emit this->verificationRequestAccepted(rand() % 2 ? Emoji : Decimal); + emit this->verificationRequestAccepted(rand() % 2 ? Emoji : Decimal); }); } //! starts the verification flow @@ -150,22 +176,23 @@ DeviceVerificationFlow::startVerificationRequest() req.from_device = http::client()->device_id(); req.transaction_id = this->transaction_id; req.method = mtx::events::msg::VerificationMethods::SASv1; - req.key_agreement_protocols = {}; - req.hashes = {}; - req.message_authentication_codes = {}; - // req.short_authentication_string = ""; - qDebug()<<"Inside Start Verification"; - qDebug()<userId; + req.key_agreement_protocols = {"curve25519-hkdf-sha256"}; + req.hashes = {"sha256"}; + req.message_authentication_codes = {"hkdf-hmac-sha256", "hmac-sha256"}; + req.short_authentication_string = {mtx::events::msg::SASMethods::Decimal, + mtx::events::msg::SASMethods::Emoji}; + body[this->toClient][this->deviceId.toStdString()] = req; http::client() ->send_to_device( - "m.key.verification.start", body, [](mtx::http::RequestErr err) { + this->transaction_id, body, [body](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to start verification request: {} {}", err->matrix_error.error, static_cast(err->status_code)); + std::cout << nlohmann::json(body).dump(2) << std::endl; }); } //! sends a verification request @@ -177,8 +204,6 @@ DeviceVerificationFlow::sendVerificationRequest() mtx::requests::ToDeviceMessages body; mtx::events::msg::KeyVerificationRequest req; - this->transaction_id = http::client()->generate_txn_id(); - req.from_device = http::client()->device_id(); req.transaction_id = this->transaction_id; req.methods.resize(1); @@ -190,7 +215,7 @@ DeviceVerificationFlow::sendVerificationRequest() http::client() ->send_to_device( - "m.key.verification.request", body, [](mtx::http::RequestErr err) { + this->transaction_id, body, [](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to send verification request: {} {}", err->matrix_error.error, @@ -214,7 +239,7 @@ DeviceVerificationFlow::cancelVerification() http::client() ->send_to_device( - "m.key.verification.cancel", body, [this](mtx::http::RequestErr err) { + this->transaction_id, body, [this](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to cancel verification request: {} {}", err->matrix_error.error, @@ -237,7 +262,7 @@ DeviceVerificationFlow::sendVerificationKey() http::client() ->send_to_device( - "m.key.verification.cancel", body, [](mtx::http::RequestErr err) { + this->transaction_id, body, [](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to send verification key: {} {}", err->matrix_error.error, @@ -260,7 +285,7 @@ DeviceVerificationFlow::sendVerificationMac() http::client() ->send_to_device( - "m.key.verification.cancel", body, [](mtx::http::RequestErr err) { + this->transaction_id, body, [](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to send verification MAC: {} {}", err->matrix_error.error, diff --git a/src/DeviceVerificationFlow.h b/src/DeviceVerificationFlow.h index 561a3717..b651394b 100644 --- a/src/DeviceVerificationFlow.h +++ b/src/DeviceVerificationFlow.h @@ -1,5 +1,7 @@ #pragma once +#include "Olm.h" + #include #include @@ -9,6 +11,8 @@ class DeviceVerificationFlow : public QObject { Q_OBJECT // Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + Q_PROPERTY(QString tranId READ getTransactionId WRITE setTransactionId) + Q_PROPERTY(bool sender READ getSender WRITE setSender) Q_PROPERTY(QString userId READ getUserId WRITE setUserId) Q_PROPERTY(QString deviceId READ getDeviceId WRITE setDeviceId) Q_PROPERTY(Method method READ getMethod WRITE setMethod) @@ -22,12 +26,16 @@ public: Q_ENUM(Method) DeviceVerificationFlow(QObject *parent = nullptr); + QString getTransactionId(); QString getUserId(); QString getDeviceId(); Method getMethod(); + void setTransactionId(QString transaction_id_); + bool getSender(); void setUserId(QString userID); void setDeviceId(QString deviceID); void setMethod(Method method_); + void setSender(bool sender_); public slots: //! sends a verification request @@ -55,9 +63,9 @@ private: QString userId; QString deviceId; Method method; + bool sender; QTimer *timeout = nullptr; std::string transaction_id; mtx::identifiers::User toClient; }; -Q_DECLARE_METATYPE(mtx::events::collections::DeviceEvents) \ No newline at end of file diff --git a/src/emoji/EmojiModel.h b/src/emoji/EmojiModel.h index 8d43e000..88bacdee 100644 --- a/src/emoji/EmojiModel.h +++ b/src/emoji/EmojiModel.h @@ -60,5 +60,4 @@ private: EmojiCategory category_ = EmojiCategory::Search; emoji::Provider emoji_provider_; }; - } \ No newline at end of file diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index f4d1c00e..22fe4d6d 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -16,12 +16,38 @@ #include "dialogs/ImageOverlay.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" -#include "../ui/UserProfile.h" #include "src/ui/UserProfile.h" #include "src/ui/UserProfileModel.h" Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) +namespace msgs = mtx::events::msg; + +void +DeviceVerificationList::add(QString tran_id) +{ + this->dv_list.push_back(tran_id); +} +void +DeviceVerificationList::remove(QString tran_id) +{ + for (QVector::iterator it = 0; it != (this->dv_list).end(); ++it) { + if (*it == tran_id) { + this->dv_list.erase(it); + break; + } + } +} +bool +DeviceVerificationList::exist(QString tran_id) +{ + for (int i = 0; i < (this->dv_list).size(); ++i) { + if (dv_list[i] == tran_id) + return true; + } + return false; +} + void TimelineViewManager::updateEncryptedDescriptions() { @@ -63,12 +89,12 @@ TimelineViewManager::userColor(QString id, QColor background) return userColors.value(id); } -QString -TimelineViewManager::userPresence(QString id) const -{ - return QString::fromStdString( - mtx::presence::to_string(cache::presenceState(id.toStdString()))); -} +// QString +// TimelineViewManager::userPresence(QString id) const +// { +// return QString::fromStdString( +// mtx::presence::to_string(cache::presenceState(id.toStdString()))); +// } QString TimelineViewManager::userStatus(QString id) const { @@ -81,6 +107,7 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin , blurhashProvider(new BlurhashProvider()) , settings(userSettings) { + qRegisterMetaType(); qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject, "im.nheko", 1, @@ -106,6 +133,7 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin 0, "EmojiCategory", "Error: Only enums"); + this->dvList = new DeviceVerificationList; #ifdef USE_QUICK_VIEW view = new QQuickView(); @@ -127,6 +155,7 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin container->setMinimumSize(200, 200); view->rootContext()->setContextProperty("timelineManager", this); view->rootContext()->setContextProperty("settings", settings.data()); + view->rootContext()->setContextProperty("deviceVerificationList", this->dvList); updateColorPalette(); view->engine()->addImageProvider("MxcImage", imgProvider); view->engine()->addImageProvider("colorimage", colorImgProvider); @@ -141,6 +170,32 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin &ChatPage::decryptSidebarChanged, this, &TimelineViewManager::updateEncryptedDescriptions); + connect(dynamic_cast(parent), + &ChatPage::recievedDeviceVerificationRequest, + this, + [this](const mtx::events::collections::DeviceEvents &message) { + auto msg = + std::get>(message); + QString tranID = QString::fromStdString(msg.content.transaction_id); + QString deviceId = QString::fromStdString(msg.content.from_device); + QString userId = QString::fromStdString(msg.sender); + if (!(this->dvList->exist(tranID))) { + emit newDeviceVerificationRequest(tranID, userId, deviceId); + } + }); + connect(dynamic_cast(parent), + &ChatPage::recievedDeviceVerificationStart, + this, + [this](const mtx::events::collections::DeviceEvents &message) { + auto msg = + std::get>(message); + QString tranID = QString::fromStdString(msg.content.transaction_id); + QString deviceId = QString::fromStdString(msg.content.from_device); + QString userId = QString::fromStdString(msg.sender); + if (!(this->dvList->exist(tranID))) { + emit newDeviceVerificationRequest(tranID, userId, deviceId); + } + }); } void @@ -468,9 +523,3 @@ TimelineViewManager::queueVideoMessage(const QString &roomid, model->sendMessage(video); } - -void -TimelineViewManager::startDummyVerification() -{ - emit deviceVerificationRequest(new DeviceVerificationFlow(this)); -} diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 583a9e4c..70912715 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -22,6 +22,18 @@ class BlurhashProvider; class ColorImageProvider; class UserSettings; +class DeviceVerificationList : public QObject +{ + Q_OBJECT +public: + Q_INVOKABLE void add(QString tran_id); + Q_INVOKABLE void remove(QString tran_id); + Q_INVOKABLE bool exist(QString tran_id); + +private: + QVector dv_list; +}; + class TimelineViewManager : public QObject { Q_OBJECT @@ -44,9 +56,8 @@ public: Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; } Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const; Q_INVOKABLE QColor userColor(QString id, QColor background); - Q_INVOKABLE void startDummyVerification(); - Q_INVOKABLE QString userPresence(QString id) const; + // Q_INVOKABLE QString userPresence(QString id) const; Q_INVOKABLE QString userStatus(QString id) const; signals: @@ -56,7 +67,7 @@ signals: void initialSyncChanged(bool isInitialSync); void replyingEventChanged(QString replyingEvent); void replyClosed(); - void deviceVerificationRequest(DeviceVerificationFlow *deviceVerificationFlow); + void newDeviceVerificationRequest(QString transactionId, QString userId, QString deviceId); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); @@ -114,4 +125,7 @@ private: QSharedPointer settings; QHash userColors; + + DeviceVerificationList *dvList; }; +Q_DECLARE_METATYPE(mtx::events::collections::DeviceEvents) \ No newline at end of file