From 21c5decc04d83fa49403ef01cb80451b98774c96 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 6 Jun 2023 22:01:52 +0800 Subject: [PATCH] Revert "Merge pull request #5527 from nextcloud/feature/file-provider-try-2" This reverts commit c4d12115a9a9fd9c10627c434f16d7f280d82ca9, reversing changes made to 9b77da6569ec49b8a14db8f5df367a7948f34702. Signed-off-by: Claudio Cambra --- .gitignore | 1 - CMakeLists.txt | 5 - shell_integration/MacOSX/CMakeLists.txt | 71 +- .../contents.xcworkspacedata | 7 - ...loudFilesDatabaseManager+Directories.swift | 145 -- ...cloudFilesDatabaseManager+LocalFiles.swift | 91 -- .../NextcloudFilesDatabaseManager.swift | 326 ----- .../NextcloudItemMetadataTable+NKFile.swift | 128 -- .../Database/NextcloudItemMetadataTable.swift | 213 --- .../NextcloudLocalFileMetadataTable.swift | 29 - .../Extensions/Logger+Extensions.swift | 27 - .../Extensions/NKError+Extensions.swift | 68 - .../Extensions/Progress+Extensions.swift | 57 - .../FileProviderEnumerator+SyncEngine.swift | 313 ---- .../FileProviderEnumerator.swift | 352 ----- .../FileProviderExt.entitlements | 16 - ...ileProviderExtension+ClientInterface.swift | 71 - .../FileProviderExtension+Thumbnailing.swift | 62 - .../FileProviderExtension.swift | 633 --------- .../FileProviderExt/FileProviderItem.swift | 133 -- ...viderMaterialisedEnumerationObserver.swift | 77 - .../FileProviderSocketLineProcessor.swift | 56 - .../FileProviderExt/Info.plist | 25 - .../FileProviderExt/LocalFilesUtils.swift | 57 - .../FileProviderExt/NextcloudAccount.swift | 32 - .../NCDesktopClientSocketKit/LineProcessor.h | 24 - .../NCDesktopClientSocketKit.h | 19 - .../project.pbxproj | 1261 ----------------- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../contents.xcworkspacedata | 2 +- .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/OwnCloud.xccheckout | 0 .../FinderSyncExt/FinderSync.h | 7 +- .../FinderSyncExt/FinderSync.m | 22 +- .../FinderSyncExt/FinderSyncExt.entitlements | 0 .../FinderSyncExt/Info.plist | 4 +- .../FinderSyncExt/LineProcessor.h} | 14 +- .../FinderSyncExt/LineProcessor.m} | 4 +- .../FinderSyncExt}/LocalSocketClient.h | 30 +- .../FinderSyncExt}/LocalSocketClient.m | 173 +-- .../FinderSyncExt/SyncClient.h | 0 .../project.pbxproj | 600 ++++++++ .../xcschemes/FinderSyncExt.xcscheme | 21 +- .../desktopclient/Info.plist | 0 .../desktopclient/main.m | 0 src/gui/CMakeLists.txt | 20 +- src/gui/application.cpp | 8 +- src/gui/application.h | 10 +- src/gui/macOS/fileprovider.h | 52 - src/gui/macOS/fileprovider_mac.mm | 92 -- src/gui/macOS/fileproviderdomainmanager.h | 62 - .../macOS/fileproviderdomainmanager_mac.mm | 636 --------- .../macOS/fileprovidersocketcontroller.cpp | 207 --- src/gui/macOS/fileprovidersocketcontroller.h | 60 - src/gui/macOS/fileprovidersocketserver.cpp | 84 -- src/gui/macOS/fileprovidersocketserver.h | 49 - src/gui/macOS/fileprovidersocketserver_mac.mm | 40 - src/libsync/configfile.cpp | 14 - src/libsync/configfile.h | 4 +- 59 files changed, 750 insertions(+), 5772 deletions(-) delete mode 100644 shell_integration/MacOSX/Nextcloud.xcworkspace/contents.xcworkspacedata delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudLocalFileMetadataTable.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt.entitlements delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename shell_integration/MacOSX/{NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace => OwnCloud.xcworkspace}/contents.xcworkspacedata (59%) rename shell_integration/MacOSX/{Nextcloud.xcworkspace => OwnCloud.xcworkspace}/xcshareddata/IDEWorkspaceChecks.plist (100%) rename shell_integration/MacOSX/{Nextcloud.xcworkspace => OwnCloud.xcworkspace}/xcshareddata/OwnCloud.xccheckout (100%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/FinderSyncExt/FinderSync.h (85%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/FinderSyncExt/FinderSync.m (95%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/FinderSyncExt/FinderSyncExt.entitlements (100%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/FinderSyncExt/Info.plist (100%) rename shell_integration/MacOSX/{NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h => OwnCloudFinderSync/FinderSyncExt/LineProcessor.h} (75%) rename shell_integration/MacOSX/{NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m => OwnCloudFinderSync/FinderSyncExt/LineProcessor.m} (97%) rename shell_integration/MacOSX/{NextcloudIntegration/NCDesktopClientSocketKit => OwnCloudFinderSync/FinderSyncExt}/LocalSocketClient.h (75%) rename shell_integration/MacOSX/{NextcloudIntegration/NCDesktopClientSocketKit => OwnCloudFinderSync/FinderSyncExt}/LocalSocketClient.m (61%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/FinderSyncExt/SyncClient.h (100%) create mode 100644 shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj rename shell_integration/MacOSX/{NextcloudIntegration/NextcloudIntegration.xcodeproj => OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj}/xcshareddata/xcschemes/FinderSyncExt.xcscheme (80%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/desktopclient/Info.plist (100%) rename shell_integration/MacOSX/{NextcloudIntegration => OwnCloudFinderSync}/desktopclient/main.m (100%) delete mode 100644 src/gui/macOS/fileprovider.h delete mode 100644 src/gui/macOS/fileprovider_mac.mm delete mode 100644 src/gui/macOS/fileproviderdomainmanager.h delete mode 100644 src/gui/macOS/fileproviderdomainmanager_mac.mm delete mode 100644 src/gui/macOS/fileprovidersocketcontroller.cpp delete mode 100644 src/gui/macOS/fileprovidersocketcontroller.h delete mode 100644 src/gui/macOS/fileprovidersocketserver.cpp delete mode 100644 src/gui/macOS/fileprovidersocketserver.h delete mode 100644 src/gui/macOS/fileprovidersocketserver_mac.mm diff --git a/.gitignore b/.gitignore index 85a87ed91464e..249c4a2c7c346 100644 --- a/.gitignore +++ b/.gitignore @@ -88,7 +88,6 @@ dlldata.c # macOS specific xcuserdata/ **/.DS_Store -**/Carthage/ # Visual C++ cache files ipch/ diff --git a/CMakeLists.txt b/CMakeLists.txt index d38c8169c5b26..ba0195b57efd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,11 +187,6 @@ else() unset(CMAKE_CXX_CLANG_TIDY) endif() -if (APPLE) - # build macOS File Provider module - option(BUILD_FILE_PROVIDER_MODULE "BUILD_FILE_PROVIDER_MODULE" ON) -endif() - # When this option is enabled, 5xx errors are not added to the blacklist # Normally you don't want to enable this option because if a particular file # triggers a bug on the server, you want the file to be blacklisted. diff --git a/shell_integration/MacOSX/CMakeLists.txt b/shell_integration/MacOSX/CMakeLists.txt index 85d901920db6d..99116c76d987b 100644 --- a/shell_integration/MacOSX/CMakeLists.txt +++ b/shell_integration/MacOSX/CMakeLists.txt @@ -1,55 +1,26 @@ if(APPLE) - set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns") + set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns") - if (CMAKE_BUILD_TYPE MATCHES "Debug" OR CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo") - set(XCODE_TARGET_CONFIGURATION "Debug") - else() - set(XCODE_TARGET_CONFIGURATION "Release") - endif() + # The bundle identifier and application group need to have compatible values with the client + # to be able to open a Mach port across the extension's sandbox boundary. + # Pass the info through the xcodebuild command line and make sure that the project uses + # those user-defined settings to build the plist. + add_custom_target( mac_overlayplugin ALL + xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO + -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj + -target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}" + "OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}" + "OC_APPLICATION_NAME=${APPLICATION_NAME}" + "OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}" + "OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}" + COMMENT building Mac Overlay icons + VERBATIM) + add_dependencies(mac_overlayplugin nextcloud) # for the ownCloud.icns to be generated - # The bundle identifier and application group need to have compatible values with the client - # to be able to open a Mach port across the extension's sandbox boundary. - # Pass the info through the xcodebuild command line and make sure that the project uses - # those user-defined settings to build the plist. - add_custom_target( mac_overlayplugin ALL - xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO - -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj - -target FinderSyncExt -configuration ${XCODE_TARGET_CONFIGURATION} "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}" - "OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}" - "OC_APPLICATION_NAME=${APPLICATION_NAME}" - "OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}" - "OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}" - COMMENT building Mac Overlay icons - VERBATIM) - - if (BUILD_FILE_PROVIDER_MODULE) - add_custom_target( mac_fileproviderplugin ALL - xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO - -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj - -target FileProviderExt -configuration ${XCODE_TARGET_CONFIGURATION} "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}" - "OC_APPLICATION_EXECUTABLE_NAME=${APPLICATION_EXECUTABLE}" - "OC_APPLICATION_VENDOR=${APPLICATION_VENDOR}" - "OC_APPLICATION_NAME=${APPLICATION_NAME}" - "OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}" - "OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}" - COMMENT building macOS File Provider extension - VERBATIM) - - add_dependencies(mac_overlayplugin mac_fileproviderplugin nextcloud) # for the ownCloud.icns to be generated - else() - add_dependencies(mac_overlayplugin nextcloud) # for the ownCloud.icns to be generated - endif() - - if (BUILD_OWNCLOUD_OSX_BUNDLE) - install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex - DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns - USE_SOURCE_PERMISSIONS) - - if (BUILD_FILE_PROVIDER_MODULE) - install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FileProviderExt.appex - DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns - USE_SOURCE_PERMISSIONS) - endif() - endif() + if (BUILD_OWNCLOUD_OSX_BUNDLE) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex + DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns + USE_SOURCE_PERMISSIONS) + endif() endif() diff --git a/shell_integration/MacOSX/Nextcloud.xcworkspace/contents.xcworkspacedata b/shell_integration/MacOSX/Nextcloud.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index ed78110c5ea53..0000000000000 --- a/shell_integration/MacOSX/Nextcloud.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift deleted file mode 100644 index 386791ecc65ec..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import OSLog - -extension NextcloudFilesDatabaseManager { - func directoryMetadata(account: String, serverUrl: String) -> NextcloudItemMetadataTable? { - // We want to split by "/" (e.g. cloud.nc.com/files/a/b) but we need to be mindful of "https://c.nc.com" - let problematicSeparator = "://" - let placeholderSeparator = "__TEMP_REPLACE__" - let serverUrlWithoutPrefix = serverUrl.replacingOccurrences(of: problematicSeparator, with: placeholderSeparator) - var splitServerUrl = serverUrlWithoutPrefix.split(separator: "/") - let directoryItemFileName = String(splitServerUrl.removeLast()) - let directoryItemServerUrl = splitServerUrl.joined(separator: "/").replacingOccurrences(of: placeholderSeparator, with: problematicSeparator) - - if let metadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@ AND directory == true", account, directoryItemServerUrl, directoryItemFileName).first { - return NextcloudItemMetadataTable(value: metadata) - } - - return nil - } - - func childItemsForDirectory(_ directoryMetadata: NextcloudItemMetadataTable) -> [NextcloudItemMetadataTable] { - let directoryServerUrl = directoryMetadata.serverUrl + "/" + directoryMetadata.fileName - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("serverUrl BEGINSWITH %@", directoryServerUrl) - return sortedItemMetadatas(metadatas) - } - - func childDirectoriesForDirectory(_ directoryMetadata: NextcloudItemMetadataTable) -> [NextcloudItemMetadataTable] { - let directoryServerUrl = directoryMetadata.serverUrl + "/" + directoryMetadata.fileName - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("serverUrl BEGINSWITH %@ AND directory == true", directoryServerUrl) - return sortedItemMetadatas(metadatas) - } - - func parentDirectoryMetadataForItem(_ itemMetadata: NextcloudItemMetadataTable) -> NextcloudItemMetadataTable? { - return directoryMetadata(account: itemMetadata.account, serverUrl: itemMetadata.serverUrl) - } - - func directoryMetadata(ocId: String) -> NextcloudItemMetadataTable? { - if let metadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("ocId == %@ AND directory == true", ocId).first { - return NextcloudItemMetadataTable(value: metadata) - } - - return nil - } - - func directoryMetadatas(account: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND directory == true", account) - return sortedItemMetadatas(metadatas) - } - - func directoryMetadatas(account: String, parentDirectoryServerUrl: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND parentDirectoryServerUrl == %@ AND directory == true", account, parentDirectoryServerUrl) - return sortedItemMetadatas(metadatas) - } - - // Deletes all metadatas related to the info of the directory provided - func deleteDirectoryAndSubdirectoriesMetadata(ocId: String) -> [NextcloudItemMetadataTable]? { - let database = ncDatabase() - guard let directoryMetadata = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@ AND directory == true", ocId).first else { - Logger.ncFilesDatabase.error("Could not find directory metadata for ocId \(ocId, privacy: .public). Not proceeding with deletion") - return nil - } - - let directoryMetadataCopy = NextcloudItemMetadataTable(value: directoryMetadata) - let directoryUrlPath = directoryMetadata.serverUrl + "/" + directoryMetadata.fileName - let directoryAccount = directoryMetadata.account - let directoryEtag = directoryMetadata.etag - - Logger.ncFilesDatabase.debug("Deleting root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)") - - guard deleteItemMetadata(ocId: directoryMetadata.ocId) else { - Logger.ncFilesDatabase.debug("Failure to delete root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)") - return nil - } - - var deletedMetadatas: [NextcloudItemMetadataTable] = [directoryMetadataCopy] - - let results = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryAccount, directoryUrlPath) - - for result in results { - let successfulItemMetadataDelete = deleteItemMetadata(ocId: result.ocId) - if (successfulItemMetadataDelete) { - deletedMetadatas.append(NextcloudItemMetadataTable(value: result)) - } - - if localFileMetadataFromOcId(result.ocId) != nil { - deleteLocalFileMetadata(ocId: result.ocId) - } - } - - Logger.ncFilesDatabase.debug("Completed deletions in directory recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)") - - return deletedMetadatas - } - - func renameDirectoryAndPropagateToChildren(ocId: String, newServerUrl: String, newFileName: String) -> [NextcloudItemMetadataTable]? { - - let database = ncDatabase() - - guard let directoryMetadata = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@ AND directory == true", ocId).first else { - Logger.ncFilesDatabase.error("Could not find a directory with ocID \(ocId, privacy: .public), cannot proceed with recursive renaming") - return nil - } - - let oldItemServerUrl = directoryMetadata.serverUrl - let oldDirectoryServerUrl = oldItemServerUrl + "/" + directoryMetadata.fileName - let newDirectoryServerUrl = newServerUrl + "/" + newFileName - let childItemResults = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, oldDirectoryServerUrl) - - renameItemMetadata(ocId: ocId, newServerUrl: newServerUrl, newFileName: newFileName) - Logger.ncFilesDatabase.debug("Renamed root renaming directory") - - do { - try database.write { - for childItem in childItemResults { - let oldServerUrl = childItem.serverUrl - let movedServerUrl = oldServerUrl.replacingOccurrences(of: oldDirectoryServerUrl, with: newDirectoryServerUrl) - childItem.serverUrl = movedServerUrl - database.add(childItem, update: .all) - Logger.ncFilesDatabase.debug("Moved childItem at \(oldServerUrl) to \(movedServerUrl)") - } - } - } catch let error { - Logger.ncFilesDatabase.error("Could not rename directory metadata with ocId: \(ocId, privacy: .public) to new serverUrl: \(newServerUrl), received error: \(error.localizedDescription, privacy: .public)") - - return nil - } - - let updatedChildItemResults = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, newDirectoryServerUrl) - return sortedItemMetadatas(updatedChildItemResults) - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift deleted file mode 100644 index 2241d200c698b..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import RealmSwift -import OSLog - -extension NextcloudFilesDatabaseManager { - func localFileMetadataFromOcId(_ ocId: String) -> NextcloudLocalFileMetadataTable? { - if let metadata = ncDatabase().objects(NextcloudLocalFileMetadataTable.self).filter("ocId == %@", ocId).first { - return NextcloudLocalFileMetadataTable(value: metadata) - } - - return nil - } - - func addLocalFileMetadataFromItemMetadata(_ itemMetadata: NextcloudItemMetadataTable) { - let database = ncDatabase() - - do { - try database.write { - let newLocalFileMetadata = NextcloudLocalFileMetadataTable() - - newLocalFileMetadata.ocId = itemMetadata.ocId - newLocalFileMetadata.fileName = itemMetadata.fileName - newLocalFileMetadata.account = itemMetadata.account - newLocalFileMetadata.etag = itemMetadata.etag - newLocalFileMetadata.exifDate = Date() - newLocalFileMetadata.exifLatitude = "-1" - newLocalFileMetadata.exifLongitude = "-1" - - database.add(newLocalFileMetadata, update: .all) - Logger.ncFilesDatabase.debug("Added local file metadata from item metadata. ocID: \(itemMetadata.ocId, privacy: .public), etag: \(itemMetadata.etag, privacy: .public), fileName: \(itemMetadata.fileName, privacy: .public)") - } - } catch let error { - Logger.ncFilesDatabase.error("Could not add local file metadata from item metadata. ocID: \(itemMetadata.ocId, privacy: .public), etag: \(itemMetadata.etag, privacy: .public), fileName: \(itemMetadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - } - } - - func deleteLocalFileMetadata(ocId: String) { - let database = ncDatabase() - - do { - try database.write { - let results = database.objects(NextcloudLocalFileMetadataTable.self).filter("ocId == %@", ocId) - database.delete(results) - } - } catch let error { - Logger.ncFilesDatabase.error("Could not delete local file metadata with ocId: \(ocId, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - } - } - - private func sortedLocalFileMetadatas(_ metadatas: Results) -> [NextcloudLocalFileMetadataTable] { - let sortedMetadatas = metadatas.sorted(byKeyPath: "fileName", ascending: true) - return Array(sortedMetadatas.map { NextcloudLocalFileMetadataTable(value: $0) }) - } - - func localFileMetadatas(account: String) -> [NextcloudLocalFileMetadataTable] { - let results = ncDatabase().objects(NextcloudLocalFileMetadataTable.self).filter("account == %@", account) - return sortedLocalFileMetadatas(results) - } - - func localFileItemMetadatas(account: String) -> [NextcloudItemMetadataTable] { - let localFileMetadatas = localFileMetadatas(account: account) - let localFileMetadatasOcIds = Array(localFileMetadatas.map { $0.ocId }) - - var itemMetadatas: [NextcloudItemMetadataTable] = [] - - for ocId in localFileMetadatasOcIds { - guard let itemMetadata = itemMetadataFromOcId(ocId) else { - Logger.ncFilesDatabase.error("Could not find matching item metadata for local file metadata with ocId: \(ocId, privacy: .public) with request from account: \(account)") - continue; - } - - itemMetadatas.append(NextcloudItemMetadataTable(value: itemMetadata)) - } - - return itemMetadatas - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift deleted file mode 100644 index 158f28111a4bd..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import RealmSwift -import FileProvider -import NextcloudKit -import OSLog - -class NextcloudFilesDatabaseManager : NSObject { - static let shared = { - return NextcloudFilesDatabaseManager(); - }() - - let relativeDatabaseFolderPath = "Database/" - let databaseFilename = "fileproviderextdatabase.realm" - let relativeDatabaseFilePath: String - var databasePath: URL? - - let schemaVersion: UInt64 = 100 - - override init() { - self.relativeDatabaseFilePath = self.relativeDatabaseFolderPath + self.databaseFilename - - guard let fileProviderDataDirUrl = pathForFileProviderExtData() else { - super.init() - return - } - - self.databasePath = fileProviderDataDirUrl.appendingPathComponent(self.relativeDatabaseFilePath) - - // Disable file protection for directory DB - // https://docs.mongodb.com/realm/sdk/ios/examples/configure-and-open-a-realm/#std-label-ios-open-a-local-realm - let dbFolder = fileProviderDataDirUrl.appendingPathComponent(self.relativeDatabaseFolderPath) - let dbFolderPath = dbFolder.path - do { - try FileManager.default.createDirectory(at: dbFolder, withIntermediateDirectories: true) - try FileManager.default.setAttributes([FileAttributeKey.protectionKey: FileProtectionType.completeUntilFirstUserAuthentication], ofItemAtPath: dbFolderPath) - } catch let error { - Logger.ncFilesDatabase.error("Could not set permission level for File Provider database folder, received error: \(error.localizedDescription, privacy: .public)") - } - - let config = Realm.Configuration( - fileURL: self.databasePath, - schemaVersion: self.schemaVersion, - objectTypes: [NextcloudItemMetadataTable.self, NextcloudLocalFileMetadataTable.self] - ) - - Realm.Configuration.defaultConfiguration = config - - do { - _ = try Realm() - Logger.ncFilesDatabase.info("Successfully started Realm db for FileProviderExt") - } catch let error as NSError { - Logger.ncFilesDatabase.error("Error opening Realm db: \(error.localizedDescription, privacy: .public)") - } - - super.init() - } - - func ncDatabase() -> Realm { - let realm = try! Realm() - realm.refresh() - return realm - } - - func anyItemMetadatasForAccount(_ account: String) -> Bool { - return !ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@", account).isEmpty - } - - func itemMetadataFromOcId(_ ocId: String) -> NextcloudItemMetadataTable? { - // Realm objects are live-fire, i.e. they will be changed and invalidated according to changes in the db - // Let's therefore create a copy - if let itemMetadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("ocId == %@", ocId).first { - return NextcloudItemMetadataTable(value: itemMetadata) - } - - return nil - } - - func sortedItemMetadatas(_ metadatas: Results) -> [NextcloudItemMetadataTable] { - let sortedMetadatas = metadatas.sorted(byKeyPath: "fileName", ascending: true) - return Array(sortedMetadatas.map { NextcloudItemMetadataTable(value: $0) }) - } - - func itemMetadatas(account: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@", account) - return sortedItemMetadatas(metadatas) - } - - func itemMetadatas(account: String, serverUrl: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@", account, serverUrl) - return sortedItemMetadatas(metadatas) - } - - func itemMetadatas(account: String, serverUrl: String, status: NextcloudItemMetadataTable.Status) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@ AND status == %@", account, serverUrl, status.rawValue) - return sortedItemMetadatas(metadatas) - } - - func itemMetadataFromFileProviderItemIdentifier(_ identifier: NSFileProviderItemIdentifier) -> NextcloudItemMetadataTable? { - let ocId = identifier.rawValue - return itemMetadataFromOcId(ocId) - } - - private func processItemMetadatasToDelete(existingMetadatas: Results, - updatedMetadatas: [NextcloudItemMetadataTable]) -> [NextcloudItemMetadataTable] { - - var deletedMetadatas: [NextcloudItemMetadataTable] = [] - - for existingMetadata in existingMetadatas { - guard !updatedMetadatas.contains(where: { $0.ocId == existingMetadata.ocId }), - let metadataToDelete = itemMetadataFromOcId(existingMetadata.ocId) else { continue } - - deletedMetadatas.append(metadataToDelete) - - Logger.ncFilesDatabase.debug("Deleting item metadata during update. ocID: \(existingMetadata.ocId, privacy: .public), etag: \(existingMetadata.etag, privacy: .public), fileName: \(existingMetadata.fileName, privacy: .public)") - } - - return deletedMetadatas - } - - private func processItemMetadatasToUpdate(existingMetadatas: Results, - updatedMetadatas: [NextcloudItemMetadataTable], - updateDirectoryEtags: Bool) -> (newMetadatas: [NextcloudItemMetadataTable], updatedMetadatas: [NextcloudItemMetadataTable], directoriesNeedingRename: [NextcloudItemMetadataTable]) { - - var returningNewMetadatas: [NextcloudItemMetadataTable] = [] - var returningUpdatedMetadatas: [NextcloudItemMetadataTable] = [] - var directoriesNeedingRename: [NextcloudItemMetadataTable] = [] - - for updatedMetadata in updatedMetadatas { - if let existingMetadata = existingMetadatas.first(where: { $0.ocId == updatedMetadata.ocId }) { - - if existingMetadata.status == NextcloudItemMetadataTable.Status.normal.rawValue && - !existingMetadata.isInSameDatabaseStoreableRemoteState(updatedMetadata) { - - if updatedMetadata.directory { - - if updatedMetadata.serverUrl != existingMetadata.serverUrl || updatedMetadata.fileName != existingMetadata.fileName { - - directoriesNeedingRename.append(NextcloudItemMetadataTable(value: updatedMetadata)) - updatedMetadata.etag = "" // Renaming doesn't change the etag so reset manually - - } else if !updateDirectoryEtags { - updatedMetadata.etag = existingMetadata.etag - } - } - - returningUpdatedMetadatas.append(updatedMetadata) - - - Logger.ncFilesDatabase.debug("Updated existing item metadata. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)") - } else { - Logger.ncFilesDatabase.debug("Skipping item metadata update; same as existing, or still downloading/uploading. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)") - } - - } else { // This is a new metadata - if !updateDirectoryEtags && updatedMetadata.directory { - updatedMetadata.etag = "" - } - - returningNewMetadatas.append(updatedMetadata) - - Logger.ncFilesDatabase.debug("Created new item metadata during update. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)") - } - } - - return (returningNewMetadatas, returningUpdatedMetadatas, directoriesNeedingRename) - } - - func updateItemMetadatas(account: String, serverUrl: String, updatedMetadatas: [NextcloudItemMetadataTable], updateDirectoryEtags: Bool) -> (newMetadatas: [NextcloudItemMetadataTable]?, updatedMetadatas: [NextcloudItemMetadataTable]?, deletedMetadatas: [NextcloudItemMetadataTable]?) { - let database = ncDatabase() - - do { - let existingMetadatas = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@ AND status == %@", account, serverUrl, NextcloudItemMetadataTable.Status.normal.rawValue) - - let metadatasToDelete = processItemMetadatasToDelete(existingMetadatas: existingMetadatas, - updatedMetadatas: updatedMetadatas) - - let metadatasToChange = processItemMetadatasToUpdate(existingMetadatas: existingMetadatas, - updatedMetadatas: updatedMetadatas, - updateDirectoryEtags: updateDirectoryEtags) - - var metadatasToUpdate = metadatasToChange.updatedMetadatas - let metadatasToCreate = metadatasToChange.newMetadatas - let directoriesNeedingRename = metadatasToChange.directoriesNeedingRename - - let metadatasToAdd = Array(metadatasToUpdate.map { NextcloudItemMetadataTable(value: $0) }) + - Array(metadatasToCreate.map { NextcloudItemMetadataTable(value: $0) }) - - for metadata in directoriesNeedingRename { - - if let updatedDirectoryChildren = renameDirectoryAndPropagateToChildren(ocId: metadata.ocId, newServerUrl: metadata.serverUrl, newFileName: metadata.fileName) { - metadatasToUpdate += updatedDirectoryChildren - } - } - - try database.write { - for metadata in metadatasToDelete { - // Can't pass copies, we need the originals from the database - database.delete(ncDatabase().objects(NextcloudItemMetadataTable.self).filter("ocId == %@", metadata.ocId)) - } - - for metadata in metadatasToAdd { - database.add(metadata, update: .all) - } - - } - - return (newMetadatas: metadatasToCreate, updatedMetadatas: metadatasToUpdate, deletedMetadatas: metadatasToDelete) - } catch let error { - Logger.ncFilesDatabase.error("Could not update any item metadatas, received error: \(error.localizedDescription, privacy: .public)") - return (nil, nil, nil) - } - } - - func setStatusForItemMetadata(_ metadata: NextcloudItemMetadataTable, status: NextcloudItemMetadataTable.Status, completionHandler: @escaping(_ updatedMetadata: NextcloudItemMetadataTable?) -> Void) { - let database = ncDatabase() - - do { - try database.write { - guard let result = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@", metadata.ocId).first else { - Logger.ncFilesDatabase.debug("Did not update status for item metadata as it was not found. ocID: \(metadata.ocId, privacy: .public)") - return - } - - result.status = status.rawValue - database.add(result, update: .all) - Logger.ncFilesDatabase.debug("Updated status for item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") - - completionHandler(NextcloudItemMetadataTable(value: result)) - } - } catch let error { - Logger.ncFilesDatabase.error("Could not update status for item metadata with ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - completionHandler(nil) - } - } - - func addItemMetadata(_ metadata: NextcloudItemMetadataTable) { - let database = ncDatabase() - - do { - try database.write { - database.add(metadata, update: .all) - Logger.ncFilesDatabase.debug("Added item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") - } - } catch let error { - Logger.ncFilesDatabase.error("Could not add item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - } - } - - @discardableResult func deleteItemMetadata(ocId: String) -> Bool { - let database = ncDatabase() - - do { - try database.write { - let results = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@", ocId) - - Logger.ncFilesDatabase.debug("Deleting item metadata. \(ocId, privacy: .public)") - database.delete(results) - } - - return true - } catch let error { - Logger.ncFilesDatabase.error("Could not delete item metadata with ocId: \(ocId, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - return false - } - } - - func renameItemMetadata(ocId: String, newServerUrl: String, newFileName: String) { - let database = ncDatabase() - - do { - try database.write { - guard let itemMetadata = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@", ocId).first else { - Logger.ncFilesDatabase.debug("Could not find an item with ocID \(ocId, privacy: .public) to rename to \(newFileName, privacy: .public)") - return - } - - let oldFileName = itemMetadata.fileName - let oldServerUrl = itemMetadata.serverUrl - - itemMetadata.fileName = newFileName - itemMetadata.fileNameView = newFileName - itemMetadata.serverUrl = newServerUrl - - database.add(itemMetadata, update: .all) - - Logger.ncFilesDatabase.debug("Renamed item \(oldFileName, privacy: .public) to \(newFileName, privacy: .public), moved from serverUrl: \(oldServerUrl, privacy: .public) to serverUrl: \(newServerUrl, privacy: .public)") - } - } catch let error { - Logger.ncFilesDatabase.error("Could not rename filename of item metadata with ocID: \(ocId, privacy: .public) to proposed name \(newFileName, privacy: .public) at proposed serverUrl \(newServerUrl, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - } - } - - func parentItemIdentifierFromMetadata(_ metadata: NextcloudItemMetadataTable) -> NSFileProviderItemIdentifier? { - let homeServerFilesUrl = metadata.urlBase + "/remote.php/dav/files/" + metadata.userId - - if metadata.serverUrl == homeServerFilesUrl { - return .rootContainer - } - - guard let itemParentDirectory = parentDirectoryMetadataForItem(metadata) else { - Logger.ncFilesDatabase.error("Could not get item parent directory metadata for metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") - return nil - } - - if let parentDirectoryMetadata = itemMetadataFromOcId(itemParentDirectory.ocId) { - return NSFileProviderItemIdentifier(parentDirectoryMetadata.ocId) - } - - Logger.ncFilesDatabase.error("Could not get item parent directory item metadata for metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") - return nil - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift deleted file mode 100644 index 29683e7220c68..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import NextcloudKit - -extension NextcloudItemMetadataTable { - static func fromNKFile(_ file: NKFile, account: String) -> NextcloudItemMetadataTable { - let metadata = NextcloudItemMetadataTable() - - metadata.account = account - metadata.checksums = file.checksums - metadata.commentsUnread = file.commentsUnread - metadata.contentType = file.contentType - if let date = file.creationDate { - metadata.creationDate = date as Date - } else { - metadata.creationDate = file.date as Date - } - metadata.dataFingerprint = file.dataFingerprint - metadata.date = file.date as Date - metadata.directory = file.directory - metadata.downloadURL = file.downloadURL - metadata.e2eEncrypted = file.e2eEncrypted - metadata.etag = file.etag - metadata.favorite = file.favorite - metadata.fileId = file.fileId - metadata.fileName = file.fileName - metadata.fileNameView = file.fileName - metadata.hasPreview = file.hasPreview - metadata.iconName = file.iconName - metadata.mountType = file.mountType - metadata.name = file.name - metadata.note = file.note - metadata.ocId = file.ocId - metadata.ownerId = file.ownerId - metadata.ownerDisplayName = file.ownerDisplayName - metadata.lock = file.lock - metadata.lockOwner = file.lockOwner - metadata.lockOwnerEditor = file.lockOwnerEditor - metadata.lockOwnerType = file.lockOwnerType - metadata.lockOwnerDisplayName = file.lockOwnerDisplayName - metadata.lockTime = file.lockTime - metadata.lockTimeOut = file.lockTimeOut - metadata.path = file.path - metadata.permissions = file.permissions - metadata.quotaUsedBytes = file.quotaUsedBytes - metadata.quotaAvailableBytes = file.quotaAvailableBytes - metadata.richWorkspace = file.richWorkspace - metadata.resourceType = file.resourceType - metadata.serverUrl = file.serverUrl - metadata.sharePermissionsCollaborationServices = file.sharePermissionsCollaborationServices - for element in file.sharePermissionsCloudMesh { - metadata.sharePermissionsCloudMesh.append(element) - } - for element in file.shareType { - metadata.shareType.append(element) - } - metadata.size = file.size - metadata.classFile = file.classFile - //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown - if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NKCommon.TypeClassFile.unknow.rawValue { - metadata.classFile = NKCommon.TypeClassFile.document.rawValue - } - if let date = file.uploadDate { - metadata.uploadDate = date as Date - } else { - metadata.uploadDate = file.date as Date - } - metadata.urlBase = file.urlBase - metadata.user = file.user - metadata.userId = file.userId - - // Support for finding the correct filename for e2ee files should go here - - return metadata - } - - static func metadatasFromDirectoryReadNKFiles(_ files: [NKFile], - account: String, - completionHandler: @escaping (_ directoryMetadata: NextcloudItemMetadataTable, - _ childDirectoriesMetadatas: [NextcloudItemMetadataTable], - _ metadatas: [NextcloudItemMetadataTable]) -> Void) { - - var directoryMetadataSet = false - var directoryMetadata = NextcloudItemMetadataTable() - var childDirectoriesMetadatas: [NextcloudItemMetadataTable] = [] - var metadatas: [NextcloudItemMetadataTable] = [] - - let conversionQueue = DispatchQueue(label: "nkFileToMetadataConversionQueue", qos: .userInitiated, attributes: .concurrent) - let appendQueue = DispatchQueue(label: "metadataAppendQueue", qos: .userInitiated) // Serial queue - let dispatchGroup = DispatchGroup() - - for file in files { - if metadatas.isEmpty && !directoryMetadataSet { - let metadata = NextcloudItemMetadataTable.fromNKFile(file, account: account) - directoryMetadata = metadata; - directoryMetadataSet = true; - } else { - conversionQueue.async(group: dispatchGroup) { - let metadata = NextcloudItemMetadataTable.fromNKFile(file, account: account) - - appendQueue.async(group: dispatchGroup) { - metadatas.append(metadata) - if metadata.directory { - childDirectoriesMetadatas.append(metadata) - } - } - } - } - } - - dispatchGroup.notify(queue: DispatchQueue.main) { - completionHandler(directoryMetadata, childDirectoriesMetadatas, metadatas) - } - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift deleted file mode 100644 index 44b1ddf95ce0b..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import RealmSwift -import FileProvider -import NextcloudKit - -class NextcloudItemMetadataTable: Object { - enum Status: Int { - case downloadError = -4 - case downloading = -3 - case inDownload = -2 - case waitDownload = -1 - - case normal = 0 - - case waitUpload = 1 - case inUpload = 2 - case uploading = 3 - case uploadError = 4 - } - - enum SharePermissions: Int { - case readShare = 1 - case updateShare = 2 - case createShare = 4 - case deleteShare = 8 - case shareShare = 16 - - case maxFileShare = 19 - case maxFolderShare = 31 - } - - @Persisted(primaryKey: true) var ocId: String - @Persisted var account = "" - @Persisted var assetLocalIdentifier = "" - @Persisted var checksums = "" - @Persisted var chunk: Bool = false - @Persisted var classFile = "" - @Persisted var commentsUnread: Bool = false - @Persisted var contentType = "" - @Persisted var creationDate = Date() - @Persisted var dataFingerprint = "" - @Persisted var date = Date() - @Persisted var directory: Bool = false - @Persisted var deleteAssetLocalIdentifier: Bool = false - @Persisted var downloadURL = "" - @Persisted var e2eEncrypted: Bool = false - @Persisted var edited: Bool = false - @Persisted var etag = "" - @Persisted var etagResource = "" - @Persisted var favorite: Bool = false - @Persisted var fileId = "" - @Persisted var fileName = "" - @Persisted var fileNameView = "" - @Persisted var hasPreview: Bool = false - @Persisted var iconName = "" - @Persisted var iconUrl = "" - @Persisted var isExtractFile: Bool = false - @Persisted var livePhoto: Bool = false - @Persisted var mountType = "" - @Persisted var name = "" // for unifiedSearch is the provider.id - @Persisted var note = "" - @Persisted var ownerId = "" - @Persisted var ownerDisplayName = "" - @Persisted var lock = false - @Persisted var lockOwner = "" - @Persisted var lockOwnerEditor = "" - @Persisted var lockOwnerType = 0 - @Persisted var lockOwnerDisplayName = "" - @Persisted var lockTime: Date? - @Persisted var lockTimeOut: Date? - @Persisted var path = "" - @Persisted var permissions = "" - @Persisted var quotaUsedBytes: Int64 = 0 - @Persisted var quotaAvailableBytes: Int64 = 0 - @Persisted var resourceType = "" - @Persisted var richWorkspace: String? - @Persisted var serverUrl = "" // For parent directory!! - @Persisted var session = "" - @Persisted var sessionError = "" - @Persisted var sessionSelector = "" - @Persisted var sessionTaskIdentifier: Int = 0 - @Persisted var sharePermissionsCollaborationServices: Int = 0 - let sharePermissionsCloudMesh = List() // TODO: Find a way to compare these in remote state check - let shareType = List() - @Persisted var size: Int64 = 0 - @Persisted var status: Int = 0 - @Persisted var subline: String? - @Persisted var trashbinFileName = "" - @Persisted var trashbinOriginalLocation = "" - @Persisted var trashbinDeletionTime = Date() - @Persisted var uploadDate = Date() - @Persisted var url = "" - @Persisted var urlBase = "" - @Persisted var user = "" - @Persisted var userId = "" - - var fileExtension: String { - (fileNameView as NSString).pathExtension - } - - var fileNoExtension: String { - (fileNameView as NSString).deletingPathExtension - } - - var isRenameable: Bool { - return lock - } - - var isPrintable: Bool { - if isDocumentViewableOnly { - return false - } - if ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/") || classFile == NKCommon.TypeClassFile.image.rawValue { - return true - } - return false - } - - var isDocumentViewableOnly: Bool { - return sharePermissionsCollaborationServices == SharePermissions.readShare.rawValue && - classFile == NKCommon.TypeClassFile.document.rawValue - } - - var isCopyableInPasteboard: Bool { - !isDocumentViewableOnly && !directory - } - - var isModifiableWithQuickLook: Bool { - if directory || isDocumentViewableOnly { - return false - } - return contentType == "com.adobe.pdf" || contentType == "application/pdf" || classFile == NKCommon.TypeClassFile.image.rawValue - } - - var isSettableOnOffline: Bool { - return session.isEmpty && !isDocumentViewableOnly - } - - var canOpenIn: Bool { - return session.isEmpty && !isDocumentViewableOnly && !directory - } - - var isDownloadUpload: Bool { - return status == Status.inDownload.rawValue || - status == Status.downloading.rawValue || - status == Status.inUpload.rawValue || - status == Status.uploading.rawValue - } - - var isDownload: Bool { - status == Status.inDownload.rawValue || status == Status.downloading.rawValue - } - - var isUpload: Bool { - status == Status.inUpload.rawValue || status == Status.uploading.rawValue - } - - override func isEqual(_ object: Any?) -> Bool { - if let object = object as? NextcloudItemMetadataTable { - return self.fileId == object.fileId && - self.account == object.account && - self.path == object.path && - self.fileName == object.fileName - } - - return false - } - - func isInSameDatabaseStoreableRemoteState(_ comparingMetadata: NextcloudItemMetadataTable) -> Bool { - return comparingMetadata.etag == self.etag && - comparingMetadata.fileNameView == self.fileNameView && - comparingMetadata.date == self.date && - comparingMetadata.permissions == self.permissions && - comparingMetadata.hasPreview == self.hasPreview && - comparingMetadata.note == self.note && - comparingMetadata.lock == self.lock && - comparingMetadata.sharePermissionsCollaborationServices == self.sharePermissionsCollaborationServices && - comparingMetadata.favorite == self.favorite - } - - /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else - func canUnlock(as user: String) -> Bool { - return !lock || (lockOwner == user && lockOwnerType == 0) - } - - func thumbnailUrl(size: CGSize) -> URL? { - guard hasPreview else { - return nil - } - - let urlBase = urlBase.urlEncoded! - let webdavUrl = urlBase + NextcloudAccount.webDavFilesUrlSuffix + user // Leave the leading slash - let serverFileRelativeUrl = serverUrl.replacingOccurrences(of: webdavUrl, with: "") + "/" + fileName - - let urlString = "\(urlBase)/index.php/core/preview.png?file=\(serverFileRelativeUrl)&x=\(size.width)&y=\(size.height)&a=1&mode=cover" - - return URL(string: urlString) - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudLocalFileMetadataTable.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudLocalFileMetadataTable.swift deleted file mode 100644 index 7eda4817c0253..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudLocalFileMetadataTable.swift +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import RealmSwift - -class NextcloudLocalFileMetadataTable: Object { - @Persisted(primaryKey: true) var ocId: String - @Persisted var account = "" - @Persisted var etag = "" - @Persisted var exifDate: Date? - @Persisted var exifLatitude = "" - @Persisted var exifLongitude = "" - @Persisted var exifLensModel: String? - @Persisted var favorite: Bool = false - @Persisted var fileName = "" - @Persisted var offline: Bool = false -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift deleted file mode 100644 index 97119492821fb..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import OSLog - -extension Logger { - private static var subsystem = Bundle.main.bundleIdentifier! - - static let desktopClientConnection = Logger(subsystem: subsystem, category: "desktopclientconnection") - static let enumeration = Logger(subsystem: subsystem, category: "enumeration") - static let fileProviderExtension = Logger(subsystem: subsystem, category: "fileproviderextension") - static let fileTransfer = Logger(subsystem: subsystem, category: "filetransfer") - static let localFileOps = Logger(subsystem: subsystem, category: "localfileoperations") - static let ncFilesDatabase = Logger(subsystem: subsystem, category: "nextcloudfilesdatabase") - static let materialisedFileHandling = Logger(subsystem: subsystem, category: "materialisedfilehandling") -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift deleted file mode 100644 index f9ca6681faf41..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import FileProvider -import NextcloudKit - -extension NKError { - static var noChangesErrorCode: Int { - return -200 - } - - var isCouldntConnectError: Bool { - return errorCode == -9999 || - errorCode == -1001 || - errorCode == -1004 || - errorCode == -1005 || - errorCode == -1009 || - errorCode == -1012 || - errorCode == -1200 || - errorCode == -1202 || - errorCode == 500 || - errorCode == 503 || - errorCode == 200 - } - - var isUnauthenticatedError: Bool { - return errorCode == -1013 - } - - var isGoingOverQuotaError: Bool { - return errorCode == 507 - } - - var isNotFoundError: Bool { - return errorCode == 404 - } - - var isNoChangesError: Bool { - return errorCode == NKError.noChangesErrorCode - } - - var fileProviderError: NSFileProviderError { - if isNotFoundError { - return NSFileProviderError(.noSuchItem) - } else if isCouldntConnectError { - // Provide something the file provider can do something with - return NSFileProviderError(.serverUnreachable) - } else if isUnauthenticatedError { - return NSFileProviderError(.notAuthenticated) - } else if isGoingOverQuotaError { - return NSFileProviderError(.insufficientQuota) - } else { - return NSFileProviderError(.cannotSynchronize) - } - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift deleted file mode 100644 index e15e2e0adf0ff..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import Alamofire - -extension Progress { - func setHandlersFromAfRequest(_ request: Request) { - self.cancellationHandler = { request.cancel() } - self.pausingHandler = { request.suspend() } - self.resumingHandler = { request.resume() } - } - - func copyCurrentStateToProgress(_ otherProgress: Progress, includeHandlers: Bool = false) { - if includeHandlers { - otherProgress.cancellationHandler = self.cancellationHandler - otherProgress.pausingHandler = self.pausingHandler - otherProgress.resumingHandler = self.resumingHandler - } - - otherProgress.totalUnitCount = self.totalUnitCount - otherProgress.completedUnitCount = self.completedUnitCount - otherProgress.estimatedTimeRemaining = self.estimatedTimeRemaining - otherProgress.localizedDescription = self.localizedAdditionalDescription - otherProgress.localizedAdditionalDescription = self.localizedAdditionalDescription - otherProgress.isCancellable = self.isCancellable - otherProgress.isPausable = self.isPausable - otherProgress.fileCompletedCount = self.fileCompletedCount - otherProgress.fileURL = self.fileURL - otherProgress.fileTotalCount = self.fileTotalCount - otherProgress.fileCompletedCount = self.fileCompletedCount - otherProgress.fileOperationKind = self.fileOperationKind - otherProgress.kind = self.kind - otherProgress.throughput = self.throughput - - for (key, object) in self.userInfo { - otherProgress.setUserInfoObject(object, forKey: key) - } - } - - func copyOfCurrentState(includeHandlers: Bool = false) -> Progress { - let newProgress = Progress() - copyCurrentStateToProgress(newProgress, includeHandlers: includeHandlers) - return newProgress - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift deleted file mode 100644 index fdd81f83f0932..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import FileProvider -import NextcloudKit -import OSLog - -extension FileProviderEnumerator { - func fullRecursiveScan(ncAccount: NextcloudAccount, - ncKit: NextcloudKit, - scanChangesOnly: Bool, - completionHandler: @escaping(_ metadatas: [NextcloudItemMetadataTable], - _ newMetadatas: [NextcloudItemMetadataTable], - _ updatedMetadatas: [NextcloudItemMetadataTable], - _ deletedMetadatas: [NextcloudItemMetadataTable], - _ error: NKError?) -> Void) { - - let rootContainerDirectoryMetadata = NextcloudItemMetadataTable() - rootContainerDirectoryMetadata.directory = true - rootContainerDirectoryMetadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue - - // Create a serial dispatch queue - let dispatchQueue = DispatchQueue(label: "recursiveChangeEnumerationQueue", qos: .userInitiated) - - dispatchQueue.async { - let results = self.scanRecursively(rootContainerDirectoryMetadata, - ncAccount: ncAccount, - ncKit: ncKit, - scanChangesOnly: scanChangesOnly) - - // Run a check to ensure files deleted in one location are not updated in another (e.g. when moved) - // The recursive scan provides us with updated/deleted metadatas only on a folder by folder basis; - // so we need to check we are not simultaneously marking a moved file as deleted and updated - var checkedDeletedMetadatas = results.deletedMetadatas - - for updatedMetadata in results.updatedMetadatas { - guard let matchingDeletedMetadataIdx = checkedDeletedMetadatas.firstIndex(where: { $0.ocId == updatedMetadata.ocId } ) else { - continue; - } - - checkedDeletedMetadatas.remove(at: matchingDeletedMetadataIdx) - } - - DispatchQueue.main.async { - completionHandler(results.metadatas, results.newMetadatas, results.updatedMetadatas, checkedDeletedMetadatas, results.error) - } - } - } - - private func scanRecursively(_ directoryMetadata: NextcloudItemMetadataTable, - ncAccount: NextcloudAccount, - ncKit: NextcloudKit, - scanChangesOnly: Bool) -> (metadatas: [NextcloudItemMetadataTable], - newMetadatas: [NextcloudItemMetadataTable], - updatedMetadatas: [NextcloudItemMetadataTable], - deletedMetadatas: [NextcloudItemMetadataTable], - error: NKError?) { - - if self.isInvalidated { - return ([], [], [], [], nil) - } - - assert(directoryMetadata.directory, "Can only recursively scan a directory.") - - // Will include results of recursive calls - var allMetadatas: [NextcloudItemMetadataTable] = [] - var allNewMetadatas: [NextcloudItemMetadataTable] = [] - var allUpdatedMetadatas: [NextcloudItemMetadataTable] = [] - var allDeletedMetadatas: [NextcloudItemMetadataTable] = [] - - let dbManager = NextcloudFilesDatabaseManager.shared - let dispatchGroup = DispatchGroup() // TODO: Maybe own thread? - - dispatchGroup.enter() - - var criticalError: NKError? - let itemServerUrl = directoryMetadata.ocId == NSFileProviderItemIdentifier.rootContainer.rawValue ? - ncAccount.davFilesUrl : directoryMetadata.serverUrl + "/" + directoryMetadata.fileName - - Logger.enumeration.debug("About to read: \(itemServerUrl, privacy: .public)") - - FileProviderEnumerator.readServerUrl(itemServerUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: scanChangesOnly) { metadatas, newMetadatas, updatedMetadatas, deletedMetadatas, readError in - - if readError != nil { - let nkReadError = NKError(error: readError!) - - // Is the error is that we have found matching etags on this item, then ignore it - // if we are doing a full rescan - guard nkReadError.isNoChangesError && scanChangesOnly else { - Logger.enumeration.error("Finishing enumeration of changes at \(itemServerUrl, privacy: .public) with \(readError!.localizedDescription, privacy: .public)") - - if nkReadError.isNotFoundError { - Logger.enumeration.info("404 error means item no longer exists. Deleting metadata and reporting as deletion without error") - - if let deletedMetadatas = dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: directoryMetadata.ocId) { - allDeletedMetadatas += deletedMetadatas - } else { - Logger.enumeration.error("An error occurred while trying to delete directory and children not found in recursive scan") - } - - } else if nkReadError.isNoChangesError { // All is well, just no changed etags - Logger.enumeration.info("Error was to say no changed files -- not bad error. No need to check children.") - - } else if nkReadError.isUnauthenticatedError || nkReadError.isCouldntConnectError { - // If it is a critical error then stop, if not then continue - Logger.enumeration.error("Error will affect next enumerated items, so stopping enumeration.") - criticalError = nkReadError - - } - - dispatchGroup.leave() - return - } - } - - Logger.enumeration.info("Finished reading serverUrl: \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - - if let metadatas = metadatas { - allMetadatas += metadatas - } else { - Logger.enumeration.warning("WARNING: Nil metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - } - - if let newMetadatas = newMetadatas { - allNewMetadatas += newMetadatas - } else { - Logger.enumeration.warning("WARNING: Nil new metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - } - - if let updatedMetadatas = updatedMetadatas { - allUpdatedMetadatas += updatedMetadatas - } else { - Logger.enumeration.warning("WARNING: Nil updated metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - } - - if let deletedMetadatas = deletedMetadatas { - allDeletedMetadatas += deletedMetadatas - } else { - Logger.enumeration.warning("WARNING: Nil deleted metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - } - - dispatchGroup.leave() - } - - dispatchGroup.wait() - - guard criticalError == nil else { - return ([], [], [], [], error: criticalError) - } - - var childDirectoriesToScan: [NextcloudItemMetadataTable] = [] - var candidateMetadatas: [NextcloudItemMetadataTable] - - if scanChangesOnly { - candidateMetadatas = allUpdatedMetadatas + allNewMetadatas - } else { - candidateMetadatas = allMetadatas - } - - for candidateMetadata in candidateMetadatas { - if candidateMetadata.directory { - childDirectoriesToScan.append(candidateMetadata) - } - } - - if childDirectoriesToScan.isEmpty { - return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas, nil) - } - - for childDirectory in childDirectoriesToScan { - let childScanResult = scanRecursively(childDirectory, - ncAccount: ncAccount, - ncKit: ncKit, - scanChangesOnly: scanChangesOnly) - - allMetadatas += childScanResult.metadatas - allNewMetadatas += childScanResult.newMetadatas - allUpdatedMetadatas += childScanResult.updatedMetadatas - allDeletedMetadatas += childScanResult.deletedMetadatas - } - - return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas, nil) - } - - static func handleDepth1ReadFileOrFolder(serverUrl: String, - ncAccount: NextcloudAccount, - files: [NKFile], - error: NKError, - completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, - _ newMetadatas: [NextcloudItemMetadataTable]?, - _ updatedMetadatas: [NextcloudItemMetadataTable]?, - _ deletedMetadatas: [NextcloudItemMetadataTable]?, - _ readError: Error?) -> Void) { - - guard error == .success else { - Logger.enumeration.error("1 depth readFileOrFolder of url: \(serverUrl, privacy: .public) did not complete successfully, received error: \(error.errorDescription, privacy: .public)") - completionHandler(nil, nil, nil, nil, error.error) - return - } - - Logger.enumeration.debug("Starting async conversion of NKFiles for serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - - let dbManager = NextcloudFilesDatabaseManager.shared - - DispatchQueue.global(qos: .userInitiated).async { - NextcloudItemMetadataTable.metadatasFromDirectoryReadNKFiles(files, account: ncAccount.ncKitAccount) { directoryMetadata, childDirectoriesMetadata, metadatas in - - // STORE DATA FOR CURRENTLY SCANNED DIRECTORY - // We have now scanned this directory's contents, so update with etag in order to not check again if not needed - // unless it's the root container - if serverUrl != ncAccount.davFilesUrl { - dbManager.addItemMetadata(directoryMetadata) - } - - // Don't update the etags for folders as we haven't checked their contents. - // When we do a recursive check, if we update the etags now, we will think - // that our local copies are up to date -- instead, leave them as the old. - // They will get updated when they are the subject of a readServerUrl call. - // (See above) - let changedMetadatas = dbManager.updateItemMetadatas(account: ncAccount.ncKitAccount, serverUrl: serverUrl, updatedMetadatas: metadatas, updateDirectoryEtags: false) - - DispatchQueue.main.async { - completionHandler(metadatas, changedMetadatas.newMetadatas, changedMetadatas.updatedMetadatas, changedMetadatas.deletedMetadatas, nil) - } - } - } - } - - static func readServerUrl(_ serverUrl: String, - ncAccount: NextcloudAccount, - ncKit: NextcloudKit, - stopAtMatchingEtags: Bool = false, - depth: String = "1", - completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, - _ newMetadatas: [NextcloudItemMetadataTable]?, - _ updatedMetadatas: [NextcloudItemMetadataTable]?, - _ deletedMetadatas: [NextcloudItemMetadataTable]?, - _ readError: Error?) -> Void) { - - let dbManager = NextcloudFilesDatabaseManager.shared - let ncKitAccount = ncAccount.ncKitAccount - - Logger.enumeration.debug("Starting to read serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public) at depth \(depth, privacy: .public). NCKit info: userId: \(ncKit.nkCommonInstance.user, privacy: .public), password is empty: \(ncKit.nkCommonInstance.password == "" ? "EMPTY PASSWORD" : "NOT EMPTY PASSWORD"), urlBase: \(ncKit.nkCommonInstance.urlBase, privacy: .public), ncVersion: \(ncKit.nkCommonInstance.nextcloudVersion, privacy: .public)") - - ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: depth, showHiddenFiles: true) { _, files, _, error in - guard error == .success else { - Logger.enumeration.error("\(depth, privacy: .public) depth readFileOrFolder of url: \(serverUrl, privacy: .public) did not complete successfully, received error: \(error.errorDescription, privacy: .public)") - completionHandler(nil, nil, nil, nil, error.error) - return - } - - guard let receivedFile = files.first else { - Logger.enumeration.error("Received no items from readFileOrFolder of \(serverUrl, privacy: .public), not much we can do...") - completionHandler(nil, nil, nil, nil, error.error) - return - } - - guard receivedFile.directory else { - Logger.enumeration.debug("Read item is a file. Converting NKfile for serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - let itemMetadata = NextcloudItemMetadataTable.fromNKFile(receivedFile, account: ncKitAccount) - dbManager.addItemMetadata(itemMetadata) // TODO: Return some value when it is an update - completionHandler([itemMetadata], nil, nil, nil, error.error) - return - } - - if stopAtMatchingEtags, - let directoryMetadata = dbManager.directoryMetadata(account: ncKitAccount, serverUrl: serverUrl) { - - let directoryEtag = directoryMetadata.etag - - guard directoryEtag == "" || directoryEtag != receivedFile.etag else { - Logger.enumeration.debug("Read server url called with flag to stop enumerating at matching etags. Returning and providing soft error.") - - let description = "Fetched directory etag is same as that stored locally. Not fetching child items." - let nkError = NKError(errorCode: NKError.noChangesErrorCode, errorDescription: description) - - let metadatas = dbManager.itemMetadatas(account: ncKitAccount, serverUrl: serverUrl) - - completionHandler(metadatas, nil, nil, nil, nkError.error) - return - } - } - - if depth == "0" { - if serverUrl != ncAccount.davFilesUrl { - let metadata = NextcloudItemMetadataTable.fromNKFile(receivedFile, account: ncKitAccount) - let isNew = dbManager.itemMetadataFromOcId(metadata.ocId) == nil - let updatedMetadatas = isNew ? [] : [metadata] - let newMetadatas = isNew ? [metadata] : [] - - dbManager.addItemMetadata(metadata) - - DispatchQueue.main.async { - completionHandler([metadata], newMetadatas, updatedMetadatas, nil, nil) - } - } - } else { - handleDepth1ReadFileOrFolder(serverUrl: serverUrl, ncAccount: ncAccount, files: files, error: error, completionHandler: completionHandler) - } - } - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift deleted file mode 100644 index a9dfacc9ff433..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import FileProvider -import NextcloudKit -import OSLog - -class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { - - private let enumeratedItemIdentifier: NSFileProviderItemIdentifier - private var enumeratedItemMetadata: NextcloudItemMetadataTable? - private var enumeratingSystemIdentifier: Bool { - return FileProviderEnumerator.isSystemIdentifier(enumeratedItemIdentifier) - } - private let anchor = NSFileProviderSyncAnchor(Date().description.data(using: .utf8)!) // TODO: actually use this in NCKit and server requests - private static let maxItemsPerFileProviderPage = 100 - let ncAccount: NextcloudAccount - let ncKit: NextcloudKit - var serverUrl: String = "" - var isInvalidated = false - - private static func isSystemIdentifier(_ identifier: NSFileProviderItemIdentifier) -> Bool { - return identifier == .rootContainer || - identifier == .trashContainer || - identifier == .workingSet - } - - init(enumeratedItemIdentifier: NSFileProviderItemIdentifier, ncAccount: NextcloudAccount, ncKit: NextcloudKit) { - self.enumeratedItemIdentifier = enumeratedItemIdentifier - self.ncAccount = ncAccount - self.ncKit = ncKit - - if FileProviderEnumerator.isSystemIdentifier(enumeratedItemIdentifier) { - Logger.enumeration.debug("Providing enumerator for a system defined container: \(enumeratedItemIdentifier.rawValue, privacy: .public)") - self.serverUrl = ncAccount.davFilesUrl - } else { - Logger.enumeration.debug("Providing enumerator for item with identifier: \(enumeratedItemIdentifier.rawValue, privacy: .public)") - let dbManager = NextcloudFilesDatabaseManager.shared - - enumeratedItemMetadata = dbManager.itemMetadataFromFileProviderItemIdentifier(enumeratedItemIdentifier) - if enumeratedItemMetadata != nil { - self.serverUrl = enumeratedItemMetadata!.serverUrl + "/" + enumeratedItemMetadata!.fileName - } else { - Logger.enumeration.error("Could not find itemMetadata for file with identifier: \(enumeratedItemIdentifier.rawValue, privacy: .public)") - } - } - - Logger.enumeration.info("Set up enumerator for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - super.init() - } - - func invalidate() { - Logger.enumeration.debug("Enumerator is being invalidated for item with identifier: \(self.enumeratedItemIdentifier.rawValue, privacy: .public)") - self.isInvalidated = true - } - - // MARK: - Protocol methods - - func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) { - Logger.enumeration.debug("Received enumerate items request for enumerator with user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - /* - - inspect the page to determine whether this is an initial or a follow-up request (TODO) - - If this is an enumerator for a directory, the root container or all directories: - - perform a server request to fetch directory contents - If this is an enumerator for the working set: - - perform a server request to update your local database - - fetch the working set from your local database - - - inform the observer about the items returned by the server (possibly multiple times) - - inform the observer that you are finished with this page - */ - - if enumeratedItemIdentifier == .trashContainer { - Logger.enumeration.debug("Enumerating trash set for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - // TODO! - - observer.finishEnumerating(upTo: nil) - return - } - - // Handle the working set as if it were the root container - // If we do a full server scan per the recommendations of the File Provider documentation, - // we will be stuck for a huge period of time without being able to access files as the - // entire server gets scanned. Instead, treat the working set as the root container here. - // Then, when we enumerate changes, we'll go through everything -- while we can still - // navigate a little bit in Finder, file picker, etc - - guard serverUrl != "" else { - Logger.enumeration.error("Enumerator has empty serverUrl -- can't enumerate that! For identifier: \(self.enumeratedItemIdentifier.rawValue, privacy: .public)") - observer.finishEnumeratingWithError(NSFileProviderError(.noSuchItem)) - return - } - - // TODO: Make better use of pagination and handle paging properly - if page == NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage || - page == NSFileProviderPage.initialPageSortedByName as NSFileProviderPage { - - Logger.enumeration.debug("Enumerating initial page for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - - FileProviderEnumerator.readServerUrl(serverUrl, ncAccount: ncAccount, ncKit: ncKit) { metadatas, _, _, _, readError in - - guard readError == nil else { - Logger.enumeration.error("Finishing enumeration for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with error \(readError!.localizedDescription, privacy: .public)") - - let nkReadError = NKError(error: readError!) - observer.finishEnumeratingWithError(nkReadError.fileProviderError) - return - } - - guard let metadatas = metadatas else { - Logger.enumeration.error("Finishing enumeration for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with invalid metadatas.") - observer.finishEnumeratingWithError(NSFileProviderError(.cannotSynchronize)) - return - } - - Logger.enumeration.info("Finished reading serverUrl: \(self.serverUrl, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public). Processed \(metadatas.count) metadatas") - - FileProviderEnumerator.completeEnumerationObserver(observer, ncKit: self.ncKit, numPage: 1, itemMetadatas: metadatas) - } - - return; - } - - let numPage = Int(String(data: page.rawValue, encoding: .utf8)!)! - Logger.enumeration.debug("Enumerating page \(numPage, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - // TODO: Handle paging properly - // FileProviderEnumerator.completeObserver(observer, ncKit: ncKit, numPage: numPage, itemMetadatas: nil) - observer.finishEnumerating(upTo: nil) - } - - func enumerateChanges(for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor) { - Logger.enumeration.debug("Received enumerate changes request for enumerator for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - /* - - query the server for updates since the passed-in sync anchor (TODO) - - If this is an enumerator for the working set: - - note the changes in your local database - - - inform the observer about item deletions and updates (modifications + insertions) - - inform the observer when you have finished enumerating up to a subsequent sync anchor - */ - - if enumeratedItemIdentifier == .workingSet { - Logger.enumeration.debug("Enumerating changes in working set for user: \(self.ncAccount.ncKitAccount, privacy: .public)") - - // Unlike when enumerating items we can't progressively enumerate items as we need to wait to resolve which items are truly deleted and which - // have just been moved elsewhere. - fullRecursiveScan(ncAccount: self.ncAccount, - ncKit: self.ncKit, - scanChangesOnly: true) { _, newMetadatas, updatedMetadatas, deletedMetadatas, error in - - if self.isInvalidated { - Logger.enumeration.info("Enumerator invalidated during working set change scan. For user: \(self.ncAccount.ncKitAccount, privacy: .public)") - observer.finishEnumeratingWithError(NSFileProviderError(.cannotSynchronize)) - return - } - - guard error == nil else { - Logger.enumeration.info("Finished recursive change enumeration of working set for user: \(self.ncAccount.ncKitAccount, privacy: .public) with error: \(error!.errorDescription, privacy: .public)") - observer.finishEnumeratingWithError(error!.fileProviderError) - return - } - - Logger.enumeration.info("Finished recursive change enumeration of working set for user: \(self.ncAccount.ncKitAccount, privacy: .public). Enumerating items.") - - FileProviderEnumerator.completeChangesObserver(observer, - anchor: anchor, - ncKit: self.ncKit, - newMetadatas: newMetadatas, - updatedMetadatas: updatedMetadatas, - deletedMetadatas: deletedMetadatas) - } - return - } else if enumeratedItemIdentifier == .trashContainer { - Logger.enumeration.debug("Enumerating changes in trash set for user: \(self.ncAccount.ncKitAccount, privacy: .public)") - // TODO! - - observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) - return - } - - Logger.enumeration.info("Enumerating changes for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - - // No matter what happens here we finish enumeration in some way, either from the error - // handling below or from the completeChangesObserver - // TODO: Move to the sync engine extension - FileProviderEnumerator.readServerUrl(serverUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: true) { _, newMetadatas, updatedMetadatas, deletedMetadatas, readError in - - // If we get a 404 we might add more deleted metadatas - var currentDeletedMetadatas: [NextcloudItemMetadataTable] = [] - if let notNilDeletedMetadatas = deletedMetadatas { - currentDeletedMetadatas = notNilDeletedMetadatas - } - - guard readError == nil else { - Logger.enumeration.error("Finishing enumeration of changes for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with error: \(readError!.localizedDescription, privacy: .public)") - - let nkReadError = NKError(error: readError!) - let fpError = nkReadError.fileProviderError - - if nkReadError.isNotFoundError { - Logger.enumeration.info("404 error means item no longer exists. Deleting metadata and reporting \(self.serverUrl, privacy: .public) as deletion without error") - - guard let itemMetadata = self.enumeratedItemMetadata else { - Logger.enumeration.error("Invalid enumeratedItemMetadata, could not delete metadata nor report deletion") - observer.finishEnumeratingWithError(fpError) - return - } - - let dbManager = NextcloudFilesDatabaseManager.shared - if itemMetadata.directory { - if let deletedDirectoryMetadatas = dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: itemMetadata.ocId) { - currentDeletedMetadatas += deletedDirectoryMetadatas - } else { - Logger.enumeration.error("Something went wrong when recursively deleting directory not found.") - } - } else { - dbManager.deleteItemMetadata(ocId: itemMetadata.ocId) - } - - FileProviderEnumerator.completeChangesObserver(observer, anchor: anchor, ncKit: self.ncKit, newMetadatas: nil, updatedMetadatas: nil, deletedMetadatas: [itemMetadata]) - return - } else if nkReadError.isNoChangesError { // All is well, just no changed etags - Logger.enumeration.info("Error was to say no changed files -- not bad error. Finishing change enumeration.") - observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) - return; - } - - observer.finishEnumeratingWithError(fpError) - return - } - - Logger.enumeration.info("Finished reading serverUrl: \(self.serverUrl, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public)") - - FileProviderEnumerator.completeChangesObserver(observer, anchor: anchor, ncKit: self.ncKit, newMetadatas: newMetadatas, updatedMetadatas: updatedMetadatas, deletedMetadatas: deletedMetadatas) - } - } - - func currentSyncAnchor(completionHandler: @escaping (NSFileProviderSyncAnchor?) -> Void) { - completionHandler(anchor) - } - - // MARK: - Helper methods - - private static func metadatasToFileProviderItems(_ itemMetadatas: [NextcloudItemMetadataTable], ncKit: NextcloudKit, completionHandler: @escaping(_ items: [NSFileProviderItem]) -> Void) { - var items: [NSFileProviderItem] = [] - - let conversionQueue = DispatchQueue(label: "metadataToItemConversionQueue", qos: .userInitiated, attributes: .concurrent) - let appendQueue = DispatchQueue(label: "enumeratorItemAppendQueue", qos: .userInitiated) // Serial queue - let dispatchGroup = DispatchGroup() - - for itemMetadata in itemMetadatas { - conversionQueue.async(group: dispatchGroup) { - if itemMetadata.e2eEncrypted { - Logger.enumeration.info("Skipping encrypted metadata in enumeration: \(itemMetadata.ocId, privacy: .public) \(itemMetadata.fileName, privacy: .public)") - return - } - - if let parentItemIdentifier = NextcloudFilesDatabaseManager.shared.parentItemIdentifierFromMetadata(itemMetadata) { - let item = FileProviderItem(metadata: itemMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit) - Logger.enumeration.debug("Will enumerate item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: .public)") - - appendQueue.async(group: dispatchGroup) { - items.append(item) - } - } else { - Logger.enumeration.error("Could not get valid parentItemIdentifier for item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: .public), skipping enumeration") - } - } - } - - dispatchGroup.notify(queue: DispatchQueue.main) { - completionHandler(items) - } - } - - private static func fileProviderPageforNumPage(_ numPage: Int) -> NSFileProviderPage { - return NSFileProviderPage("\(numPage)".data(using: .utf8)!) - } - - private static func completeEnumerationObserver(_ observer: NSFileProviderEnumerationObserver, ncKit: NextcloudKit, numPage: Int, itemMetadatas: [NextcloudItemMetadataTable]) { - - metadatasToFileProviderItems(itemMetadatas, ncKit: ncKit) { items in - observer.didEnumerate(items) - Logger.enumeration.info("Did enumerate \(items.count) items") - - // TODO: Handle paging properly - /* - if items.count == maxItemsPerFileProviderPage { - let nextPage = numPage + 1 - let providerPage = NSFileProviderPage("\(nextPage)".data(using: .utf8)!) - observer.finishEnumerating(upTo: providerPage) - } else { - observer.finishEnumerating(upTo: nil) - } - */ - observer.finishEnumerating(upTo: fileProviderPageforNumPage(numPage)) - } - } - - private static func completeChangesObserver(_ observer: NSFileProviderChangeObserver, anchor: NSFileProviderSyncAnchor, ncKit: NextcloudKit, newMetadatas: [NextcloudItemMetadataTable]?, updatedMetadatas: [NextcloudItemMetadataTable]?, deletedMetadatas: [NextcloudItemMetadataTable]?) { - - guard newMetadatas != nil || updatedMetadatas != nil || deletedMetadatas != nil else { - Logger.enumeration.error("Received invalid newMetadatas, updatedMetadatas or deletedMetadatas. Finished enumeration of changes with error.") - observer.finishEnumeratingWithError(NSFileProviderError(.noSuchItem)) - return - } - - // Observer does not care about new vs updated, so join - var allUpdatedMetadatas: [NextcloudItemMetadataTable] = [] - var allDeletedMetadatas: [NextcloudItemMetadataTable] = [] - - if let newMetadatas = newMetadatas { - allUpdatedMetadatas += newMetadatas - } - - if let updatedMetadatas = updatedMetadatas { - allUpdatedMetadatas += updatedMetadatas - } - - if let deletedMetadatas = deletedMetadatas { - allDeletedMetadatas = deletedMetadatas - } - - let allFpItemDeletionsIdentifiers = Array(allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) }) - if !allFpItemDeletionsIdentifiers.isEmpty { - observer.didDeleteItems(withIdentifiers: allFpItemDeletionsIdentifiers) - } - - metadatasToFileProviderItems(allUpdatedMetadatas, ncKit: ncKit) { updatedItems in - - if !updatedItems.isEmpty { - observer.didUpdate(updatedItems) - } - - Logger.enumeration.info("Processed \(updatedItems.count) new or updated metadatas, \(allDeletedMetadatas.count) deleted metadatas.") - observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) - } - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt.entitlements b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt.entitlements deleted file mode 100644 index eab912dc49600..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt.entitlements +++ /dev/null @@ -1,16 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.application-groups - - $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) - - com.apple.security.network.client - - com.apple.security.network.server - - - diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift deleted file mode 100644 index dd3bef8d87380..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import FileProvider -import OSLog -import NCDesktopClientSocketKit -import NextcloudKit - -extension FileProviderExtension { - func sendFileProviderDomainIdentifier() { - let command = "FILE_PROVIDER_DOMAIN_IDENTIFIER_REQUEST_REPLY" - let argument = domain.identifier.rawValue - let message = command + ":" + argument + "\n" - socketClient?.sendMessage(message) - } - - private func signalEnumeratorAfterAccountSetup() { - guard let fpManager = NSFileProviderManager(for: domain) else { - Logger.fileProviderExtension.error("Could not get file provider manager for domain \(self.domain.displayName, privacy: .public), cannot notify after account setup") - return - } - - assert(ncAccount != nil) - - fpManager.signalErrorResolved(NSFileProviderError(.notAuthenticated)) { error in - if error != nil { - Logger.fileProviderExtension.error("Error resolving not authenticated, received error: \(error!.localizedDescription)") - } - } - - Logger.fileProviderExtension.debug("Signalling enumerators for user \(self.ncAccount!.username) at server \(self.ncAccount!.serverUrl, privacy: .public)") - - fpManager.signalEnumerator(for: .workingSet) { error in - if error != nil { - Logger.fileProviderExtension.error("Error signalling enumerator for working set, received error: \(error!.localizedDescription, privacy: .public)") - } - } - } - - func setupDomainAccount(user: String, serverUrl: String, password: String) { - ncAccount = NextcloudAccount(user: user, serverUrl: serverUrl, password: password) - ncKit.setup(user: ncAccount!.username, - userId: ncAccount!.username, - password: ncAccount!.password, - urlBase: ncAccount!.serverUrl, - userAgent: "Nextcloud-macOS/FileProviderExt", - nextcloudVersion: 25, - delegate: nil) // TODO: add delegate methods for self - - Logger.fileProviderExtension.info("Nextcloud account set up in File Provider extension for user: \(user, privacy: .public) at server: \(serverUrl, privacy: .public)") - - signalEnumeratorAfterAccountSetup() - } - - func removeAccountConfig() { - Logger.fileProviderExtension.info("Received instruction to remove account data for user \(self.ncAccount!.username, privacy: .public) at server \(self.ncAccount!.serverUrl, privacy: .public)") - ncAccount = nil - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift deleted file mode 100644 index 7abc46090cb16..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import FileProvider -import NextcloudKit -import OSLog - -extension FileProviderExtension: NSFileProviderThumbnailing { - func fetchThumbnails(for itemIdentifiers: [NSFileProviderItemIdentifier], - requestedSize size: CGSize, - perThumbnailCompletionHandler: @escaping (NSFileProviderItemIdentifier, - Data?, - Error?) -> Void, - completionHandler: @escaping (Error?) -> Void) -> Progress { - - let progress = Progress(totalUnitCount: Int64(itemIdentifiers.count)) - var progressCounter: Int64 = 0 - - func finishCurrent() { - progressCounter += 1 - - if progressCounter == progress.totalUnitCount { - completionHandler(nil) - } - } - - for itemIdentifier in itemIdentifiers { - Logger.fileProviderExtension.debug("Fetching thumbnail for item with identifier:\(itemIdentifier.rawValue, privacy: .public)") - guard let metadata = NextcloudFilesDatabaseManager.shared.itemMetadataFromFileProviderItemIdentifier(itemIdentifier), - let thumbnailUrl = metadata.thumbnailUrl(size: size) else { - Logger.fileProviderExtension.debug("Did not fetch thumbnail URL") - finishCurrent() - continue - } - - Logger.fileProviderExtension.debug("Fetching thumbnail for file:\(metadata.fileName) at:\(thumbnailUrl.absoluteString, privacy: .public)") - - self.ncKit.getPreview(url: thumbnailUrl) { _, data, error in - if error == .success && data != nil { - perThumbnailCompletionHandler(itemIdentifier, data, nil) - } else { - perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable)) - } - finishCurrent() - } - } - - return progress - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift deleted file mode 100644 index e4912dbaac2db..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import FileProvider -import OSLog -import NCDesktopClientSocketKit -import NextcloudKit - -class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKCommonDelegate { - let domain: NSFileProviderDomain - let ncKit = NextcloudKit() - lazy var ncKitBackground: NKBackground = { - let nckb = NKBackground(nkCommonInstance: ncKit.nkCommonInstance) - return nckb - }() - - let appGroupIdentifier: String? = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String - var ncAccount: NextcloudAccount? - lazy var socketClient: LocalSocketClient? = { - guard let containerUrl = pathForAppGroupContainer() else { - Logger.fileProviderExtension.critical("Could not start file provider socket client properly as could not get container url") - return nil; - } - - let socketPath = containerUrl.appendingPathComponent(".fileprovidersocket", conformingTo: .archive) - let lineProcessor = FileProviderSocketLineProcessor(delegate: self) - - return LocalSocketClient(socketPath: socketPath.path, lineProcessor: lineProcessor) - }() - - let urlSessionIdentifier: String = "com.nextcloud.session.upload.fileproviderext" - let urlSessionMaximumConnectionsPerHost = 5 - lazy var urlSession: URLSession = { - let configuration = URLSessionConfiguration.background(withIdentifier: urlSessionIdentifier) - configuration.allowsCellularAccess = true - configuration.sessionSendsLaunchEvents = true - configuration.isDiscretionary = false - configuration.httpMaximumConnectionsPerHost = urlSessionMaximumConnectionsPerHost - configuration.requestCachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData - configuration.sharedContainerIdentifier = appGroupIdentifier - - let session = URLSession(configuration: configuration, delegate: ncKitBackground, delegateQueue: OperationQueue.main) - return session - }() - - required init(domain: NSFileProviderDomain) { - self.domain = domain - // The containing application must create a domain using `NSFileProviderManager.add(_:, completionHandler:)`. The system will then launch the application extension process, call `FileProviderExtension.init(domain:)` to instantiate the extension for that domain, and call methods on the instance. - - super.init() - self.socketClient?.start() - } - - func invalidate() { - // TODO: cleanup any resources - Logger.fileProviderExtension.debug("Extension for domain \(self.domain.displayName, privacy: .public) is being torn down") - } - - // MARK: NSFileProviderReplicatedExtension protocol methods - - func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress { - // resolve the given identifier to a record in the model - - Logger.fileProviderExtension.debug("Received item request for item with identifier: \(identifier.rawValue, privacy: .public)") - if identifier == .rootContainer { - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not providing item: \(identifier.rawValue, privacy: .public) as account not set up yet") - completionHandler(nil, NSFileProviderError(.notAuthenticated)) - return Progress() - } - - let metadata = NextcloudItemMetadataTable() - - metadata.account = ncAccount.ncKitAccount - metadata.directory = true - metadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue - metadata.fileName = "root" - metadata.fileNameView = "root" - metadata.serverUrl = ncAccount.serverUrl - metadata.classFile = NKCommon.TypeClassFile.directory.rawValue - - completionHandler(FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier.rootContainer, ncKit: ncKit), nil) - return Progress() - } - - let dbManager = NextcloudFilesDatabaseManager.shared - - guard let metadata = dbManager.itemMetadataFromFileProviderItemIdentifier(identifier), - let parentItemIdentifier = dbManager.parentItemIdentifierFromMetadata(metadata) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return Progress() - } - - completionHandler(FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit), nil) - return Progress() - } - - func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress { - - Logger.fileProviderExtension.debug("Received request to fetch contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public)") - - guard requestedVersion == nil else { - // TODO: Add proper support for file versioning - Logger.fileProviderExtension.error("Can't return contents for specific version as this is not supported.") - completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])) - return Progress() - } - - guard ncAccount != nil else { - Logger.fileProviderExtension.error("Not fetching contents item: \(itemIdentifier.rawValue, privacy: .public) as account not set up yet") - completionHandler(nil, nil, NSFileProviderError(.notAuthenticated)) - return Progress() - } - - let dbManager = NextcloudFilesDatabaseManager.shared - let ocId = itemIdentifier.rawValue - guard let metadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileProviderExtension.error("Could not acquire metadata of item with identifier: \(itemIdentifier.rawValue, privacy: .public)") - completionHandler(nil, nil, NSFileProviderError(.noSuchItem)) - return Progress() - } - - guard !metadata.isDocumentViewableOnly else { - Logger.fileProviderExtension.error("Could not get contents of item as is readonly: \(itemIdentifier.rawValue, privacy: .public) \(metadata.fileName, privacy: .public)") - completionHandler(nil, nil, NSFileProviderError(.cannotSynchronize)) - return Progress() - } - - let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName - - Logger.fileProviderExtension.debug("Fetching file with name \(metadata.fileName, privacy: .public) at URL: \(serverUrlFileName, privacy: .public)") - - let progress = Progress() - - // TODO: Handle folders nicely - do { - let fileNameLocalPath = try localPathForNCFile(ocId: metadata.ocId, fileNameView: metadata.fileNameView, domain: self.domain) - - dbManager.setStatusForItemMetadata(metadata, status: NextcloudItemMetadataTable.Status.downloading) { updatedMetadata in - - guard let updatedMetadata = updatedMetadata else { - Logger.fileProviderExtension.error("Could not acquire updated metadata of item with identifier: \(itemIdentifier.rawValue, privacy: .public), unable to update item status to downloading") - completionHandler(nil, nil, NSFileProviderError(.noSuchItem)) - return - } - - self.ncKit.download(serverUrlFileName: serverUrlFileName, - fileNameLocalPath: fileNameLocalPath.path, - requestHandler: { request in - progress.setHandlersFromAfRequest(request) - }, taskHandler: { task in - NSFileProviderManager(for: self.domain)?.register(task, forItemWithIdentifier: itemIdentifier, completionHandler: { _ in }) - }, progressHandler: { downloadProgress in - downloadProgress.copyCurrentStateToProgress(progress) - }) { _, etag, date, _, _, _, error in - if error == .success { - Logger.fileTransfer.debug("Acquired contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public) and filename: \(updatedMetadata.fileName, privacy: .public)") - - updatedMetadata.status = NextcloudItemMetadataTable.Status.normal.rawValue - updatedMetadata.sessionError = "" - updatedMetadata.date = (date ?? NSDate()) as Date - updatedMetadata.etag = etag ?? "" - - dbManager.addLocalFileMetadataFromItemMetadata(updatedMetadata) - dbManager.addItemMetadata(updatedMetadata) - - guard let parentItemIdentifier = dbManager.parentItemIdentifierFromMetadata(updatedMetadata) else { - completionHandler(nil, nil, NSFileProviderError(.noSuchItem)) - return - } - - let fpItem = FileProviderItem(metadata: updatedMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) - - completionHandler(fileNameLocalPath, fpItem, nil) - } else { - Logger.fileTransfer.error("Could not acquire contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public) and fileName: \(updatedMetadata.fileName, privacy: .public)") - - updatedMetadata.status = NextcloudItemMetadataTable.Status.downloadError.rawValue - updatedMetadata.sessionError = error.errorDescription - - dbManager.addItemMetadata(updatedMetadata) - - completionHandler(nil, nil, error.fileProviderError) - } - } - } - } catch let error { - Logger.fileProviderExtension.error("Could not find local path for file \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") - completionHandler(nil, nil, NSFileProviderError(.cannotSynchronize)) - } - - return progress - } - - func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress { - // TODO: a new item was created on disk, process the item's creation - - Logger.fileProviderExtension.debug("Received create item request for item with identifier: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) and filename: \(itemTemplate.filename, privacy: .public)") - - guard itemTemplate.contentType != .symbolicLink else { - Logger.fileProviderExtension.error("Cannot create item, symbolic links not supported.") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])) - return Progress() - } - - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) as account not set up yet") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.notAuthenticated)) - return Progress() - } - - let dbManager = NextcloudFilesDatabaseManager.shared - let parentItemIdentifier = itemTemplate.parentItemIdentifier - let itemTemplateIsFolder = itemTemplate.contentType == .folder || - itemTemplate.contentType == .directory - - if options.contains(.mayAlreadyExist) { - // TODO: This needs to be properly handled with a check in the db - Logger.fileProviderExtension.info("Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) as it may already exist") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) - return Progress() - } - - var parentItemServerUrl: String - - if parentItemIdentifier == .rootContainer { - parentItemServerUrl = ncAccount.davFilesUrl - } else { - guard let parentItemMetadata = dbManager.directoryMetadata(ocId: parentItemIdentifier.rawValue) else { - Logger.fileProviderExtension.error("Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public), could not find metadata for parentItemIdentifier \(parentItemIdentifier.rawValue, privacy: .public)") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) - return Progress() - } - - parentItemServerUrl = parentItemMetadata.serverUrl + "/" + parentItemMetadata.fileName - } - - let fileNameLocalPath = url?.path ?? "" - let newServerUrlFileName = parentItemServerUrl + "/" + itemTemplate.filename - - Logger.fileProviderExtension.debug("About to upload item with identifier: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) of type: \(itemTemplate.contentType?.identifier ?? "UNKNOWN") (is folder: \(itemTemplateIsFolder ? "yes" : "no") and filename: \(itemTemplate.filename) to server url: \(newServerUrlFileName, privacy: .public) with contents located at: \(fileNameLocalPath, privacy: .public)") - - if itemTemplateIsFolder { - self.ncKit.createFolder(serverUrlFileName: newServerUrlFileName) { account, ocId, _, error in - guard error == .success else { - Logger.fileTransfer.error("Could not create new folder with name: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") - completionHandler(itemTemplate, [], false, error.fileProviderError) - return - } - - // Read contents after creation - self.ncKit.readFileOrFolder(serverUrlFileName: newServerUrlFileName, depth: "0", showHiddenFiles: true) { account, files, _, error in - guard error == .success else { - Logger.fileTransfer.error("Could not read new folder with name: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") - return - } - - DispatchQueue.global().async { - NextcloudItemMetadataTable.metadatasFromDirectoryReadNKFiles(files, account: account) { directoryMetadata, childDirectoriesMetadata, metadatas in - - dbManager.addItemMetadata(directoryMetadata) - - let fpItem = FileProviderItem(metadata: directoryMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) - - completionHandler(fpItem, [], true, nil) - } - } - } - } - - return Progress() - } - - let progress = Progress() - - self.ncKit.upload(serverUrlFileName: newServerUrlFileName, - fileNameLocalPath: fileNameLocalPath, - requestHandler: { request in - progress.setHandlersFromAfRequest(request) - }, taskHandler: { task in - NSFileProviderManager(for: self.domain)?.register(task, forItemWithIdentifier: itemTemplate.itemIdentifier, completionHandler: { _ in }) - }, progressHandler: { uploadProgress in - uploadProgress.copyCurrentStateToProgress(progress) - }) { account, ocId, etag, date, size, _, _, error in - guard error == .success, let ocId = ocId else { - Logger.fileTransfer.error("Could not upload item with filename: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") - completionHandler(itemTemplate, [], false, error.fileProviderError) - return - } - - Logger.fileTransfer.info("Successfully uploaded item with identifier: \(ocId, privacy: .public) and filename: \(itemTemplate.filename, privacy: .public)") - - if size != itemTemplate.documentSize as? Int64 { - Logger.fileTransfer.warning("Created item upload reported as successful, but there are differences between the received file size (\(size, privacy: .public)) and the original file size (\(itemTemplate.documentSize??.int64Value ?? 0))") - } - - let newMetadata = NextcloudItemMetadataTable() - newMetadata.date = (date ?? NSDate()) as Date - newMetadata.etag = etag ?? "" - newMetadata.account = account - newMetadata.fileName = itemTemplate.filename - newMetadata.fileNameView = itemTemplate.filename - newMetadata.ocId = ocId - newMetadata.size = size - newMetadata.contentType = itemTemplate.contentType?.preferredMIMEType ?? "" - newMetadata.directory = itemTemplateIsFolder - newMetadata.serverUrl = parentItemServerUrl - newMetadata.session = "" - newMetadata.sessionError = "" - newMetadata.sessionTaskIdentifier = 0 - newMetadata.status = NextcloudItemMetadataTable.Status.normal.rawValue - - dbManager.addLocalFileMetadataFromItemMetadata(newMetadata) - dbManager.addItemMetadata(newMetadata) - - let fpItem = FileProviderItem(metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) - - completionHandler(fpItem, [], false, nil) - } - - return progress - } - - func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress { - // An item was modified on disk, process the item's modification - // TODO: Handle finder things like tags, other possible item changed fields - - Logger.fileProviderExtension.debug("Received modify item request for item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) and filename: \(item.filename, privacy: .public)") - - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public) as account not set up yet") - completionHandler(item, [], false, NSFileProviderError(.notAuthenticated)) - return Progress() - } - - let dbManager = NextcloudFilesDatabaseManager.shared - let parentItemIdentifier = item.parentItemIdentifier - let itemTemplateIsFolder = item.contentType == .folder || - item.contentType == .directory - - if options.contains(.mayAlreadyExist) { - // TODO: This needs to be properly handled with a check in the db - Logger.fileProviderExtension.warning("Modification for item: \(item.itemIdentifier.rawValue, privacy: .public) may already exist") - } - - var parentItemServerUrl: String - - if parentItemIdentifier == .rootContainer { - parentItemServerUrl = ncAccount.davFilesUrl - } else { - guard let parentItemMetadata = dbManager.directoryMetadata(ocId: parentItemIdentifier.rawValue) else { - Logger.fileProviderExtension.error("Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public), could not find metadata for parentItemIdentifier \(parentItemIdentifier.rawValue, privacy: .public)") - completionHandler(item, [], false, NSFileProviderError(.noSuchItem)) - return Progress() - } - - parentItemServerUrl = parentItemMetadata.serverUrl + "/" + parentItemMetadata.fileName - } - - let fileNameLocalPath = newContents?.path ?? "" - let newServerUrlFileName = parentItemServerUrl + "/" + item.filename - - Logger.fileProviderExtension.debug("About to upload modified item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) of type: \(item.contentType?.identifier ?? "UNKNOWN") (is folder: \(itemTemplateIsFolder ? "yes" : "no") and filename: \(item.filename, privacy: .public) to server url: \(newServerUrlFileName, privacy: .public) with contents located at: \(fileNameLocalPath, privacy: .public)") - - var modifiedItem = item - - // Create a serial dispatch queue - // We want to wait for network operations to finish before we fire off subsequent network - // operations, or we might cause explosions (e.g. trying to modify items that have just been - // moved elsewhere) - let dispatchQueue = DispatchQueue(label: "modifyItemQueue", qos: .userInitiated) - - if changedFields.contains(.filename) || changedFields.contains(.parentItemIdentifier) { - dispatchQueue.async { - let ocId = item.itemIdentifier.rawValue - Logger.fileProviderExtension.debug("Changed fields for item \(ocId, privacy: .public) with filename \(item.filename, privacy: .public) includes filename or parentitemidentifier...") - - guard let metadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileProviderExtension.error("Could not acquire metadata of item with identifier: \(item.itemIdentifier.rawValue, privacy: .public)") - completionHandler(item, [], false, NSFileProviderError(.noSuchItem)) - return - } - - var renameError: NSFileProviderError? - let oldServerUrlFileName = metadata.serverUrl + "/" + metadata.fileName - - let moveFileOrFolderDispatchGroup = DispatchGroup() // Make this block wait until done - moveFileOrFolderDispatchGroup.enter() - - self.ncKit.moveFileOrFolder(serverUrlFileNameSource: oldServerUrlFileName, - serverUrlFileNameDestination: newServerUrlFileName, - overwrite: false) { account, error in - guard error == .success else { - Logger.fileTransfer.error("Could not move file or folder: \(oldServerUrlFileName, privacy: .public) to \(newServerUrlFileName, privacy: .public), received error: \(error.errorDescription, privacy: .public)") - renameError = error.fileProviderError - moveFileOrFolderDispatchGroup.leave() - return - } - - // Remember that a folder metadata's serverUrl is its direct server URL, while for - // an item metadata the server URL is the parent folder's URL - if itemTemplateIsFolder { - _ = dbManager.renameDirectoryAndPropagateToChildren(ocId: ocId, newServerUrl: newServerUrlFileName, newFileName: item.filename) - self.signalEnumerator { error in - if error != nil { - Logger.fileTransfer.error("Error notifying change in moved directory: \(error)") - } - } - } else { - dbManager.renameItemMetadata(ocId: ocId, newServerUrl: parentItemServerUrl, newFileName: item.filename) - } - - guard let newMetadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileTransfer.error("Could not acquire metadata of item with identifier: \(ocId, privacy: .public), cannot correctly inform of modification") - renameError = NSFileProviderError(.noSuchItem) - moveFileOrFolderDispatchGroup.leave() - return - } - - modifiedItem = FileProviderItem(metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) - moveFileOrFolderDispatchGroup.leave() - } - - moveFileOrFolderDispatchGroup.wait() - - guard renameError == nil else { - Logger.fileTransfer.error("Stopping rename of item with ocId \(ocId, privacy: .public) due to error: \(renameError!.localizedDescription, privacy: .public)") - completionHandler(modifiedItem, [], false, renameError) - return - } - - guard !itemTemplateIsFolder else { - Logger.fileTransfer.debug("Only handling renaming for folders. ocId: \(ocId, privacy: .public)") - completionHandler(modifiedItem, [], false, nil) - return - } - } - - // Return the progress if item is folder here while the async block runs - guard !itemTemplateIsFolder else { - return Progress() - } - } - - guard !itemTemplateIsFolder else { - Logger.fileTransfer.debug("System requested modification for folder with ocID \(item.itemIdentifier.rawValue, privacy: .public) (\(newServerUrlFileName, privacy: .public)) of something other than folder name.") - completionHandler(modifiedItem, [], false, nil) - return Progress() - } - - let progress = Progress() - - if changedFields.contains(.contents) { - dispatchQueue.async { - Logger.fileProviderExtension.debug("Item modification for \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public) includes contents") - - guard newContents != nil else { - Logger.fileProviderExtension.warning("WARNING. Could not upload modified contents as was provided nil contents url. ocId: \(item.itemIdentifier.rawValue, privacy: .public)") - completionHandler(modifiedItem, [], false, NSFileProviderError(.noSuchItem)) - return - } - - let ocId = item.itemIdentifier.rawValue - guard let metadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileProviderExtension.error("Could not acquire metadata of item with identifier: \(ocId, privacy: .public)") - completionHandler(item, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) - return - } - - dbManager.setStatusForItemMetadata(metadata, status: NextcloudItemMetadataTable.Status.uploading) { updatedMetadata in - - if updatedMetadata == nil { - Logger.fileProviderExtension.warning("Could not acquire updated metadata of item with identifier: \(ocId, privacy: .public), unable to update item status to uploading") - } - - self.ncKit.upload(serverUrlFileName: newServerUrlFileName, - fileNameLocalPath: fileNameLocalPath, - requestHandler: { request in - progress.setHandlersFromAfRequest(request) - }, taskHandler: { task in - NSFileProviderManager(for: self.domain)?.register(task, forItemWithIdentifier: item.itemIdentifier, completionHandler: { _ in }) - }, progressHandler: { uploadProgress in - uploadProgress.copyCurrentStateToProgress(progress) - }) { account, ocId, etag, date, size, _, _, error in - if error == .success, let ocId = ocId { - Logger.fileProviderExtension.info("Successfully uploaded item with identifier: \(ocId, privacy: .public) and filename: \(item.filename, privacy: .public)") - - if size != item.documentSize as? Int64 { - Logger.fileTransfer.warning("Created item upload reported as successful, but there are differences between the received file size (\(size, privacy: .public)) and the original file size (\(item.documentSize??.int64Value ?? 0))") - } - - let newMetadata = NextcloudItemMetadataTable() - newMetadata.date = (date ?? NSDate()) as Date - newMetadata.etag = etag ?? "" - newMetadata.account = account - newMetadata.fileName = item.filename - newMetadata.fileNameView = item.filename - newMetadata.ocId = ocId - newMetadata.size = size - newMetadata.contentType = item.contentType?.preferredMIMEType ?? "" - newMetadata.directory = itemTemplateIsFolder - newMetadata.serverUrl = parentItemServerUrl - newMetadata.session = "" - newMetadata.sessionError = "" - newMetadata.sessionTaskIdentifier = 0 - newMetadata.status = NextcloudItemMetadataTable.Status.normal.rawValue - - dbManager.addLocalFileMetadataFromItemMetadata(newMetadata) - dbManager.addItemMetadata(newMetadata) - - modifiedItem = FileProviderItem(metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) - completionHandler(modifiedItem, [], false, nil) - } else { - Logger.fileTransfer.error("Could not upload item \(item.itemIdentifier.rawValue, privacy: .public) with filename: \(item.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") - - metadata.status = NextcloudItemMetadataTable.Status.uploadError.rawValue - metadata.sessionError = error.errorDescription - - dbManager.addItemMetadata(metadata) - - completionHandler(modifiedItem, [], false, error.fileProviderError) - return - } - } - } - } - } else { - Logger.fileProviderExtension.debug("Nothing more to do with \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public), modifications complete") - completionHandler(modifiedItem, [], false, nil) - } - - return progress - } - - func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress { - - Logger.fileProviderExtension.debug("Received delete item request for item with identifier: \(identifier.rawValue, privacy: .public)") - - guard ncAccount != nil else { - Logger.fileProviderExtension.error("Not deleting item: \(identifier.rawValue, privacy: .public) as account not set up yet") - completionHandler(NSFileProviderError(.notAuthenticated)) - return Progress() - } - - let dbManager = NextcloudFilesDatabaseManager.shared - let ocId = identifier.rawValue - guard let itemMetadata = dbManager.itemMetadataFromOcId(ocId) else { - completionHandler(NSFileProviderError(.noSuchItem)) - return Progress() - } - - let serverFileNameUrl = itemMetadata.serverUrl + "/" + itemMetadata.fileName - guard serverFileNameUrl != "" else { - completionHandler(NSFileProviderError(.noSuchItem)) - return Progress() - } - - self.ncKit.deleteFileOrFolder(serverUrlFileName: serverFileNameUrl) { account, error in - guard error == .success else { - Logger.fileTransfer.error("Could not delete item with ocId \(identifier.rawValue, privacy: .public) at \(serverFileNameUrl, privacy: .public), received error: \(error.errorDescription, privacy: .public)") - completionHandler(error.fileProviderError) - return - } - - Logger.fileTransfer.info("Successfully deleted item with identifier: \(identifier.rawValue, privacy: .public) at: \(serverFileNameUrl, privacy: .public)") - - if itemMetadata.directory { - _ = dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: ocId) - } else { - dbManager.deleteItemMetadata(ocId: ocId) - if dbManager.localFileMetadataFromOcId(ocId) != nil { - dbManager.deleteLocalFileMetadata(ocId: ocId) - } - } - - completionHandler(nil) - } - - return Progress() - } - - func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator { - - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not providing enumerator for container with identifier \(containerItemIdentifier.rawValue, privacy: .public) yet as account not set up") - throw NSFileProviderError(.notAuthenticated) - } - - return FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, ncAccount: ncAccount, ncKit: ncKit) - } - - func materializedItemsDidChange(completionHandler: @escaping () -> Void) { - guard let ncAccount = self.ncAccount else { - Logger.fileProviderExtension.error("Not purging stale local file metadatas, account not set up") - completionHandler() - return - } - - guard let fpManager = NSFileProviderManager(for: domain) else { - Logger.fileProviderExtension.error("Could not get file provider manager for domain: \(self.domain.displayName, privacy: .public)") - completionHandler() - return - } - - let materialisedEnumerator = fpManager.enumeratorForMaterializedItems() - let materialisedObserver = FileProviderMaterialisedEnumerationObserver(ncKitAccount: ncAccount.ncKitAccount) { _ in - completionHandler() - } - let startingPage = NSFileProviderPage(NSFileProviderPage.initialPageSortedByName as Data) - - materialisedEnumerator.enumerateItems(for: materialisedObserver, startingAt: startingPage) - } - - func signalEnumerator(completionHandler: @escaping(_ error: Error?) -> Void) { - guard let fpManager = NSFileProviderManager(for: self.domain) else { - Logger.fileProviderExtension.error("Could not get file provider manager for domain, could not signal enumerator. This might lead to future conflicts.") - return - } - - fpManager.signalEnumerator(for: .workingSet, completionHandler: completionHandler) - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift deleted file mode 100644 index 9a3c3e7224fa9..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import FileProvider -import UniformTypeIdentifiers -import NextcloudKit - -class FileProviderItem: NSObject, NSFileProviderItem { - - enum FileProviderItemTransferError: Error { - case downloadError - case uploadError - } - - let metadata: NextcloudItemMetadataTable - let parentItemIdentifier: NSFileProviderItemIdentifier - let ncKit: NextcloudKit - - var itemIdentifier: NSFileProviderItemIdentifier { - return NSFileProviderItemIdentifier(metadata.ocId) - } - - var capabilities: NSFileProviderItemCapabilities { - guard !metadata.directory else { - return [ .allowsAddingSubItems, - .allowsContentEnumerating, - .allowsReading, - .allowsDeleting, - .allowsRenaming ] - } - guard !metadata.lock else { - return [ .allowsReading ] - } - return [ .allowsWriting, - .allowsReading, - .allowsDeleting, - .allowsRenaming, - .allowsReparenting ] - } - - var itemVersion: NSFileProviderItemVersion { - NSFileProviderItemVersion(contentVersion: metadata.etag.data(using: .utf8)!, - metadataVersion: metadata.etag.data(using: .utf8)!) - } - - var filename: String { - return metadata.fileNameView - } - - var contentType: UTType { - if self.itemIdentifier == .rootContainer || metadata.directory { - return .folder - } - - let internalType = ncKit.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, - mimeType: "", - directory: metadata.directory) - return UTType(filenameExtension: internalType.ext) ?? .content - } - - var documentSize: NSNumber? { - return NSNumber(value: metadata.size) - } - - var creationDate: Date? { - return metadata.creationDate as Date - } - - var lastUsedDate: Date? { - return metadata.date as Date - } - - var contentModificationDate: Date? { - return metadata.date as Date - } - - var isDownloaded: Bool { - return metadata.directory || NextcloudFilesDatabaseManager.shared.localFileMetadataFromOcId(metadata.ocId) != nil - } - - var isDownloading: Bool { - return metadata.status == NextcloudItemMetadataTable.Status.downloading.rawValue - } - - var downloadingError: Error? { - if metadata.status == NextcloudItemMetadataTable.Status.downloadError.rawValue { - return FileProviderItemTransferError.downloadError - } - return nil - } - - var isUploaded: Bool { - return NextcloudFilesDatabaseManager.shared.localFileMetadataFromOcId(metadata.ocId) != nil - } - - var isUploading: Bool { - return metadata.status == NextcloudItemMetadataTable.Status.uploading.rawValue - } - - var uploadingError: Error? { - if metadata.status == NextcloudItemMetadataTable.Status.uploadError.rawValue { - return FileProviderItemTransferError.uploadError - } else { - return nil - } - } - - var childItemCount: NSNumber? { - if metadata.directory { - return NSNumber(integerLiteral: NextcloudFilesDatabaseManager.shared.childItemsForDirectory(metadata).count) - } else { - return nil - } - } - - required init(metadata: NextcloudItemMetadataTable, parentItemIdentifier: NSFileProviderItemIdentifier, ncKit: NextcloudKit) { - self.metadata = metadata - self.parentItemIdentifier = parentItemIdentifier - self.ncKit = ncKit - super.init() - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift deleted file mode 100644 index 168de6680c731..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import FileProvider -import OSLog - -class FileProviderMaterialisedEnumerationObserver : NSObject, NSFileProviderEnumerationObserver { - let ncKitAccount: String - let completionHandler: (_ deletedOcIds: Set) -> Void - var allEnumeratedItemIds: Set = Set() - - required init(ncKitAccount: String, completionHandler: @escaping(_ deletedOcIds: Set) -> Void) { - self.ncKitAccount = ncKitAccount - self.completionHandler = completionHandler - super.init() - } - - func didEnumerate(_ updatedItems: [NSFileProviderItemProtocol]) { - let updatedItemsIds = Array(updatedItems.map { $0.itemIdentifier.rawValue }) - - for updatedItemsId in updatedItemsIds { - allEnumeratedItemIds.insert(updatedItemsId) - } - } - - func finishEnumerating(upTo nextPage: NSFileProviderPage?) { - Logger.materialisedFileHandling.debug("Handling enumerated materialised items.") - FileProviderMaterialisedEnumerationObserver.handleEnumeratedItems(self.allEnumeratedItemIds, - account: self.ncKitAccount, - completionHandler: self.completionHandler) - } - - func finishEnumeratingWithError(_ error: Error) { - Logger.materialisedFileHandling.error("Ran into error when enumerating materialised items: \(error.localizedDescription, privacy: .public). Handling items enumerated so far") - FileProviderMaterialisedEnumerationObserver.handleEnumeratedItems(self.allEnumeratedItemIds, - account: self.ncKitAccount, - completionHandler: self.completionHandler) - } - - static func handleEnumeratedItems(_ itemIds: Set, account: String, completionHandler: @escaping(_ deletedOcIds: Set) -> Void) { - let dbManager = NextcloudFilesDatabaseManager.shared - let databaseLocalFileMetadatas = dbManager.localFileMetadatas(account: account) - var noLongerMaterialisedIds = Set() - - DispatchQueue.global(qos: .background).async { - for localFile in databaseLocalFileMetadatas { - let localFileOcId = localFile.ocId - - guard itemIds.contains(localFileOcId) else { - noLongerMaterialisedIds.insert(localFileOcId) - continue; - } - } - - DispatchQueue.main.async { - Logger.materialisedFileHandling.info("Cleaning up local file metadatas for unmaterialised items") - for itemId in noLongerMaterialisedIds { - dbManager.deleteLocalFileMetadata(ocId: itemId) - } - - completionHandler(noLongerMaterialisedIds) - } - } - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift deleted file mode 100644 index cf6ff8c771eb4..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import NCDesktopClientSocketKit -import OSLog - -class FileProviderSocketLineProcessor: NSObject, LineProcessor { - var delegate: FileProviderExtension - - required init(delegate: FileProviderExtension) { - self.delegate = delegate - } - - func process(_ line: String) { - if (line.contains("~")) { // We use this as the separator specifically in ACCOUNT_DETAILS - Logger.desktopClientConnection.debug("Processing file provider line with potentially sensitive user data") - } else { - Logger.desktopClientConnection.debug("Processing file provider line: \(line, privacy: .public)") - } - - let splitLine = line.split(separator: ":", maxSplits: 1) - guard let commandSubsequence = splitLine.first else { - Logger.desktopClientConnection.error("Input line did not have a first element") - return; - } - let command = String(commandSubsequence); - - Logger.desktopClientConnection.debug("Received command: \(command, privacy: .public)") - if (command == "SEND_FILE_PROVIDER_DOMAIN_IDENTIFIER") { - delegate.sendFileProviderDomainIdentifier() - } else if (command == "ACCOUNT_NOT_AUTHENTICATED") { - delegate.removeAccountConfig() - } else if (command == "ACCOUNT_DETAILS") { - guard let accountDetailsSubsequence = splitLine.last else { return } - let splitAccountDetails = accountDetailsSubsequence.split(separator: "~", maxSplits: 2) - - let user = String(splitAccountDetails[0]) - let serverUrl = String(splitAccountDetails[1]) - let password = String(splitAccountDetails[2]) - - delegate.setupDomainAccount(user: user, serverUrl: serverUrl, password: password) - } - } -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist deleted file mode 100644 index e5ab2fbecbd5e..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - CFBundleName - $(PRODUCT_NAME) - CFBundleDisplayName - $(OC_APPLICATION_NAME) File Provider Extension - CFBundleIdentifier - $(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME) - NSExtension - - NSExtensionFileProviderDocumentGroup - $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) - NSExtensionFileProviderSupportsEnumeration - - NSExtensionPointIdentifier - com.apple.fileprovider-nonui - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).FileProviderExtension - - SocketApiPrefix - $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) - - diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift deleted file mode 100644 index 1e68cf890ea26..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2023 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import FileProvider -import OSLog - -func pathForAppGroupContainer() -> URL? { - guard let appGroupIdentifier = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String else { - Logger.localFileOps.critical("Could not get container url as missing SocketApiPrefix info in app Info.plist") - return nil - } - - return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) -} - -func pathForFileProviderExtData() -> URL? { - let containerUrl = pathForAppGroupContainer() - return containerUrl?.appendingPathComponent("FileProviderExt/") -} - -func pathForFileProviderTempFilesForDomain(_ domain: NSFileProviderDomain) throws -> URL? { - guard let fpManager = NSFileProviderManager(for: domain) else { - Logger.localFileOps.error("Unable to get file provider manager for domain: \(domain.displayName, privacy: .public)") - throw NSFileProviderError(.providerNotFound) - } - - let fileProviderDataUrl = try fpManager.temporaryDirectoryURL() - return fileProviderDataUrl.appendingPathComponent("TemporaryNextcloudFiles/") -} - -func localPathForNCFile(ocId: String, fileNameView: String, domain: NSFileProviderDomain) throws -> URL { - guard let fileProviderFilesPathUrl = try pathForFileProviderTempFilesForDomain(domain) else { - Logger.localFileOps.error("Unable to get path for file provider temp files for domain: \(domain.displayName, privacy: .public)") - throw URLError(.badURL) - } - - let filePathUrl = fileProviderFilesPathUrl.appendingPathComponent(fileNameView) - let filePath = filePathUrl.path - - if !FileManager.default.fileExists(atPath: filePath) { - FileManager.default.createFile(atPath: filePath, contents: nil) - } - - return filePathUrl -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift deleted file mode 100644 index 0dc628d7d42c8..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -import Foundation -import FileProvider - -class NextcloudAccount: NSObject { - static let webDavFilesUrlSuffix: String = "/remote.php/dav/files/" - let username, password, ncKitAccount, serverUrl, davFilesUrl: String - - init(user: String, serverUrl: String, password: String) { - self.username = user - self.password = password - self.ncKitAccount = user + " " + serverUrl - self.serverUrl = serverUrl - self.davFilesUrl = serverUrl + NextcloudAccount.webDavFilesUrlSuffix + user - - super.init() - } -} - diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h b/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h deleted file mode 100644 index 75cf619dd48d8..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef LineProcessor_h -#define LineProcessor_h - -@protocol LineProcessor - -- (void)process:(NSString*)line; - -@end - -#endif /* LineProcessor_h */ diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h b/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h deleted file mode 100644 index 8626125b94366..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// NCDesktopClientSocketKit.h -// NCDesktopClientSocketKit -// -// Created by Claudio Cambra on 23/12/22. -// - -#import - -//! Project version number for NCDesktopClientSocketKit. -FOUNDATION_EXPORT double NCDesktopClientSocketKitVersionNumber; - -//! Project version string for NCDesktopClientSocketKit. -FOUNDATION_EXPORT const unsigned char NCDesktopClientSocketKitVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -#import -#import diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj deleted file mode 100644 index 0f850fb74b7cb..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1261 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 52; - objects = { - -/* Begin PBXBuildFile section */ - 5307A6E62965C6FA001E0C6A /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6E52965C6FA001E0C6A /* NextcloudKit */; }; - 5307A6E82965DAD8001E0C6A /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6E72965DAD8001E0C6A /* NextcloudKit */; }; - 5307A6EB2965DB8D001E0C6A /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6EA2965DB8D001E0C6A /* RealmSwift */; }; - 5307A6F229675346001E0C6A /* NextcloudFilesDatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5307A6F129675346001E0C6A /* NextcloudFilesDatabaseManager.swift */; }; - 5318AD9129BF42FB00CBB71C /* NextcloudItemMetadataTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5318AD9029BF42FB00CBB71C /* NextcloudItemMetadataTable.swift */; }; - 5318AD9529BF438F00CBB71C /* NextcloudLocalFileMetadataTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5318AD9429BF438F00CBB71C /* NextcloudLocalFileMetadataTable.swift */; }; - 5318AD9729BF493600CBB71C /* FileProviderMaterialisedEnumerationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5318AD9629BF493600CBB71C /* FileProviderMaterialisedEnumerationObserver.swift */; }; - 5318AD9929BF58D000CBB71C /* NKError+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5318AD9829BF58D000CBB71C /* NKError+Extensions.swift */; }; - 5352B36629DC14970011CE03 /* NextcloudFilesDatabaseManager+Directories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5352B36529DC14970011CE03 /* NextcloudFilesDatabaseManager+Directories.swift */; }; - 5352B36829DC17D60011CE03 /* NextcloudFilesDatabaseManager+LocalFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5352B36729DC17D60011CE03 /* NextcloudFilesDatabaseManager+LocalFiles.swift */; }; - 5352B36C29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5352B36B29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift */; }; - 5352E85B29B7BFE6002CE85C /* Progress+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5352E85A29B7BFE6002CE85C /* Progress+Extensions.swift */; }; - 535AE30E29C0A2CC0042A9BA /* Logger+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535AE30D29C0A2CC0042A9BA /* Logger+Extensions.swift */; }; - 536EFBF7295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */; }; - 536EFC36295E3C1100F4CB13 /* NextcloudAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536EFC35295E3C1100F4CB13 /* NextcloudAccount.swift */; }; - 538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */; }; - 538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396C27F4765000FA63D5 /* FileProviderExtension.swift */; }; - 538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396E27F4765000FA63D5 /* FileProviderItem.swift */; }; - 538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */; }; - 538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 538E396727F4765000FA63D5 /* FileProviderExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 53903D1E2956164F00D0B308 /* NCDesktopClientSocketKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 53903D0E2956164F00D0B308 /* NCDesktopClientSocketKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 53903D212956164F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; }; - 53903D222956164F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 53903D2A295616F000D0B308 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; }; - 53903D2B2956173000D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; }; - 53903D2C2956173000D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 53903D302956173F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; }; - 53903D312956173F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 53903D352956184400D0B308 /* LocalSocketClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 539158B127BE891500816F56 /* LocalSocketClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 53903D37295618A400D0B308 /* LineProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 53903D36295618A400D0B308 /* LineProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 539158AC27BE71A900816F56 /* FinderSyncSocketLineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.m */; }; - 53D056312970594F00988392 /* LocalFilesUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53D056302970594F00988392 /* LocalFilesUtils.swift */; }; - 53ED472029C5E64200795DB1 /* FileProviderEnumerator+SyncEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53ED471F29C5E64200795DB1 /* FileProviderEnumerator+SyncEngine.swift */; }; - 53ED472829C88E7000795DB1 /* NextcloudItemMetadataTable+NKFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53ED472729C88E7000795DB1 /* NextcloudItemMetadataTable+NKFile.swift */; }; - 53ED473029C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53ED472F29C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift */; }; - C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; }; - C2B573D21B1CD94B00303B36 /* main.m in Resources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; }; - C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573DD1B1CD9CE00303B36 /* FinderSync.m */; }; - C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - C2B573F31B1DAD6400303B36 /* error.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EB1B1DAD6400303B36 /* error.iconset */; }; - C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */; }; - C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573ED1B1DAD6400303B36 /* ok.iconset */; }; - C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EF1B1DAD6400303B36 /* sync.iconset */; }; - C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573F11B1DAD6400303B36 /* warning.iconset */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 538E397427F4765000FA63D5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C2B573951B1CD88000303B36 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 538E396627F4765000FA63D5; - remoteInfo = FileProviderExt; - }; - 53903D1F2956164F00D0B308 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C2B573951B1CD88000303B36 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 53903D0B2956164F00D0B308; - remoteInfo = NCDesktopClientSocketKit; - }; - 53903D2D2956173000D0B308 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C2B573951B1CD88000303B36 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 53903D0B2956164F00D0B308; - remoteInfo = NCDesktopClientSocketKit; - }; - 53903D322956173F00D0B308 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C2B573951B1CD88000303B36 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 53903D0B2956164F00D0B308; - remoteInfo = NCDesktopClientSocketKit; - }; - C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C2B573951B1CD88000303B36 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C2B573D61B1CD9CE00303B36; - remoteInfo = FinderSyncExt; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 53903D232956165000D0B308 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 53903D222956164F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; - 53903D2F2956173000D0B308 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 53903D2C2956173000D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; - 53903D342956173F00D0B308 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 53903D312956173F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573E11B1CD9CE00303B36 /* Embed App Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */, - 538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */, - ); - name = "Embed App Extensions"; - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 5307A6F129675346001E0C6A /* NextcloudFilesDatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudFilesDatabaseManager.swift; sourceTree = ""; }; - 5318AD9029BF42FB00CBB71C /* NextcloudItemMetadataTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudItemMetadataTable.swift; sourceTree = ""; }; - 5318AD9429BF438F00CBB71C /* NextcloudLocalFileMetadataTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudLocalFileMetadataTable.swift; sourceTree = ""; }; - 5318AD9629BF493600CBB71C /* FileProviderMaterialisedEnumerationObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderMaterialisedEnumerationObserver.swift; sourceTree = ""; }; - 5318AD9829BF58D000CBB71C /* NKError+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NKError+Extensions.swift"; sourceTree = ""; }; - 5352B36529DC14970011CE03 /* NextcloudFilesDatabaseManager+Directories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NextcloudFilesDatabaseManager+Directories.swift"; sourceTree = ""; }; - 5352B36729DC17D60011CE03 /* NextcloudFilesDatabaseManager+LocalFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NextcloudFilesDatabaseManager+LocalFiles.swift"; sourceTree = ""; }; - 5352B36B29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderExtension+Thumbnailing.swift"; sourceTree = ""; }; - 5352E85A29B7BFE6002CE85C /* Progress+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+Extensions.swift"; sourceTree = ""; }; - 535AE30D29C0A2CC0042A9BA /* Logger+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Extensions.swift"; sourceTree = ""; }; - 536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderSocketLineProcessor.swift; sourceTree = ""; }; - 536EFC35295E3C1100F4CB13 /* NextcloudAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudAccount.swift; sourceTree = ""; }; - 538E396727F4765000FA63D5 /* FileProviderExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FileProviderExt.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - 538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; }; - 538E396C27F4765000FA63D5 /* FileProviderExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderExtension.swift; sourceTree = ""; }; - 538E396E27F4765000FA63D5 /* FileProviderItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderItem.swift; sourceTree = ""; }; - 538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderEnumerator.swift; sourceTree = ""; }; - 538E397227F4765000FA63D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 538E397327F4765000FA63D5 /* FileProviderExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FileProviderExt.entitlements; sourceTree = ""; }; - 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NCDesktopClientSocketKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 53903D0E2956164F00D0B308 /* NCDesktopClientSocketKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCDesktopClientSocketKit.h; sourceTree = ""; }; - 53903D36295618A400D0B308 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = ""; }; - 539158A927BE606500816F56 /* FinderSyncSocketLineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinderSyncSocketLineProcessor.h; sourceTree = ""; }; - 539158AA27BE67CC00816F56 /* SyncClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyncClient.h; sourceTree = ""; }; - 539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FinderSyncSocketLineProcessor.m; sourceTree = ""; }; - 539158B127BE891500816F56 /* LocalSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalSocketClient.h; sourceTree = ""; }; - 539158B227BEC98A00816F56 /* LocalSocketClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalSocketClient.m; sourceTree = ""; }; - 53D056302970594F00988392 /* LocalFilesUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalFilesUtils.swift; sourceTree = ""; }; - 53ED471F29C5E64200795DB1 /* FileProviderEnumerator+SyncEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderEnumerator+SyncEngine.swift"; sourceTree = ""; }; - 53ED472729C88E7000795DB1 /* NextcloudItemMetadataTable+NKFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NextcloudItemMetadataTable+NKFile.swift"; sourceTree = ""; }; - 53ED472F29C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderExtension+ClientInterface.swift"; sourceTree = ""; }; - C2B573B11B1CD91E00303B36 /* desktopclient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktopclient.app; sourceTree = BUILT_PRODUCTS_DIR; }; - C2B573B51B1CD91E00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C2B573B91B1CD91E00303B36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FinderSyncExt.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - C2B573DA1B1CD9CE00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = FinderSyncExt.entitlements; sourceTree = ""; }; - C2B573DC1B1CD9CE00303B36 /* FinderSync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinderSync.h; sourceTree = ""; }; - C2B573DD1B1CD9CE00303B36 /* FinderSync.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FinderSync.m; sourceTree = ""; }; - C2B573EB1B1DAD6400303B36 /* error.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = error.iconset; path = ../../icons/nopadding/error.iconset; sourceTree = SOURCE_ROOT; }; - C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok_swm.iconset; path = ../../icons/nopadding/ok_swm.iconset; sourceTree = SOURCE_ROOT; }; - C2B573ED1B1DAD6400303B36 /* ok.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok.iconset; path = ../../icons/nopadding/ok.iconset; sourceTree = SOURCE_ROOT; }; - C2B573EF1B1DAD6400303B36 /* sync.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = sync.iconset; path = ../../icons/nopadding/sync.iconset; sourceTree = SOURCE_ROOT; }; - C2B573F11B1DAD6400303B36 /* warning.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = warning.iconset; path = ../../icons/nopadding/warning.iconset; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 538E396427F4765000FA63D5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 5307A6EB2965DB8D001E0C6A /* RealmSwift in Frameworks */, - 5307A6E82965DAD8001E0C6A /* NextcloudKit in Frameworks */, - 538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */, - 53903D302956173F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53903D092956164F00D0B308 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573AE1B1CD91E00303B36 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 5307A6E62965C6FA001E0C6A /* NextcloudKit in Frameworks */, - 53903D212956164F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573D41B1CD9CE00303B36 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 53903D2B2956173000D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 5318AD8F29BF406500CBB71C /* Database */ = { - isa = PBXGroup; - children = ( - 5307A6F129675346001E0C6A /* NextcloudFilesDatabaseManager.swift */, - 5352B36529DC14970011CE03 /* NextcloudFilesDatabaseManager+Directories.swift */, - 5352B36729DC17D60011CE03 /* NextcloudFilesDatabaseManager+LocalFiles.swift */, - 5318AD9029BF42FB00CBB71C /* NextcloudItemMetadataTable.swift */, - 53ED472729C88E7000795DB1 /* NextcloudItemMetadataTable+NKFile.swift */, - 5318AD9429BF438F00CBB71C /* NextcloudLocalFileMetadataTable.swift */, - ); - path = Database; - sourceTree = ""; - }; - 5352E85929B7BFB4002CE85C /* Extensions */ = { - isa = PBXGroup; - children = ( - 535AE30D29C0A2CC0042A9BA /* Logger+Extensions.swift */, - 5318AD9829BF58D000CBB71C /* NKError+Extensions.swift */, - 5352E85A29B7BFE6002CE85C /* Progress+Extensions.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - 538E396827F4765000FA63D5 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 538E396B27F4765000FA63D5 /* FileProviderExt */ = { - isa = PBXGroup; - children = ( - 5318AD8F29BF406500CBB71C /* Database */, - 5352E85929B7BFB4002CE85C /* Extensions */, - 538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */, - 53ED471F29C5E64200795DB1 /* FileProviderEnumerator+SyncEngine.swift */, - 538E396C27F4765000FA63D5 /* FileProviderExtension.swift */, - 53ED472F29C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift */, - 5352B36B29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift */, - 538E396E27F4765000FA63D5 /* FileProviderItem.swift */, - 5318AD9629BF493600CBB71C /* FileProviderMaterialisedEnumerationObserver.swift */, - 536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */, - 53D056302970594F00988392 /* LocalFilesUtils.swift */, - 536EFC35295E3C1100F4CB13 /* NextcloudAccount.swift */, - 538E397327F4765000FA63D5 /* FileProviderExt.entitlements */, - 538E397227F4765000FA63D5 /* Info.plist */, - ); - path = FileProviderExt; - sourceTree = ""; - }; - 53903D0D2956164F00D0B308 /* NCDesktopClientSocketKit */ = { - isa = PBXGroup; - children = ( - 53903D0E2956164F00D0B308 /* NCDesktopClientSocketKit.h */, - 539158B127BE891500816F56 /* LocalSocketClient.h */, - 539158B227BEC98A00816F56 /* LocalSocketClient.m */, - 53903D36295618A400D0B308 /* LineProcessor.h */, - ); - path = NCDesktopClientSocketKit; - sourceTree = ""; - }; - C2B573941B1CD88000303B36 = { - isa = PBXGroup; - children = ( - C2B573B31B1CD91E00303B36 /* desktopclient */, - C2B573D81B1CD9CE00303B36 /* FinderSyncExt */, - 538E396B27F4765000FA63D5 /* FileProviderExt */, - 53903D0D2956164F00D0B308 /* NCDesktopClientSocketKit */, - 538E396827F4765000FA63D5 /* Frameworks */, - C2B573B21B1CD91E00303B36 /* Products */, - ); - sourceTree = ""; - }; - C2B573B21B1CD91E00303B36 /* Products */ = { - isa = PBXGroup; - children = ( - C2B573B11B1CD91E00303B36 /* desktopclient.app */, - C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */, - 538E396727F4765000FA63D5 /* FileProviderExt.appex */, - 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */, - ); - name = Products; - sourceTree = ""; - }; - C2B573B31B1CD91E00303B36 /* desktopclient */ = { - isa = PBXGroup; - children = ( - C2B573B41B1CD91E00303B36 /* Supporting Files */, - ); - path = desktopclient; - sourceTree = ""; - }; - C2B573B41B1CD91E00303B36 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - C2B573B51B1CD91E00303B36 /* Info.plist */, - C2B573B91B1CD91E00303B36 /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - C2B573D81B1CD9CE00303B36 /* FinderSyncExt */ = { - isa = PBXGroup; - children = ( - 539158AA27BE67CC00816F56 /* SyncClient.h */, - C2B573DC1B1CD9CE00303B36 /* FinderSync.h */, - C2B573DD1B1CD9CE00303B36 /* FinderSync.m */, - 539158A927BE606500816F56 /* FinderSyncSocketLineProcessor.h */, - 539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.m */, - C2B573D91B1CD9CE00303B36 /* Supporting Files */, - ); - path = FinderSyncExt; - sourceTree = ""; - }; - C2B573D91B1CD9CE00303B36 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - C2B573EB1B1DAD6400303B36 /* error.iconset */, - C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */, - C2B573ED1B1DAD6400303B36 /* ok.iconset */, - C2B573EF1B1DAD6400303B36 /* sync.iconset */, - C2B573F11B1DAD6400303B36 /* warning.iconset */, - C2B573DA1B1CD9CE00303B36 /* Info.plist */, - C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 53903D072956164F00D0B308 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 53903D352956184400D0B308 /* LocalSocketClient.h in Headers */, - 53903D37295618A400D0B308 /* LineProcessor.h in Headers */, - 53903D1E2956164F00D0B308 /* NCDesktopClientSocketKit.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 538E396627F4765000FA63D5 /* FileProviderExt */ = { - isa = PBXNativeTarget; - buildConfigurationList = 538E397927F4765000FA63D5 /* Build configuration list for PBXNativeTarget "FileProviderExt" */; - buildPhases = ( - 538E396327F4765000FA63D5 /* Sources */, - 538E396427F4765000FA63D5 /* Frameworks */, - 538E396527F4765000FA63D5 /* Resources */, - 53903D342956173F00D0B308 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 53903D332956173F00D0B308 /* PBXTargetDependency */, - ); - name = FileProviderExt; - packageProductDependencies = ( - 5307A6E72965DAD8001E0C6A /* NextcloudKit */, - 5307A6EA2965DB8D001E0C6A /* RealmSwift */, - ); - productName = FileProviderExt; - productReference = 538E396727F4765000FA63D5 /* FileProviderExt.appex */; - productType = "com.apple.product-type.app-extension"; - }; - 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */ = { - isa = PBXNativeTarget; - buildConfigurationList = 53903D282956165000D0B308 /* Build configuration list for PBXNativeTarget "NCDesktopClientSocketKit" */; - buildPhases = ( - 53903D072956164F00D0B308 /* Headers */, - 53903D082956164F00D0B308 /* Sources */, - 53903D092956164F00D0B308 /* Frameworks */, - 53903D0A2956164F00D0B308 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = NCDesktopClientSocketKit; - productName = NCDesktopClientSocketKit; - productReference = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; - productType = "com.apple.product-type.framework"; - }; - C2B573B01B1CD91E00303B36 /* desktopclient */ = { - isa = PBXNativeTarget; - buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */; - buildPhases = ( - C2B573AD1B1CD91E00303B36 /* Sources */, - C2B573AE1B1CD91E00303B36 /* Frameworks */, - C2B573AF1B1CD91E00303B36 /* Resources */, - C2B573E11B1CD9CE00303B36 /* Embed App Extensions */, - 53903D232956165000D0B308 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */, - 538E397527F4765000FA63D5 /* PBXTargetDependency */, - 53903D202956164F00D0B308 /* PBXTargetDependency */, - ); - name = desktopclient; - packageProductDependencies = ( - 5307A6E52965C6FA001E0C6A /* NextcloudKit */, - ); - productName = desktopclient; - productReference = C2B573B11B1CD91E00303B36 /* desktopclient.app */; - productType = "com.apple.product-type.application"; - }; - C2B573D61B1CD9CE00303B36 /* FinderSyncExt */ = { - isa = PBXNativeTarget; - buildConfigurationList = C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */; - buildPhases = ( - C2B573D31B1CD9CE00303B36 /* Sources */, - C2B573D41B1CD9CE00303B36 /* Frameworks */, - C2B573D51B1CD9CE00303B36 /* Resources */, - 5B3335471CA058E200E11A45 /* ShellScript */, - 53903D2F2956173000D0B308 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 53903D2E2956173000D0B308 /* PBXTargetDependency */, - ); - name = FinderSyncExt; - productName = FinderSyncExt; - productReference = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */; - productType = "com.apple.product-type.app-extension"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - C2B573951B1CD88000303B36 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1420; - LastUpgradeCheck = 1240; - TargetAttributes = { - 538E396627F4765000FA63D5 = { - CreatedOnToolsVersion = 13.3; - }; - 53903D0B2956164F00D0B308 = { - CreatedOnToolsVersion = 14.2; - ProvisioningStyle = Manual; - }; - C2B573B01B1CD91E00303B36 = { - CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = 9B5WD74GWJ; - ProvisioningStyle = Manual; - }; - C2B573D61B1CD9CE00303B36 = { - CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = 9B5WD74GWJ; - ProvisioningStyle = Manual; - SystemCapabilities = { - com.apple.ApplicationGroups.Mac = { - enabled = 1; - }; - }; - }; - }; - }; - buildConfigurationList = C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "NextcloudIntegration" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - en, - Base, - ); - mainGroup = C2B573941B1CD88000303B36; - packageReferences = ( - 5307A6E42965C6FA001E0C6A /* XCRemoteSwiftPackageReference "NextcloudKit" */, - 5307A6E92965DB57001E0C6A /* XCRemoteSwiftPackageReference "realm-swift" */, - ); - productRefGroup = C2B573B21B1CD91E00303B36 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - C2B573B01B1CD91E00303B36 /* desktopclient */, - C2B573D61B1CD9CE00303B36 /* FinderSyncExt */, - 538E396627F4765000FA63D5 /* FileProviderExt */, - 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 538E396527F4765000FA63D5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53903D0A2956164F00D0B308 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573AF1B1CD91E00303B36 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C2B573D21B1CD94B00303B36 /* main.m in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573D51B1CD9CE00303B36 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */, - C2B573F31B1DAD6400303B36 /* error.iconset in Resources */, - C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */, - C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */, - C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 5B3335471CA058E200E11A45 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [[ ${OC_OEM_SHARE_ICNS} ]]; then\n cp ${OC_OEM_SHARE_ICNS} ${BUILT_PRODUCTS_DIR}/FinderSyncExt.appex/Contents/Resources/app.icns\nfi"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 538E396327F4765000FA63D5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5352E85B29B7BFE6002CE85C /* Progress+Extensions.swift in Sources */, - 536EFC36295E3C1100F4CB13 /* NextcloudAccount.swift in Sources */, - 53ED473029C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift in Sources */, - 538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */, - 536EFBF7295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift in Sources */, - 53ED472029C5E64200795DB1 /* FileProviderEnumerator+SyncEngine.swift in Sources */, - 5318AD9929BF58D000CBB71C /* NKError+Extensions.swift in Sources */, - 53ED472829C88E7000795DB1 /* NextcloudItemMetadataTable+NKFile.swift in Sources */, - 5318AD9529BF438F00CBB71C /* NextcloudLocalFileMetadataTable.swift in Sources */, - 535AE30E29C0A2CC0042A9BA /* Logger+Extensions.swift in Sources */, - 5307A6F229675346001E0C6A /* NextcloudFilesDatabaseManager.swift in Sources */, - 53D056312970594F00988392 /* LocalFilesUtils.swift in Sources */, - 538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */, - 5352B36829DC17D60011CE03 /* NextcloudFilesDatabaseManager+LocalFiles.swift in Sources */, - 5318AD9129BF42FB00CBB71C /* NextcloudItemMetadataTable.swift in Sources */, - 5352B36629DC14970011CE03 /* NextcloudFilesDatabaseManager+Directories.swift in Sources */, - 5318AD9729BF493600CBB71C /* FileProviderMaterialisedEnumerationObserver.swift in Sources */, - 5352B36C29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift in Sources */, - 538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53903D082956164F00D0B308 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53903D2A295616F000D0B308 /* LocalSocketClient.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573AD1B1CD91E00303B36 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C2B573BA1B1CD91E00303B36 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2B573D31B1CD9CE00303B36 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 539158AC27BE71A900816F56 /* FinderSyncSocketLineProcessor.m in Sources */, - C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 538E397527F4765000FA63D5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 538E396627F4765000FA63D5 /* FileProviderExt */; - targetProxy = 538E397427F4765000FA63D5 /* PBXContainerItemProxy */; - }; - 53903D202956164F00D0B308 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */; - targetProxy = 53903D1F2956164F00D0B308 /* PBXContainerItemProxy */; - }; - 53903D2E2956173000D0B308 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */; - targetProxy = 53903D2D2956173000D0B308 /* PBXContainerItemProxy */; - }; - 53903D332956173F00D0B308 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */; - targetProxy = 53903D322956173F00D0B308 /* PBXContainerItemProxy */; - }; - C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */; - targetProxy = C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 538E397727F4765000FA63D5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = FileProviderExt/FileProviderExt.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; - CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = FileProviderExt/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 538E397827F4765000FA63D5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = FileProviderExt/FileProviderExt.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; - CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = ""; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = FileProviderExt/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 53903D242956165000D0B308 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GENERATE_INFOPLIST_FILE = YES; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - LD_RUNPATH_SEARCH_PATHS = ( - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.NCDesktopClientSocketKit; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = auto; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = macosx; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 53903D252956165000D0B308 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GENERATE_INFOPLIST_FILE = YES; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - LD_RUNPATH_SEARCH_PATHS = ( - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.NCDesktopClientSocketKit; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = auto; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = macosx; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - C2B573991B1CD88000303B36 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - }; - name = Debug; - }; - C2B5739A1B1CD88000303B36 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - }; - name = Release; - }; - C2B573CD1B1CD91E00303B36 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = desktopclient/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = macosx; - SWIFT_OBJC_BRIDGING_HEADER = "desktopclient/desktopclient-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - C2B573CE1B1CD91E00303B36 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = desktopclient/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = macosx; - SWIFT_OBJC_BRIDGING_HEADER = "desktopclient/desktopclient-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - C2B573E41B1CD9CE00303B36 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = FinderSyncExt/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = YES; - OC_APPLICATION_NAME = ownCloud; - OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient; - OC_OEM_SHARE_ICNS = ""; - OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = ""; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - C2B573E51B1CD9CE00303B36 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = FinderSyncExt/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = NO; - OC_APPLICATION_NAME = ownCloud; - OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient; - OC_OEM_SHARE_ICNS = ""; - OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 538E397927F4765000FA63D5 /* Build configuration list for PBXNativeTarget "FileProviderExt" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 538E397727F4765000FA63D5 /* Debug */, - 538E397827F4765000FA63D5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 53903D282956165000D0B308 /* Build configuration list for PBXNativeTarget "NCDesktopClientSocketKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53903D242956165000D0B308 /* Debug */, - 53903D252956165000D0B308 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "NextcloudIntegration" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2B573991B1CD88000303B36 /* Debug */, - C2B5739A1B1CD88000303B36 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2B573CD1B1CD91E00303B36 /* Debug */, - C2B573CE1B1CD91E00303B36 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2B573E41B1CD9CE00303B36 /* Debug */, - C2B573E51B1CD9CE00303B36 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - -/* Begin XCRemoteSwiftPackageReference section */ - 5307A6E42965C6FA001E0C6A /* XCRemoteSwiftPackageReference "NextcloudKit" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/nextcloud/NextcloudKit"; - requirement = { - branch = develop; - kind = branch; - }; - }; - 5307A6E92965DB57001E0C6A /* XCRemoteSwiftPackageReference "realm-swift" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/realm/realm-swift.git"; - requirement = { - kind = exactVersion; - version = 10.33.0; - }; - }; -/* End XCRemoteSwiftPackageReference section */ - -/* Begin XCSwiftPackageProductDependency section */ - 5307A6E52965C6FA001E0C6A /* NextcloudKit */ = { - isa = XCSwiftPackageProductDependency; - package = 5307A6E42965C6FA001E0C6A /* XCRemoteSwiftPackageReference "NextcloudKit" */; - productName = NextcloudKit; - }; - 5307A6E72965DAD8001E0C6A /* NextcloudKit */ = { - isa = XCSwiftPackageProductDependency; - package = 5307A6E42965C6FA001E0C6A /* XCRemoteSwiftPackageReference "NextcloudKit" */; - productName = NextcloudKit; - }; - 5307A6EA2965DB8D001E0C6A /* RealmSwift */ = { - isa = XCSwiftPackageProductDependency; - package = 5307A6E92965DB57001E0C6A /* XCRemoteSwiftPackageReference "realm-swift" */; - productName = RealmSwift; - }; -/* End XCSwiftPackageProductDependency section */ - }; - rootObject = C2B573951B1CD88000303B36 /* Project object */; -} diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68d..0000000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/shell_integration/MacOSX/OwnCloud.xcworkspace/contents.xcworkspacedata similarity index 59% rename from shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to shell_integration/MacOSX/OwnCloud.xcworkspace/contents.xcworkspacedata index 919434a6254f0..ed88ebf479b81 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/shell_integration/MacOSX/OwnCloud.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "group:OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj"> diff --git a/shell_integration/MacOSX/Nextcloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from shell_integration/MacOSX/Nextcloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/shell_integration/MacOSX/Nextcloud.xcworkspace/xcshareddata/OwnCloud.xccheckout b/shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/OwnCloud.xccheckout similarity index 100% rename from shell_integration/MacOSX/Nextcloud.xcworkspace/xcshareddata/OwnCloud.xccheckout rename to shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/OwnCloud.xccheckout diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h similarity index 85% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.h rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h index 8d73f92d3a8cd..4cf5765bd882d 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.h +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h @@ -15,10 +15,9 @@ #import #import -#import - #import "SyncClient.h" -#import "FinderSyncSocketLineProcessor.h" +#import "LineProcessor.h" +#import "LocalSocketClient.h" @interface FinderSync : FIFinderSync { @@ -29,7 +28,7 @@ NSCondition *_menuIsComplete; } -@property FinderSyncSocketLineProcessor *lineProcessor; +@property LineProcessor *lineProcessor; @property LocalSocketClient *localSocketClient; @end diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m similarity index 95% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m index 3e8123e82b525..84a124f5106db 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m @@ -27,13 +27,13 @@ - (instancetype)init NSBundle *extBundle = [NSBundle bundleForClass:[self class]]; // This was added to the bundle's Info.plist to get it from the build system NSString *socketApiPrefix = [extBundle objectForInfoDictionaryKey:@"SocketApiPrefix"]; - + NSImage *ok = [extBundle imageForResource:@"ok.icns"]; NSImage *ok_swm = [extBundle imageForResource:@"ok_swm.icns"]; NSImage *sync = [extBundle imageForResource:@"sync.icns"]; NSImage *warning = [extBundle imageForResource:@"warning.icns"]; NSImage *error = [extBundle imageForResource:@"error.icns"]; - + [syncController setBadgeImage:ok label:@"Up to date" forBadgeIdentifier:@"OK"]; [syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC"]; [syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW"]; @@ -44,7 +44,7 @@ - (instancetype)init [syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW+SWM"]; [syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE+SWM"]; [syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR+SWM"]; - + // The Mach port name needs to: // - Be prefixed with the code signing Team ID // - Then infixed with the sandbox App Group @@ -55,22 +55,24 @@ - (instancetype)init // the OS doesn't seem to put any restriction on the port name, so we just follow what // the sandboxed App Extension needs. // https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24 - + NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:socketApiPrefix]; NSURL *socketPath = [container URLByAppendingPathComponent:@".socket" isDirectory:NO]; - + NSLog(@"Socket path: %@", socketPath.path); - + if (socketPath.path) { - self.lineProcessor = [[FinderSyncSocketLineProcessor alloc] initWithDelegate:self]; - self.localSocketClient = [[LocalSocketClient alloc] initWithSocketPath:socketPath.path - lineProcessor:self.lineProcessor]; + self.lineProcessor = [[LineProcessor alloc] initWithDelegate:self]; + self.localSocketClient = [[LocalSocketClient alloc] init:socketPath.path + lineProcessor:self.lineProcessor]; [self.localSocketClient start]; - [self.localSocketClient askOnSocket:@"" query:@"GET_STRINGS"]; } else { NSLog(@"No socket path. Not initiating local socket client."); self.localSocketClient = nil; } + _registeredDirectories = [[NSMutableSet alloc] init]; + _strings = [[NSMutableDictionary alloc] init]; + _menuIsComplete = [[NSCondition alloc] init]; } return self; diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncExt.entitlements b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSyncExt.entitlements similarity index 100% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncExt.entitlements rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSyncExt.entitlements diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/Info.plist b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist similarity index 100% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/Info.plist rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist index 2a669ce7374d9..88bb87e9163c1 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/Info.plist +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist @@ -2,6 +2,8 @@ + SocketApiPrefix + $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) CFBundleDevelopmentRegion en CFBundleDisplayName @@ -37,7 +39,5 @@ NSPrincipalClass NSApplication - SocketApiPrefix - $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h similarity index 75% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h index 0ff77c892feef..137ce62de5ebc 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h @@ -12,24 +12,22 @@ * for more details. */ -#import - #import "SyncClient.h" -#ifndef FinderSyncSocketLineProcessor_h -#define FinderSyncSocketLineProcessor_h +#ifndef LineProcessor_h +#define LineProcessor_h /// This class is in charge of dispatching all work that must be done on the UI side of the extension. /// Tasks are dispatched on the main UI thread for this reason. /// -/// These tasks are parsed from byte data (UTF8 strings) acquired from the socket; look at the +/// These tasks are parsed from byte data (UTF9 strings) acquired from the socket; look at the /// LocalSocketClient for more detail on how data is read from and written to the socket. -@interface FinderSyncSocketLineProcessor : NSObject - -@property(nonatomic, weak) id delegate; +@interface LineProcessor : NSObject +@property(nonatomic, weak)id delegate; - (instancetype)initWithDelegate:(id)delegate; +- (void)process:(NSString*)line; @end #endif /* LineProcessor_h */ diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m similarity index 97% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m index 7952e5d611db3..56ec7046a2b56 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m @@ -13,9 +13,9 @@ */ #import -#import "FinderSyncSocketLineProcessor.h" +#import "LineProcessor.h" -@implementation FinderSyncSocketLineProcessor +@implementation LineProcessor -(instancetype)initWithDelegate:(id)delegate { diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h similarity index 75% rename from shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h index 208659a6513eb..4a858cda2236f 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h @@ -12,7 +12,7 @@ * for more details. */ -#import +#import "LineProcessor.h" #ifndef LocalSocketClient_h #define LocalSocketClient_h @@ -37,20 +37,26 @@ @interface LocalSocketClient : NSObject -- (instancetype)initWithSocketPath:(NSString*)socketPath - lineProcessor:(id)lineProcessor; - -@property (readonly) BOOL isConnected; - +@property NSString* socketPath; +@property LineProcessor* lineProcessor; +@property int sock; +@property dispatch_queue_t localSocketQueue; +@property dispatch_source_t readSource; +@property dispatch_source_t writeSource; +@property NSMutableData* inBuffer; +@property NSMutableData* outBuffer; + +- (instancetype)init:(NSString*)socketPath lineProcessor:(LineProcessor*)lineProcessor; +- (BOOL)isConnected; - (void)start; - (void)restart; - (void)closeConnection; - -- (void)sendMessage:(NSString*)message; -- (void)askOnSocket:(NSString*)path - query:(NSString*)verb; -- (void)askForIcon:(NSString*)path - isDirectory:(BOOL)isDirectory; +- (NSString*)strErr; +- (void)askOnSocket:(NSString*)path query:(NSString*)verb; +- (void)askForIcon:(NSString*)path isDirectory:(BOOL)isDirectory; +- (void)readFromSocket; +- (void)writeToSocket; +- (void)processInBuffer; @end #endif /* LocalSocketClient_h */ diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m similarity index 61% rename from shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m index 7e62fc0f37346..ab43a5df2f98b 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m +++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m @@ -13,45 +13,28 @@ */ #import - +#import "LocalSocketClient.h" #include #include #include #include -#import "LocalSocketClient.h" - -@interface LocalSocketClient() -{ - NSString* _socketPath; - id _lineProcessor; - - int _sock; - dispatch_queue_t _localSocketQueue; - dispatch_source_t _readSource; - dispatch_source_t _writeSource; - NSMutableData* _inBuffer; - NSMutableData* _outBuffer; -} -@end - @implementation LocalSocketClient -- (instancetype)initWithSocketPath:(NSString*)socketPath - lineProcessor:(id)lineProcessor +- (instancetype)init:(NSString*)socketPath lineProcessor:(LineProcessor*)lineProcessor { - NSLog(@"Initiating local socket client pointing to %@", socketPath); + NSLog(@"Initiating local socket client."); self = [super init]; if(self) { - _socketPath = socketPath; - _lineProcessor = lineProcessor; + self.socketPath = socketPath; + self.lineProcessor = lineProcessor; - _sock = -1; - _localSocketQueue = dispatch_queue_create("localSocketQueue", DISPATCH_QUEUE_SERIAL); + self.sock = -1; + self.localSocketQueue = dispatch_queue_create("localSocketQueue", DISPATCH_QUEUE_SERIAL); - _inBuffer = [NSMutableData data]; - _outBuffer = [NSMutableData data]; + self.inBuffer = [NSMutableData data]; + self.outBuffer = [NSMutableData data]; } return self; @@ -59,8 +42,8 @@ - (instancetype)initWithSocketPath:(NSString*)socketPath - (BOOL)isConnected { - NSLog(@"Checking is connected: %@", _sock != -1 ? @"YES" : @"NO"); - return _sock != -1; + NSLog(@"Checking is connected: %@", self.sock != -1 ? @"YES" : @"NO"); + return self.sock != -1; } - (void)start @@ -71,44 +54,44 @@ - (void)start } struct sockaddr_un localSocketAddr; - unsigned long socketPathByteCount = [_socketPath lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; // add 1 for the NUL terminator char + unsigned long socketPathByteCount = [self.socketPath lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; // add 1 for the NUL terminator char int maxByteCount = sizeof(localSocketAddr.sun_path); if(socketPathByteCount > maxByteCount) { // LOG THAT THE SOCKET PATH IS TOO LONG HERE - NSLog(@"Socket path '%@' is too long: maximum socket path length is %i, this path is of length %lu", _socketPath, maxByteCount, socketPathByteCount); + NSLog(@"Socket path '%@' is too long: maximum socket path length is %i, this path is of length %lu", self.socketPath, maxByteCount, socketPathByteCount); return; } NSLog(@"Opening local socket..."); // LOG THAT THE SOCKET IS BEING OPENED HERE - _sock = socket(AF_LOCAL, SOCK_STREAM, 0); + self.sock = socket(AF_LOCAL, SOCK_STREAM, 0); - if(_sock == -1) { + if(self.sock == -1) { NSLog(@"Cannot open socket: '%@'", [self strErr]); [self restart]; return; } - NSLog(@"Local socket opened. Connecting to '%@' ...", _socketPath); + NSLog(@"Local socket opened. Connecting to '%@' ...", self.socketPath); localSocketAddr.sun_family = AF_LOCAL & 0xff; - const char* pathBytes = [_socketPath UTF8String]; + const char* pathBytes = [self.socketPath UTF8String]; strcpy(localSocketAddr.sun_path, pathBytes); - int connectionStatus = connect(_sock, (struct sockaddr*)&localSocketAddr, sizeof(localSocketAddr)); + int connectionStatus = connect(self.sock, (struct sockaddr*)&localSocketAddr, sizeof(localSocketAddr)); if(connectionStatus == -1) { - NSLog(@"Could not connect to '%@': '%@'", _socketPath, [self strErr]); + NSLog(@"Could not connect to '%@': '%@'", self.socketPath, [self strErr]); [self restart]; return; } - int flags = fcntl(_sock, F_GETFL, 0); + int flags = fcntl(self.sock, F_GETFL, 0); - if(fcntl(_sock, F_SETFL, flags | O_NONBLOCK) == -1) { + if(fcntl(self.sock, F_SETFL, flags | O_NONBLOCK) == -1) { NSLog(@"Could not set socket to non-blocking mode: '%@'", [self strErr]); [self restart]; return; @@ -116,17 +99,17 @@ - (void)start NSLog(@"Connected to socket. Setting up dispatch sources..."); - _readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, _sock, 0, _localSocketQueue); - dispatch_source_set_event_handler(_readSource, ^(void){ [self readFromSocket]; }); - dispatch_source_set_cancel_handler(_readSource, ^(void){ - self->_readSource = nil; + self.readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, self.sock, 0, self.localSocketQueue); + dispatch_source_set_event_handler(self.readSource, ^(void){ [self readFromSocket]; }); + dispatch_source_set_cancel_handler(self.readSource, ^(void){ + self.readSource = nil; [self closeConnection]; }); - _writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, _sock, 0, _localSocketQueue); - dispatch_source_set_event_handler(_writeSource, ^(void){ [self writeToSocket]; }); - dispatch_source_set_cancel_handler(_writeSource, ^(void){ - self->_writeSource = nil; + self.writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, self.sock, 0, self.localSocketQueue); + dispatch_source_set_event_handler(self.writeSource, ^(void){ [self writeToSocket]; }); + dispatch_source_set_cancel_handler(self.writeSource, ^(void){ + self.writeSource = nil; [self closeConnection]; }); @@ -136,7 +119,8 @@ - (void)start NSLog(@"Starting to read from socket"); - dispatch_resume(_readSource); + dispatch_resume(self.readSource); + [self askOnSocket:@"" query:@"GET_STRINGS"]; } - (void)restart @@ -154,35 +138,35 @@ - (void)closeConnection { NSLog(@"Closing connection."); - if(_readSource) { + if(self.readSource) { // Since dispatch_source_cancel works asynchronously, if we deallocate the dispatch source here then we can // cause a crash. So instead we strongly hold a reference to the read source and deallocate it asynchronously // with the handler. - __block dispatch_source_t previousReadSource = _readSource; - dispatch_source_set_cancel_handler(_readSource, ^{ + __block dispatch_source_t previousReadSource = self.readSource; + dispatch_source_set_cancel_handler(self.readSource, ^{ previousReadSource = nil; }); - dispatch_source_cancel(_readSource); + dispatch_source_cancel(self.readSource); // The readSource is still alive due to the other reference and will be deallocated by the cancel handler - _readSource = nil; + self.readSource = nil; } - if(_writeSource) { + if(self.writeSource) { // Same deal with the write source - __block dispatch_source_t previousWriteSource = _writeSource; - dispatch_source_set_cancel_handler(_writeSource, ^{ + __block dispatch_source_t previousWriteSource = self.writeSource; + dispatch_source_set_cancel_handler(self.writeSource, ^{ previousWriteSource = nil; }); - dispatch_source_cancel(_writeSource); - _writeSource = nil; + dispatch_source_cancel(self.writeSource); + self.writeSource = nil; } - [_inBuffer setLength:0]; - [_outBuffer setLength: 0]; + [self.inBuffer setLength:0]; + [self.outBuffer setLength: 0]; - if(_sock != -1) { - close(_sock); - _sock = -1; + if(self.sock != -1) { + close(self.sock); + self.sock = -1; } } @@ -199,50 +183,45 @@ - (NSString*)strErr } } -- (void)sendMessage:(NSString *)message +- (void)askOnSocket:(NSString *)path query:(NSString *)verb { - dispatch_async(_localSocketQueue, ^(void) { + NSString *line = [NSString stringWithFormat:@"%@:%@\n", verb, path]; + dispatch_async(self.localSocketQueue, ^(void) { if(![self isConnected]) { return; } - - BOOL writeSourceIsSuspended = [self->_outBuffer length] == 0; - - [self->_outBuffer appendData:[message dataUsingEncoding:NSUTF8StringEncoding]]; - - NSLog(@"Writing to out buffer: '%@'", message); - NSLog(@"Out buffer now %li bytes", [self->_outBuffer length]); - + + BOOL writeSourceIsSuspended = [self.outBuffer length] == 0; + + [self.outBuffer appendData:[line dataUsingEncoding:NSUTF8StringEncoding]]; + + NSLog(@"Writing to out buffer: '%@'", line); + NSLog(@"Out buffer now %li bytes", [self.outBuffer length]); + if(writeSourceIsSuspended) { NSLog(@"Resuming write dispatch source."); - dispatch_resume(self->_writeSource); + dispatch_resume(self.writeSource); } }); } -- (void)askOnSocket:(NSString *)path query:(NSString *)verb -{ - NSString *line = [NSString stringWithFormat:@"%@:%@\n", verb, path]; - [self sendMessage:line]; -} - - (void)writeToSocket { if(![self isConnected]) { return; } - if([_outBuffer length] == 0) { + if([self.outBuffer length] == 0) { NSLog(@"Empty out buffer, suspending write dispatch source."); - dispatch_suspend(_writeSource); + dispatch_suspend(self.writeSource); return; } - NSLog(@"About to write %li bytes from outbuffer to socket.", [_outBuffer length]); + NSLog(@"About to write %li bytes from outbuffer to socket.", [self.outBuffer length]); - long bytesWritten = write(_sock, [_outBuffer bytes], [_outBuffer length]); - char lineWritten[[_outBuffer length]]; - memcpy(lineWritten, [_outBuffer bytes], [_outBuffer length]); + long bytesWritten = write(self.sock, [self.outBuffer bytes], [self.outBuffer length]); + char lineWritten[[self.outBuffer length]]; + memcpy(lineWritten, [self.outBuffer bytes], [self.outBuffer length]); NSLog(@"Wrote %li bytes to socket. Line written was: '%@'", bytesWritten, [NSString stringWithUTF8String:lineWritten]); if(bytesWritten == 0) { @@ -261,13 +240,13 @@ - (void)writeToSocket [self restart]; } } else if(bytesWritten > 0) { - [_outBuffer replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0]; + [self.outBuffer replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0]; - NSLog(@"Out buffer cleared. Now count is %li bytes.", [_outBuffer length]); + NSLog(@"Out buffer cleared. Now count is %li bytes.", [self.outBuffer length]); - if([_outBuffer length] == 0) { + if([self.outBuffer length] == 0) { NSLog(@"Out buffer has been emptied, suspending write dispatch source."); - dispatch_suspend(_writeSource); + dispatch_suspend(self.writeSource); } } } @@ -298,7 +277,7 @@ - (void)readFromSocket char buffer[bufferLength]; while(true) { - long bytesRead = read(_sock, buffer, bufferLength); + long bytesRead = read(self.sock, buffer, bufferLength); NSLog(@"Read %li bytes from socket.", bytesRead); @@ -318,7 +297,7 @@ - (void)readFromSocket return; } } else { - [_inBuffer appendBytes:buffer length:bytesRead]; + [self.inBuffer appendBytes:buffer length:bytesRead]; [self processInBuffer]; } } @@ -326,22 +305,22 @@ - (void)readFromSocket - (void)processInBuffer { - NSLog(@"Processing in buffer. In buffer length %li", [_inBuffer length]); + NSLog(@"Processing in buffer. In buffer length %li", [self.inBuffer length]); UInt8 separator[] = {0xa}; // Byte value for "\n" while(true) { - NSRange firstSeparatorIndex = [_inBuffer rangeOfData:[NSData dataWithBytes:separator length:1] options:0 range:NSMakeRange(0, [_inBuffer length])]; + NSRange firstSeparatorIndex = [self.inBuffer rangeOfData:[NSData dataWithBytes:separator length:1] options:0 range:NSMakeRange(0, [self.inBuffer length])]; if(firstSeparatorIndex.location == NSNotFound) { NSLog(@"No separator found. Stopping."); return; // No separator, nope out } else { - unsigned char *buffer = [_inBuffer mutableBytes]; + unsigned char *buffer = [self.inBuffer mutableBytes]; buffer[firstSeparatorIndex.location] = 0; // Add NULL terminator, so we can use C string methods - NSString *newLine = [NSString stringWithUTF8String:[_inBuffer bytes]]; + NSString *newLine = [NSString stringWithUTF8String:[self.inBuffer bytes]]; - [_inBuffer replaceBytesInRange:NSMakeRange(0, firstSeparatorIndex.location + 1) withBytes:NULL length:0]; - [_lineProcessor process:newLine]; + [self.inBuffer replaceBytesInRange:NSMakeRange(0, firstSeparatorIndex.location + 1) withBytes:NULL length:0]; + [self.lineProcessor process:newLine]; } } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/SyncClient.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClient.h similarity index 100% rename from shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/SyncClient.h rename to shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClient.h diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000..ad6d849dce408 --- /dev/null +++ b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj @@ -0,0 +1,600 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 539158AC27BE71A900816F56 /* LineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* LineProcessor.m */; }; + 539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; }; + C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; }; + C2B573D21B1CD94B00303B36 /* main.m in Resources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; }; + C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573DD1B1CD9CE00303B36 /* FinderSync.m */; }; + C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + C2B573F31B1DAD6400303B36 /* error.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EB1B1DAD6400303B36 /* error.iconset */; }; + C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */; }; + C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573ED1B1DAD6400303B36 /* ok.iconset */; }; + C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EF1B1DAD6400303B36 /* sync.iconset */; }; + C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573F11B1DAD6400303B36 /* warning.iconset */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C2B573951B1CD88000303B36 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2B573D61B1CD9CE00303B36; + remoteInfo = FinderSyncExt; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + C2B573E11B1CD9CE00303B36 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 539158A927BE606500816F56 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = ""; }; + 539158AA27BE67CC00816F56 /* SyncClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyncClient.h; sourceTree = ""; }; + 539158AB27BE71A900816F56 /* LineProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LineProcessor.m; sourceTree = ""; }; + 539158B127BE891500816F56 /* LocalSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalSocketClient.h; sourceTree = ""; }; + 539158B227BEC98A00816F56 /* LocalSocketClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalSocketClient.m; sourceTree = ""; }; + C2B573B11B1CD91E00303B36 /* desktopclient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktopclient.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C2B573B51B1CD91E00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C2B573B91B1CD91E00303B36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FinderSyncExt.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + C2B573DA1B1CD9CE00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = FinderSyncExt.entitlements; sourceTree = ""; }; + C2B573DC1B1CD9CE00303B36 /* FinderSync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinderSync.h; sourceTree = ""; }; + C2B573DD1B1CD9CE00303B36 /* FinderSync.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FinderSync.m; sourceTree = ""; }; + C2B573EB1B1DAD6400303B36 /* error.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = error.iconset; path = ../../icons/nopadding/error.iconset; sourceTree = SOURCE_ROOT; }; + C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok_swm.iconset; path = ../../icons/nopadding/ok_swm.iconset; sourceTree = SOURCE_ROOT; }; + C2B573ED1B1DAD6400303B36 /* ok.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok.iconset; path = ../../icons/nopadding/ok.iconset; sourceTree = SOURCE_ROOT; }; + C2B573EF1B1DAD6400303B36 /* sync.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = sync.iconset; path = ../../icons/nopadding/sync.iconset; sourceTree = SOURCE_ROOT; }; + C2B573F11B1DAD6400303B36 /* warning.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = warning.iconset; path = ../../icons/nopadding/warning.iconset; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + C2B573AE1B1CD91E00303B36 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2B573D41B1CD9CE00303B36 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + C2B573941B1CD88000303B36 = { + isa = PBXGroup; + children = ( + C2B573B31B1CD91E00303B36 /* desktopclient */, + C2B573D81B1CD9CE00303B36 /* FinderSyncExt */, + C2B573B21B1CD91E00303B36 /* Products */, + ); + sourceTree = ""; + }; + C2B573B21B1CD91E00303B36 /* Products */ = { + isa = PBXGroup; + children = ( + C2B573B11B1CD91E00303B36 /* desktopclient.app */, + C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */, + ); + name = Products; + sourceTree = ""; + }; + C2B573B31B1CD91E00303B36 /* desktopclient */ = { + isa = PBXGroup; + children = ( + C2B573B41B1CD91E00303B36 /* Supporting Files */, + ); + path = desktopclient; + sourceTree = ""; + }; + C2B573B41B1CD91E00303B36 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + C2B573B51B1CD91E00303B36 /* Info.plist */, + C2B573B91B1CD91E00303B36 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + C2B573D81B1CD9CE00303B36 /* FinderSyncExt */ = { + isa = PBXGroup; + children = ( + 539158AA27BE67CC00816F56 /* SyncClient.h */, + C2B573DC1B1CD9CE00303B36 /* FinderSync.h */, + C2B573DD1B1CD9CE00303B36 /* FinderSync.m */, + 539158A927BE606500816F56 /* LineProcessor.h */, + 539158AB27BE71A900816F56 /* LineProcessor.m */, + 539158B127BE891500816F56 /* LocalSocketClient.h */, + 539158B227BEC98A00816F56 /* LocalSocketClient.m */, + C2B573D91B1CD9CE00303B36 /* Supporting Files */, + ); + path = FinderSyncExt; + sourceTree = ""; + }; + C2B573D91B1CD9CE00303B36 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + C2B573EB1B1DAD6400303B36 /* error.iconset */, + C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */, + C2B573ED1B1DAD6400303B36 /* ok.iconset */, + C2B573EF1B1DAD6400303B36 /* sync.iconset */, + C2B573F11B1DAD6400303B36 /* warning.iconset */, + C2B573DA1B1CD9CE00303B36 /* Info.plist */, + C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + C2B573B01B1CD91E00303B36 /* desktopclient */ = { + isa = PBXNativeTarget; + buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */; + buildPhases = ( + C2B573AD1B1CD91E00303B36 /* Sources */, + C2B573AE1B1CD91E00303B36 /* Frameworks */, + C2B573AF1B1CD91E00303B36 /* Resources */, + C2B573E11B1CD9CE00303B36 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */, + ); + name = desktopclient; + productName = desktopclient; + productReference = C2B573B11B1CD91E00303B36 /* desktopclient.app */; + productType = "com.apple.product-type.application"; + }; + C2B573D61B1CD9CE00303B36 /* FinderSyncExt */ = { + isa = PBXNativeTarget; + buildConfigurationList = C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */; + buildPhases = ( + C2B573D31B1CD9CE00303B36 /* Sources */, + C2B573D41B1CD9CE00303B36 /* Frameworks */, + C2B573D51B1CD9CE00303B36 /* Resources */, + 5B3335471CA058E200E11A45 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FinderSyncExt; + productName = FinderSyncExt; + productReference = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C2B573951B1CD88000303B36 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1240; + TargetAttributes = { + C2B573B01B1CD91E00303B36 = { + CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = 9B5WD74GWJ; + ProvisioningStyle = Manual; + }; + C2B573D61B1CD9CE00303B36 = { + CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = 9B5WD74GWJ; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.ApplicationGroups.Mac = { + enabled = 1; + }; + }; + }; + }; + }; + buildConfigurationList = C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "OwnCloudFinderSync" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = C2B573941B1CD88000303B36; + productRefGroup = C2B573B21B1CD91E00303B36 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C2B573B01B1CD91E00303B36 /* desktopclient */, + C2B573D61B1CD9CE00303B36 /* FinderSyncExt */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + C2B573AF1B1CD91E00303B36 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B573D21B1CD94B00303B36 /* main.m in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2B573D51B1CD9CE00303B36 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */, + C2B573F31B1DAD6400303B36 /* error.iconset in Resources */, + C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */, + C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */, + C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 5B3335471CA058E200E11A45 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [[ ${OC_OEM_SHARE_ICNS} ]]; then\n cp ${OC_OEM_SHARE_ICNS} ${BUILT_PRODUCTS_DIR}/FinderSyncExt.appex/Contents/Resources/app.icns\nfi"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + C2B573AD1B1CD91E00303B36 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B573BA1B1CD91E00303B36 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2B573D31B1CD9CE00303B36 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */, + 539158AC27BE71A900816F56 /* LineProcessor.m in Sources */, + C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */; + targetProxy = C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C2B573991B1CD88000303B36 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + }; + name = Debug; + }; + C2B5739A1B1CD88000303B36 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + }; + name = Release; + }; + C2B573CD1B1CD91E00303B36 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = desktopclient/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = macosx; + }; + name = Debug; + }; + C2B573CE1B1CD91E00303B36 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = desktopclient/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = macosx; + }; + name = Release; + }; + C2B573E41B1CD9CE00303B36 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = FinderSyncExt/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + OC_APPLICATION_NAME = ownCloud; + OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient; + OC_OEM_SHARE_ICNS = ""; + OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = ""; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + C2B573E51B1CD9CE00303B36 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = FinderSyncExt/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + OC_APPLICATION_NAME = ownCloud; + OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient; + OC_OEM_SHARE_ICNS = ""; + OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "OwnCloudFinderSync" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2B573991B1CD88000303B36 /* Debug */, + C2B5739A1B1CD88000303B36 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2B573CD1B1CD91E00303B36 /* Debug */, + C2B573CE1B1CD91E00303B36 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2B573E41B1CD9CE00303B36 /* Debug */, + C2B573E51B1CD9CE00303B36 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C2B573951B1CD88000303B36 /* Project object */; +} diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme similarity index 80% rename from shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme rename to shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme index 174aab5bb930c..63ec0b6c5817b 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme +++ b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme @@ -18,7 +18,7 @@ BlueprintIdentifier = "C2B573D61B1CD9CE00303B36" BuildableName = "FinderSyncExt.appex" BlueprintName = "FinderSyncExt" - ReferencedContainer = "container:NextcloudIntegration.xcodeproj"> + ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj"> + ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj"> @@ -48,21 +48,10 @@ BlueprintIdentifier = "C2B573D61B1CD9CE00303B36" BuildableName = "FinderSyncExt.appex" BlueprintName = "FinderSyncExt" - ReferencedContainer = "container:NextcloudIntegration.xcodeproj"> + ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj"> - - - - + ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj"> @@ -103,7 +92,7 @@ BlueprintIdentifier = "C2B573B01B1CD91E00303B36" BuildableName = "desktopclient.app" BlueprintName = "desktopclient" - ReferencedContainer = "container:NextcloudIntegration.xcodeproj"> + ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj"> diff --git a/shell_integration/MacOSX/NextcloudIntegration/desktopclient/Info.plist b/shell_integration/MacOSX/OwnCloudFinderSync/desktopclient/Info.plist similarity index 100% rename from shell_integration/MacOSX/NextcloudIntegration/desktopclient/Info.plist rename to shell_integration/MacOSX/OwnCloudFinderSync/desktopclient/Info.plist diff --git a/shell_integration/MacOSX/NextcloudIntegration/desktopclient/main.m b/shell_integration/MacOSX/OwnCloudFinderSync/desktopclient/main.m similarity index 100% rename from shell_integration/MacOSX/NextcloudIntegration/desktopclient/main.m rename to shell_integration/MacOSX/OwnCloudFinderSync/desktopclient/main.m diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index e4af0e33a6fef..42745aa9a0f70 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -285,19 +285,6 @@ IF( APPLE ) list(APPEND client_SRCS cocoainitializer_mac.mm) list(APPEND client_SRCS systray.mm) - if (BUILD_FILE_PROVIDER_MODULE) - list(APPEND client_SRCS - macOS/fileprovider.h - macOS/fileprovider_mac.mm - macOS/fileproviderdomainmanager.h - macOS/fileproviderdomainmanager_mac.mm - macOS/fileprovidersocketcontroller.h - macOS/fileprovidersocketcontroller.cpp - macOS/fileprovidersocketserver.h - macOS/fileprovidersocketserver.cpp - macOS/fileprovidersocketserver_mac.mm) - endif() - if(SPARKLE_FOUND AND BUILD_UPDATER) # Define this, we need to check in updater.cpp add_definitions(-DHAVE_SPARKLE) @@ -670,12 +657,7 @@ endif() if (APPLE) find_package(Qt5 COMPONENTS MacExtras) - - if (BUILD_FILE_PROVIDER_MODULE) - target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications -framework FileProvider") - else() - target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications") - endif() + target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications") endif() if(WITH_CRASHREPORTER) diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 0db5f96d16d3b..304df1d835327 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -51,8 +51,6 @@ #if defined(Q_OS_WIN) #include -#elif defined(Q_OS_MACOS) -#include "macOS/fileprovider.h" #endif #if defined(WITH_CRASHREPORTER) @@ -374,7 +372,7 @@ Application::Application(int &argc, char **argv) } _folderManager.reset(new FolderMan); -#if defined(Q_OS_WIN) +#ifdef Q_OS_WIN _shellExtensionsServer.reset(new ShellExtensionsServer); #endif @@ -403,10 +401,6 @@ Application::Application(int &argc, char **argv) } } -#if defined(Q_OS_MACOS) - _fileProvider.reset(new Mac::FileProvider); -#endif - FolderMan::instance()->setSyncEnabled(true); setQuitOnLastWindowClosed(false); diff --git a/src/gui/application.h b/src/gui/application.h index bb9f97bef0b57..5a21cc8745db4 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -49,12 +49,6 @@ class Folder; class ShellExtensionsServer; class SslErrorDialog; -#ifdef Q_OS_MACOS -namespace Mac { -class FileProvider; -} -#endif - /** * @brief The Application class * @ingroup gui @@ -158,10 +152,8 @@ protected slots: QScopedPointer _crashHandler; #endif QScopedPointer _folderManager; -#if defined(Q_OS_WIN) +#ifdef Q_OS_WIN QScopedPointer _shellExtensionsServer; -#elif defined(Q_OS_MACOS) - QScopedPointer _fileProvider; #endif }; diff --git a/src/gui/macOS/fileprovider.h b/src/gui/macOS/fileprovider.h deleted file mode 100644 index d45ba987d2a5b..0000000000000 --- a/src/gui/macOS/fileprovider.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#pragma once - -#include - -#include "fileproviderdomainmanager.h" -#include "fileprovidersocketserver.h" - -namespace OCC { - -class Application; - -namespace Mac { - -// NOTE: For the file provider extension to work, the app bundle will -// need to be correctly codesigned! - -class FileProvider : public QObject -{ - Q_OBJECT - -public: - static FileProvider *instance(); - ~FileProvider() override; - - static bool fileProviderAvailable(); - -private: - std::unique_ptr _domainManager; - std::unique_ptr _socketServer; - - static FileProvider *_instance; - explicit FileProvider(QObject * const parent = nullptr); - - friend class OCC::Application; -}; - -} // namespace Mac -} // namespace OCC diff --git a/src/gui/macOS/fileprovider_mac.mm b/src/gui/macOS/fileprovider_mac.mm deleted file mode 100644 index 56db4d2447b07..0000000000000 --- a/src/gui/macOS/fileprovider_mac.mm +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#import - -#include - -#include "configfile.h" - -#include "fileprovider.h" - -namespace OCC { - -Q_LOGGING_CATEGORY(lcMacFileProvider, "nextcloud.gui.macfileprovider", QtInfoMsg) - -namespace Mac { - -FileProvider* FileProvider::_instance = nullptr; - -FileProvider::FileProvider(QObject * const parent) - : QObject(parent) -{ - Q_ASSERT(!_instance); - - if (!fileProviderAvailable()) { - qCInfo(lcMacFileProvider) << "File provider system is not available on this version of macOS."; - deleteLater(); - return; - } else if (!ConfigFile().macFileProviderModuleEnabled()) { - qCInfo(lcMacFileProvider) << "File provider module is not enabled in application config."; - deleteLater(); - return; - } - - qCInfo(lcMacFileProvider) << "Initialising file provider domain manager."; - _domainManager = std::make_unique(new FileProviderDomainManager(this)); - - if (_domainManager) { - qCDebug(lcMacFileProvider()) << "Initialized file provider domain manager"; - } - - qCDebug(lcMacFileProvider) << "Initialising file provider socket server."; - _socketServer = std::make_unique(new FileProviderSocketServer(this)); - - if (_socketServer) { - qCDebug(lcMacFileProvider) << "Initialised file provider socket server."; - } -} - -FileProvider *FileProvider::instance() -{ - if (!fileProviderAvailable()) { - qCInfo(lcMacFileProvider) << "File provider system is not available on this version of macOS."; - return nullptr; - } else if (!ConfigFile().macFileProviderModuleEnabled()) { - qCInfo(lcMacFileProvider) << "File provider module is not enabled in application config."; - return nullptr; - } - - if (!_instance) { - _instance = new FileProvider(); - } - return _instance; -} - -FileProvider::~FileProvider() -{ - _instance = nullptr; -} - -bool FileProvider::fileProviderAvailable() -{ - if (@available(macOS 11.0, *)) { - return true; - } - - return false; -} - -} // namespace Mac -} // namespace OCC diff --git a/src/gui/macOS/fileproviderdomainmanager.h b/src/gui/macOS/fileproviderdomainmanager.h deleted file mode 100644 index 3aa80d39be3c5..0000000000000 --- a/src/gui/macOS/fileproviderdomainmanager.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#pragma once - -#include - -#include "accountstate.h" - -namespace OCC { - -class Account; - -namespace Mac { - -class FileProviderDomainManager : public QObject -{ - Q_OBJECT - -public: - explicit FileProviderDomainManager(QObject * const parent = nullptr); - ~FileProviderDomainManager() override; - - static AccountStatePtr accountStateFromFileProviderDomainIdentifier(const QString &domainIdentifier); - -private slots: - void setupFileProviderDomains(); - - void addFileProviderDomainForAccount(const OCC::AccountState * const accountState); - void removeFileProviderDomainForAccount(const OCC::AccountState * const accountState); - void disconnectFileProviderDomainForAccount(const OCC::AccountState * const accountState, const QString &reason); - void reconnectFileProviderDomainForAccount(const OCC::AccountState * const accountState); - - void trySetupPushNotificationsForAccount(const OCC::Account * const account); - void setupPushNotificationsForAccount(const OCC::Account * const account); - void signalEnumeratorChanged(const OCC::Account * const account); - - void slotAccountStateChanged(const OCC::AccountState * const accountState); - void slotEnumeratorSignallingTimerTimeout(); - -private: - // Starts regular enumerator signalling if no push notifications available - QTimer _enumeratorSignallingTimer; - - class MacImplementation; - std::unique_ptr d; -}; - -} // namespace Mac - -} // namespace OCC diff --git a/src/gui/macOS/fileproviderdomainmanager_mac.mm b/src/gui/macOS/fileproviderdomainmanager_mac.mm deleted file mode 100644 index 29b3ee244c27b..0000000000000 --- a/src/gui/macOS/fileproviderdomainmanager_mac.mm +++ /dev/null @@ -1,636 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "configfile.h" -#import - -#include - -#include "config.h" -#include "fileproviderdomainmanager.h" -#include "pushnotifications.h" - -#include "gui/accountmanager.h" -#include "libsync/account.h" - -// Ensure that conversion to/from domain identifiers and display names -// are consistent throughout these classes -namespace { - -QString domainIdentifierForAccount(const OCC::Account * const account) -{ - Q_ASSERT(account); - return account->userIdAtHostWithPort(); -} - -QString domainIdentifierForAccount(const OCC::AccountPtr account) -{ - return domainIdentifierForAccount(account.get()); -} - -QString domainDisplayNameForAccount(const OCC::Account * const account) -{ - Q_ASSERT(account); - return account->displayName(); -} - -QString domainDisplayNameForAccount(const OCC::AccountPtr account) -{ - return domainDisplayNameForAccount(account.get()); -} - -QString accountIdFromDomainId(const QString &domainId) -{ - return domainId; -} - -QString accountIdFromDomainId(NSString * const domainId) -{ - return accountIdFromDomainId(QString::fromNSString(domainId)); -} - -API_AVAILABLE(macos(11.0)) -QString accountIdFromDomain(NSFileProviderDomain * const domain) -{ - return accountIdFromDomainId(domain.identifier); -} - -bool accountFilesPushNotificationsReady(const OCC::AccountPtr &account) -{ - const auto pushNotifications = account->pushNotifications(); - const auto pushNotificationsCapability = account->capabilities().availablePushNotifications() & OCC::PushNotificationType::Files; - - return pushNotificationsCapability && pushNotifications && pushNotifications->isReady(); -} - -} - -namespace OCC { - -Q_LOGGING_CATEGORY(lcMacFileProviderDomainManager, "nextcloud.gui.macfileproviderdomainmanager", QtInfoMsg) - -namespace Mac { - -class API_AVAILABLE(macos(11.0)) FileProviderDomainManager::MacImplementation { - - public: - MacImplementation() = default; - ~MacImplementation() = default; - - void findExistingFileProviderDomains() - { - if (@available(macOS 11.0, *)) { - // Wait for this to finish - dispatch_group_t dispatchGroup = dispatch_group_create(); - dispatch_group_enter(dispatchGroup); - - [NSFileProviderManager getDomainsWithCompletionHandler:^(NSArray * const domains, NSError * const error) { - if(error) { - qCDebug(lcMacFileProviderDomainManager) << "Could not get existing file provider domains: " - << error.code - << error.localizedDescription; - dispatch_group_leave(dispatchGroup); - return; - } - - if (domains.count == 0) { - qCDebug(lcMacFileProviderDomainManager) << "Found no existing file provider domains"; - dispatch_group_leave(dispatchGroup); - return; - } - - for (NSFileProviderDomain * const domain in domains) { - const auto accountId = accountIdFromDomain(domain); - - if (const auto accountState = AccountManager::instance()->accountFromUserId(accountId); - accountState && - accountState->account() && - domainDisplayNameForAccount(accountState->account()) == QString::fromNSString(domain.displayName)) { - - qCDebug(lcMacFileProviderDomainManager) << "Found existing file provider domain for account:" - << accountState->account()->displayName(); - [domain retain]; - _registeredDomains.insert(accountId, domain); - - NSFileProviderManager * const fpManager = [NSFileProviderManager managerForDomain:domain]; - [fpManager reconnectWithCompletionHandler:^(NSError * const error) { - if (error) { - qCDebug(lcMacFileProviderDomainManager) << "Error reconnecting file provider domain: " - << domain.displayName - << error.code - << error.localizedDescription; - return; - } - - qCDebug(lcMacFileProviderDomainManager) << "Successfully reconnected file provider domain: " - << domain.displayName; - }]; - - } else { - qCDebug(lcMacFileProviderDomainManager) << "Found existing file provider domain with no known configured account:" - << domain.displayName; - [NSFileProviderManager removeDomain:domain completionHandler:^(NSError * const error) { - if(error) { - qCDebug(lcMacFileProviderDomainManager) << "Error removing file provider domain: " - << error.code - << error.localizedDescription; - } - }]; - } - } - - dispatch_group_leave(dispatchGroup); - }]; - - dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER); - } - } - - void addFileProviderDomain(const AccountState * const accountState) - { - if (@available(macOS 11.0, *)) { - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - const auto domainDisplayName = domainDisplayNameForAccount(account); - const auto domainId = domainIdentifierForAccount(account); - - qCDebug(lcMacFileProviderDomainManager) << "Adding new file provider domain with id: " << domainId; - - if(_registeredDomains.contains(domainId) && _registeredDomains.value(domainId) != nil) { - qCDebug(lcMacFileProviderDomainManager) << "File provider domain with id already exists: " << domainId; - return; - } - - NSFileProviderDomain * const fileProviderDomain = [[NSFileProviderDomain alloc] initWithIdentifier:domainId.toNSString() - displayName:domainDisplayName.toNSString()]; - [fileProviderDomain retain]; - - [NSFileProviderManager addDomain:fileProviderDomain completionHandler:^(NSError * const error) { - if(error) { - qCDebug(lcMacFileProviderDomainManager) << "Error adding file provider domain: " - << error.code - << error.localizedDescription; - } - - _registeredDomains.insert(domainId, fileProviderDomain); - }]; - } - } - - void removeFileProviderDomain(const AccountState * const accountState) - { - if (@available(macOS 11.0, *)) { - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - const auto domainId = domainIdentifierForAccount(account); - qCDebug(lcMacFileProviderDomainManager) << "Removing file provider domain with id: " << domainId; - - if(!_registeredDomains.contains(domainId)) { - qCDebug(lcMacFileProviderDomainManager) << "File provider domain not found for id: " << domainId; - return; - } - - NSFileProviderDomain * const fileProviderDomain = _registeredDomains[domainId]; - - [NSFileProviderManager removeDomain:fileProviderDomain completionHandler:^(NSError *error) { - if(error) { - qCDebug(lcMacFileProviderDomainManager) << "Error removing file provider domain: " - << error.code - << error.localizedDescription; - } - - NSFileProviderDomain * const domain = _registeredDomains.take(domainId); - [domain release]; - }]; - } - } - - void removeAllFileProviderDomains() - { - if (@available(macOS 11.0, *)) { - qCDebug(lcMacFileProviderDomainManager) << "Removing all file provider domains."; - - [NSFileProviderManager removeAllDomainsWithCompletionHandler:^(NSError * const error) { - if(error) { - qCDebug(lcMacFileProviderDomainManager) << "Error removing all file provider domains: " - << error.code - << error.localizedDescription; - return; - } - - const auto registeredDomainPtrs = _registeredDomains.values(); - for (NSFileProviderDomain * const domain : registeredDomainPtrs) { - if (domain != nil) { - [domain release]; - } - } - _registeredDomains.clear(); - }]; - } - } - - void wipeAllFileProviderDomains() - { - if (@available(macOS 12.0, *)) { - qCDebug(lcMacFileProviderDomainManager) << "Removing and wiping all file provider domains"; - - [NSFileProviderManager getDomainsWithCompletionHandler:^(NSArray * const domains, NSError * const error) { - if (error) { - qCDebug(lcMacFileProviderDomainManager) << "Error removing and wiping file provider domains: " - << error.code - << error.localizedDescription; - return; - } - - for (NSFileProviderDomain * const domain in domains) { - [NSFileProviderManager removeDomain:domain mode:NSFileProviderDomainRemovalModeRemoveAll completionHandler:^(NSURL * const preservedLocation, NSError * const error) { - Q_UNUSED(preservedLocation) - - if (error) { - qCDebug(lcMacFileProviderDomainManager) << "Error removing and wiping file provider domain: " - << domain.displayName - << error.code - << error.localizedDescription; - return; - } - - NSFileProviderDomain * const registeredDomainPtr = _registeredDomains.take(QString::fromNSString(domain.identifier)); - if (registeredDomainPtr != nil) { - [domain release]; - } - }]; - } - }]; - } else if (@available(macOS 11.0, *)) { - qCDebug(lcMacFileProviderDomainManager) << "Removing all file provider domains, can't specify wipe on macOS 11"; - removeAllFileProviderDomains(); - } - } - - void disconnectFileProviderDomainForAccount(const AccountState * const accountState, const QString &message) - { - if (@available(macOS 11.0, *)) { - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - const auto domainId = domainIdentifierForAccount(account); - qCDebug(lcMacFileProviderDomainManager) << "Disconnecting file provider domain with id: " << domainId; - - if(!_registeredDomains.contains(domainId)) { - qCDebug(lcMacFileProviderDomainManager) << "File provider domain not found for id: " << domainId; - return; - } - - NSFileProviderDomain * const fileProviderDomain = _registeredDomains[domainId]; - Q_ASSERT(fileProviderDomain != nil); - - NSFileProviderManager * const fpManager = [NSFileProviderManager managerForDomain:fileProviderDomain]; - [fpManager disconnectWithReason:message.toNSString() - options:NSFileProviderManagerDisconnectionOptionsTemporary - completionHandler:^(NSError * const error) { - if (error) { - qCDebug(lcMacFileProviderDomainManager) << "Error disconnecting file provider domain: " - << fileProviderDomain.displayName - << error.code - << error.localizedDescription; - return; - } - - qCDebug(lcMacFileProviderDomainManager) << "Successfully disconnected file provider domain: " - << fileProviderDomain.displayName; - }]; - } - } - - void reconnectFileProviderDomainForAccount(const AccountState * const accountState) - { - if (@available(macOS 11.0, *)) { - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - const auto domainId = domainIdentifierForAccount(account); - qCDebug(lcMacFileProviderDomainManager) << "Reconnecting file provider domain with id: " << domainId; - - if(!_registeredDomains.contains(domainId)) { - qCDebug(lcMacFileProviderDomainManager) << "File provider domain not found for id: " << domainId; - return; - } - - NSFileProviderDomain * const fileProviderDomain = _registeredDomains[domainId]; - Q_ASSERT(fileProviderDomain != nil); - - NSFileProviderManager * const fpManager = [NSFileProviderManager managerForDomain:fileProviderDomain]; - [fpManager reconnectWithCompletionHandler:^(NSError * const error) { - if (error) { - qCDebug(lcMacFileProviderDomainManager) << "Error reconnecting file provider domain: " - << fileProviderDomain.displayName - << error.code - << error.localizedDescription; - return; - } - - qCDebug(lcMacFileProviderDomainManager) << "Successfully reconnected file provider domain: " - << fileProviderDomain.displayName; - - signalEnumeratorChanged(account.get()); - }]; - } - } - - void signalEnumeratorChanged(const Account * const account) - { - if (@available(macOS 11.0, *)) { - Q_ASSERT(account); - const auto domainId = domainIdentifierForAccount(account); - - qCDebug(lcMacFileProviderDomainManager) << "Signalling enumerator changed in file provider domain for account with id: " << domainId; - - if(!_registeredDomains.contains(domainId)) { - qCDebug(lcMacFileProviderDomainManager) << "File provider domain not found for id: " << domainId; - return; - } - - NSFileProviderDomain * const fileProviderDomain = _registeredDomains[domainId]; - Q_ASSERT(fileProviderDomain != nil); - - NSFileProviderManager * const fpManager = [NSFileProviderManager managerForDomain:fileProviderDomain]; - [fpManager signalEnumeratorForContainerItemIdentifier:NSFileProviderWorkingSetContainerItemIdentifier completionHandler:^(NSError * const error) { - if (error != nil) { - qCDebug(lcMacFileProviderDomainManager) << "Error signalling enumerator changed for working set:" - << error.localizedDescription; - } - }]; - } - } - - QStringList configuredDomainIds() const { - return _registeredDomains.keys(); - } - -private: - QHash _registeredDomains; -}; - -FileProviderDomainManager::FileProviderDomainManager(QObject * const parent) - : QObject(parent) -{ - if (@available(macOS 11.0, *)) { - d.reset(new FileProviderDomainManager::MacImplementation()); - - ConfigFile cfg; - std::chrono::milliseconds polltime = cfg.remotePollInterval(); - _enumeratorSignallingTimer.setInterval(polltime.count()); - connect(&_enumeratorSignallingTimer, &QTimer::timeout, - this, &FileProviderDomainManager::slotEnumeratorSignallingTimerTimeout); - _enumeratorSignallingTimer.start(); - - setupFileProviderDomains(); - - connect(AccountManager::instance(), &AccountManager::accountAdded, - this, &FileProviderDomainManager::addFileProviderDomainForAccount); - // If an account is deleted from the client, accountSyncConnectionRemoved will be - // emitted first. So we treat accountRemoved as only being relevant to client - // shutdowns. - connect(AccountManager::instance(), &AccountManager::accountSyncConnectionRemoved, - this, &FileProviderDomainManager::removeFileProviderDomainForAccount); - connect(AccountManager::instance(), &AccountManager::accountRemoved, - this, [this](const AccountState * const accountState) { - - const auto trReason = tr("%1 application has been closed. Reopen to reconnect.").arg(APPLICATION_NAME); - disconnectFileProviderDomainForAccount(accountState, trReason); - }); - } else { - qCWarning(lcMacFileProviderDomainManager()) << "Trying to run File Provider on system that does not support it."; - } -} - -FileProviderDomainManager::~FileProviderDomainManager() = default; - -void FileProviderDomainManager::setupFileProviderDomains() -{ - if (!d) { - return; - } - - d->findExistingFileProviderDomains(); - - for(auto &accountState : AccountManager::instance()->accounts()) { - addFileProviderDomainForAccount(accountState.data()); - } -} - -void FileProviderDomainManager::addFileProviderDomainForAccount(const AccountState * const accountState) -{ - if (!d) { - return; - } - - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - d->addFileProviderDomain(accountState); - - // Disconnect the domain when something changes regarding authentication - connect(accountState, &AccountState::stateChanged, this, [this, accountState] { - slotAccountStateChanged(accountState); - }); - - // Setup push notifications - const auto accountCapabilities = account->capabilities().isValid(); - if (!accountCapabilities) { - connect(account.get(), &Account::capabilitiesChanged, this, [this, account] { - trySetupPushNotificationsForAccount(account.get()); - }); - return; - } - - trySetupPushNotificationsForAccount(account.get()); -} - -void FileProviderDomainManager::trySetupPushNotificationsForAccount(const Account * const account) -{ - if (!d) { - return; - } - - Q_ASSERT(account); - - const auto pushNotifications = account->pushNotifications(); - const auto pushNotificationsCapability = account->capabilities().availablePushNotifications() & PushNotificationType::Files; - - if (pushNotificationsCapability && pushNotifications && pushNotifications->isReady()) { - qCDebug(lcMacFileProviderDomainManager) << "Push notifications already ready, connecting them to enumerator signalling." - << account->displayName(); - setupPushNotificationsForAccount(account); - } else if (pushNotificationsCapability) { - qCDebug(lcMacFileProviderDomainManager) << "Push notifications not yet ready, will connect to signalling when ready." - << account->displayName(); - connect(account, &Account::pushNotificationsReady, this, &FileProviderDomainManager::setupPushNotificationsForAccount); - } -} - -void FileProviderDomainManager::setupPushNotificationsForAccount(const Account * const account) -{ - if (!d) { - return; - } - - Q_ASSERT(account); - - qCDebug(lcMacFileProviderDomainManager) << "Setting up push notifications for file provider domain for account:" - << account->displayName(); - - connect(account->pushNotifications(), &PushNotifications::filesChanged, this, &FileProviderDomainManager::signalEnumeratorChanged); - disconnect(account, &Account::pushNotificationsReady, this, &FileProviderDomainManager::setupPushNotificationsForAccount); -} - -void FileProviderDomainManager::signalEnumeratorChanged(const Account * const account) -{ - if (!d) { - return; - } - - Q_ASSERT(account); - d->signalEnumeratorChanged(account); -} - -void FileProviderDomainManager::removeFileProviderDomainForAccount(const AccountState * const accountState) -{ - if (!d) { - return; - } - - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - d->removeFileProviderDomain(accountState); - - if (accountFilesPushNotificationsReady(account)) { - const auto pushNotifications = account->pushNotifications(); - disconnect(pushNotifications, &PushNotifications::filesChanged, this, &FileProviderDomainManager::signalEnumeratorChanged); - } else if (const auto hasFilesPushNotificationsCapability = account->capabilities().availablePushNotifications() & PushNotificationType::Files) { - disconnect(account.get(), &Account::pushNotificationsReady, this, &FileProviderDomainManager::setupPushNotificationsForAccount); - } -} - -void FileProviderDomainManager::disconnectFileProviderDomainForAccount(const AccountState * const accountState, const QString &reason) -{ - if (!d) { - return; - } - - Q_ASSERT(accountState); - const auto account = accountState->account(); - Q_ASSERT(account); - - d->disconnectFileProviderDomainForAccount(accountState, reason); -} - -void FileProviderDomainManager::reconnectFileProviderDomainForAccount(const AccountState * const accountState) -{ - if (!d) { - return; - } - - Q_ASSERT(accountState); - const auto account = accountState->account(); - - d->reconnectFileProviderDomainForAccount(accountState); -} - -void FileProviderDomainManager::slotAccountStateChanged(const AccountState * const accountState) -{ - if (!d) { - return; - } - - Q_ASSERT(accountState); - const auto state = accountState->state(); - - qCDebug(lcMacFileProviderDomainManager) << "Account state changed for account:" - << accountState->account()->displayName() - << "changing connection status of file provider domain."; - - switch(state) { - case AccountState::Disconnected: - case AccountState::ConfigurationError: - case AccountState::NetworkError: - case AccountState::ServiceUnavailable: - case AccountState::MaintenanceMode: - // Do nothing, File Provider will by itself figure out connection issue - break; - case AccountState::SignedOut: - case AccountState::AskingCredentials: - { - // Disconnect File Provider domain while unauthenticated - const auto trReason = tr("This account is not authenticated. Please check your account state in the %1 application.").arg(APPLICATION_NAME); - disconnectFileProviderDomainForAccount(accountState, trReason); - break; - } - case AccountState::Connected: - // Provide credentials - reconnectFileProviderDomainForAccount(accountState); - break; - } -} - -void FileProviderDomainManager::slotEnumeratorSignallingTimerTimeout() -{ - if (!d) { - return; - } - - qCDebug(lcMacFileProviderDomainManager) << "Enumerator signalling timer timed out, notifying domains for accounts without push notifications"; - - const auto registeredDomainIds = d->configuredDomainIds(); - for (const auto &domainId : registeredDomainIds) { - const auto accountUserId = accountIdFromDomainId(domainId); - const auto accountState = AccountManager::instance()->accountFromUserId(accountUserId); - const auto account = accountState->account(); - - if (!accountFilesPushNotificationsReady(account)) { - qCDebug(lcMacFileProviderDomainManager) << "Notifying domain for account:" << account->userIdAtHostWithPort(); - d->signalEnumeratorChanged(account.get()); - } - } -} - -AccountStatePtr FileProviderDomainManager::accountStateFromFileProviderDomainIdentifier(const QString &domainIdentifier) -{ - if (domainIdentifier.isEmpty()) { - qCWarning(lcMacFileProviderDomainManager) << "Cannot return accountstateptr for empty domain identifier"; - return AccountStatePtr(); - } - - const auto accountUserId = accountIdFromDomainId(domainIdentifier); - const auto accountForReceivedDomainIdentifier = AccountManager::instance()->accountFromUserId(accountUserId); - if (!accountForReceivedDomainIdentifier) { - qCWarning(lcMacFileProviderDomainManager) << "Could not find account matching user id matching file provider domain identifier:" - << domainIdentifier; - } - - return accountForReceivedDomainIdentifier; -} - -} // namespace Mac - -} // namespace OCC diff --git a/src/gui/macOS/fileprovidersocketcontroller.cpp b/src/gui/macOS/fileprovidersocketcontroller.cpp deleted file mode 100644 index 9fa7f2b68c0f8..0000000000000 --- a/src/gui/macOS/fileprovidersocketcontroller.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "fileprovidersocketcontroller.h" - -#include -#include - -#include "accountmanager.h" -#include "fileproviderdomainmanager.h" - -namespace OCC { - -namespace Mac { - -Q_LOGGING_CATEGORY(lcFileProviderSocketController, "nextcloud.gui.macos.fileprovider.socketcontroller", QtInfoMsg) - -FileProviderSocketController::FileProviderSocketController(QLocalSocket * const socket, QObject * const parent) - : QObject{parent} - , _socket(socket) -{ - connect(socket, &QLocalSocket::readyRead, - this, &FileProviderSocketController::slotReadyRead); - connect(socket, &QLocalSocket::disconnected, - this, &FileProviderSocketController::slotOnDisconnected); - connect(socket, &QLocalSocket::destroyed, - this, &FileProviderSocketController::slotSocketDestroyed); -} - -void FileProviderSocketController::slotOnDisconnected() -{ - qCInfo(lcFileProviderSocketController) << "File provider socket disconnected"; - _socket->deleteLater(); -} - -void FileProviderSocketController::slotSocketDestroyed(const QObject * const object) -{ - Q_UNUSED(object) - qCInfo(lcFileProviderSocketController) << "File provider socket object has been destroyed, destroying controller"; - Q_EMIT socketDestroyed(_socket); -} - -void FileProviderSocketController::slotReadyRead() -{ - Q_ASSERT(_socket); - if (!_socket) { - qCWarning(lcFileProviderSocketController) << "Cannot read data on dead socket"; - return; - } - - while(_socket->canReadLine()) { - const auto line = QString::fromUtf8(_socket->readLine().trimmed()).normalized(QString::NormalizationForm_C); - qCDebug(lcFileProviderSocketController) << "Received message in file provider socket:" << line; - - parseReceivedLine(line); - } -} - -void FileProviderSocketController::parseReceivedLine(const QString &receivedLine) -{ - if (receivedLine.isEmpty()) { - qCWarning(lcFileProviderSocketController) << "Received empty line, can't parse."; - return; - } - - const auto argPos = receivedLine.indexOf(QLatin1Char(':')); - if (argPos == -1) { - qCWarning(lcFileProviderSocketController) << "Received line:" - << receivedLine - << "is incorrectly structured. Can't parse."; - return; - } - - const auto command = receivedLine.mid(0, argPos); - const auto argument = receivedLine.mid(argPos + 1); - - if (command == QStringLiteral("FILE_PROVIDER_DOMAIN_IDENTIFIER_REQUEST_REPLY")) { - _accountState = FileProviderDomainManager::accountStateFromFileProviderDomainIdentifier(argument); - sendAccountDetails(); - return; - } - - qCWarning(lcFileProviderSocketController) << "Unknown command or reply:" << receivedLine; -} - -void FileProviderSocketController::sendMessage(const QString &message) const -{ - if (!_socket) { - qCWarning(lcFileProviderSocketController) << "Not sending message on dead file provider socket:" << message; - return; - } - - qCDebug(lcFileProviderSocketController) << "Sending File Provider socket message:" << message; - const auto lineEndChar = '\n'; - const auto messageToSend = message.endsWith(lineEndChar) ? message : message + lineEndChar; - const auto bytesToSend = messageToSend.toUtf8(); - const auto sent = _socket->write(bytesToSend); - - if (sent != bytesToSend.length()) { - qCWarning(lcFileProviderSocketController) << "Could not send all data on file provider socket for:" << message; - } -} - - -void FileProviderSocketController::start() -{ - Q_ASSERT(_socket); - if (!_socket) { - qCWarning(lcFileProviderSocketController) << "Cannot start communication on dead socket"; - return; - } - - requestFileProviderDomainInfo(); -} - -void FileProviderSocketController::requestFileProviderDomainInfo() const -{ - Q_ASSERT(_socket); - if (!_socket) { - qCWarning(lcFileProviderSocketController) << "Cannot request file provider domain data on dead socket"; - return; - } - - const auto requestMessage = QStringLiteral("SEND_FILE_PROVIDER_DOMAIN_IDENTIFIER"); - sendMessage(requestMessage); -} - -void FileProviderSocketController::slotAccountStateChanged(const AccountState::State state) -{ - switch(state) { - case AccountState::Disconnected: - case AccountState::ConfigurationError: - case AccountState::NetworkError: - case AccountState::ServiceUnavailable: - case AccountState::MaintenanceMode: - // Do nothing, File Provider will by itself figure out connection issue - break; - case AccountState::SignedOut: - case AccountState::AskingCredentials: - // Notify File Provider that it should show the not authenticated message - sendNotAuthenticated(); - break; - case AccountState::Connected: - // Provide credentials - sendAccountDetails(); - break; - } -} - -void FileProviderSocketController::sendNotAuthenticated() const -{ - Q_ASSERT(_accountState); - const auto account = _accountState->account(); - Q_ASSERT(account); - - qCDebug(lcFileProviderSocketController) << "About to send not authenticated message to file provider extension" - << account->displayName(); - - const auto message = QString(QStringLiteral("ACCOUNT_NOT_AUTHENTICATED")); - sendMessage(message); -} - -void FileProviderSocketController::sendAccountDetails() const -{ - Q_ASSERT(_accountState); - const auto account = _accountState->account(); - Q_ASSERT(account); - - qCDebug(lcFileProviderSocketController) << "About to send account details to file provider extension" - << account->displayName(); - - connect(_accountState.data(), &AccountState::stateChanged, this, &FileProviderSocketController::slotAccountStateChanged, Qt::UniqueConnection); - - if (!_accountState->isConnected()) { - qCDebug(lcFileProviderSocketController) << "Not sending account details yet as account is not connected" - << account->displayName(); - return; - } - - const auto credentials = account->credentials(); - Q_ASSERT(credentials); - const auto accountUser = credentials->user(); - const auto accountUrl = account->url().toString(); - const auto accountPassword = credentials->password(); - - // We cannot use colons as separators here due to "https://" in the url - const auto message = QString(QStringLiteral("ACCOUNT_DETAILS:") + - accountUser + "~" + - accountUrl + "~" + - accountPassword); - sendMessage(message); -} - -} - -} diff --git a/src/gui/macOS/fileprovidersocketcontroller.h b/src/gui/macOS/fileprovidersocketcontroller.h deleted file mode 100644 index ca7c353343237..0000000000000 --- a/src/gui/macOS/fileprovidersocketcontroller.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#pragma once - -#include - -#include "accountstate.h" - -class QLocalSocket; - -namespace OCC { - -namespace Mac { - -class FileProviderSocketController : public QObject -{ - Q_OBJECT - -public: - explicit FileProviderSocketController(QLocalSocket * const socket, QObject * const parent = nullptr); - -signals: - void socketDestroyed(const QLocalSocket * const socket); - -public slots: - void sendMessage(const QString &message) const; - void start(); - -private slots: - void slotOnDisconnected(); - void slotSocketDestroyed(const QObject * const object); - void slotReadyRead(); - - void slotAccountStateChanged(const OCC::AccountState::State state); - - void parseReceivedLine(const QString &receivedLine); - void requestFileProviderDomainInfo() const; - void sendAccountDetails() const; - void sendNotAuthenticated() const; - -private: - QPointer _socket; - AccountStatePtr _accountState; -}; - -} // namespace Mac - -} // namespace OCC diff --git a/src/gui/macOS/fileprovidersocketserver.cpp b/src/gui/macOS/fileprovidersocketserver.cpp deleted file mode 100644 index 70b01615705fd..0000000000000 --- a/src/gui/macOS/fileprovidersocketserver.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "fileprovidersocketserver.h" - -#include -#include - -#include "fileprovidersocketcontroller.h" - -namespace OCC { - -namespace Mac { - -Q_LOGGING_CATEGORY(lcFileProviderSocketServer, "nextcloud.gui.macos.fileprovider.socketserver", QtInfoMsg) - -FileProviderSocketServer::FileProviderSocketServer(QObject *parent) - : QObject{parent} -{ - _socketPath = fileProviderSocketPath(); - startListening(); -} - -void FileProviderSocketServer::startListening() -{ - QLocalServer::removeServer(_socketPath); - - const auto serverStarted = _socketServer.listen(_socketPath); - if (!serverStarted) { - qCWarning(lcFileProviderSocketServer) << "Could not start file provider socket server" - << _socketPath; - } else { - qCInfo(lcFileProviderSocketServer) << "File provider socket server started, listening" - << _socketPath; - } - - connect(&_socketServer, &QLocalServer::newConnection, - this, &FileProviderSocketServer::slotNewConnection); -} - -void FileProviderSocketServer::slotNewConnection() -{ - if (!_socketServer.hasPendingConnections()) { - return; - } - - qCInfo(lcFileProviderSocketServer) << "New connection in file provider socket server"; - const auto socket = _socketServer.nextPendingConnection(); - if (!socket) { - return; - } - - const FileProviderSocketControllerPtr socketController(new FileProviderSocketController(socket, this)); - connect(socketController.data(), &FileProviderSocketController::socketDestroyed, - this, &FileProviderSocketServer::slotSocketDestroyed); - _socketControllers.insert(socket, socketController); - - socketController->start(); -} - -void FileProviderSocketServer::slotSocketDestroyed(const QLocalSocket * const socket) -{ - const auto socketController = _socketControllers.take(socket); - - if (socketController) { - const auto rawSocketControllerPtr = socketController.data(); - delete rawSocketControllerPtr; - } -} - -} // namespace Mac - -} // namespace OCC diff --git a/src/gui/macOS/fileprovidersocketserver.h b/src/gui/macOS/fileprovidersocketserver.h deleted file mode 100644 index 893de666e5a46..0000000000000 --- a/src/gui/macOS/fileprovidersocketserver.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#pragma once - -#include -#include - -namespace OCC { - -namespace Mac { - -class FileProviderSocketController; -using FileProviderSocketControllerPtr = QPointer; - -QString fileProviderSocketPath(); - -class FileProviderSocketServer : public QObject -{ - Q_OBJECT - -public: - explicit FileProviderSocketServer(QObject *parent = nullptr); - -private slots: - void startListening(); - void slotNewConnection(); - void slotSocketDestroyed(const QLocalSocket * const socket); - -private: - QString _socketPath; - QLocalServer _socketServer; - QHash _socketControllers; -}; - -} // namespace Mac - -} // namespace OCC diff --git a/src/gui/macOS/fileprovidersocketserver_mac.mm b/src/gui/macOS/fileprovidersocketserver_mac.mm deleted file mode 100644 index 8377adb9607c9..0000000000000 --- a/src/gui/macOS/fileprovidersocketserver_mac.mm +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2022 by Claudio Cambra - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#import -#import - -#include "config.h" - -namespace OCC -{ - -namespace Mac -{ - -QString fileProviderSocketPath() -{ - // This must match the code signing Team setting of the extension - // Example for developer builds (with ad-hoc signing identity): "" "com.owncloud.desktopclient" ".fileprovidersocket" - // Example for official signed packages: "9B5WD74GWJ." "com.owncloud.desktopclient" ".fileprovidersocket" - NSString *appGroupId = @SOCKETAPI_TEAM_IDENTIFIER_PREFIX APPLICATION_REV_DOMAIN; - - NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupId]; - NSURL *socketPath = [container URLByAppendingPathComponent:@".fileprovidersocket" isDirectory:false]; - return QString::fromNSString(socketPath.path); -} - -} // namespace Mac - -} // namespace OCC diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index c6447ffe52c1c..c47f00f1ad52f 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -106,8 +106,6 @@ static constexpr char certPath[] = "http_certificatePath"; static constexpr char certPasswd[] = "http_certificatePasswd"; static const QSet validUpdateChannels { QStringLiteral("stable"), QStringLiteral("beta") }; - -static constexpr auto macFileProviderModuleEnabledC = "macFileProviderModuleEnabled"; } namespace OCC { @@ -1173,16 +1171,4 @@ void ConfigFile::setDiscoveredLegacyConfigPath(const QString &discoveredLegacyCo _discoveredLegacyConfigPath = discoveredLegacyConfigPath; } -bool ConfigFile::macFileProviderModuleEnabled() const -{ - QSettings settings(configFile(), QSettings::IniFormat); - return settings.value(macFileProviderModuleEnabledC, false).toBool(); -} - -void ConfigFile::setMacFileProviderModuleEnabled(const bool moduleEnabled) -{ - QSettings settings(configFile(), QSettings::IniFormat); - settings.setValue(QLatin1String(macFileProviderModuleEnabledC), moduleEnabled); -} - } diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index 5d0ee5460fcef..3fc7f5e4fa359 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -223,9 +223,6 @@ class OWNCLOUDSYNC_EXPORT ConfigFile [[nodiscard]] static QString discoveredLegacyConfigPath(); static void setDiscoveredLegacyConfigPath(const QString &discoveredLegacyConfigPath); - [[nodiscard]] bool macFileProviderModuleEnabled() const; - void setMacFileProviderModuleEnabled(const bool moduleEnabled); - protected: [[nodiscard]] QVariant getPolicySetting(const QString &policy, const QVariant &defaultValue = QVariant()) const; void storeData(const QString &group, const QString &key, const QVariant &value); @@ -240,6 +237,7 @@ class OWNCLOUDSYNC_EXPORT ConfigFile [[nodiscard]] QString keychainProxyPasswordKey() const; +private: using SharedCreds = QSharedPointer; static QString _confDir;