Fix crash on missing sync root
authorHannah von Reth <hannah.vonreth@owncloud.com>
Mon, 13 Sep 2021 13:01:34 +0000 (15:01 +0200)
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>
Thu, 12 Dec 2024 13:27:48 +0000 (13:27 +0000)
Fixes: #9016
src/common/vfs.cpp
src/common/vfs.h
src/gui/accountsettings.cpp
src/gui/folder.cpp
src/gui/folder.h
src/gui/folderman.cpp
src/gui/folderman.h
src/gui/folderwizard.cpp
src/gui/wizard/owncloudadvancedsetuppage.cpp
src/libsync/syncengine.cpp

index 84df80c76ec41f591f01c7c95b4c8cdac459a2cc..69e51be50944c72c7ad7523cec02f60176129244 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "common/filesystembase.h"
 
+#include <QDir>
 #include <QPluginLoader>
 #include <QLoggingCategory>
 
@@ -65,9 +66,8 @@ Optional<Vfs::Mode> Vfs::modeFromString(const QString &str)
     return {};
 }
 
-Result<bool, QString> Vfs::checkAvailability(const QString &path)
+Result<void, QString> 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<bool, QString> Vfs::checkAvailability(const QString &path)
     Q_UNUSED(mode)
     Q_UNUSED(path)
 #endif
-    return true;
+    return {};
 }
 
 void Vfs::start(const VfsSetupParams &params)
index b3c5df9d08262d7380b20120ff29a13d3f797bd7..1e925ccdca10bedcde7a75744fbb444b6eeb92d4 100644 (file)
@@ -125,7 +125,7 @@ public:
     static QString modeToString(Mode mode);
     static Optional<Mode> modeFromString(const QString &str);
 
-    static Result<bool, QString> checkAvailability(const QString &path);
+    static Result<void, QString> checkAvailability(const QString &path, OCC::Vfs::Mode mode);
 
     enum class AvailabilityError
     {
index 986ca7f8786f0349c9e11fe2ab6114c478da5c42..bc5bda41d1dece39bbb323203984dd86507999ba 100644 (file)
@@ -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
index 8b8bb0c16f828ac4479334860177f5e46a1ed913..6b7f2ad45fc34f74e12c36bccc0df426ac3a76d9 100644 (file)
@@ -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();
index 8b59fc6a309784cf2cd6f93ea5d30dcbe136a88d..7b1b53929223e5a8c9e12a2d20de2b3fe80802cb 100644 (file)
@@ -474,7 +474,7 @@ private:
 
     void showSyncResultPopup();
 
-    void checkLocalPath();
+    bool checkLocalPath();
 
     SyncOptions initializeSyncOptions() const;
 
index 2f08c40a2f29c831065e05ab4da849ed4b001834..93e55952474d42c8f091b414afdf82322d322c63 100644 (file)
@@ -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
index ef892a57473e5d7b4d5ce3375193850062f5acdd..f0dafc4f211f7274f22399dc216cd4896d8450d8 100644 (file)
@@ -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.
index 3b8ac7aac9a9df551f618ea56178e4ec76be641d..d5a2225276e821368ee9ccb67960d6793daa3e4f 100644 (file)
@@ -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);
index 08017098100c11b0197afdfc803ad592dade60ff..f515e1c716a65072c2fb94acd801b7b4922e9464 100644 (file)
@@ -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);
index 0f8691cd0596020d927619ca497bee48a485b1a4..c64b9219ca3cd15ad4d08a910c0438bf6037d04f 100644 (file)
@@ -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);