nextcloud-desktop/src/libsync/propagateremotedeleteencrypted.cpp

130 lines
5 KiB
C++

#include "propagateremotedeleteencrypted.h"
#include "clientsideencryptionjobs.h"
#include "clientsideencryption.h"
#include "owncloudpropagator.h"
#include <QLoggingCategory>
#include <QMimeDatabase>
#include <QFileInfo>
#include <QDir>
using namespace OCC;
Q_LOGGING_CATEGORY(PROPAGATE_REMOVE_ENCRYPTED, "nextcloud.sync.propagator.remove.encrypted")
PropagateRemoteDeleteEncrypted::PropagateRemoteDeleteEncrypted(OwncloudPropagator *propagator, SyncFileItemPtr item, QObject *parent)
: QObject(parent)
, _propagator(propagator)
, _item(item)
{
}
void PropagateRemoteDeleteEncrypted::start()
{
QFileInfo info(_item->_file);
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Folder is encrypted, let's get the Id from it.";
auto job = new LsColJob(_propagator->account(), info.path(), this);
job->setProperties({"resourcetype", "http://owncloud.org/ns:fileid"});
connect(job, &LsColJob::directoryListingSubfolders, this, &PropagateRemoteDeleteEncrypted::slotFolderEncryptedIdReceived);
connect(job, &LsColJob::finishedWithError, this, &PropagateRemoteDeleteEncrypted::taskFailed);
job->start();
}
void PropagateRemoteDeleteEncrypted::slotFolderEncryptedIdReceived(const QStringList &list)
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Received id of folder, trying to lock it so we can prepare the metadata";
auto job = qobject_cast<LsColJob *>(sender());
const ExtraFolderInfo folderInfo = job->_folderInfos.value(list.first());
slotTryLock(folderInfo.fileId);
}
void PropagateRemoteDeleteEncrypted::slotTryLock(const QByteArray &folderId)
{
auto lockJob = new LockEncryptFolderApiJob(_propagator->account(), folderId, this);
connect(lockJob, &LockEncryptFolderApiJob::success, this, &PropagateRemoteDeleteEncrypted::slotFolderLockedSuccessfully);
connect(lockJob, &LockEncryptFolderApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
lockJob->start();
}
void PropagateRemoteDeleteEncrypted::slotFolderLockedSuccessfully(const QByteArray &folderId, const QByteArray &token)
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Folder id" << folderId << "Locked Successfully for Upload, Fetching Metadata";
_folderLocked = true;
_folderToken = token;
_folderId = folderId;
auto job = new GetMetadataApiJob(_propagator->account(), _folderId);
connect(job, &GetMetadataApiJob::jsonReceived, this, &PropagateRemoteDeleteEncrypted::slotFolderEncryptedMetadataReceived);
connect(job, &GetMetadataApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
job->start();
}
void PropagateRemoteDeleteEncrypted::slotFolderEncryptedMetadataReceived(const QJsonDocument &json, int statusCode)
{
if (statusCode == 404) {
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Metadata not found, ignoring.";
unlockFolder();
return;
}
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Metadata Received, Preparing it for the new file.";
// Encrypt File!
FolderMetadata metadata(_propagator->account(), json.toJson(QJsonDocument::Compact), statusCode);
QFileInfo info(_propagator->_localDir + QDir::separator() + _item->_file);
const QString fileName = info.fileName();
// Find existing metadata for this file
bool found = false;
const QVector<EncryptedFile> files = metadata.files();
for (const EncryptedFile &file : files) {
if (file.encryptedFilename == fileName) {
metadata.removeEncryptedFile(file);
found = true;
break;
}
}
if (!found) {
// The removed file was not in the JSON so nothing else to do
unlockFolder();
}
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Metadata updated, sending to the server.";
auto job = new UpdateMetadataApiJob(_propagator->account(),
_folderId,
metadata.encryptedMetadata(),
_folderToken);
connect(job, &UpdateMetadataApiJob::success, this, &PropagateRemoteDeleteEncrypted::unlockFolder);
connect(job, &UpdateMetadataApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
job->start();
}
void PropagateRemoteDeleteEncrypted::unlockFolder()
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Unlocking folder" << _folderId;
auto unlockJob = new UnlockEncryptFolderApiJob(_propagator->account(),
_folderId, _folderToken, this);
connect(unlockJob, &UnlockEncryptFolderApiJob::success, [this] {
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Folder successfully unlocked" << _folderId;
_folderLocked = false;
emit finished(true);
});
connect(unlockJob, &UnlockEncryptFolderApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
unlockJob->start();
}
void PropagateRemoteDeleteEncrypted::taskFailed()
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Task failed of job" << sender();
if (_folderLocked) {
unlockFolder();
} else {
emit finished(false);
}
}