From 47132d3bebd1781c7e76efe7c9cebc6a905ae6f2 Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Mon, 13 Sep 2021 15:01:34 +0200 Subject: [PATCH] Fix crash on missing sync root Fixes: #9016 --- src/common/vfs.cpp | 6 ++-- src/common/vfs.h | 2 +- src/gui/accountsettings.cpp | 5 +-- src/gui/folder.cpp | 37 +++++++++++++------- src/gui/folder.h | 2 +- src/gui/folderman.cpp | 5 +++ src/gui/folderman.h | 3 ++ src/gui/folderwizard.cpp | 5 +-- src/gui/wizard/owncloudadvancedsetuppage.cpp | 2 +- src/libsync/syncengine.cpp | 2 +- 10 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/common/vfs.cpp b/src/common/vfs.cpp index 84df80c76..69e51be50 100644 --- a/src/common/vfs.cpp +++ b/src/common/vfs.cpp @@ -24,6 +24,7 @@ #include "common/filesystembase.h" +#include #include #include @@ -65,9 +66,8 @@ Optional Vfs::modeFromString(const QString &str) return {}; } -Result Vfs::checkAvailability(const QString &path) +Result Vfs::checkAvailability(const QString &path, Vfs::Mode mode) { - const auto mode = bestAvailableVfsMode(); #ifdef Q_OS_WIN if (mode == Mode::WindowsCfApi) { const auto info = QFileInfo(path); @@ -87,7 +87,7 @@ Result Vfs::checkAvailability(const QString &path) Q_UNUSED(mode) Q_UNUSED(path) #endif - return true; + return {}; } void Vfs::start(const VfsSetupParams ¶ms) diff --git a/src/common/vfs.h b/src/common/vfs.h index b3c5df9d0..1e925ccdc 100644 --- a/src/common/vfs.h +++ b/src/common/vfs.h @@ -125,7 +125,7 @@ public: static QString modeToString(Mode mode); static Optional modeFromString(const QString &str); - static Result checkAvailability(const QString &path); + static Result checkAvailability(const QString &path, OCC::Vfs::Mode mode); enum class AvailabilityError { diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 986ca7f87..bc5bda41d 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -710,8 +710,9 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos) ac->setDisabled(Theme::instance()->enforceVirtualFilesSyncFolder()); } - if (Theme::instance()->showVirtualFilesOption() && !folder->virtualFilesEnabled() && Vfs::checkAvailability(folder->path())) { - const auto mode = bestAvailableVfsMode(); + if (const auto mode = bestAvailableVfsMode(); + Theme::instance()->showVirtualFilesOption() + && !folder->virtualFilesEnabled() && Vfs::checkAvailability(folder->path(), mode)) { if (mode == Vfs::WindowsCfApi || ConfigFile().showExperimentalOptions()) { ac = menu->addAction(tr("Enable virtual file support %1 …").arg(mode == Vfs::WindowsCfApi ? QString() : tr("(experimental)"))); // TODO: remove when UX decision is made diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 8b8bb0c16..6b7f2ad45 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -81,7 +81,7 @@ Folder::Folder(const FolderDefinition &definition, _syncResult.setStatus(status); // check if the local path exists - checkLocalPath(); + const auto folderOk = checkLocalPath(); _syncResult.setFolder(_definition.alias); @@ -155,8 +155,10 @@ Folder::Folder(const FolderDefinition &definition, saveToSettings(); } - // Initialize the vfs plugin - startVfs(); + if (folderOk) { + // Initialize the vfs plugin + startVfs(); + } } Folder::~Folder() @@ -169,7 +171,7 @@ Folder::~Folder() _engine.reset(); } -void Folder::checkLocalPath() +bool Folder::checkLocalPath() { const QFileInfo fi(_definition.localPath); _canonicalLocalPath = fi.canonicalFilePath(); @@ -187,18 +189,22 @@ void Folder::checkLocalPath() if (FileSystem::isDir(_definition.localPath) && FileSystem::isReadable(_definition.localPath)) { qCDebug(lcFolder) << "Checked local path ok"; } else { + QString error; // Check directory again if (!FileSystem::fileExists(_definition.localPath, fi)) { - _syncResult.appendErrorString(tr("Local folder %1 does not exist.").arg(_definition.localPath)); - _syncResult.setStatus(SyncResult::SetupError); - } else if (!FileSystem::isDir(_definition.localPath)) { - _syncResult.appendErrorString(tr("%1 should be a folder but is not.").arg(_definition.localPath)); - _syncResult.setStatus(SyncResult::SetupError); - } else if (!FileSystem::isReadable(_definition.localPath)) { - _syncResult.appendErrorString(tr("%1 is not readable.").arg(_definition.localPath)); + error = tr("Local folder %1 does not exist.").arg(_definition.localPath); + } else if (!fi.isDir()) { + error = tr("%1 should be a folder but is not.").arg(_definition.localPath); + } else if (!fi.isReadable()) { + error = tr("%1 is not readable.").arg(_definition.localPath); + } + if (!error.isEmpty()) { + _syncResult.appendErrorString(error); _syncResult.setStatus(SyncResult::SetupError); + return false; } } + return true; } QString Folder::shortGuiRemotePathOrAppName() const @@ -297,7 +303,7 @@ bool Folder::syncPaused() const bool Folder::canSync() const { - return !syncPaused() && accountState()->isConnected(); + return !syncPaused() && accountState()->isConnected() && _syncResult.status() != SyncResult::SetupError; } void Folder::setSyncPaused(bool paused) @@ -507,6 +513,13 @@ void Folder::startVfs() ENFORCE(_vfs); ENFORCE(_vfs->mode() == _definition.virtualFilesMode); + const auto result = Vfs::checkAvailability(path(), _vfs->mode()); + if (!result) { + _syncResult.appendErrorString(result.error()); + _syncResult.setStatus(SyncResult::SetupError); + return; + } + VfsSetupParams vfsParams; vfsParams.filesystemPath = path(); vfsParams.displayName = shortGuiRemotePathOrAppName(); diff --git a/src/gui/folder.h b/src/gui/folder.h index 8b59fc6a3..7b1b53929 100644 --- a/src/gui/folder.h +++ b/src/gui/folder.h @@ -474,7 +474,7 @@ private: void showSyncResultPopup(); - void checkLocalPath(); + bool checkLocalPath(); SyncOptions initializeSyncOptions() const; diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index 2f08c40a2..93e559524 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -2027,4 +2027,9 @@ void FolderMan::slotConnectToPushNotifications(Account *account) } } +bool FolderMan::checkVfsAvailability(const QString &path, Vfs::Mode mode) const +{ + return unsupportedConfiguration(path) && Vfs::checkAvailability(path, mode); +} + } // namespace OCC diff --git a/src/gui/folderman.h b/src/gui/folderman.h index ef892a574..f0dafc4f2 100644 --- a/src/gui/folderman.h +++ b/src/gui/folderman.h @@ -231,6 +231,9 @@ public: /** removes current user from the share **/ void leaveShare(const QString &localFile); + /** Whether or not vfs is supported in the location. */ + bool checkVfsAvailability(const QString &path, Vfs::Mode mode = bestAvailableVfsMode()) const; + signals: /** * signal to indicate a folder has changed its sync state. diff --git a/src/gui/folderwizard.cpp b/src/gui/folderwizard.cpp index 3b8ac7aac..d5a222527 100644 --- a/src/gui/folderwizard.cpp +++ b/src/gui/folderwizard.cpp @@ -620,9 +620,10 @@ void FolderWizardSelectiveSync::initializePage() bool FolderWizardSelectiveSync::validatePage() { - const bool useVirtualFiles = _virtualFilesCheckBox && _virtualFilesCheckBox->isChecked(); + const auto mode = bestAvailableVfsMode(); + const bool useVirtualFiles = (Theme::instance()->forceVirtualFilesOption() && mode == Vfs::WindowsCfApi) || (_virtualFilesCheckBox && _virtualFilesCheckBox->isChecked()); if (useVirtualFiles) { - const auto availability = Vfs::checkAvailability(wizard()->field(QStringLiteral("sourceFolder")).toString()); + const auto availability = Vfs::checkAvailability(wizard()->field(QStringLiteral("sourceFolder")).toString(), mode); if (!availability) { auto msg = new QMessageBox(QMessageBox::Warning, tr("Virtual files are not available for the selected folder"), availability.error(), QMessageBox::Ok, this); msg->setAttribute(Qt::WA_DeleteOnClose); diff --git a/src/gui/wizard/owncloudadvancedsetuppage.cpp b/src/gui/wizard/owncloudadvancedsetuppage.cpp index 080170981..f515e1c71 100644 --- a/src/gui/wizard/owncloudadvancedsetuppage.cpp +++ b/src/gui/wizard/owncloudadvancedsetuppage.cpp @@ -393,7 +393,7 @@ bool OwncloudAdvancedSetupPage::isConfirmBigFolderChecked() const bool OwncloudAdvancedSetupPage::validatePage() { if (useVirtualFileSync()) { - const auto availability = Vfs::checkAvailability(localFolder()); + const auto availability = Vfs::checkAvailability(localFolder(), bestAvailableVfsMode()); if (!availability) { auto msg = new QMessageBox(QMessageBox::Warning, tr("Virtual files are not available for the selected folder"), availability.error(), QMessageBox::Ok, this); msg->setAttribute(Qt::WA_DeleteOnClose); diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 0f8691cd0..c64b9219c 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -541,7 +541,7 @@ void SyncEngine::startSync() _progressInfo->reset(); - if (!QDir(_localPath).exists()) { + if (!QFileInfo::exists(_localPath)) { _anotherSyncNeeded = DelayedFollowUp; // No _tr, it should only occur in non-mirall Q_EMIT syncError(QStringLiteral("Unable to find local sync folder."), ErrorCategory::GenericError); -- 2.30.2