Take care of mangled paths on download as well

This means adjusting PropagateDownloadEncrypted so that it knows where
the file will end (otherwise it would create temporary files in non
existant paths for instance).
In turn we have to adjust PropagateDownloadFile accordingly so that it
resolves the local folder the file will end up in.
And last we adjust PropagateLocalMkdir to resolve paths as well and
demangle as needed.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
This commit is contained in:
Kevin Ottens 2020-06-26 09:43:06 +02:00
parent 6dc12166ad
commit 3182c613ac
5 changed files with 77 additions and 10 deletions

View File

@ -343,8 +343,27 @@ void PropagateDownloadFile::start()
qCDebug(lcPropagateDownload) << _item->_file << propagator()->_activeJobList.count();
if (propagator()->account()->capabilities().clientSideEncryptionAvailable()) {
_downloadEncryptedHelper = new PropagateDownloadEncrypted(propagator(), _item, this);
const auto rootPath = [=]() {
const auto result = propagator()->_remoteFolder;
if (result.startsWith('/')) {
return result.mid(1);
} else {
return result;
}
}();
const auto remotePath = QString(rootPath + _item->_file);
const auto remoteParentPath = remotePath.left(remotePath.lastIndexOf('/'));
const auto account = propagator()->account();
if (!account->capabilities().clientSideEncryptionAvailable() ||
!account->e2e()->isFolderEncrypted(remoteParentPath + '/')) {
startAfterIsEncryptedIsChecked();
} else {
SyncJournalFileRecord parentRec;
propagator()->_journal->getFileRecordByE2eMangledName(remoteParentPath, &parentRec);
const auto parentPath = parentRec.isValid() ? parentRec._path : remoteParentPath;
_downloadEncryptedHelper = new PropagateDownloadEncrypted(propagator(), parentPath, _item, this);
connect(_downloadEncryptedHelper, &PropagateDownloadEncrypted::folderStatusNotEncrypted, [this] {
startAfterIsEncryptedIsChecked();
});
@ -357,8 +376,6 @@ void PropagateDownloadFile::start()
tr("File %1 can not be downloaded because encryption information is missing.").arg(QDir::toNativeSeparators(_item->_file)));
});
_downloadEncryptedHelper->start();
} else {
startAfterIsEncryptedIsChecked();
}
}
@ -503,7 +520,7 @@ void PropagateDownloadFile::startDownload()
if (_item->_directDownloadUrl.isEmpty()) {
// Normal job, download from oC instance
_job = new GETFileJob(propagator()->account(),
propagator()->_remoteFolder + _item->_file,
propagator()->_remoteFolder + (_isEncrypted ? _item->_encryptedFileName : _item->_file),
&_tmpFile, headers, expectedEtagForResume, _resumeStart, this);
} else {
// We were provided a direct URL, use that one

View File

@ -6,9 +6,10 @@ Q_LOGGING_CATEGORY(lcPropagateDownloadEncrypted, "nextcloud.sync.propagator.down
namespace OCC {
PropagateDownloadEncrypted::PropagateDownloadEncrypted(OwncloudPropagator *propagator, SyncFileItemPtr item, QObject *parent)
PropagateDownloadEncrypted::PropagateDownloadEncrypted(OwncloudPropagator *propagator, const QString &localParentPath, SyncFileItemPtr item, QObject *parent)
: QObject(parent)
, _propagator(propagator)
, _localParentPath(localParentPath)
, _item(item)
, _info(_item->_file)
{
@ -89,7 +90,7 @@ void PropagateDownloadEncrypted::checkFolderEncryptedMetadata(const QJsonDocumen
if (encryptedFilename == file.encryptedFilename) {
_encryptedInfo = file;
_item->_encryptedFileName = _item->_file;
_item->_file = _item->_file.section(QLatin1Char('/'), 0, -2) + QLatin1Char('/') + _encryptedInfo.originalFilename;
_item->_file = _localParentPath + QLatin1Char('/') + _encryptedInfo.originalFilename;
qCDebug(lcPropagateDownloadEncrypted) << "Found matching encrypted metadata for file, starting download";
emit folderStatusEncrypted();

View File

@ -15,7 +15,7 @@ namespace OCC {
class PropagateDownloadEncrypted : public QObject {
Q_OBJECT
public:
PropagateDownloadEncrypted(OwncloudPropagator *propagator, SyncFileItemPtr item, QObject *parent = nullptr);
PropagateDownloadEncrypted(OwncloudPropagator *propagator, const QString &localParentPath, SyncFileItemPtr item, QObject *parent = nullptr);
void start();
void checkFolderId(const QStringList &list);
bool decryptFile(QFile& tmpFile);
@ -37,6 +37,7 @@ signals:
private:
OwncloudPropagator *_propagator;
QString _localParentPath;
SyncFileItemPtr _item;
QFileInfo _info;
EncryptedFile _encryptedInfo;

View File

@ -13,6 +13,8 @@
* for more details.
*/
#include "account.h"
#include "propagatedownloadencrypted.h"
#include "propagatorjobs.h"
#include "owncloudpropagator.h"
#include "owncloudpropagator_p.h"
@ -156,6 +158,36 @@ void PropagateLocalMkdir::start()
if (propagator()->_abortRequested.fetchAndAddRelaxed(0))
return;
const auto rootPath = [=]() {
const auto result = propagator()->_remoteFolder;
if (result.startsWith('/')) {
return result.mid(1);
} else {
return result;
}
}();
const auto remotePath = QString(rootPath + _item->_file);
const auto remoteParentPath = remotePath.left(remotePath.lastIndexOf('/'));
const auto account = propagator()->account();
if (!account->capabilities().clientSideEncryptionAvailable() ||
!account->e2e()->isFolderEncrypted(remoteParentPath + '/')) {
startLocalMkdir();
} else {
SyncJournalFileRecord parentRec;
propagator()->_journal->getFileRecordByE2eMangledName(remoteParentPath, &parentRec);
const auto parentPath = parentRec.isValid() ? parentRec._path : remoteParentPath;
startDemanglingName(parentPath);
}
}
void PropagateLocalMkdir::setDeleteExistingFile(bool enabled)
{
_deleteExistingFile = enabled;
}
void PropagateLocalMkdir::startLocalMkdir()
{
QDir newDir(propagator()->getFilePath(_item->_file));
QString newDirStr = QDir::toNativeSeparators(newDir.path());
@ -211,9 +243,22 @@ void PropagateLocalMkdir::start()
done(resultStatus);
}
void PropagateLocalMkdir::setDeleteExistingFile(bool enabled)
void PropagateLocalMkdir::startDemanglingName(const QString &parentPath)
{
_deleteExistingFile = enabled;
auto downloadEncryptedHelper = new PropagateDownloadEncrypted(propagator(), parentPath, _item, this);
connect(downloadEncryptedHelper, &PropagateDownloadEncrypted::folderStatusEncrypted,
this, &PropagateLocalMkdir::startLocalMkdir);
connect(downloadEncryptedHelper, &PropagateDownloadEncrypted::folderStatusNotEncrypted, this, [this] {
// We were wrong after all? Actually might happen due to legacy clients creating broken encrypted folders
qCDebug(lcPropagateLocalMkdir) << "Parent of" << _item->_file << "wasn't encrypted, creating with the original name";
startLocalMkdir();
});
connect(downloadEncryptedHelper, &PropagateDownloadEncrypted::failed, [this] {
// This also might happen due to legacy clients creating broken encrypted folders...
qCDebug(lcPropagateLocalMkdir) << "Directory" << _item->_file << "doesn't exist in its parent metadata, creating with the original name";
startLocalMkdir();
});
downloadEncryptedHelper->start();
}
void PropagateLocalRename::start()

View File

@ -71,6 +71,9 @@ public:
void setDeleteExistingFile(bool enabled);
private:
void startLocalMkdir();
void startDemanglingName(const QString &parentPath);
bool _deleteExistingFile;
};