aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--lib/mxcreply.cpp54
-rw-r--r--lib/mxcreply.h29
-rw-r--r--lib/networkaccessmanager.cpp56
-rw-r--r--lib/networkaccessmanager.h6
5 files changed, 146 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3c6e7548..178602da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -141,6 +141,7 @@ list(APPEND lib_SRCS
lib/encryptionmanager.cpp
lib/eventitem.cpp
lib/accountregistry.cpp
+ lib/mxcreply.cpp
lib/events/event.cpp
lib/events/roomevent.cpp
lib/events/stateevent.cpp
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;