@@ -768,29 +768,40 @@ static QString canonicalPath(const QString &path)
768768
769769static QString checkPathForSyncRootMarkingRecursive (const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid)
770770{
771+ // First do basic checks if this path is usable
772+ const QFileInfo selectedPathInfo (path);
773+ if (!selectedPathInfo.isDir ()) {
774+ return FolderMan::tr (" The selected path is not a folder." );
775+ }
776+
777+ if (numberOfSyncJournals (selectedPathInfo.filePath ()) != 0 ) {
778+ return FolderMan::tr (" The folder %1 is used in a folder sync connection." ).arg (QDir::toNativeSeparators (selectedPathInfo.filePath ()));
779+ }
780+
781+ // Check for sync root markings in this folder
771782 std::pair<QString, QUuid> existingTags = Utility::getDirectorySyncRootMarkings (path);
772783 if (!existingTags.first .isEmpty ()) {
773784 if (existingTags.first != Theme::instance ()->orgDomainName ()) {
774785 // another application uses this as spaces root folder
775- return FolderMan::tr (" Folder '%1' is already in use by application %2! " ).arg (path, existingTags.first );
786+ return FolderMan::tr (" Folder '%1' is already in use by application %2. " ).arg (path, existingTags.first );
776787 }
777788
778789 // Looks good, it's our app, let's check the account tag:
779790 switch (folderType) {
780791 case FolderMan::NewFolderType::SpacesFolder:
781792 if (existingTags.second == accountUuid) {
782- // Nice, that's what we like, the sync root for our account in our app. No error.
793+ // Nice, that's what we like, the sync root for our account in our app. No error, and we don't need to check the parent folders .
783794 return {};
784795 }
785796 [[fallthrough]];
786- case FolderMan::NewFolderType::OC10SyncRoot:
787- [[fallthrough]];
788797 case FolderMan::NewFolderType::SpacesSyncRoot:
789798 // It's our application but we don't want to create a spaces folder, so it must be another space root
790799 return FolderMan::tr (" Folder '%1' is already in use by another account." ).arg (path);
791800 }
792801 }
793802
803+ // This folder is ok, but check the parent folders if they are used
804+
794805 QString parent = QFileInfo (path).path ();
795806 if (parent == path) { // root dir, stop recursing
796807 return {};
@@ -799,51 +810,7 @@ static QString checkPathForSyncRootMarkingRecursive(const QString &path, FolderM
799810 return checkPathForSyncRootMarkingRecursive (parent, folderType, accountUuid);
800811}
801812
802- QString FolderMan::checkPathValidityRecursive (const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid)
803- {
804- if (path.isEmpty ()) {
805- return FolderMan::tr (" No valid folder selected!" );
806- }
807-
808- #ifdef Q_OS_WIN
809- Utility::NtfsPermissionLookupRAII ntfs_perm;
810- #endif
811-
812- auto pathLengthCheck = Folder::checkPathLength (path);
813- if (!pathLengthCheck) {
814- return pathLengthCheck.error ();
815- }
816-
817- const QFileInfo selectedPathInfo (path);
818- if (!selectedPathInfo.exists ()) {
819- const QString parentPath = selectedPathInfo.path ();
820- if (parentPath != path) {
821- return checkPathValidityRecursive (parentPath, folderType, accountUuid);
822- }
823- return FolderMan::tr (" The selected path does not exist!" );
824- }
825-
826- if (numberOfSyncJournals (selectedPathInfo.filePath ()) != 0 ) {
827- return FolderMan::tr (" The folder %1 is used in a folder sync connection!" ).arg (QDir::toNativeSeparators (selectedPathInfo.filePath ()));
828- }
829-
830- // At this point we know there is no syncdb in the parent hierarchy, check for spaces sync root.
831-
832- if (!selectedPathInfo.isDir ()) {
833- return FolderMan::tr (" The selected path is not a folder!" );
834- }
835-
836- if (!selectedPathInfo.isWritable ()) {
837- return FolderMan::tr (" You have no permission to write to the selected folder!" );
838- }
839-
840- return checkPathForSyncRootMarkingRecursive (path, folderType, accountUuid);
841- }
842-
843813/*
844- * OC10 folder:
845- * - sync root not in syncdb folder
846- * - sync root not in spaces root
847814 * with spaces:
848815 * - spaces sync root not in syncdb folder
849816 * - spaces sync root not in another spaces sync root
@@ -852,37 +819,67 @@ QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::Ne
852819 * - space *can* be in sync root
853820 * - space not in spaces sync root of other account (check with account uuid)
854821 */
855- QString FolderMan::checkPathValidityForNewFolder (const QString &path, NewFolderType folderType, const QUuid &accountUuid) const
822+ QString FolderMan::checkPathValidity (const QString &path, NewFolderType folderType, const QUuid &accountUuid)
856823{
857- // check if the local directory isn't used yet in another ownCloud sync
824+ // Do checks against existing folders. This catches cases where:
825+ // - the user deleted a folder from the filesystem, but there is still a folder sync connection in the configuration
826+ // - check if this folder contains other folders for spaces
827+ // If so, error out.
858828 const auto cs = Utility::fsCaseSensitivity ();
859-
860829 const QString userDir = QDir::cleanPath (canonicalPath (path)) + QLatin1Char (' /' );
861- for (auto f : _folders ) {
830+ for (auto f : FolderMan::instance ()-> folders () ) {
862831 const QString folderDir = QDir::cleanPath (canonicalPath (f->path ())) + QLatin1Char (' /' );
863-
864832 if (QString::compare (folderDir, userDir, cs) == 0 ) {
865- return tr (" There is already a sync from the server to this local folder. "
866- " Please pick another local folder!" );
833+ return tr (" There is already a sync from the server to this local folder." );
867834 }
868835 if (FileSystem::isChildPathOf (folderDir, userDir)) {
869- return tr (" The local folder %1 already contains a folder used in a folder sync connection. "
870- " Please pick another local folder!" )
836+ return tr (" The local folder %1 already contains a folder used in a folder sync connection." )
871837 .arg (QDir::toNativeSeparators (path));
872838 }
873839
874840 if (FileSystem::isChildPathOf (userDir, folderDir)) {
875- return tr (" The local folder %1 is already contained in a folder used in a folder sync connection. "
876- " Please pick another local folder!" )
841+ return tr (" The local folder %1 is already contained in a folder used in a folder sync connection." )
877842 .arg (QDir::toNativeSeparators (path));
878843 }
879844 }
880845
881- const auto result = checkPathValidityRecursive (path, folderType, accountUuid);
882- if (!result.isEmpty ()) {
883- return tr (" %1 Please pick another local folder!" ).arg (result);
846+ // Now run filesystem based checks
847+ return checkPathValidityRecursive (path, folderType, accountUuid);
848+ }
849+
850+ QString FolderMan::checkPathValidityRecursive (const QString &path, NewFolderType folderType, const QUuid &accountUuid)
851+ {
852+ if (path.isEmpty ()) {
853+ return FolderMan::tr (" No valid folder selected." );
854+ }
855+
856+ #ifdef Q_OS_WIN
857+ Utility::NtfsPermissionLookupRAII ntfs_perm;
858+ #endif
859+
860+ auto pathLengthCheck = Folder::checkPathLength (path);
861+ if (!pathLengthCheck) {
862+ return pathLengthCheck.error ();
863+ }
864+
865+ // If this is a new folder, recurse up to the first parent that exists, to see if we can use that to create a new folder
866+ const QFileInfo selectedPathInfo (path);
867+ if (!selectedPathInfo.exists ()) {
868+ const QString parentPath = selectedPathInfo.path ();
869+ if (parentPath != path) {
870+ return checkPathValidityRecursive (parentPath, folderType, accountUuid);
871+ }
872+ return FolderMan::tr (" The selected path does not exist." );
873+ }
874+
875+ // At this point we have an existing folder, so check if we can create files/folders here.
876+ // Note: we don't need to write to any parent, so we don't need to check writablility when traversing the parents.
877+ if (!selectedPathInfo.isWritable ()) {
878+ return FolderMan::tr (" You have no permission to write to the selected folder." );
884879 }
885- return {};
880+
881+ // Now check if none of the parents is already used.
882+ return checkPathForSyncRootMarkingRecursive (canonicalPath (path), folderType, accountUuid);
886883}
887884
888885QString FolderMan::findGoodPathForNewSyncFolder (
@@ -906,7 +903,7 @@ QString FolderMan::findGoodPathForNewSyncFolder(
906903 {
907904 QString folder = normalisedPath;
908905 for (int attempt = 2 ; attempt <= 100 ; ++attempt) {
909- if (!QFileInfo::exists (folder) && FolderMan::instance ()-> checkPathValidityForNewFolder (folder, folderType, accountUuid).isEmpty ()) {
906+ if (!QFileInfo::exists (folder) && checkPathValidity (folder, folderType, accountUuid).isEmpty ()) {
910907 return canonicalPath (folder);
911908 }
912909 folder = normalisedPath + QStringLiteral (" (%1)" ).arg (attempt);
@@ -1050,7 +1047,7 @@ void FolderMan::addFolderFromGui(AccountState *accountState, const SyncConnectio
10501047 setSyncEnabled (true );
10511048}
10521049
1053- QString FolderMan::suggestSyncFolder (NewFolderType folderType, const QUuid &accountUuid)
1050+ QString FolderMan::suggestSyncFolder (NewFolderType folderType, const QUuid &accountUuid)// XXX
10541051{
10551052 return FolderMan::instance ()->findGoodPathForNewSyncFolder (QDir::homePath (), Theme::instance ()->appName (), folderType, accountUuid);
10561053}
0 commit comments