diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index 87635ea767..ce1c39ea96 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -546,7 +546,8 @@ QString FolderMan::trayTooltipStatusString( // parent directories. static QString canonicalPath(const QString &path) { - QFileInfo selFile(path); + // QFile::canonicalFilePath for C: returns the current working dir 🤷‍♀️ + QFileInfo selFile(Utility::ensureTrailingSlash(path)); if (!selFile.exists()) { const auto parentPath = selFile.dir().path(); @@ -557,7 +558,7 @@ static QString canonicalPath(const QString &path) return path; } - return canonicalPath(parentPath) + QLatin1Char('/') + selFile.fileName(); + return canonicalPath(parentPath) + '/'_L1 + selFile.fileName(); } return selFile.canonicalFilePath(); } @@ -596,7 +597,7 @@ static QString checkPathForSyncRootMarkingRecursive(const QString &path, FolderM QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid) { if (path.isEmpty()) { - return FolderMan::tr("No valid folder selected!"); + return tr("No valid folder selected!"); } #ifdef Q_OS_WIN @@ -614,21 +615,21 @@ QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::Ne if (parentPath != path) { return checkPathValidityRecursive(parentPath, folderType, accountUuid); } - return FolderMan::tr("The selected path does not exist!"); + return tr("The selected path does not exist!"); } if (numberOfSyncJournals(selectedPathInfo.filePath()) != 0) { - return FolderMan::tr("The folder »%1« is used in a folder sync connection!").arg(QDir::toNativeSeparators(selectedPathInfo.filePath())); + return tr("The folder »%1« is used in a folder sync connection!").arg(QDir::toNativeSeparators(selectedPathInfo.filePath())); } // At this point we know there is no syncdb in the parent hyrarchy, check for spaces sync root. if (!selectedPathInfo.isDir()) { - return FolderMan::tr("The selected path is not a folder!"); + return tr("The selected path is not a folder!"); } if (!selectedPathInfo.isWritable()) { - return FolderMan::tr("You have no permission to write to the selected folder!"); + return tr("You have no permission to write to the selected folder!"); } return checkPathForSyncRootMarkingRecursive(path, folderType, accountUuid); @@ -644,27 +645,26 @@ QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::Ne */ QString FolderMan::checkPathValidityForNewFolder(const QString &path, NewFolderType folderType, const QUuid &accountUuid) const { - // check if the local directory isn't used yet in another sync - const auto cs = Utility::fsCaseSensitivity(); + if (FileSystem::isChildPathOf2(path, QDir::homePath()).testAnyFlag(FileSystem::ChildResult::IsEqual)) { + return tr("The home directory is not allowed to be used as a sync folder!"); + } - const QString userDir = QDir::cleanPath(canonicalPath(path)) + QLatin1Char('/'); + // check if the local directory isn't used yet in another sync + const QString userDir = QDir::cleanPath(canonicalPath(path)); for (auto f : _folders) { - const QString folderDir = QDir::cleanPath(canonicalPath(f->path())) + QLatin1Char('/'); + const QString folderDir = QDir::cleanPath(canonicalPath(f->path())); - if (QString::compare(folderDir, userDir, cs) == 0) { - return tr("There is already a sync from the server to this local folder. " - "Please pick another local folder!"); + if (FileSystem::isChildPathOf2(folderDir, userDir).testAnyFlag(FileSystem::ChildResult::IsEqual)) { + return tr("There is already a sync from the server to this local folder. Please pick another local folder!"); } - if (FileSystem::isChildPathOf(folderDir, userDir)) { - return tr("The local folder »%1« already contains a folder used in a folder sync connection. " - "Please pick another local folder!") - .arg(QDir::toNativeSeparators(path)); + if (FileSystem::isChildPathOf2(folderDir, userDir).testAnyFlags(FileSystem::ChildResult::IsChild | FileSystem::ChildResult::IsEqual)) { + return tr("The local folder »%1« already contains a folder used in a folder sync connection »%2«. Please pick another local folder!") + .arg(QDir::toNativeSeparators(path), QDir::toNativeSeparators(folderDir)); } - if (FileSystem::isChildPathOf(userDir, folderDir)) { - return tr("The local folder »%1« is already contained in a folder used in a folder sync connection. " - "Please pick another local folder!") - .arg(QDir::toNativeSeparators(path)); + if (FileSystem::isChildPathOf2(userDir, folderDir).testAnyFlags(FileSystem::ChildResult::IsChild | FileSystem::ChildResult::IsEqual)) { + return tr("The local folder »%1« is already contained in a folder used in a folder sync connection »%2«. Please pick another local folder!") + .arg(QDir::toNativeSeparators(path), QDir::toNativeSeparators(folderDir)); } } diff --git a/test/testfolderman.cpp b/test/testfolderman.cpp index a0ed19a51c..b0565d4231 100644 --- a/test/testfolderman.cpp +++ b/test/testfolderman.cpp @@ -23,6 +23,8 @@ #include "common/utility_win.h" #endif + +using namespace Qt::Literals::StringLiterals; using namespace OCC; @@ -52,13 +54,24 @@ private Q_SLOTS: auto newAccountState = TestUtils::createDummyAccount(); FolderMan *folderman = TestUtils::folderMan(); QCOMPARE(folderman, FolderMan::instance()); + + const auto type = FolderMan::NewFolderType::SpacesFolder; + const QUuid uuid = {}; + + if (Utility::isWindows()) { // drive-letter tests + if (QFileInfo(QStringLiteral("c:/")).isWritable()) { + // we expect success + QCOMPARE(folderman->checkPathValidityForNewFolder(QStringLiteral("c:"), type, uuid), QString()); + QCOMPARE(folderman->checkPathValidityForNewFolder(QStringLiteral("c:/"), type, uuid), QString()); + QCOMPARE(folderman->checkPathValidityForNewFolder(QStringLiteral("c:/foo"), type, uuid), QString()); + } + } + QVERIFY(folderman->addFolder( newAccountState.get(), TestUtils::createDummyFolderDefinition(newAccountState->account(), dirPath + QStringLiteral("/sub/OpenCloud1")))); QVERIFY(folderman->addFolder( newAccountState.get(), TestUtils::createDummyFolderDefinition(newAccountState->account(), dirPath + QStringLiteral("/OpenCloud2")))); - const auto type = FolderMan::NewFolderType::SpacesFolder; - const QUuid uuid = {}; // those should be allowed // QString FolderMan::checkPathValidityForNewFolder(const QString& path, const QUrl &serverUrl, bool forNewDirectory) @@ -71,15 +84,15 @@ private Q_SLOTS: // QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/bliblablu/some/more")), QString()); // A file -> Error - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/file.txt"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/file.txt"), type, uuid), QString()); // The following both fail because they refer to the same account - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/"), type, uuid), QString()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath, type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder/f"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath, type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder/f"), type, uuid), QString()); #ifndef Q_OS_WIN // no links on windows, no permissions // make a bunch of links @@ -89,75 +102,75 @@ private Q_SLOTS: QVERIFY(QFile::link(dirPath + QStringLiteral("/sub/OpenCloud1/folder"), dirPath + QStringLiteral("/link4"))); // Ok - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link1"), type, uuid).isNull()); - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link2/free"), type, uuid).isNull()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link1"), type, uuid), QString()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link2/free"), type, uuid), QString()); // Not Ok - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link2"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link2"), type, uuid), QString()); // link 3 points to an existing sync folder. To make it fail, the account must be the same - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3"), type, uuid), QString()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link4"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3/folder"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link4"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3/folder"), type, uuid), QString()); // test some non existing sub path (error) - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/some/sub/path"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/blublu"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder/g/h"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3/folder/neu_folder"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/some/sub/path"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/blublu"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder/g/h"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3/folder/neu_folder"), type, uuid), QString()); // Subfolder of links - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link1/subfolder"), type, uuid).isNull()); - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link2/free/subfolder"), type, uuid).isNull()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link1/subfolder"), type, uuid), QString()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link2/free/subfolder"), type, uuid), QString()); if (getuid() != 0) { // Should not have the rights - QVERIFY(!folderman->checkPathValidityForNewFolder(QStringLiteral("/"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(QStringLiteral("/usr/bin/somefolder"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(QStringLiteral("/"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(QStringLiteral("/usr/bin/somefolder"), type, uuid), QString()); } #endif - if (Utility::isWindows()) { // drive-letter tests - if (!QFileInfo(QStringLiteral("v:/")).exists()) { - QVERIFY(!folderman->checkPathValidityForNewFolder(QStringLiteral("v:"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(QStringLiteral("v:/"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(QStringLiteral("v:/foo"), type, uuid).isNull()); - } - if (QFileInfo(QStringLiteral("c:/")).isWritable()) { - QVERIFY(folderman->checkPathValidityForNewFolder(QStringLiteral("c:"), type, uuid).isNull()); - QVERIFY(folderman->checkPathValidityForNewFolder(QStringLiteral("c:/"), type, uuid).isNull()); - QVERIFY(folderman->checkPathValidityForNewFolder(QStringLiteral("c:/foo"), type, uuid).isNull()); - } - } - // Invalid paths - QVERIFY(!folderman->checkPathValidityForNewFolder({}, type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder({}, type, uuid), QString()); // REMOVE OpenCloud2 from the filesystem, but keep a folder sync'ed to it. QDir(dirPath + QStringLiteral("/OpenCloud2/")).removeRecursively(); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/blublu"), type, uuid).isNull()); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/sub/subsub/sub"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/blublu"), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/sub/subsub/sub"), type, uuid), QString()); { // check for rejection of a directory with `.sync_*.db` QVERIFY(dir2.mkpath(QStringLiteral("db-check1"))); - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check1"), type, uuid).isNull()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check1"), type, uuid), QString()); QFile f(dirPath + QStringLiteral("/db-check1/.sync_something.db")); QVERIFY(f.open(QFile::Truncate | QFile::WriteOnly)); f.close(); QVERIFY(QFileInfo::exists(dirPath + QStringLiteral("/db-check1/.sync_something.db"))); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check1"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check1"), type, uuid), QString()); } { // check for rejection of a directory with `._sync_*.db` QVERIFY(dir2.mkpath(QStringLiteral("db-check2"))); - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check2"), type, uuid).isNull()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check2"), type, uuid), QString()); QFile f(dirPath + QStringLiteral("/db-check2/._sync_something.db")); QVERIFY(f.open(QFile::Truncate | QFile::WriteOnly)); f.close(); QVERIFY(QFileInfo::exists(dirPath + QStringLiteral("/db-check2/._sync_something.db"))); - QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check2"), type, uuid).isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/db-check2"), type, uuid), QString()); + } + + + if (Utility::isWindows()) { // drive-letter tests + const auto driveLetter = QFileInfo(dirPath).absoluteDir().absolutePath().at(0); + const auto drive = u"%1:/"_s.arg(driveLetter); + if (QFileInfo(drive).isWritable()) { + // fails as we already sync dirPath + QStringLiteral("/sub/OpenCloud1") + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(u"%1:"_s.arg(driveLetter), type, uuid), QString()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder(u"%1:/"_s.arg(driveLetter), type, uuid), QString()); + // succeeds as the sub dir foo does not contain OpenCloud1 + QCOMPARE(folderman->checkPathValidityForNewFolder(u"%1:/foo"_s.arg(driveLetter), type, uuid), QString()); + } } } @@ -235,28 +248,25 @@ private Q_SLOTS: const auto ourUuid = QUuid::createUuid(); // Spaces Sync Root in another Spaces Sync Root should fail - QVERIFY(!folderman - ->checkPathValidityForNewFolder( - dirPath + QStringLiteral("/AnotherSpacesSyncRoot/OurSpacesSyncRoot"), FolderMan::NewFolderType::SpacesSyncRoot, ourUuid) - .isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder( + dirPath + QStringLiteral("/AnotherSpacesSyncRoot/OurSpacesSyncRoot"), FolderMan::NewFolderType::SpacesSyncRoot, ourUuid), + QString()); // Spaces Sync Root one level up should be fine - QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OurSpacesSyncRoot"), FolderMan::NewFolderType::SpacesSyncRoot, ourUuid) - .isNull()); + QCOMPARE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OurSpacesSyncRoot"), FolderMan::NewFolderType::SpacesSyncRoot, ourUuid), + QString()); // Create the sync root so we can test Spaces Folder creation below QVERIFY(dir2.mkpath(QStringLiteral("OurSpacesSyncRoot"))); Utility::markDirectoryAsSyncRoot(dir2.filePath(QStringLiteral("OurSpacesSyncRoot")), ourUuid); // A folder for a Space in a sync root for another account should fail - QVERIFY(!folderman - ->checkPathValidityForNewFolder( - dirPath + QStringLiteral("/AnotherSpacesSyncRoot/OurSpacesFolder"), FolderMan::NewFolderType::SpacesFolder, ourUuid) - .isNull()); + QCOMPARE_NE(folderman->checkPathValidityForNewFolder( + dirPath + QStringLiteral("/AnotherSpacesSyncRoot/OurSpacesFolder"), FolderMan::NewFolderType::SpacesFolder, ourUuid), + QString()); // But in our sync root that should just be fine - QVERIFY( - folderman - ->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OurSpacesSyncRoot/OurSpacesFolder"), FolderMan::NewFolderType::SpacesFolder, ourUuid) - .isNull()); + QCOMPARE(folderman->checkPathValidityForNewFolder( + dirPath + QStringLiteral("/OurSpacesSyncRoot/OurSpacesFolder"), FolderMan::NewFolderType::SpacesFolder, ourUuid), + QString()); } };