diff options
author | Tobias Fella <fella@posteo.de> | 2021-08-31 21:47:10 +0200 |
---|---|---|
committer | Tobias Fella <fella@posteo.de> | 2021-09-05 22:09:17 +0200 |
commit | 4bab0f2ef2c68b478d669f90557d6bef6332e823 (patch) | |
tree | 59059f327120c318ee216c01040ee4aad8851ad0 /lib | |
parent | 06a8ef6ebed5962117121486059ba46dc7f6d4f9 (diff) | |
download | libquotient-4bab0f2ef2c68b478d669f90557d6bef6332e823.tar.gz libquotient-4bab0f2ef2c68b478d669f90557d6bef6332e823.zip |
Implement the mxc protocol in the NetworkAccessManager
Allows images to be loaded using the NetworkAccessManager instead of an
ImageProvider
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mxcreply.cpp | 54 | ||||
-rw-r--r-- | lib/mxcreply.h | 29 | ||||
-rw-r--r-- | lib/networkaccessmanager.cpp | 56 | ||||
-rw-r--r-- | lib/networkaccessmanager.h | 6 |
4 files changed, 145 insertions, 0 deletions
diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp new file mode 100644 index 00000000..49ebe603 --- /dev/null +++ b/lib/mxcreply.cpp @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Tobias Fella <fella@posteo.de> +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "mxcreply.h" + +#include <QtCore/QBuffer> +#include "connection.h" +#include "room.h" +#include "networkaccessmanager.h" +#include "events/stickerevent.h" + +using namespace Quotient; + +class MxcReply::Private +{ +public: + QNetworkReply *m_reply = nullptr; +}; + +MxcReply::MxcReply(QNetworkReply* reply) +{ + reply->setParent(this); + d->m_reply = reply; + connect(d->m_reply, &QNetworkReply::finished, this, [this]() { + setError(d->m_reply->error(), d->m_reply->errorString()); + Q_EMIT finished(); + }); +} + +MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) + : d(std::make_unique<Private>()) +{ + reply->setParent(this); + d->m_reply = reply; + connect(d->m_reply, &QNetworkReply::finished, this, [this, eventId]() { + setError(d->m_reply->error(), d->m_reply->errorString()); + Q_EMIT finished(); + }); +} + +bool MxcReply::isSequential() const +{ + return true; +} + +qint64 MxcReply::readData(char *data, qint64 maxSize) +{ + return d->m_reply->read(data, maxSize); +} + +void MxcReply::abort() +{ + d->m_reply->abort(); +}
\ No newline at end of file diff --git a/lib/mxcreply.h b/lib/mxcreply.h new file mode 100644 index 00000000..26dea2d0 --- /dev/null +++ b/lib/mxcreply.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Tobias Fella <fella@posteo.de> +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include <QtNetwork/QNetworkReply> +#include <memory> + +namespace Quotient { +class Room; +class Connection; +class MxcReply : public QNetworkReply +{ +public: + MxcReply(QNetworkReply* reply, Room* room, const QString &eventId); + MxcReply(QNetworkReply* reply); + + bool isSequential() const override; + +public slots: + void abort() override; + +protected: + qint64 readData(char *data, qint64 maxSize) override; +private: + class Private; + std::unique_ptr<Private> d; +}; +}
\ No newline at end of file diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index a94ead34..e4132957 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -5,6 +5,11 @@ #include <QtCore/QCoreApplication> #include <QtNetwork/QNetworkReply> +#include "accountregistry.h" +#include "mxcreply.h" +#include "connection.h" + +#include "room.h" using namespace Quotient; @@ -56,7 +61,58 @@ NetworkAccessManager::~NetworkAccessManager() = default; QNetworkReply* NetworkAccessManager::createRequest( Operation op, const QNetworkRequest& request, QIODevice* outgoingData) { + if(request.url().scheme() == QStringLiteral("mxc")) { + const auto fragment = request.url().fragment(); + const auto fragmentParts = fragment.split(QLatin1Char('/')); + const auto mediaId = request.url().toString(QUrl::RemoveScheme | QUrl::RemoveFragment); + if(fragmentParts.size() == 3) { + auto connection = AccountRegistry::instance().get(fragmentParts[0]); + if(!connection) { + qWarning() << "Connection not found"; + return nullptr; + } + auto room = connection->room(fragmentParts[1]); + if(!room) { + qWarning() << "Room not found"; + return nullptr; + } + QNetworkRequest r(request); + r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); + auto reply = createRequest(QNetworkAccessManager::GetOperation, r); + return new MxcReply(reply, room, fragmentParts[2]); + } else if(fragmentParts.size() == 1) { + auto connection = AccountRegistry::instance().get(fragment); + if(!connection) { + qWarning() << "Connection not found"; + return nullptr; + } + QNetworkRequest r(request); + r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); + auto reply = createRequest(QNetworkAccessManager::GetOperation, r); + return new MxcReply(reply); + } else { + qWarning() << "Invalid request"; + return nullptr; + } + } auto reply = QNetworkAccessManager::createRequest(op, request, outgoingData); reply->ignoreSslErrors(d->ignoredSslErrors); return reply; } + +QStringList NetworkAccessManager::supportedSchemesImplementation() const +{ + auto schemes = QNetworkAccessManager::supportedSchemesImplementation(); + schemes += QStringLiteral("mxc"); + return schemes; +} + +QUrl NetworkAccessManager::urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId) +{ + return QUrl(QStringLiteral("mxc:%1#%2/%3/%4").arg(mediaId, room->connection()->userId(), room->id(), eventId)); +} + +QUrl NetworkAccessManager::urlForFile(Connection *connection, const QString &mediaId) +{ + return QUrl(QStringLiteral("mxc:%1#%2").arg(mediaId, connection->userId())); +}
\ No newline at end of file diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index 47729a1b..5d262f98 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -8,6 +8,8 @@ #include <memory> namespace Quotient { +class Room; +class Connection; class NetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: @@ -21,6 +23,10 @@ public: /** Get a pointer to the singleton */ static NetworkAccessManager* instance(); +public Q_SLOTS: + QStringList supportedSchemesImplementation() const; + QUrl urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId); + QUrl urlForFile(Connection *connection, const QString &mediaId); private: QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData = Q_NULLPTR) override; |