aboutsummaryrefslogtreecommitdiff
path: root/lib/jobs/downloadfilejob.cpp
diff options
context:
space:
mode:
authorn-peugnet <n.peugnet@free.fr>2022-10-06 19:27:24 +0200
committern-peugnet <n.peugnet@free.fr>2022-10-06 19:27:24 +0200
commitd911b207f49e936b3e992200796110f0749ed150 (patch)
tree96d20ebb4d074a4c1755e21cb316a52d584daee3 /lib/jobs/downloadfilejob.cpp
parent8ad8a74152c5701b6ca1f9a00487ba9257a439b4 (diff)
parent56c2f2e2b809b9077393eb617828f33d144f5634 (diff)
downloadlibquotient-d911b207f49e936b3e992200796110f0749ed150.tar.gz
libquotient-d911b207f49e936b3e992200796110f0749ed150.zip
New upstream version 0.7.0
Diffstat (limited to 'lib/jobs/downloadfilejob.cpp')
-rw-r--r--lib/jobs/downloadfilejob.cpp158
1 files changed, 107 insertions, 51 deletions
diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp
index 2bf9dd8f..759d52c9 100644
--- a/lib/jobs/downloadfilejob.cpp
+++ b/lib/jobs/downloadfilejob.cpp
@@ -1,56 +1,80 @@
+// SPDX-FileCopyrightText: 2018 Kitsune Ral <Kitsune-Ral@users.sf.net>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
#include "downloadfilejob.h"
-#include <QtNetwork/QNetworkReply>
#include <QtCore/QFile>
#include <QtCore/QTemporaryFile>
+#include <QtNetwork/QNetworkReply>
-using namespace QMatrixClient;
+#ifdef Quotient_E2EE_ENABLED
+# include "events/filesourceinfo.h"
-class DownloadFileJob::Private
-{
- public:
- Private() : tempFile(new QTemporaryFile()) { }
+# include <QtCore/QCryptographicHash>
+#endif
- explicit Private(const QString& localFilename)
- : targetFile(new QFile(localFilename))
- , tempFile(new QFile(targetFile->fileName() + ".qmcdownload"))
- { }
+using namespace Quotient;
+class DownloadFileJob::Private {
+public:
+ Private() : tempFile(new QTemporaryFile()) {}
- QScopedPointer<QFile> targetFile;
- QScopedPointer<QFile> tempFile;
+ explicit Private(const QString& localFilename)
+ : targetFile(new QFile(localFilename))
+ , tempFile(new QFile(targetFile->fileName() + ".qtntdownload"))
+ {}
+
+ QScopedPointer<QFile> targetFile;
+ QScopedPointer<QFile> tempFile;
+
+#ifdef Quotient_E2EE_ENABLED
+ Omittable<EncryptedFileMetadata> encryptedFileMetadata;
+#endif
};
QUrl DownloadFileJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri)
{
- return makeRequestUrl(baseUrl, mxcUri.authority(), mxcUri.path().mid(1));
+ return makeRequestUrl(std::move(baseUrl), mxcUri.authority(),
+ mxcUri.path().mid(1));
}
DownloadFileJob::DownloadFileJob(const QString& serverName,
const QString& mediaId,
const QString& localFilename)
: GetContentJob(serverName, mediaId)
- , d(localFilename.isEmpty() ? new Private : new Private(localFilename))
+ , d(localFilename.isEmpty() ? makeImpl<Private>()
+ : makeImpl<Private>(localFilename))
{
- setObjectName("DownloadFileJob");
+ setObjectName(QStringLiteral("DownloadFileJob"));
}
+#ifdef Quotient_E2EE_ENABLED
+DownloadFileJob::DownloadFileJob(const QString& serverName,
+ const QString& mediaId,
+ const EncryptedFileMetadata& file,
+ const QString& localFilename)
+ : GetContentJob(serverName, mediaId)
+ , d(localFilename.isEmpty() ? makeImpl<Private>()
+ : makeImpl<Private>(localFilename))
+{
+ setObjectName(QStringLiteral("DownloadFileJob"));
+ d->encryptedFileMetadata = file;
+}
+#endif
QString DownloadFileJob::targetFileName() const
{
return (d->targetFile ? d->targetFile : d->tempFile)->fileName();
}
-void DownloadFileJob::beforeStart(const ConnectionData*)
+void DownloadFileJob::doPrepare()
{
- if (d->targetFile && !d->targetFile->isReadable() &&
- !d->targetFile->open(QIODevice::WriteOnly))
- {
- qCWarning(JOBS) << "Couldn't open the file"
- << d->targetFile->fileName() << "for writing";
+ if (d->targetFile && !d->targetFile->isReadable()
+ && !d->targetFile->open(QIODevice::WriteOnly)) {
+ qCWarning(JOBS) << "Couldn't open the file" << d->targetFile->fileName()
+ << "for writing";
setStatus(FileError, "Could not open the target file for writing");
return;
}
- if (!d->tempFile->isReadable() && !d->tempFile->open(QIODevice::WriteOnly))
- {
+ if (!d->tempFile->isReadable() && !d->tempFile->open(QIODevice::ReadWrite)) {
qCWarning(JOBS) << "Couldn't open the temporary file"
<< d->tempFile->fileName() << "for writing";
setStatus(FileError, "Could not open the temporary download file");
@@ -59,18 +83,16 @@ void DownloadFileJob::beforeStart(const ConnectionData*)
qCDebug(JOBS) << "Downloading to" << d->tempFile->fileName();
}
-void DownloadFileJob::afterStart(const ConnectionData*, QNetworkReply* reply)
+void DownloadFileJob::onSentRequest(QNetworkReply* reply)
{
- connect(reply, &QNetworkReply::metaDataChanged, this, [this,reply] {
+ connect(reply, &QNetworkReply::metaDataChanged, this, [this, reply] {
if (!status().good())
return;
auto sizeHeader = reply->header(QNetworkRequest::ContentLengthHeader);
- if (sizeHeader.isValid())
- {
- auto targetSize = sizeHeader.value<qint64>();
+ if (sizeHeader.isValid()) {
+ auto targetSize = sizeHeader.toLongLong();
if (targetSize != -1)
- if (!d->tempFile->resize(targetSize))
- {
+ if (!d->tempFile->resize(targetSize)) {
qCWarning(JOBS) << "Failed to allocate" << targetSize
<< "bytes for" << d->tempFile->fileName();
setStatus(FileError,
@@ -78,45 +100,79 @@ void DownloadFileJob::afterStart(const ConnectionData*, QNetworkReply* reply)
}
}
});
- connect(reply, &QIODevice::readyRead, this, [this,reply] {
+ connect(reply, &QIODevice::readyRead, this, [this, reply] {
if (!status().good())
return;
auto bytes = reply->read(reply->bytesAvailable());
if (!bytes.isEmpty())
d->tempFile->write(bytes);
else
- qCWarning(JOBS)
- << "Unexpected empty chunk when downloading from"
- << reply->url() << "to" << d->tempFile->fileName();
+ qCWarning(JOBS) << "Unexpected empty chunk when downloading from"
+ << reply->url() << "to" << d->tempFile->fileName();
});
}
-void DownloadFileJob::beforeAbandon(QNetworkReply*)
+void DownloadFileJob::beforeAbandon()
{
if (d->targetFile)
d->targetFile->remove();
d->tempFile->remove();
}
-BaseJob::Status DownloadFileJob::parseReply(QNetworkReply*)
+void decryptFile(QFile& sourceFile, const EncryptedFileMetadata& metadata,
+ QFile& targetFile)
{
- if (d->targetFile)
- {
- d->targetFile->close();
- if (!d->targetFile->remove())
- {
- qCWarning(JOBS) << "Failed to remove the target file placeholder";
- return { FileError, "Couldn't finalise the download" };
+ sourceFile.seek(0);
+ const auto encrypted = sourceFile.readAll(); // TODO: stream decryption
+ const auto decrypted = decryptFile(encrypted, metadata);
+ targetFile.write(decrypted);
+}
+
+BaseJob::Status DownloadFileJob::prepareResult()
+{
+ if (d->targetFile) {
+#ifdef Quotient_E2EE_ENABLED
+ if (d->encryptedFileMetadata.has_value()) {
+ decryptFile(*d->tempFile, *d->encryptedFileMetadata, *d->targetFile);
+ d->tempFile->remove();
+ } else {
+#endif
+ d->targetFile->close();
+ if (!d->targetFile->remove()) {
+ qWarning(JOBS) << "Failed to remove the target file placeholder";
+ return { FileError, "Couldn't finalise the download" };
+ }
+ if (!d->tempFile->rename(d->targetFile->fileName())) {
+ qWarning(JOBS) << "Failed to rename" << d->tempFile->fileName()
+ << "to" << d->targetFile->fileName();
+ return { FileError, "Couldn't finalise the download" };
+ }
+#ifdef Quotient_E2EE_ENABLED
}
- if (!d->tempFile->rename(d->targetFile->fileName()))
- {
- qCWarning(JOBS) << "Failed to rename" << d->tempFile->fileName()
- << "to" << d->targetFile->fileName();
- return { FileError, "Couldn't finalise the download" };
+#endif
+ } else {
+#ifdef Quotient_E2EE_ENABLED
+ if (d->encryptedFileMetadata.has_value()) {
+ QTemporaryFile tempTempFile; // Assuming it to be next to tempFile
+ decryptFile(*d->tempFile, *d->encryptedFileMetadata, tempTempFile);
+ d->tempFile->close();
+ if (!d->tempFile->remove()) {
+ qWarning(JOBS)
+ << "Failed to remove the decrypted file placeholder";
+ return { FileError, "Couldn't finalise the download" };
+ }
+ if (!tempTempFile.rename(d->tempFile->fileName())) {
+ qWarning(JOBS) << "Failed to rename" << tempTempFile.fileName()
+ << "to" << d->tempFile->fileName();
+ return { FileError, "Couldn't finalise the download" };
+ }
+ } else {
+#endif
+ d->tempFile->close();
+#ifdef Quotient_E2EE_ENABLED
}
+#endif
}
- else
- d->tempFile->close();
- qCDebug(JOBS) << "Saved a file as" << targetFileName();
+ qDebug(JOBS) << "Saved a file as" << targetFileName();
return Success;
}