diff --git a/CMakeLists.txt b/CMakeLists.txt index c918d8343b43530a5cf4c0ac0a0b815d6c5f6d64..67a1dfb09c1074ddcdc27bbfb286669e809a9b79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,6 +365,7 @@ qt5_wrap_cpp(MOC_HEADERS src/CommunitiesList.h src/LoginPage.h src/MainWindow.h + src/MxcImageProvider.h src/InviteeItem.h src/QuickSwitcher.h src/RegisterPage.h diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp index 556b019b4178ea6d8d0543bfc9255483854e9066..edf6ceb5cec2b5f04883616534706e946f339c36 100644 --- a/src/MxcImageProvider.cpp +++ b/src/MxcImageProvider.cpp @@ -5,7 +5,7 @@ void MxcImageResponse::run() { - if (m_requestedSize.isValid()) { + if (m_requestedSize.isValid() && !m_encryptionInfo) { QString fileName = QString("%1_%2x%3_crop") .arg(m_id) .arg(m_requestedSize.width()) @@ -65,7 +65,12 @@ MxcImageResponse::run() return; } - auto data = QByteArray(res.data(), res.size()); + auto temp = res; + if (m_encryptionInfo) + temp = mtx::crypto::to_string( + mtx::crypto::decrypt_file(temp, m_encryptionInfo.value())); + + auto data = QByteArray(temp.data(), temp.size()); m_image.loadFromData(data); m_image.setText("original filename", QString::fromStdString(originalFilename)); diff --git a/src/MxcImageProvider.h b/src/MxcImageProvider.h index 19d8a74e23803b44101498502807699957343c60..2c197a13c552fe944be896c6f3c487210007c4e3 100644 --- a/src/MxcImageProvider.h +++ b/src/MxcImageProvider.h @@ -6,14 +6,21 @@ #include <QImage> #include <QThreadPool> +#include <mtx/common.hpp> + +#include <boost/optional.hpp> + class MxcImageResponse : public QQuickImageResponse , public QRunnable { public: - MxcImageResponse(const QString &id, const QSize &requestedSize) + MxcImageResponse(const QString &id, + const QSize &requestedSize, + boost::optional<mtx::crypto::EncryptedFile> encryptionInfo) : m_id(id) , m_requestedSize(requestedSize) + , m_encryptionInfo(encryptionInfo) { setAutoDelete(false); } @@ -29,19 +36,34 @@ public: QString m_id, m_error; QSize m_requestedSize; QImage m_image; + boost::optional<mtx::crypto::EncryptedFile> m_encryptionInfo; }; -class MxcImageProvider : public QQuickAsyncImageProvider +class MxcImageProvider + : public QObject + , public QQuickAsyncImageProvider { -public: + Q_OBJECT +public slots: QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override { - MxcImageResponse *response = new MxcImageResponse(id, requestedSize); + boost::optional<mtx::crypto::EncryptedFile> info; + auto temp = infos.find("mxc://" + id); + if (temp != infos.end()) + info = *temp; + + MxcImageResponse *response = new MxcImageResponse(id, requestedSize, info); pool.start(response); return response; } + void addEncryptionInfo(mtx::crypto::EncryptedFile info) + { + infos.insert(QString::fromStdString(info.url), info); + } + private: QThreadPool pool; + QHash<QString, mtx::crypto::EncryptedFile> infos; }; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index f606b603a87237defcc72a67b6daabb7ba5ea5ac..2c58e2f5803c742779d18e96abc22c3549748ccc 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -673,6 +673,19 @@ TimelineModel::internalAddEvents( continue; // don't insert redaction into timeline } + if (auto event = + boost::get<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&e)) { + auto temp = decryptEvent(*event).event; + auto encInfo = boost::apply_visitor( + [](const auto &ev) -> boost::optional<mtx::crypto::EncryptedFile> { + return eventEncryptionInfo(ev); + }, + temp); + + if (encInfo) + emit newEncryptedImage(encInfo.value()); + } + this->events.insert(id, e); ids.push_back(id); } diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index f52091e6822fe69a68a2542c5c3ffc92bed5c3ce..06c64acf5475aaedd5be7630bae52013b752f9fb 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -6,6 +6,7 @@ #include <QHash> #include <QSet> +#include <mtx/common.hpp> #include <mtx/responses.hpp> #include "Cache.h" @@ -188,6 +189,7 @@ signals: void nextPendingMessage(); void newMessageToSend(mtx::events::collections::TimelineEvents event); void mediaCached(QString mxcUrl, QString cacheUrl); + void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo); private: DecryptionResult decryptEvent( diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index c44bcbbfd3b329465a3ab7f7d61748aaa7a6d5aa..25f72a6d2045d23560b53cfa749335d02dee82e0 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -102,9 +102,14 @@ TimelineViewManager::sync(const mtx::responses::Rooms &rooms) void TimelineViewManager::addRoom(const QString &room_id) { - if (!models.contains(room_id)) - models.insert(room_id, - QSharedPointer<TimelineModel>(new TimelineModel(this, room_id))); + if (!models.contains(room_id)) { + QSharedPointer<TimelineModel> newRoom(new TimelineModel(this, room_id)); + connect(newRoom.data(), + &TimelineModel::newEncryptedImage, + imgProvider, + &MxcImageProvider::addEncryptionInfo); + models.insert(room_id, std::move(newRoom)); + } } void