2021-03-05 02:35:15 +03:00
|
|
|
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2019-09-07 23:22:07 +03:00
|
|
|
#include "MxcImageProvider.h"
|
|
|
|
|
2021-03-17 05:27:28 +03:00
|
|
|
#include <optional>
|
|
|
|
|
2020-10-27 19:45:28 +03:00
|
|
|
#include <mtxclient/crypto/client.hpp>
|
|
|
|
|
2021-03-17 05:27:28 +03:00
|
|
|
#include <QByteArray>
|
2021-03-17 21:08:17 +03:00
|
|
|
#include <QDir>
|
2021-03-17 05:27:28 +03:00
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QStandardPaths>
|
|
|
|
|
2019-12-15 04:56:04 +03:00
|
|
|
#include "Logging.h"
|
2019-12-15 05:34:17 +03:00
|
|
|
#include "MatrixClient.h"
|
2020-04-26 12:26:51 +03:00
|
|
|
#include "Utils.h"
|
2019-09-07 23:22:07 +03:00
|
|
|
|
2021-03-17 05:27:28 +03:00
|
|
|
QHash<QString, mtx::crypto::EncryptedFile> infos;
|
|
|
|
|
|
|
|
QQuickImageResponse *
|
|
|
|
MxcImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
|
|
|
|
{
|
|
|
|
MxcImageResponse *response = new MxcImageResponse(id, requestedSize);
|
|
|
|
pool.start(response);
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MxcImageProvider::addEncryptionInfo(mtx::crypto::EncryptedFile info)
|
|
|
|
{
|
|
|
|
infos.insert(QString::fromStdString(info.url), info);
|
|
|
|
}
|
2019-09-07 23:22:07 +03:00
|
|
|
void
|
|
|
|
MxcImageResponse::run()
|
|
|
|
{
|
2021-03-17 05:27:28 +03:00
|
|
|
MxcImageProvider::download(
|
|
|
|
m_id, m_requestedSize, [this](QString, QSize, QImage image, QString) {
|
|
|
|
if (image.isNull()) {
|
|
|
|
m_error = "Failed to download image.";
|
|
|
|
} else {
|
|
|
|
m_image = image;
|
|
|
|
}
|
|
|
|
emit finished();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MxcImageProvider::download(const QString &id,
|
|
|
|
const QSize &requestedSize,
|
|
|
|
std::function<void(QString, QSize, QImage, QString)> then)
|
|
|
|
{
|
|
|
|
std::optional<mtx::crypto::EncryptedFile> encryptionInfo;
|
|
|
|
auto temp = infos.find("mxc://" + id);
|
|
|
|
if (temp != infos.end())
|
|
|
|
encryptionInfo = *temp;
|
|
|
|
|
|
|
|
if (requestedSize.isValid() && !encryptionInfo) {
|
|
|
|
QString fileName =
|
|
|
|
QString("%1_%2x%3_crop")
|
|
|
|
.arg(QString::fromUtf8(id.toUtf8().toBase64(QByteArray::Base64UrlEncoding |
|
2021-03-17 21:08:17 +03:00
|
|
|
QByteArray::OmitTrailingEquals)))
|
|
|
|
.arg(requestedSize.width())
|
|
|
|
.arg(requestedSize.height());
|
2021-03-17 05:27:28 +03:00
|
|
|
QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
|
|
|
|
"/media_cache",
|
|
|
|
fileName);
|
2021-03-17 21:08:17 +03:00
|
|
|
QDir().mkpath(fileInfo.absolutePath());
|
2021-03-17 05:27:28 +03:00
|
|
|
|
|
|
|
if (fileInfo.exists()) {
|
|
|
|
QImage image(fileInfo.absoluteFilePath());
|
|
|
|
if (!image.isNull()) {
|
|
|
|
image = image.scaled(
|
|
|
|
requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
|
|
|
|
|
|
if (!image.isNull()) {
|
|
|
|
then(id, requestedSize, image, fileInfo.absoluteFilePath());
|
2020-09-07 19:02:17 +03:00
|
|
|
return;
|
|
|
|
}
|
2020-04-26 12:26:51 +03:00
|
|
|
}
|
2019-09-07 23:22:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mtx::http::ThumbOpts opts;
|
2021-03-17 05:27:28 +03:00
|
|
|
opts.mxc_url = "mxc://" + id.toStdString();
|
|
|
|
opts.width = requestedSize.width() > 0 ? requestedSize.width() : -1;
|
|
|
|
opts.height = requestedSize.height() > 0 ? requestedSize.height() : -1;
|
2019-11-03 03:17:40 +03:00
|
|
|
opts.method = "crop";
|
2019-09-07 23:22:07 +03:00
|
|
|
http::client()->get_thumbnail(
|
2021-03-17 05:27:28 +03:00
|
|
|
opts,
|
|
|
|
[fileInfo, requestedSize, then, id](const std::string &res,
|
|
|
|
mtx::http::RequestErr err) {
|
2020-09-07 19:02:17 +03:00
|
|
|
if (err || res.empty()) {
|
2021-03-17 05:27:28 +03:00
|
|
|
then(id, QSize(), {}, "");
|
2019-09-07 23:22:07 +03:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-17 05:27:28 +03:00
|
|
|
auto data = QByteArray(res.data(), (int)res.size());
|
|
|
|
QImage image = utils::readImage(data);
|
|
|
|
if (!image.isNull()) {
|
|
|
|
image = image.scaled(
|
|
|
|
requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
2020-09-07 19:02:17 +03:00
|
|
|
}
|
2021-03-17 05:27:28 +03:00
|
|
|
image.setText("mxc url", "mxc://" + id);
|
2021-03-17 21:08:17 +03:00
|
|
|
if (image.save(fileInfo.absoluteFilePath(), "png"))
|
|
|
|
nhlog::ui()->debug("Wrote: {}",
|
|
|
|
fileInfo.absoluteFilePath().toStdString());
|
|
|
|
else
|
|
|
|
nhlog::ui()->debug("Failed to write: {}",
|
|
|
|
fileInfo.absoluteFilePath().toStdString());
|
2019-09-07 23:22:07 +03:00
|
|
|
|
2021-03-17 05:27:28 +03:00
|
|
|
then(id, requestedSize, image, fileInfo.absoluteFilePath());
|
2019-09-07 23:22:07 +03:00
|
|
|
});
|
|
|
|
} else {
|
2021-03-17 05:27:28 +03:00
|
|
|
try {
|
|
|
|
QString fileName = QString::fromUtf8(id.toUtf8().toBase64(
|
|
|
|
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals));
|
|
|
|
QFileInfo fileInfo(
|
|
|
|
QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
|
|
|
|
"/media_cache",
|
|
|
|
fileName);
|
2021-03-17 21:08:17 +03:00
|
|
|
QDir().mkpath(fileInfo.absolutePath());
|
2021-03-17 05:27:28 +03:00
|
|
|
|
|
|
|
if (fileInfo.exists()) {
|
|
|
|
if (encryptionInfo) {
|
|
|
|
QFile f(fileInfo.absoluteFilePath());
|
|
|
|
f.open(QIODevice::ReadOnly);
|
|
|
|
|
|
|
|
QByteArray fileData = f.readAll();
|
2021-03-17 22:32:12 +03:00
|
|
|
auto tempData =
|
2021-03-17 05:27:28 +03:00
|
|
|
mtx::crypto::to_string(mtx::crypto::decrypt_file(
|
|
|
|
fileData.toStdString(), encryptionInfo.value()));
|
2021-03-17 22:32:12 +03:00
|
|
|
auto data =
|
|
|
|
QByteArray(tempData.data(), (int)tempData.size());
|
2021-03-17 05:27:28 +03:00
|
|
|
QImage image = utils::readImage(data);
|
|
|
|
image.setText("mxc url", "mxc://" + id);
|
|
|
|
if (!image.isNull()) {
|
|
|
|
then(id,
|
|
|
|
requestedSize,
|
|
|
|
image,
|
|
|
|
fileInfo.absoluteFilePath());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
QImage image(fileInfo.absoluteFilePath());
|
|
|
|
if (!image.isNull()) {
|
|
|
|
then(id,
|
|
|
|
requestedSize,
|
|
|
|
image,
|
|
|
|
fileInfo.absoluteFilePath());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-04-26 12:26:51 +03:00
|
|
|
}
|
2021-03-17 05:27:28 +03:00
|
|
|
|
|
|
|
http::client()->download(
|
|
|
|
"mxc://" + id.toStdString(),
|
|
|
|
[fileInfo, requestedSize, then, id, encryptionInfo](
|
|
|
|
const std::string &res,
|
|
|
|
const std::string &,
|
|
|
|
const std::string &originalFilename,
|
|
|
|
mtx::http::RequestErr err) {
|
|
|
|
if (err) {
|
|
|
|
then(id, QSize(), {}, "");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:32:12 +03:00
|
|
|
auto tempData = res;
|
2021-03-17 05:27:28 +03:00
|
|
|
QFile f(fileInfo.absoluteFilePath());
|
|
|
|
if (!f.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
|
|
|
|
then(id, QSize(), {}, "");
|
|
|
|
return;
|
|
|
|
}
|
2021-03-17 22:32:12 +03:00
|
|
|
f.write(tempData.data(), tempData.size());
|
2021-03-17 05:27:28 +03:00
|
|
|
f.close();
|
|
|
|
|
|
|
|
if (encryptionInfo) {
|
2021-03-17 22:32:12 +03:00
|
|
|
tempData =
|
|
|
|
mtx::crypto::to_string(mtx::crypto::decrypt_file(
|
|
|
|
tempData, encryptionInfo.value()));
|
|
|
|
auto data =
|
|
|
|
QByteArray(tempData.data(), (int)tempData.size());
|
2021-03-17 05:27:28 +03:00
|
|
|
QImage image = utils::readImage(data);
|
|
|
|
image.setText("original filename",
|
|
|
|
QString::fromStdString(originalFilename));
|
|
|
|
image.setText("mxc url", "mxc://" + id);
|
|
|
|
then(
|
|
|
|
id, requestedSize, image, fileInfo.absoluteFilePath());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QImage image(fileInfo.absoluteFilePath());
|
|
|
|
image.setText("original filename",
|
|
|
|
QString::fromStdString(originalFilename));
|
|
|
|
image.setText("mxc url", "mxc://" + id);
|
|
|
|
image.save(fileInfo.absoluteFilePath());
|
|
|
|
then(id, requestedSize, image, fileInfo.absoluteFilePath());
|
|
|
|
});
|
|
|
|
} catch (std::exception &e) {
|
|
|
|
nhlog::net()->error("Exception while downloading media: {}", e.what());
|
2019-09-07 23:22:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|