diff --git a/ownCloud File Provider UI/DocumentActionViewController.swift b/ownCloud File Provider UI/DocumentActionViewController.swift index a7d0d6cb5..eda1f6daf 100644 --- a/ownCloud File Provider UI/DocumentActionViewController.swift +++ b/ownCloud File Provider UI/DocumentActionViewController.swift @@ -61,6 +61,16 @@ class DocumentActionViewController: FPUIActionExtensionViewController { } } + func prepareNavigationController() { + if themeNavigationController == nil { + themeNavigationController = ThemeNavigationController() + if let themeNavigationController = themeNavigationController { + view.addSubview(themeNavigationController.view) + addChild(themeNavigationController) + } + } + } + override func prepare(forAction actionIdentifier: String, itemIdentifiers: [NSFileProviderItemIdentifier]) { guard let identifier = itemIdentifiers.first else { @@ -71,11 +81,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController { let collection = Theme.shared.activeCollection self.view.backgroundColor = collection.toolbarColors.backgroundColor - themeNavigationController = ThemeNavigationController() - if let themeNavigationController = themeNavigationController { - view.addSubview(themeNavigationController.view) - addChild(themeNavigationController) - } + prepareNavigationController() showCancelLabel(with: "Connecting…".localized) @@ -151,6 +157,12 @@ class DocumentActionViewController: FPUIActionExtensionViewController { } override func prepare(forError error: Error) { + if !OCFileProviderSettings.browseable { + prepareNavigationController() + showCancelLabel(with: "File Provider access has been disabled by the administrator.\n\nPlease use the app to access your files.".localized) + return + } + if AppLockManager.supportedOnDevice { AppLockManager.shared.passwordViewHostViewController = self AppLockManager.shared.biometricCancelLabel = "Cancel".localized @@ -163,6 +175,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController { AppLockManager.shared.showLockscreenIfNeeded() } else { + prepareNavigationController() showCancelLabel(with: "Passcode protection is not supported on this device.\nPlease disable passcode lock in the app settings.".localized) } } diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index 269bf2b8a..32b636300 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -475,6 +475,12 @@ - (void)createDirectoryWithName:(NSString *)directoryName inParentItemIdentifier NSError *error = nil; OCItem *parentItem; + if (!OCFileProviderSettings.browseable) + { + completionHandler(nil, [OCErrorWithDescription(OCErrorInternal, OCLocalized(@"File Provider access has been disabled by the administrator. Please use the app to create new folders.")) translatedError]); + return; + } + FPLogCmdBegin(@"CreateDir", @"Start of createDirectoryWithName=%@, inParentItemIdentifier=%@", directoryName, parentItemIdentifier); if ((parentItem = (OCItem *)[self itemForIdentifier:parentItemIdentifier error:&error]) != nil) @@ -647,6 +653,12 @@ - (void)importDocumentAtURL:(NSURL *)fileURL toParentItemIdentifier:(NSFileProvi NSError *error = nil; BOOL stopAccess = NO; + if (!OCFileProviderSettings.browseable) + { + completionHandler(nil, [OCErrorWithDescription(OCErrorInternal, OCLocalized(@"File Provider access has been disabled by the administrator. Please use the share extension to import files.")) translatedError]); + return; + } + if (![Branding.sharedBranding isImportMethodAllowed:BrandingFileImportMethodFileProvider]) { completionHandler(nil, [OCErrorWithDescription(OCErrorInternal, OCLocalized(@"Importing files through the File Provider is not allowed on this device.")) translatedError]); @@ -871,6 +883,16 @@ - (void)setLastUsedDate:(NSDate *)lastUsedDate forItemIdentifier:(NSFileProvider #pragma mark - Enumeration - (nullable id)enumeratorForContainerItemIdentifier:(NSFileProviderItemIdentifier)containerItemIdentifier error:(NSError **)error { + if (!OCFileProviderSettings.browseable) + { + if (error != NULL) + { + *error = [NSError errorWithDomain:NSFileProviderErrorDomain code:NSFileProviderErrorNotAuthenticated userInfo:nil]; + } + + return (nil); + } + if (AppLockSettings.sharedAppLockSettings.lockEnabled) { NSData *lockedDateData = [[[OCAppIdentity sharedAppIdentity] keychain] readDataFromKeychainItemForAccount:@"app.passcode" path:@"lockedDate"]; diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj index 75f0fe523..343b345a5 100644 --- a/ownCloud.xcodeproj/project.pbxproj +++ b/ownCloud.xcodeproj/project.pbxproj @@ -323,6 +323,8 @@ DC4FEAE7209E3A7700D4476B /* OCIssue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4FEAE6209E3A7700D4476B /* OCIssue+Extension.swift */; }; DC51FD922475715F0069AB79 /* CellularSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC51FD912475715F0069AB79 /* CellularSettingsViewController.swift */; }; DC576EC022647A070087316D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC576EC222647A070087316D /* Localizable.strings */; }; + DC6179E728E0578400C7C4E0 /* OCFileProviderSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = DC6179E528E0578400C7C4E0 /* OCFileProviderSettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DC6179E828E0578400C7C4E0 /* OCFileProviderSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6179E628E0578400C7C4E0 /* OCFileProviderSettings.m */; }; DC625141225C904700736874 /* NSError+MessageResolution.m in Sources */ = {isa = PBXBuildFile; fileRef = DC625140225C904700736874 /* NSError+MessageResolution.m */; }; DC625148225CEB2C00736874 /* UploadFileAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC625147225CEB2C00736874 /* UploadFileAction.swift */; }; DC62514A225CEB4300736874 /* UploadMediaAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC625149225CEB4300736874 /* UploadMediaAction.swift */; }; @@ -1264,6 +1266,8 @@ DC51FD912475715F0069AB79 /* CellularSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellularSettingsViewController.swift; sourceTree = ""; }; DC576EC122647A070087316D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; DC5D9E742496512400BFFE8E /* MessageQueueExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageQueueExample.swift; sourceTree = ""; }; + DC6179E528E0578400C7C4E0 /* OCFileProviderSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCFileProviderSettings.h; sourceTree = ""; }; + DC6179E628E0578400C7C4E0 /* OCFileProviderSettings.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OCFileProviderSettings.m; sourceTree = ""; }; DC62513F225C904700736874 /* NSError+MessageResolution.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+MessageResolution.h"; sourceTree = ""; }; DC625140225C904700736874 /* NSError+MessageResolution.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+MessageResolution.m"; sourceTree = ""; }; DC625147225CEB2C00736874 /* UploadFileAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadFileAction.swift; sourceTree = ""; }; @@ -2987,6 +2991,8 @@ DCF2DA7524C82C9F0026D790 /* OCFileProviderService.h */, DC049155258C00C400DEDC27 /* OCFileProviderServiceStandby.m */, DC049154258C00C400DEDC27 /* OCFileProviderServiceStandby.h */, + DC6179E628E0578400C7C4E0 /* OCFileProviderSettings.m */, + DC6179E528E0578400C7C4E0 /* OCFileProviderSettings.h */, ); path = "File Provider Services"; sourceTree = ""; @@ -3189,6 +3195,7 @@ DCC832F1242CC27B00153F8C /* NotificationMessagePresenter.h in Headers */, DC080CF2238C8DF70044C5D2 /* OCLicenseAppStoreItem.h in Headers */, DCD9B87B2379612B00691929 /* OCLicenseManager+Internal.h in Headers */, + DC6179E728E0578400C7C4E0 /* OCFileProviderSettings.h in Headers */, DC774E6322F44E6D000B11A1 /* OCCore+BundleImport.h in Headers */, DCDBB60A2525305600FAD707 /* NotificationAuthErrorForwarder.h in Headers */, DC080CE6238AE3F40044C5D2 /* OCLicenseAppStoreProvider.h in Headers */, @@ -4294,6 +4301,7 @@ DC24B29825BA2A34005783E2 /* Branding.m in Sources */, DCFEFE3E236877B7009A142F /* OCLicenseProduct.m in Sources */, DC774E6422F44E6D000B11A1 /* OCCore+BundleImport.m in Sources */, + DC6179E828E0578400C7C4E0 /* OCFileProviderSettings.m in Sources */, DCF2DA7E24C835BF0026D790 /* OCVault+FPServices.m in Sources */, DCDC208D239912DC003CFF5B /* OCLicenseTransaction.m in Sources */, DC23D1D9238F390A00423F62 /* OCLicenseAppStoreReceipt.m in Sources */, diff --git a/ownCloud/Resources/en.lproj/Localizable.strings b/ownCloud/Resources/en.lproj/Localizable.strings index a9d5daaf5..ba44fbc42 100644 --- a/ownCloud/Resources/en.lproj/Localizable.strings +++ b/ownCloud/Resources/en.lproj/Localizable.strings @@ -775,6 +775,12 @@ "Preparing…" = "Preparing…"; "Save here" = "Save here"; +/* FileProvider */ +/* - Disabled */ +"File Provider access has been disabled by the administrator.\n\nPlease use the app to access your files." = "File Provider access has been disabled by the administrator.\n\nPlease use the app to access your files."; +"File Provider access has been disabled by the administrator. Please use the app to create new folders." = "File Provider access has been disabled by the administrator. Please use the app to create new folders."; +"File Provider access has been disabled by the administrator. Please use the share extension to import files." = "File Provider access has been disabled by the administrator. Please use the share extension to import files."; + /* Disallowed Import Methods */ /* - Share Extension */ "Share Extension disabled" = "Share Extension disabled"; diff --git a/ownCloudAppFramework/File Provider Services/OCFileProviderSettings.h b/ownCloudAppFramework/File Provider Services/OCFileProviderSettings.h new file mode 100644 index 000000000..6e218867a --- /dev/null +++ b/ownCloudAppFramework/File Provider Services/OCFileProviderSettings.h @@ -0,0 +1,33 @@ +// +// OCFileProviderSettings.h +// ownCloudApp +// +// Created by Felix Schwarz on 25.09.22. +// Copyright © 2022 ownCloud GmbH. All rights reserved. +// + +/* + * Copyright (C) 2022, ownCloud GmbH. + * + * This code is covered by the GNU Public License Version 3. + * + * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + * You should have received a copy of this license along with this program. If not, see . + * + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OCFileProviderSettings : NSObject + +@property(class,readonly,nonatomic) BOOL browseable; + +@end + +extern OCClassSettingsIdentifier OCClassSettingsIdentifierFileProvider; +extern OCClassSettingsKey OCClassSettingsKeyFileProviderBrowseable; + +NS_ASSUME_NONNULL_END diff --git a/ownCloudAppFramework/File Provider Services/OCFileProviderSettings.m b/ownCloudAppFramework/File Provider Services/OCFileProviderSettings.m new file mode 100644 index 000000000..88869cd39 --- /dev/null +++ b/ownCloudAppFramework/File Provider Services/OCFileProviderSettings.m @@ -0,0 +1,55 @@ +// +// OCFileProviderSettings.m +// ownCloudApp +// +// Created by Felix Schwarz on 25.09.22. +// Copyright © 2022 ownCloud GmbH. All rights reserved. +// + +/* + * Copyright (C) 2022, ownCloud GmbH. + * + * This code is covered by the GNU Public License Version 3. + * + * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + * You should have received a copy of this license along with this program. If not, see . + * + */ + +#import "OCFileProviderSettings.h" + +@implementation OCFileProviderSettings + ++ (OCClassSettingsIdentifier)classSettingsIdentifier +{ + return (OCClassSettingsIdentifierFileProvider); +} + ++ (nullable NSDictionary *)defaultSettingsForIdentifier:(nonnull OCClassSettingsIdentifier)identifier { + return (@{ + OCClassSettingsKeyFileProviderBrowseable : @(YES) + }); +} + ++ (OCClassSettingsMetadataCollection)classSettingsMetadata +{ + return (@{ + // FileProvider + OCClassSettingsKeyFileProviderBrowseable : @{ + OCClassSettingsMetadataKeyType : OCClassSettingsMetadataTypeBoolean, + OCClassSettingsMetadataKeyDescription : @"Controls whether the account content is available to other apps via File Provider / Files.app.", + OCClassSettingsMetadataKeyStatus : OCClassSettingsKeyStatusSupported, + OCClassSettingsMetadataKeyCategory : @"FileProvider", + } + }); +} + ++ (BOOL)browseable +{ + return ([([self classSettingForOCClassSettingsKey:OCClassSettingsKeyFileProviderBrowseable]) boolValue]); +} + +@end + +OCClassSettingsIdentifier OCClassSettingsIdentifierFileProvider = @"fileprovider"; +OCClassSettingsKey OCClassSettingsKeyFileProviderBrowseable = @"browseable"; diff --git a/ownCloudAppFramework/ownCloudApp.h b/ownCloudAppFramework/ownCloudApp.h index 2f90e6990..bd7bec6a8 100644 --- a/ownCloudAppFramework/ownCloudApp.h +++ b/ownCloudAppFramework/ownCloudApp.h @@ -44,6 +44,7 @@ FOUNDATION_EXPORT const unsigned char ownCloudAppVersionString[]; #import #import #import +#import #import #import