1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2025-05-12 23:34:11 +02:00

Properly remove encryption data from JSON of deleted file

This commit is contained in:
Daniel Nicoletti 2018-04-03 19:41:11 -03:00 committed by Tomaz Canabrava
parent a9208f6581
commit b12066f1aa
9 changed files with 200 additions and 8 deletions

View File

@ -43,6 +43,7 @@ set(libsync_SRCS
propagateuploadv1.cpp
propagateuploadng.cpp
propagateremotedelete.cpp
propagateremotedeleteencrypted.cpp
propagateremotemove.cpp
propagateremotemkdir.cpp
propagateuploadencrypted.cpp

View File

@ -1334,6 +1334,16 @@ void FolderMetadata::addEncryptedFile(const EncryptedFile &f) {
_files.append(f);
}
void FolderMetadata::removeEncryptedFile(const EncryptedFile &f)
{
for (int i = 0; i < _files.size(); i++) {
if (_files.at(i).originalFilename == f.originalFilename) {
_files.removeAt(i);
break;
}
}
}
QVector<EncryptedFile> FolderMetadata::files() const {
return _files;
}

View File

@ -142,6 +142,7 @@ public:
FolderMetadata(AccountPtr account, const QByteArray& metadata = QByteArray(), int statusCode = -1);
QByteArray encryptedMetadata();
void addEncryptedFile(const EncryptedFile& f);
void removeEncryptedFile(const EncryptedFile& f);
QVector<EncryptedFile> files() const;

View File

@ -81,7 +81,7 @@ void PropagateDownloadEncrypted::checkFolderEncryptedMetadata(const QJsonDocumen
for (const EncryptedFile &file : files) {
qCDebug(lcPropagateDownloadEncrypted) << "file" << filename << file.encryptedFilename << file.originalFilename << file.encryptionKey;
if (filename == file.originalFilename) {
if (filename == file.encryptedFilename) {
_encryptedInfo = file;
qCDebug(lcPropagateDownloadEncrypted) << "Found matching encrypted metadata for file, starting download";
emit folderStatusEncrypted();

View File

@ -13,6 +13,7 @@
*/
#include "propagateremotedelete.h"
#include "propagateremotedeleteencrypted.h"
#include "owncloudpropagator_p.h"
#include "account.h"
#include "common/asserts.h"
@ -65,18 +66,25 @@ void PropagateRemoteDelete::start()
if (propagator()->_abortRequested.fetchAndAddRelaxed(0))
return;
QString remoteFile = _item->_file;
if (!_item->_encryptedFileName.isEmpty()) {
remoteFile = _item->_encryptedFileName;
// TODO update the JSON metadata
auto job = new PropagateRemoteDeleteEncrypted(propagator(), _item, this);
connect(job, &PropagateRemoteDeleteEncrypted::finished, this, [this] (bool success) {
Q_UNUSED(success) // Should we skip file deletion in case of failure?
createDeleteJob(_item->_encryptedFileName);
});
job->start();
} else {
createDeleteJob(_item->_file);
}
}
qCDebug(lcPropagateRemoteDelete) << "local" << _item->_file << "remote" << remoteFile;
void PropagateRemoteDelete::createDeleteJob(const QString &filename)
{
qCInfo(lcPropagateRemoteDelete) << "Deleting file, local" << _item->_file << "remote" << filename;
_job = new DeleteJob(propagator()->account(),
propagator()->_remoteFolder + remoteFile,
this);
propagator()->_remoteFolder + filename,
this);
connect(_job.data(), &DeleteJob::finishedSignal, this, &PropagateRemoteDelete::slotDeleteJobFinished);
propagator()->_activeJobList.append(this);
_job->start();

View File

@ -52,6 +52,7 @@ public:
{
}
void start() Q_DECL_OVERRIDE;
void createDeleteJob(const QString &filename);
void abort(PropagatorJob::AbortType abortType) Q_DECL_OVERRIDE;
bool isLikelyFinishedQuickly() Q_DECL_OVERRIDE { return !_item->isDirectory(); }

View File

@ -0,0 +1,130 @@
#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);
}
}

View File

@ -0,0 +1,40 @@
#ifndef PROPAGATEREMOTEDELETEENCRYPTED_H
#define PROPAGATEREMOTEDELETEENCRYPTED_H
#include <QObject>
#include <QElapsedTimer>
#include "syncfileitem.h"
namespace OCC {
class OwncloudPropagator;
class PropagateRemoteDeleteEncrypted : public QObject
{
Q_OBJECT
public:
PropagateRemoteDeleteEncrypted(OwncloudPropagator *_propagator, SyncFileItemPtr item, QObject *parent);
void start();
signals:
void finished(bool success);
private:
void slotFolderEncryptedIdReceived(const QStringList &list);
void slotTryLock(const QByteArray &folderId);
void slotFolderLockedSuccessfully(const QByteArray &fileId, const QByteArray &token);
void slotFolderEncryptedMetadataReceived(const QJsonDocument &json, int statusCode);
void unlockFolder();
void taskFailed();
OwncloudPropagator *_propagator;
SyncFileItemPtr _item;
QByteArray _folderToken;
QByteArray _folderId;
bool _folderLocked = false;
};
}
#endif // PROPAGATEREMOTEDELETEENCRYPTED_H

View File

@ -424,6 +424,7 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other,
item->_file = fileUtf8;
}
item->_originalFile = item->_file;
item->_encryptedFileName = file->e2eMangledName;
if (item->_instruction == CSYNC_INSTRUCTION_NONE
|| (item->_instruction == CSYNC_INSTRUCTION_IGNORE && instruction != CSYNC_INSTRUCTION_NONE)) {