From 0b5e72a2c6502f22a752b72b4df5fa25746fdd25 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 26 May 2022 08:51:22 +0200 Subject: Refactor EncryptedFile and EC::FileInfo::file Besides having a misleading name (and it goes back to the spec), EncryptedFile under `file` key preempts the `url` (or `thumbnail_url`) string value so only one of the two should exist. This is a case for using std::variant<> - despite its clumsy syntax, it can actually simplify and streamline code when all the necessary bits are in place (such as conversion to JSON and getting the common piece - the URL - out of it). This commit replaces `FileInfo::url` and `FileInfo::file` with a common field `source` of type `FileSourceInfo` that is an alias for a variant type covering both underlying types; and `url()` is reintroduced as a function instead, to allow simplified access to whichever URL is available inside the variant. Oh, and EncryptedFile is EncryptedFileMetadata now, to clarify that it does not represent the file payload itself but rather the data necessary to obtain that payload. --- lib/jobs/downloadfilejob.cpp | 13 +++++++------ lib/jobs/downloadfilejob.h | 5 +++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index d00fc5f4..85c235c7 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -8,8 +8,9 @@ #include #ifdef Quotient_E2EE_ENABLED -# include -# include "events/encryptedfile.h" +# include "events/filesourceinfo.h" + +# include #endif using namespace Quotient; @@ -26,7 +27,7 @@ public: QScopedPointer tempFile; #ifdef Quotient_E2EE_ENABLED - Omittable encryptedFile; + Omittable encryptedFile; #endif }; @@ -49,7 +50,7 @@ DownloadFileJob::DownloadFileJob(const QString& serverName, #ifdef Quotient_E2EE_ENABLED DownloadFileJob::DownloadFileJob(const QString& serverName, const QString& mediaId, - const EncryptedFile& file, + const EncryptedFileMetadata& file, const QString& localFilename) : GetContentJob(serverName, mediaId) , d(localFilename.isEmpty() ? makeImpl() @@ -126,7 +127,7 @@ BaseJob::Status DownloadFileJob::prepareResult() d->tempFile->seek(0); QByteArray encrypted = d->tempFile->readAll(); - EncryptedFile file = *d->encryptedFile; + EncryptedFileMetadata file = *d->encryptedFile; const auto decrypted = file.decryptFile(encrypted); d->targetFile->write(decrypted); d->tempFile->remove(); @@ -151,7 +152,7 @@ BaseJob::Status DownloadFileJob::prepareResult() d->tempFile->seek(0); const auto encrypted = d->tempFile->readAll(); - EncryptedFile file = *d->encryptedFile; + EncryptedFileMetadata file = *d->encryptedFile; const auto decrypted = file.decryptFile(encrypted); d->tempFile->write(decrypted); } else { diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index ffa3d055..cbbfd244 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -4,7 +4,8 @@ #pragma once #include "csapi/content-repo.h" -#include "events/encryptedfile.h" + +#include "events/filesourceinfo.h" namespace Quotient { class QUOTIENT_API DownloadFileJob : public GetContentJob { @@ -16,7 +17,7 @@ public: const QString& localFilename = {}); #ifdef Quotient_E2EE_ENABLED - DownloadFileJob(const QString& serverName, const QString& mediaId, const EncryptedFile& file, const QString& localFilename = {}); + DownloadFileJob(const QString& serverName, const QString& mediaId, const EncryptedFileMetadata& file, const QString& localFilename = {}); #endif QString targetFileName() const; -- cgit v1.2.3 From c2d87291dbf8bd240e3e96138ec52aa5da22416b Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 26 May 2022 12:50:30 +0200 Subject: Move encryptFile/decryptFile out of EncryptedFileMetadata These are not operations on EncryptedFileMetadata but rather on a combination of EncryptedFileMetadata and ciphertext. If C++ had multimethods these could be bound to such a combination. --- lib/jobs/downloadfilejob.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 85c235c7..032b24f2 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -128,7 +128,7 @@ BaseJob::Status DownloadFileJob::prepareResult() QByteArray encrypted = d->tempFile->readAll(); EncryptedFileMetadata file = *d->encryptedFile; - const auto decrypted = file.decryptFile(encrypted); + const auto decrypted = decryptFile(encrypted, file); d->targetFile->write(decrypted); d->tempFile->remove(); } else { @@ -153,7 +153,7 @@ BaseJob::Status DownloadFileJob::prepareResult() const auto encrypted = d->tempFile->readAll(); EncryptedFileMetadata file = *d->encryptedFile; - const auto decrypted = file.decryptFile(encrypted); + const auto decrypted = decryptFile(encrypted, file); d->tempFile->write(decrypted); } else { #endif -- cgit v1.2.3 From 0e1f49a4ab8e6903709f387c154c2bf131a1370c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 26 May 2022 12:56:56 +0200 Subject: DownloadFileJob: refactor file decryption --- lib/jobs/downloadfilejob.cpp | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 032b24f2..99c2bf9b 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -27,7 +27,7 @@ public: QScopedPointer tempFile; #ifdef Quotient_E2EE_ENABLED - Omittable encryptedFile; + Omittable encryptedFileMetadata; #endif }; @@ -57,7 +57,7 @@ DownloadFileJob::DownloadFileJob(const QString& serverName, : makeImpl(localFilename)) { setObjectName(QStringLiteral("DownloadFileJob")); - d->encryptedFile = file; + d->encryptedFileMetadata = file; } #endif QString DownloadFileJob::targetFileName() const @@ -119,17 +119,21 @@ void DownloadFileJob::beforeAbandon() d->tempFile->remove(); } +void decryptFile(QFile& sourceFile, const EncryptedFileMetadata& metadata, + QFile& targetFile) +{ + 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->encryptedFile.has_value()) { - d->tempFile->seek(0); - QByteArray encrypted = d->tempFile->readAll(); - - EncryptedFileMetadata file = *d->encryptedFile; - const auto decrypted = decryptFile(encrypted, file); - d->targetFile->write(decrypted); + if (d->encryptedFileMetadata.has_value()) { + decryptFile(*d->tempFile, *d->encryptedFileMetadata, *d->targetFile); d->tempFile->remove(); } else { #endif @@ -148,13 +152,20 @@ BaseJob::Status DownloadFileJob::prepareResult() #endif } else { #ifdef Quotient_E2EE_ENABLED - if (d->encryptedFile.has_value()) { - d->tempFile->seek(0); - const auto encrypted = d->tempFile->readAll(); - - EncryptedFileMetadata file = *d->encryptedFile; - const auto decrypted = decryptFile(encrypted, file); - d->tempFile->write(decrypted); + 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()) { + qCWarning(JOBS) + << "Failed to remove the decrypted file placeholder"; + return { FileError, "Couldn't finalise the download" }; + } + if (!tempTempFile.rename(d->tempFile->fileName())) { + qCWarning(JOBS) << "Failed to rename" << tempTempFile.fileName() + << "to" << d->tempFile->fileName(); + return { FileError, "Couldn't finalise the download" }; + } } else { #endif d->tempFile->close(); -- cgit v1.2.3 From c2e9256b1c334bdadcc208429084cbc83496fb4b Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 26 May 2022 12:57:23 +0200 Subject: Cleanup and address Sonar warnings --- lib/jobs/downloadfilejob.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 99c2bf9b..759d52c9 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -139,11 +139,11 @@ BaseJob::Status DownloadFileJob::prepareResult() #endif d->targetFile->close(); if (!d->targetFile->remove()) { - qCWarning(JOBS) << "Failed to remove the target file placeholder"; + qWarning(JOBS) << "Failed to remove the target file placeholder"; return { FileError, "Couldn't finalise the download" }; } if (!d->tempFile->rename(d->targetFile->fileName())) { - qCWarning(JOBS) << "Failed to rename" << d->tempFile->fileName() + qWarning(JOBS) << "Failed to rename" << d->tempFile->fileName() << "to" << d->targetFile->fileName(); return { FileError, "Couldn't finalise the download" }; } @@ -157,12 +157,12 @@ BaseJob::Status DownloadFileJob::prepareResult() decryptFile(*d->tempFile, *d->encryptedFileMetadata, tempTempFile); d->tempFile->close(); if (!d->tempFile->remove()) { - qCWarning(JOBS) + qWarning(JOBS) << "Failed to remove the decrypted file placeholder"; return { FileError, "Couldn't finalise the download" }; } if (!tempTempFile.rename(d->tempFile->fileName())) { - qCWarning(JOBS) << "Failed to rename" << tempTempFile.fileName() + qWarning(JOBS) << "Failed to rename" << tempTempFile.fileName() << "to" << d->tempFile->fileName(); return { FileError, "Couldn't finalise the download" }; } @@ -173,6 +173,6 @@ BaseJob::Status DownloadFileJob::prepareResult() } #endif } - qCDebug(JOBS) << "Saved a file as" << targetFileName(); + qDebug(JOBS) << "Saved a file as" << targetFileName(); return Success; } -- cgit v1.2.3