mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-23 05:25:50 +03:00
Merge pull request #2139 from nextcloud/fix_e2ee_folder_sync_connection
Fix e2ee folder sync connection
This commit is contained in:
commit
56a6fe4731
10 changed files with 96 additions and 23 deletions
|
@ -1098,6 +1098,7 @@ bool SyncJournalDb::getFilesBelowPath(const QByteArray &path, const std::functio
|
|||
if (!_getFilesBelowPathQuery.initOrReset(QByteArrayLiteral(
|
||||
GET_FILE_RECORD_QUERY
|
||||
" WHERE " IS_PREFIX_PATH_OF("?1", "path")
|
||||
" OR " IS_PREFIX_PATH_OF("?1", "e2eMangledName")
|
||||
// We want to ensure that the contents of a directory are sorted
|
||||
// directly behind the directory itself. Without this ORDER BY
|
||||
// an ordering like foo, foo-2, foo/file would be returned.
|
||||
|
@ -1133,7 +1134,7 @@ bool SyncJournalDb::postSyncCleanup(const QSet<QString> &filepathsToKeep,
|
|||
}
|
||||
|
||||
SqlQuery query(_db);
|
||||
query.prepare("SELECT phash, path FROM metadata order by path");
|
||||
query.prepare("SELECT phash, path, e2eMangledName FROM metadata order by path");
|
||||
|
||||
if (!query.exec()) {
|
||||
return false;
|
||||
|
@ -1142,11 +1143,12 @@ bool SyncJournalDb::postSyncCleanup(const QSet<QString> &filepathsToKeep,
|
|||
QByteArrayList superfluousItems;
|
||||
|
||||
while (query.next()) {
|
||||
const QString file = query.baValue(1);
|
||||
bool keep = filepathsToKeep.contains(file);
|
||||
const auto file = QString(query.baValue(1));
|
||||
const auto mangledPath = QString(query.baValue(2));
|
||||
bool keep = filepathsToKeep.contains(file) || filepathsToKeep.contains(mangledPath);
|
||||
if (!keep) {
|
||||
foreach (const QString &prefix, prefixesToKeep) {
|
||||
if (file.startsWith(prefix)) {
|
||||
if (file.startsWith(prefix) || mangledPath.startsWith(prefix)) {
|
||||
keep = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -153,13 +153,17 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
|
|||
return QString(QLatin1String("<qt>") + Utility::escape(x._size < 0 ? x._name : tr("%1 (%2)").arg(x._name, Utility::octetsToString(x._size))) + QLatin1String("</qt>"));
|
||||
case Qt::CheckStateRole:
|
||||
return x._checked;
|
||||
case Qt::DecorationRole:
|
||||
if (_accountState->account()->e2e()->isFolderEncrypted(x._path)) {
|
||||
case Qt::DecorationRole: {
|
||||
Q_ASSERT(x._folder->remotePath().startsWith('/'));
|
||||
const auto rootPath = x._folder->remotePath().mid(1);
|
||||
const auto absoluteRemotePath = rootPath.isEmpty() ? x._path : rootPath + '/' + x._path;
|
||||
if (_accountState->account()->e2e()->isFolderEncrypted(absoluteRemotePath)) {
|
||||
return QIcon(QLatin1String(":/client/theme/lock-https.svg"));
|
||||
} else if (x._size > 0 && _accountState->account()->e2e()->isAnyParentFolderEncrypted(x._path)) {
|
||||
} else if (x._size > 0 && _accountState->account()->e2e()->isAnyParentFolderEncrypted(absoluteRemotePath)) {
|
||||
return QIcon(QLatin1String(":/client/theme/lock-broken.svg"));
|
||||
}
|
||||
return QFileIconProvider().icon(x._isExternal ? QFileIconProvider::Network : QFileIconProvider::Folder);
|
||||
}
|
||||
case Qt::ForegroundRole:
|
||||
if (x._isUndecided) {
|
||||
return QColor(Qt::red);
|
||||
|
|
|
@ -319,6 +319,13 @@ void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
|
|||
Utility::sortFilenames(sortedList);
|
||||
foreach (QString path, sortedList) {
|
||||
path.remove(webdavFolder);
|
||||
|
||||
// Don't allow to select subfolders of encrypted subfolders
|
||||
if (_account->capabilities().clientSideEncryptionAvailable() &&
|
||||
_account->e2e()->isAnyParentFolderEncrypted(path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList paths = path.split('/');
|
||||
if (paths.last().isEmpty())
|
||||
paths.removeLast();
|
||||
|
@ -344,6 +351,12 @@ void FolderWizardRemotePath::slotCurrentItemChanged(QTreeWidgetItem *item)
|
|||
{
|
||||
if (item) {
|
||||
QString dir = item->data(0, Qt::UserRole).toString();
|
||||
|
||||
// We don't want to allow creating subfolders in encrypted folders outside of the sync logic
|
||||
const auto encrypted = _account->capabilities().clientSideEncryptionAvailable() &&
|
||||
_account->e2e()->isFolderEncrypted(dir + '/');
|
||||
_ui.addFolderButton->setEnabled(!encrypted);
|
||||
|
||||
if (!dir.startsWith(QLatin1Char('/'))) {
|
||||
dir.prepend(QLatin1Char('/'));
|
||||
}
|
||||
|
|
|
@ -248,6 +248,13 @@ void SelectiveSyncWidget::slotUpdateDirectories(QStringList list)
|
|||
foreach (QString path, list) {
|
||||
auto size = job ? job->_folderInfos[path].size : 0;
|
||||
path.remove(pathToRemove);
|
||||
|
||||
// Don't allow to select subfolders of encrypted subfolders
|
||||
if (_account->capabilities().clientSideEncryptionAvailable() &&
|
||||
_account->e2e()->isAnyParentFolderEncrypted(_rootName + '/' + path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList paths = path.split('/');
|
||||
if (paths.last().isEmpty())
|
||||
paths.removeLast();
|
||||
|
|
|
@ -351,7 +351,8 @@ void PropagateDownloadFile::start()
|
|||
return result;
|
||||
}
|
||||
}();
|
||||
const auto remotePath = QString(rootPath + _item->_file);
|
||||
const auto remoteFilename = _item->_encryptedFileName.isEmpty() ? _item->_file : _item->_encryptedFileName;
|
||||
const auto remotePath = QString(rootPath + remoteFilename);
|
||||
const auto remoteParentPath = remotePath.left(remotePath.lastIndexOf('/'));
|
||||
|
||||
const auto account = propagator()->account();
|
||||
|
@ -359,9 +360,12 @@ void PropagateDownloadFile::start()
|
|||
!account->e2e()->isFolderEncrypted(remoteParentPath + '/')) {
|
||||
startAfterIsEncryptedIsChecked();
|
||||
} else {
|
||||
const auto slashPosition = remoteFilename.lastIndexOf('/');
|
||||
const auto relativeRemoteParentPath = slashPosition >= 0 ? remoteFilename.left(slashPosition) : QString();
|
||||
|
||||
SyncJournalFileRecord parentRec;
|
||||
propagator()->_journal->getFileRecordByE2eMangledName(remoteParentPath, &parentRec);
|
||||
const auto parentPath = parentRec.isValid() ? parentRec._path : remoteParentPath;
|
||||
propagator()->_journal->getFileRecordByE2eMangledName(relativeRemoteParentPath, &parentRec);
|
||||
const auto parentPath = parentRec.isValid() ? parentRec._path : relativeRemoteParentPath;
|
||||
|
||||
_downloadEncryptedHelper = new PropagateDownloadEncrypted(propagator(), parentPath, _item, this);
|
||||
connect(_downloadEncryptedHelper, &PropagateDownloadEncrypted::folderStatusNotEncrypted, [this] {
|
||||
|
|
|
@ -21,7 +21,19 @@ void PropagateDownloadEncrypted::start() {
|
|||
|
||||
void PropagateDownloadEncrypted::checkFolderEncryptedStatus()
|
||||
{
|
||||
auto getEncryptedStatus = new GetFolderEncryptStatusJob(_propagator->account(), _info.path());
|
||||
const auto rootPath = [=]() {
|
||||
const auto result = _propagator->_remoteFolder;
|
||||
if (result.startsWith('/')) {
|
||||
return result.mid(1);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}();
|
||||
const auto remoteFilename = _item->_encryptedFileName.isEmpty() ? _item->_file : _item->_encryptedFileName;
|
||||
const auto remotePath = QString(rootPath + remoteFilename);
|
||||
const auto remoteParentPath = remotePath.left(remotePath.lastIndexOf('/'));
|
||||
|
||||
auto getEncryptedStatus = new GetFolderEncryptStatusJob(_propagator->account(), remoteParentPath, this);
|
||||
connect(getEncryptedStatus, &GetFolderEncryptStatusJob::encryptStatusFolderReceived,
|
||||
this, &PropagateDownloadEncrypted::folderStatusReceived);
|
||||
|
||||
|
@ -89,8 +101,14 @@ void PropagateDownloadEncrypted::checkFolderEncryptedMetadata(const QJsonDocumen
|
|||
for (const EncryptedFile &file : files) {
|
||||
if (encryptedFilename == file.encryptedFilename) {
|
||||
_encryptedInfo = file;
|
||||
_item->_encryptedFileName = _item->_file;
|
||||
_item->_file = _localParentPath + QLatin1Char('/') + _encryptedInfo.originalFilename;
|
||||
if (_item->_encryptedFileName.isEmpty()) {
|
||||
_item->_encryptedFileName = _item->_file;
|
||||
}
|
||||
if (!_localParentPath.isEmpty()) {
|
||||
_item->_file = _localParentPath + QLatin1Char('/') + _encryptedInfo.originalFilename;
|
||||
} else {
|
||||
_item->_file = _encryptedInfo.originalFilename;
|
||||
}
|
||||
|
||||
qCDebug(lcPropagateDownloadEncrypted) << "Found matching encrypted metadata for file, starting download";
|
||||
emit folderStatusEncrypted();
|
||||
|
|
|
@ -111,8 +111,9 @@ void PropagateRemoteMkdir::slotMkdir()
|
|||
return result;
|
||||
}
|
||||
}();
|
||||
const auto path = QString(rootPath + _item->_file);
|
||||
const auto parentPath = path.left(path.lastIndexOf('/'));
|
||||
const auto path = _item->_file;
|
||||
const auto slashPosition = path.lastIndexOf('/');
|
||||
const auto parentPath = slashPosition >= 0 ? path.left(slashPosition) : QString();
|
||||
|
||||
SyncJournalFileRecord parentRec;
|
||||
bool ok = propagator()->_journal->getFileRecord(parentPath, &parentRec);
|
||||
|
@ -122,11 +123,12 @@ void PropagateRemoteMkdir::slotMkdir()
|
|||
}
|
||||
|
||||
const auto remoteParentPath = parentRec._e2eMangledName.isEmpty() ? parentPath : parentRec._e2eMangledName;
|
||||
const auto absoluteRemoteParentPath = remoteParentPath.isEmpty() ? rootPath : rootPath + remoteParentPath + '/';
|
||||
const auto account = propagator()->account();
|
||||
|
||||
if (!account->capabilities().clientSideEncryptionAvailable() ||
|
||||
(!account->e2e()->isFolderEncrypted(remoteParentPath + '/') &&
|
||||
!account->e2e()->isAnyParentFolderEncrypted(remoteParentPath + '/'))) {
|
||||
(!account->e2e()->isFolderEncrypted(absoluteRemoteParentPath) &&
|
||||
!account->e2e()->isAnyParentFolderEncrypted(absoluteRemoteParentPath))) {
|
||||
slotStartMkcolJob();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -179,8 +179,9 @@ void PropagateUploadFileCommon::start()
|
|||
return result;
|
||||
}
|
||||
}();
|
||||
const auto path = QString(rootPath + _item->_file);
|
||||
const auto parentPath = path.left(path.lastIndexOf('/'));
|
||||
const auto path = _item->_file;
|
||||
const auto slashPosition = path.lastIndexOf('/');
|
||||
const auto parentPath = slashPosition >= 0 ? path.left(slashPosition) : QString();
|
||||
|
||||
SyncJournalFileRecord parentRec;
|
||||
bool ok = propagator()->_journal->getFileRecord(parentPath, &parentRec);
|
||||
|
@ -190,10 +191,11 @@ void PropagateUploadFileCommon::start()
|
|||
}
|
||||
|
||||
const auto remoteParentPath = parentRec._e2eMangledName.isEmpty() ? parentPath : parentRec._e2eMangledName;
|
||||
const auto absoluteRemoteParentPath = remoteParentPath.isEmpty() ? rootPath : rootPath + remoteParentPath + '/';
|
||||
const auto account = propagator()->account();
|
||||
|
||||
if (!account->capabilities().clientSideEncryptionAvailable() ||
|
||||
!account->e2e()->isFolderEncrypted(remoteParentPath + '/')) {
|
||||
!account->e2e()->isFolderEncrypted(absoluteRemoteParentPath)) {
|
||||
setupUnencryptedFile();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,23 @@ PropagateUploadEncrypted::PropagateUploadEncrypted(OwncloudPropagator *propagato
|
|||
|
||||
void PropagateUploadEncrypted::start()
|
||||
{
|
||||
const auto rootPath = [=]() {
|
||||
const auto result = _propagator->_remoteFolder;
|
||||
if (result.startsWith('/')) {
|
||||
return result.mid(1);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}();
|
||||
const auto absoluteRemoteParentPath = [=]{
|
||||
auto path = QString(rootPath + _remoteParentPath);
|
||||
if (path.endsWith('/')) {
|
||||
path.chop(1);
|
||||
}
|
||||
return path;
|
||||
}();
|
||||
|
||||
|
||||
/* If the file is in a encrypted-enabled nextcloud instance, we need to
|
||||
* do the long road: Fetch the folder status of the encrypted bit,
|
||||
* if it's encrypted, find the ID of the folder.
|
||||
|
@ -40,7 +57,7 @@ void PropagateUploadEncrypted::start()
|
|||
* If the folder is unencrypted we just follow the old way.
|
||||
*/
|
||||
qCDebug(lcPropagateUploadEncrypted) << "Starting to send an encrypted file!";
|
||||
auto getEncryptedStatus = new GetFolderEncryptStatusJob(_propagator->account(), _remoteParentPath, this);
|
||||
auto getEncryptedStatus = new GetFolderEncryptStatusJob(_propagator->account(), absoluteRemoteParentPath, this);
|
||||
|
||||
connect(getEncryptedStatus, &GetFolderEncryptStatusJob::encryptStatusFolderReceived,
|
||||
this, &PropagateUploadEncrypted::slotFolderEncryptedStatusFetched);
|
||||
|
|
|
@ -174,9 +174,13 @@ void PropagateLocalMkdir::start()
|
|||
!account->e2e()->isFolderEncrypted(remoteParentPath + '/')) {
|
||||
startLocalMkdir();
|
||||
} else {
|
||||
const auto relativeRemotePath = _item->_file;
|
||||
const auto slashPosition = relativeRemotePath.lastIndexOf('/');
|
||||
const auto relativeRemoteParentPath = slashPosition >= 0 ? relativeRemotePath.left(slashPosition) : QString();
|
||||
|
||||
SyncJournalFileRecord parentRec;
|
||||
propagator()->_journal->getFileRecordByE2eMangledName(remoteParentPath, &parentRec);
|
||||
const auto parentPath = parentRec.isValid() ? parentRec._path : remoteParentPath;
|
||||
propagator()->_journal->getFileRecordByE2eMangledName(relativeRemoteParentPath, &parentRec);
|
||||
const auto parentPath = parentRec.isValid() ? parentRec._path : relativeRemoteParentPath;
|
||||
startDemanglingName(parentPath);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue