aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@users.noreply.github.com>2024-05-30 14:17:52 +0200
committerGitHub <noreply@github.com>2024-05-30 14:17:52 +0200
commit7f2a1e5b7a1724727bc274e73a9a6fd09249c7a6 (patch)
treefbc014b411855706acf31e082373e45b96640287 /lib/private
parent7292a8d8fe7e4cf8667194f4af587f6923a0f884 (diff)
parent31b0a44cf65b6625636ea0fa15fb1a1122b525e1 (diff)
downloadnextcloud-server-7f2a1e5b7a1724727bc274e73a9a6fd09249c7a6.tar.gz
nextcloud-server-7f2a1e5b7a1724727bc274e73a9a6fd09249c7a6.zip
Merge branch 'master' into refactor/OC-Server-getMailer
Signed-off-by: John Molakvoæ <skjnldsv@users.noreply.github.com>
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/Accounts/Account.php25
-rw-r--r--lib/private/Accounts/AccountManager.php59
-rw-r--r--lib/private/Accounts/AccountProperty.php26
-rw-r--r--lib/private/Accounts/AccountPropertyCollection.php23
-rw-r--r--lib/private/Accounts/Hooks.php23
-rw-r--r--lib/private/Accounts/TAccountsHelper.php23
-rw-r--r--lib/private/Activity/ActivitySettingsAdapter.php21
-rw-r--r--lib/private/Activity/Event.php159
-rw-r--r--lib/private/Activity/EventMerger.php25
-rw-r--r--lib/private/Activity/Manager.php74
-rw-r--r--lib/private/AllConfig.php58
-rw-r--r--lib/private/App/AppManager.php176
-rw-r--r--lib/private/App/AppStore/Bundles/Bundle.php30
-rw-r--r--lib/private/App/AppStore/Bundles/BundleFetcher.php31
-rw-r--r--lib/private/App/AppStore/Bundles/EducationBundle.php22
-rw-r--r--lib/private/App/AppStore/Bundles/EnterpriseBundle.php22
-rw-r--r--lib/private/App/AppStore/Bundles/GroupwareBundle.php23
-rw-r--r--lib/private/App/AppStore/Bundles/HubBundle.php22
-rw-r--r--lib/private/App/AppStore/Bundles/PublicSectorBundle.php34
-rw-r--r--lib/private/App/AppStore/Bundles/SocialSharingBundle.php22
-rw-r--r--lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php99
-rw-r--r--lib/private/App/AppStore/Fetcher/AppFetcher.php50
-rw-r--r--lib/private/App/AppStore/Fetcher/CategoryFetcher.php39
-rw-r--r--lib/private/App/AppStore/Fetcher/Fetcher.php77
-rw-r--r--lib/private/App/AppStore/Version/Version.php33
-rw-r--r--lib/private/App/AppStore/Version/VersionParser.php27
-rw-r--r--lib/private/App/CompareVersion.php21
-rw-r--r--lib/private/App/DependencyAnalyzer.php41
-rw-r--r--lib/private/App/InfoParser.php48
-rw-r--r--lib/private/App/Platform.php34
-rw-r--r--lib/private/App/PlatformRepository.php28
-rw-r--r--lib/private/AppConfig.php1711
-rw-r--r--lib/private/AppFramework/App.php39
-rw-r--r--lib/private/AppFramework/Bootstrap/ARegistration.php21
-rw-r--r--lib/private/AppFramework/Bootstrap/BootContext.php22
-rw-r--r--lib/private/AppFramework/Bootstrap/Coordinator.php81
-rw-r--r--lib/private/AppFramework/Bootstrap/EventListenerRegistration.php27
-rw-r--r--lib/private/AppFramework/Bootstrap/FunctionInjector.php21
-rw-r--r--lib/private/AppFramework/Bootstrap/MiddlewareRegistration.php22
-rw-r--r--lib/private/AppFramework/Bootstrap/ParameterRegistration.php25
-rw-r--r--lib/private/AppFramework/Bootstrap/PreviewProviderRegistration.php26
-rw-r--r--lib/private/AppFramework/Bootstrap/RegistrationContext.php202
-rw-r--r--lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php25
-rw-r--r--lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php27
-rw-r--r--lib/private/AppFramework/Bootstrap/ServiceRegistration.php21
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php68
-rw-r--r--lib/private/AppFramework/Http.php30
-rw-r--r--lib/private/AppFramework/Http/Dispatcher.php68
-rw-r--r--lib/private/AppFramework/Http/Output.php27
-rw-r--r--lib/private/AppFramework/Http/Request.php116
-rw-r--r--lib/private/AppFramework/Http/RequestId.php22
-rw-r--r--lib/private/AppFramework/Logger.php22
-rw-r--r--lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php23
-rw-r--r--lib/private/AppFramework/Middleware/CompressionMiddleware.php22
-rw-r--r--lib/private/AppFramework/Middleware/MiddlewareDispatcher.php41
-rw-r--r--lib/private/AppFramework/Middleware/NotModifiedMiddleware.php21
-rw-r--r--lib/private/AppFramework/Middleware/OCSMiddleware.php24
-rw-r--r--lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php22
-rw-r--r--lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php22
-rw-r--r--lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php24
-rw-r--r--lib/private/AppFramework/Middleware/Security/CORSMiddleware.php38
-rw-r--r--lib/private/AppFramework/Middleware/Security/CSPMiddleware.php26
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php24
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php25
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php21
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php26
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php21
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php25
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/ReloadExecutionException.php21
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php26
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php21
-rw-r--r--lib/private/AppFramework/Middleware/Security/FeaturePolicyMiddleware.php21
-rw-r--r--lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php28
-rw-r--r--lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php31
-rw-r--r--lib/private/AppFramework/Middleware/Security/ReloadExecutionMiddleware.php21
-rw-r--r--lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php24
-rw-r--r--lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php65
-rw-r--r--lib/private/AppFramework/Middleware/SessionMiddleware.php28
-rw-r--r--lib/private/AppFramework/OCS/BaseResponse.php38
-rw-r--r--lib/private/AppFramework/OCS/V1Response.php24
-rw-r--r--lib/private/AppFramework/OCS/V2Response.php23
-rw-r--r--lib/private/AppFramework/Routing/RouteActionHandler.php25
-rw-r--r--lib/private/AppFramework/Routing/RouteConfig.php36
-rw-r--r--lib/private/AppFramework/Routing/RouteParser.php30
-rw-r--r--lib/private/AppFramework/ScopedPsrLogger.php24
-rw-r--r--lib/private/AppFramework/Services/AppConfig.php331
-rw-r--r--lib/private/AppFramework/Services/InitialState.php21
-rw-r--r--lib/private/AppFramework/Utility/ControllerMethodReflector.php66
-rw-r--r--lib/private/AppFramework/Utility/QueryNotFoundException.php21
-rw-r--r--lib/private/AppFramework/Utility/SimpleContainer.php43
-rw-r--r--lib/private/AppFramework/Utility/TimeFactory.php37
-rw-r--r--lib/private/AppScriptDependency.php21
-rw-r--r--lib/private/AppScriptSort.php29
-rw-r--r--lib/private/Archive/Archive.php30
-rw-r--r--lib/private/Archive/TAR.php69
-rw-r--r--lib/private/Archive/ZIP.php32
-rw-r--r--lib/private/Authentication/Events/ARemoteWipeEvent.php21
-rw-r--r--lib/private/Authentication/Events/AppPasswordCreatedEvent.php31
-rw-r--r--lib/private/Authentication/Events/LoginFailed.php21
-rw-r--r--lib/private/Authentication/Events/RemoteWipeFinished.php21
-rw-r--r--lib/private/Authentication/Events/RemoteWipeStarted.php21
-rw-r--r--lib/private/Authentication/Exceptions/ExpiredTokenException.php41
-rw-r--r--lib/private/Authentication/Exceptions/InvalidProviderException.php23
-rw-r--r--lib/private/Authentication/Exceptions/InvalidTokenException.php29
-rw-r--r--lib/private/Authentication/Exceptions/LoginRequiredException.php22
-rw-r--r--lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php22
-rw-r--r--lib/private/Authentication/Exceptions/PasswordlessTokenException.php22
-rw-r--r--lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php21
-rw-r--r--lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php22
-rw-r--r--lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php22
-rw-r--r--lib/private/Authentication/Exceptions/WipeTokenException.php41
-rw-r--r--lib/private/Authentication/Listeners/LoginFailedListener.php22
-rw-r--r--lib/private/Authentication/Listeners/RemoteWipeActivityListener.php24
-rw-r--r--lib/private/Authentication/Listeners/RemoteWipeEmailListener.php28
-rw-r--r--lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php24
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php24
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php21
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php24
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php22
-rw-r--r--lib/private/Authentication/Listeners/UserLoggedInListener.php22
-rw-r--r--lib/private/Authentication/Login/ALoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/Chain.php43
-rw-r--r--lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php21
-rw-r--r--lib/private/Authentication/Login/CompleteLoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/CreateSessionTokenCommand.php25
-rw-r--r--lib/private/Authentication/Login/EmailLoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/FinishRememberedLoginCommand.php22
-rw-r--r--lib/private/Authentication/Login/LoggedInCheckCommand.php25
-rw-r--r--lib/private/Authentication/Login/LoginData.php32
-rw-r--r--lib/private/Authentication/Login/LoginResult.php28
-rw-r--r--lib/private/Authentication/Login/PreLoginHookCommand.php22
-rw-r--r--lib/private/Authentication/Login/SetUserTimezoneCommand.php23
-rw-r--r--lib/private/Authentication/Login/TwoFactorCommand.php30
-rw-r--r--lib/private/Authentication/Login/UidLoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php21
-rw-r--r--lib/private/Authentication/Login/UserDisabledCheckCommand.php24
-rw-r--r--lib/private/Authentication/Login/WebAuthnChain.php39
-rw-r--r--lib/private/Authentication/Login/WebAuthnLoginCommand.php21
-rw-r--r--lib/private/Authentication/LoginCredentials/Credentials.php21
-rw-r--r--lib/private/Authentication/LoginCredentials/Store.php28
-rw-r--r--lib/private/Authentication/Notifications/Notifier.php22
-rw-r--r--lib/private/Authentication/Token/INamedToken.php22
-rw-r--r--lib/private/Authentication/Token/IProvider.php87
-rw-r--r--lib/private/Authentication/Token/IToken.php133
-rw-r--r--lib/private/Authentication/Token/IWipeableToken.php22
-rw-r--r--lib/private/Authentication/Token/Manager.php92
-rw-r--r--lib/private/Authentication/Token/PublicKeyToken.php39
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenMapper.php33
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php220
-rw-r--r--lib/private/Authentication/Token/RemoteWipe.php35
-rw-r--r--lib/private/Authentication/Token/TokenCleanupJob.php20
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php76
-rw-r--r--lib/private/Authentication/TwoFactorAuth/EnforcementState.php25
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Manager.php51
-rw-r--r--lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php21
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderLoader.php22
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderManager.php21
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderSet.php23
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Registry.php24
-rw-r--r--lib/private/Authentication/WebAuthn/CredentialRepository.php25
-rw-r--r--lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php22
-rw-r--r--lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php22
-rw-r--r--lib/private/Authentication/WebAuthn/Manager.php73
-rw-r--r--lib/private/Avatar/Avatar.php42
-rw-r--r--lib/private/Avatar/AvatarManager.php101
-rw-r--r--lib/private/Avatar/GuestAvatar.php36
-rw-r--r--lib/private/Avatar/PlaceholderAvatar.php49
-rw-r--r--lib/private/Avatar/UserAvatar.php56
-rw-r--r--lib/private/BackgroundJob/Job.php98
-rw-r--r--lib/private/BackgroundJob/JobList.php94
-rw-r--r--lib/private/BackgroundJob/QueuedJob.php49
-rw-r--r--lib/private/BackgroundJob/TimedJob.php63
-rw-r--r--lib/private/BinaryFinder.php20
-rw-r--r--lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php153
-rw-r--r--lib/private/Broadcast/Events/BroadcastEvent.php21
-rw-r--r--lib/private/Cache/CappedMemoryCache.php22
-rw-r--r--lib/private/Cache/File.php38
-rw-r--r--lib/private/Calendar/CalendarQuery.php21
-rw-r--r--lib/private/Calendar/Manager.php23
-rw-r--r--lib/private/Calendar/Resource/Manager.php23
-rw-r--r--lib/private/Calendar/Room/Manager.php23
-rw-r--r--lib/private/CapabilitiesManager.php28
-rw-r--r--lib/private/Collaboration/AutoComplete/Manager.php47
-rw-r--r--lib/private/Collaboration/Collaborators/GroupPlugin.php68
-rw-r--r--lib/private/Collaboration/Collaborators/LookupPlugin.php56
-rw-r--r--lib/private/Collaboration/Collaborators/MailPlugin.php105
-rw-r--r--lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php40
-rw-r--r--lib/private/Collaboration/Collaborators/RemotePlugin.php59
-rw-r--r--lib/private/Collaboration/Collaborators/Search.php48
-rw-r--r--lib/private/Collaboration/Collaborators/SearchResult.php39
-rw-r--r--lib/private/Collaboration/Collaborators/UserPlugin.php111
-rw-r--r--lib/private/Collaboration/Reference/File/FileReferenceEventListener.php27
-rw-r--r--lib/private/Collaboration/Reference/File/FileReferenceProvider.php48
-rw-r--r--lib/private/Collaboration/Reference/LinkReferenceProvider.php186
-rw-r--r--lib/private/Collaboration/Reference/ReferenceManager.php80
-rw-r--r--lib/private/Collaboration/Reference/RenderReferenceEventListener.php30
-rw-r--r--lib/private/Collaboration/Resources/Collection.php70
-rw-r--r--lib/private/Collaboration/Resources/Listener.php22
-rw-r--r--lib/private/Collaboration/Resources/Manager.php74
-rw-r--r--lib/private/Collaboration/Resources/ProviderManager.php39
-rw-r--r--lib/private/Collaboration/Resources/Resource.php66
-rw-r--r--lib/private/Color.php22
-rw-r--r--lib/private/Command/AsyncBus.php24
-rw-r--r--lib/private/Command/CallableJob.php24
-rw-r--r--lib/private/Command/ClosureJob.php30
-rw-r--r--lib/private/Command/CommandJob.php29
-rw-r--r--lib/private/Command/CronBus.php54
-rw-r--r--lib/private/Command/FileAccess.php23
-rw-r--r--lib/private/Command/QueueBus.php24
-rw-r--r--lib/private/Comments/Comment.php69
-rw-r--r--lib/private/Comments/Manager.php189
-rw-r--r--lib/private/Comments/ManagerFactory.php26
-rw-r--r--lib/private/Config.php82
-rw-r--r--lib/private/Console/Application.php88
-rw-r--r--lib/private/Console/TimestampFormatter.php42
-rw-r--r--lib/private/Contacts/ContactsMenu/ActionFactory.php21
-rw-r--r--lib/private/Contacts/ContactsMenu/ActionProviderStore.php35
-rw-r--r--lib/private/Contacts/ContactsMenu/Actions/LinkAction.php21
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php158
-rw-r--r--lib/private/Contacts/ContactsMenu/Entry.php66
-rw-r--r--lib/private/Contacts/ContactsMenu/Manager.php52
-rw-r--r--lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php21
-rw-r--r--lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php21
-rw-r--r--lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php21
-rw-r--r--lib/private/ContactsManager.php53
-rw-r--r--lib/private/DB/Adapter.php41
-rw-r--r--lib/private/DB/AdapterMySQL.php23
-rw-r--r--lib/private/DB/AdapterOCI8.php25
-rw-r--r--lib/private/DB/AdapterPgSql.php27
-rw-r--r--lib/private/DB/AdapterSqlite.php29
-rw-r--r--lib/private/DB/BacktraceDebugStack.php19
-rw-r--r--lib/private/DB/Connection.php249
-rw-r--r--lib/private/DB/ConnectionAdapter.php44
-rw-r--r--lib/private/DB/ConnectionFactory.php56
-rw-r--r--lib/private/DB/DbDataCollector.php25
-rw-r--r--lib/private/DB/Exceptions/DbalException.php26
-rw-r--r--lib/private/DB/MigrationException.php22
-rw-r--r--lib/private/DB/MigrationService.php150
-rw-r--r--lib/private/DB/Migrator.php60
-rw-r--r--lib/private/DB/MigratorExecuteSqlEvent.php20
-rw-r--r--lib/private/DB/MissingColumnInformation.php23
-rw-r--r--lib/private/DB/MissingIndexInformation.php32
-rw-r--r--lib/private/DB/MissingPrimaryKeyInformation.php25
-rw-r--r--lib/private/DB/MySQLMigrator.php50
-rw-r--r--lib/private/DB/MySqlTools.php22
-rw-r--r--lib/private/DB/OCSqlitePlatform.php22
-rw-r--r--lib/private/DB/ObjectParameter.php32
-rw-r--r--lib/private/DB/OracleConnection.php29
-rw-r--r--lib/private/DB/OracleMigrator.php268
-rw-r--r--lib/private/DB/PgSqlTools.php25
-rw-r--r--lib/private/DB/PostgreSqlMigrator.php55
-rw-r--r--lib/private/DB/PreparedStatement.php21
-rw-r--r--lib/private/DB/QueryBuilder/CompositeExpression.php23
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php64
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php26
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php98
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php25
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php57
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php22
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php22
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php22
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php22
-rw-r--r--lib/private/DB/QueryBuilder/Literal.php28
-rw-r--r--lib/private/DB/QueryBuilder/Parameter.php27
-rw-r--r--lib/private/DB/QueryBuilder/QueryBuilder.php60
-rw-r--r--lib/private/DB/QueryBuilder/QueryFunction.php27
-rw-r--r--lib/private/DB/QueryBuilder/QuoteHelper.php23
-rw-r--r--lib/private/DB/ResultAdapter.php21
-rw-r--r--lib/private/DB/SQLiteMigrator.php35
-rw-r--r--lib/private/DB/SQLiteSessionInit.php26
-rw-r--r--lib/private/DB/SchemaWrapper.php22
-rw-r--r--lib/private/DB/SetTransactionIsolationLevel.php31
-rw-r--r--lib/private/Dashboard/Manager.php33
-rw-r--r--lib/private/DatabaseException.php23
-rw-r--r--lib/private/DatabaseSetupException.php23
-rw-r--r--lib/private/DateTimeFormatter.php59
-rw-r--r--lib/private/DateTimeZone.php25
-rw-r--r--lib/private/Diagnostics/Event.php24
-rw-r--r--lib/private/Diagnostics/EventLogger.php24
-rw-r--r--lib/private/Diagnostics/Query.php24
-rw-r--r--lib/private/Diagnostics/QueryLogger.php27
-rw-r--r--lib/private/DirectEditing/Manager.php47
-rw-r--r--lib/private/DirectEditing/Token.php21
-rw-r--r--lib/private/EmojiHelper.php22
-rw-r--r--lib/private/Encryption/DecryptAll.php53
-rw-r--r--lib/private/Encryption/EncryptionWrapper.php41
-rw-r--r--lib/private/Encryption/Exceptions/DecryptionFailedException.php23
-rw-r--r--lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php24
-rw-r--r--lib/private/Encryption/Exceptions/EncryptionFailedException.php24
-rw-r--r--lib/private/Encryption/Exceptions/EncryptionHeaderKeyExistsException.php23
-rw-r--r--lib/private/Encryption/Exceptions/EncryptionHeaderToLargeException.php23
-rw-r--r--lib/private/Encryption/Exceptions/ModuleAlreadyExistsException.php23
-rw-r--r--lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php23
-rw-r--r--lib/private/Encryption/Exceptions/UnknownCipherException.php23
-rw-r--r--lib/private/Encryption/File.php34
-rw-r--r--lib/private/Encryption/HookManager.php26
-rw-r--r--lib/private/Encryption/Keys/Storage.php57
-rw-r--r--lib/private/Encryption/Manager.php70
-rw-r--r--lib/private/Encryption/Update.php43
-rw-r--r--lib/private/Encryption/Util.php79
-rw-r--r--lib/private/EventDispatcher/EventDispatcher.php67
-rw-r--r--lib/private/EventDispatcher/ServiceEventListener.php26
-rw-r--r--lib/private/EventSource.php (renamed from lib/private/legacy/OC_EventSource.php)68
-rw-r--r--lib/private/EventSourceFactory.php39
-rw-r--r--lib/private/Federation/CloudFederationFactory.php21
-rw-r--r--lib/private/Federation/CloudFederationNotification.php21
-rw-r--r--lib/private/Federation/CloudFederationProviderManager.php182
-rw-r--r--lib/private/Federation/CloudFederationShare.php42
-rw-r--r--lib/private/Federation/CloudId.php23
-rw-r--r--lib/private/Federation/CloudIdManager.php54
-rw-r--r--lib/private/Files/AppData/AppData.php28
-rw-r--r--lib/private/Files/AppData/Factory.php24
-rw-r--r--lib/private/Files/Cache/Cache.php186
-rw-r--r--lib/private/Files/Cache/CacheDependencies.php61
-rw-r--r--lib/private/Files/Cache/CacheEntry.php25
-rw-r--r--lib/private/Files/Cache/CacheQueryBuilder.php49
-rw-r--r--lib/private/Files/Cache/FailedCache.php22
-rw-r--r--lib/private/Files/Cache/FileAccess.php99
-rw-r--r--lib/private/Files/Cache/HomeCache.php29
-rw-r--r--lib/private/Files/Cache/HomePropagator.php22
-rw-r--r--lib/private/Files/Cache/LocalRootScanner.php21
-rw-r--r--lib/private/Files/Cache/MoveFromCacheTrait.php22
-rw-r--r--lib/private/Files/Cache/NullWatcher.php21
-rw-r--r--lib/private/Files/Cache/Propagator.php25
-rw-r--r--lib/private/Files/Cache/QuerySearchHelper.php97
-rw-r--r--lib/private/Files/Cache/Scanner.php136
-rw-r--r--lib/private/Files/Cache/SearchBuilder.php259
-rw-r--r--lib/private/Files/Cache/Storage.php34
-rw-r--r--lib/private/Files/Cache/StorageGlobal.php23
-rw-r--r--lib/private/Files/Cache/Updater.php54
-rw-r--r--lib/private/Files/Cache/Watcher.php29
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheJail.php46
-rw-r--r--lib/private/Files/Cache/Wrapper/CachePermissionsMask.php23
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheWrapper.php55
-rw-r--r--lib/private/Files/Cache/Wrapper/JailPropagator.php21
-rw-r--r--lib/private/Files/Cache/Wrapper/JailWatcher.php58
-rw-r--r--lib/private/Files/Config/CachedMountFileInfo.php22
-rw-r--r--lib/private/Files/Config/CachedMountInfo.php38
-rw-r--r--lib/private/Files/Config/LazyPathCachedMountInfo.php48
-rw-r--r--lib/private/Files/Config/LazyStorageMountInfo.php30
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php32
-rw-r--r--lib/private/Files/Config/UserMountCache.php233
-rw-r--r--lib/private/Files/Config/UserMountCacheListener.php22
-rw-r--r--lib/private/Files/FileInfo.php99
-rw-r--r--lib/private/Files/Filesystem.php43
-rw-r--r--lib/private/Files/Lock/LockManager.php45
-rw-r--r--lib/private/Files/Mount/CacheMountProvider.php22
-rw-r--r--lib/private/Files/Mount/HomeMountPoint.php34
-rw-r--r--lib/private/Files/Mount/LocalHomeMountProvider.php24
-rw-r--r--lib/private/Files/Mount/Manager.php58
-rw-r--r--lib/private/Files/Mount/MountPoint.php43
-rw-r--r--lib/private/Files/Mount/MoveableMount.php23
-rw-r--r--lib/private/Files/Mount/ObjectHomeMountProvider.php29
-rw-r--r--lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php21
-rw-r--r--lib/private/Files/Mount/RootMountProvider.php19
-rw-r--r--lib/private/Files/Node/File.php29
-rw-r--r--lib/private/Files/Node/Folder.php43
-rw-r--r--lib/private/Files/Node/HookConnector.php69
-rw-r--r--lib/private/Files/Node/LazyFolder.php110
-rw-r--r--lib/private/Files/Node/LazyRoot.php54
-rw-r--r--lib/private/Files/Node/LazyUserFolder.php54
-rw-r--r--lib/private/Files/Node/Node.php90
-rw-r--r--lib/private/Files/Node/NonExistingFile.php23
-rw-r--r--lib/private/Files/Node/NonExistingFolder.php28
-rw-r--r--lib/private/Files/Node/Root.php97
-rw-r--r--lib/private/Files/Notify/Change.php21
-rw-r--r--lib/private/Files/Notify/RenameChange.php21
-rw-r--r--lib/private/Files/ObjectStore/AppdataPreviewObjectStoreStorage.php30
-rw-r--r--lib/private/Files/ObjectStore/Azure.php23
-rw-r--r--lib/private/Files/ObjectStore/HomeObjectStoreStorage.php57
-rw-r--r--lib/private/Files/ObjectStore/Mapper.php23
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreScanner.php29
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreStorage.php151
-rw-r--r--lib/private/Files/ObjectStore/S3.php22
-rw-r--r--lib/private/Files/ObjectStore/S3ConfigTrait.php37
-rw-r--r--lib/private/Files/ObjectStore/S3ConnectionTrait.php87
-rw-r--r--lib/private/Files/ObjectStore/S3ObjectTrait.php66
-rw-r--r--lib/private/Files/ObjectStore/S3Signature.php23
-rw-r--r--lib/private/Files/ObjectStore/StorageObjectStore.php24
-rw-r--r--lib/private/Files/ObjectStore/Swift.php30
-rw-r--r--lib/private/Files/ObjectStore/SwiftFactory.php28
-rw-r--r--lib/private/Files/ObjectStore/SwiftV2CachingAuthService.php26
-rw-r--r--lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php33
-rw-r--r--lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php31
-rw-r--r--lib/private/Files/Search/QueryOptimizer/MergeDistributiveOperations.php99
-rw-r--r--lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php74
-rw-r--r--lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php24
-rw-r--r--lib/private/Files/Search/QueryOptimizer/QueryOptimizer.php34
-rw-r--r--lib/private/Files/Search/QueryOptimizer/QueryOptimizerStep.php19
-rw-r--r--lib/private/Files/Search/QueryOptimizer/ReplacingOptimizerStep.php37
-rw-r--r--lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php36
-rw-r--r--lib/private/Files/Search/SearchBinaryOperator.php40
-rw-r--r--lib/private/Files/Search/SearchComparison.php71
-rw-r--r--lib/private/Files/Search/SearchOrder.php50
-rw-r--r--lib/private/Files/Search/SearchQuery.php21
-rw-r--r--lib/private/Files/SetupManager.php130
-rw-r--r--lib/private/Files/SetupManagerFactory.php64
-rw-r--r--lib/private/Files/SimpleFS/NewSimpleFile.php22
-rw-r--r--lib/private/Files/SimpleFS/SimpleFile.php23
-rw-r--r--lib/private/Files/SimpleFS/SimpleFolder.php25
-rw-r--r--lib/private/Files/Storage/Common.php98
-rw-r--r--lib/private/Files/Storage/CommonTest.php29
-rw-r--r--lib/private/Files/Storage/DAV.php52
-rw-r--r--lib/private/Files/Storage/FailedStorage.php26
-rw-r--r--lib/private/Files/Storage/Home.php31
-rw-r--r--lib/private/Files/Storage/Local.php92
-rw-r--r--lib/private/Files/Storage/LocalRootStorage.php21
-rw-r--r--lib/private/Files/Storage/LocalTempFileTrait.php24
-rw-r--r--lib/private/Files/Storage/PolyFill/CopyDirectory.php24
-rw-r--r--lib/private/Files/Storage/Storage.php25
-rw-r--r--lib/private/Files/Storage/StorageFactory.php25
-rw-r--r--lib/private/Files/Storage/Temporary.php26
-rw-r--r--lib/private/Files/Storage/Wrapper/Availability.php27
-rw-r--r--lib/private/Files/Storage/Wrapper/Encoding.php31
-rw-r--r--lib/private/Files/Storage/Wrapper/EncodingDirectoryWrapper.php23
-rw-r--r--lib/private/Files/Storage/Wrapper/Encryption.php104
-rw-r--r--lib/private/Files/Storage/Wrapper/Jail.php43
-rw-r--r--lib/private/Files/Storage/Wrapper/KnownMtime.php146
-rw-r--r--lib/private/Files/Storage/Wrapper/PermissionsMask.php32
-rw-r--r--lib/private/Files/Storage/Wrapper/Quota.php33
-rw-r--r--lib/private/Files/Storage/Wrapper/Wrapper.php58
-rw-r--r--lib/private/Files/Stream/Encryption.php62
-rw-r--r--lib/private/Files/Stream/HashWrapper.php21
-rw-r--r--lib/private/Files/Stream/Quota.php26
-rw-r--r--lib/private/Files/Stream/SeekableHttpStream.php22
-rw-r--r--lib/private/Files/Template/TemplateManager.php37
-rw-r--r--lib/private/Files/Type/Detection.php80
-rw-r--r--lib/private/Files/Type/Loader.php103
-rw-r--r--lib/private/Files/Type/TemplateManager.php26
-rw-r--r--lib/private/Files/Utils/PathHelper.php20
-rw-r--r--lib/private/Files/Utils/Scanner.php90
-rw-r--r--lib/private/Files/View.php163
-rw-r--r--lib/private/FilesMetadata/FilesMetadataManager.php303
-rw-r--r--lib/private/FilesMetadata/Job/UpdateSingleMetadata.php49
-rw-r--r--lib/private/FilesMetadata/Listener/MetadataDelete.php44
-rw-r--r--lib/private/FilesMetadata/Listener/MetadataUpdate.php47
-rw-r--r--lib/private/FilesMetadata/MetadataQuery.php176
-rw-r--r--lib/private/FilesMetadata/Model/FilesMetadata.php621
-rw-r--r--lib/private/FilesMetadata/Model/MetadataValueWrapper.php428
-rw-r--r--lib/private/FilesMetadata/Service/IndexRequestService.php178
-rw-r--r--lib/private/FilesMetadata/Service/MetadataRequestService.php169
-rw-r--r--lib/private/ForbiddenException.php23
-rw-r--r--lib/private/FullTextSearch/FullTextSearchManager.php98
-rw-r--r--lib/private/FullTextSearch/Model/DocumentAccess.php106
-rw-r--r--lib/private/FullTextSearch/Model/IndexDocument.php278
-rw-r--r--lib/private/FullTextSearch/Model/SearchOption.php97
-rw-r--r--lib/private/FullTextSearch/Model/SearchRequestSimpleQuery.php60
-rw-r--r--lib/private/FullTextSearch/Model/SearchTemplate.php77
-rw-r--r--lib/private/GlobalScale/Config.php21
-rw-r--r--lib/private/Group/Backend.php25
-rw-r--r--lib/private/Group/Database.php156
-rw-r--r--lib/private/Group/DisplayNameCache.php23
-rw-r--r--lib/private/Group/Group.php83
-rw-r--r--lib/private/Group/Manager.php169
-rw-r--r--lib/private/Group/MetaData.php40
-rw-r--r--lib/private/HintException.php21
-rw-r--r--lib/private/Hooks/BasicEmitter.php22
-rw-r--r--lib/private/Hooks/Emitter.php26
-rw-r--r--lib/private/Hooks/EmitterTrait.php27
-rw-r--r--lib/private/Hooks/PublicEmitter.php24
-rw-r--r--lib/private/Http/Client/Client.php121
-rw-r--r--lib/private/Http/Client/ClientService.php30
-rw-r--r--lib/private/Http/Client/DnsPinMiddleware.php42
-rw-r--r--lib/private/Http/Client/GuzzlePromiseAdapter.php19
-rw-r--r--lib/private/Http/Client/NegativeDnsCache.php22
-rw-r--r--lib/private/Http/Client/Response.php24
-rw-r--r--lib/private/Http/CookieHelper.php37
-rw-r--r--lib/private/Http/WellKnown/RequestManager.php25
-rw-r--r--lib/private/InitialStateService.php24
-rw-r--r--lib/private/Installer.php195
-rw-r--r--lib/private/IntegrityCheck/Checker.php113
-rw-r--r--lib/private/IntegrityCheck/Exceptions/InvalidSignatureException.php23
-rw-r--r--lib/private/IntegrityCheck/Helpers/AppLocator.php24
-rw-r--r--lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php23
-rw-r--r--lib/private/IntegrityCheck/Helpers/FileAccessHelper.php25
-rw-r--r--lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php24
-rw-r--r--lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php25
-rw-r--r--lib/private/KnownUser/KnownUser.php21
-rw-r--r--lib/private/KnownUser/KnownUserMapper.php21
-rw-r--r--lib/private/KnownUser/KnownUserService.php22
-rw-r--r--lib/private/L10N/Factory.php110
-rw-r--r--lib/private/L10N/L10N.php31
-rw-r--r--lib/private/L10N/L10NString.php28
-rw-r--r--lib/private/L10N/LanguageIterator.php22
-rw-r--r--lib/private/L10N/LanguageNotFoundException.php21
-rw-r--r--lib/private/L10N/LazyL10N.php21
-rw-r--r--lib/private/LDAP/NullLDAPProviderFactory.php21
-rwxr-xr-xlib/private/LargeFileHelper.php29
-rw-r--r--lib/private/Lock/AbstractLockingProvider.php36
-rw-r--r--lib/private/Lock/DBLockingProvider.php43
-rw-r--r--lib/private/Lock/MemcacheLockingProvider.php111
-rw-r--r--lib/private/Lock/NoopLockingProvider.php24
-rw-r--r--lib/private/Lockdown/Filesystem/NullCache.php21
-rw-r--r--lib/private/Lockdown/Filesystem/NullStorage.php22
-rw-r--r--lib/private/Lockdown/LockdownManager.php21
-rw-r--r--lib/private/Log.php146
-rw-r--r--lib/private/Log/ErrorHandler.php56
-rw-r--r--lib/private/Log/Errorlog.php40
-rw-r--r--lib/private/Log/ExceptionSerializer.php39
-rw-r--r--lib/private/Log/File.php65
-rw-r--r--lib/private/Log/LogDetails.php34
-rw-r--r--lib/private/Log/LogFactory.php81
-rw-r--r--lib/private/Log/PsrLoggerAdapter.php137
-rw-r--r--lib/private/Log/Rotate.php37
-rw-r--r--lib/private/Log/Syslog.php37
-rw-r--r--lib/private/Log/Systemdlog.php37
-rw-r--r--lib/private/Mail/Attachment.php22
-rw-r--r--lib/private/Mail/EMailTemplate.php34
-rw-r--r--lib/private/Mail/Mailer.php35
-rw-r--r--lib/private/Mail/Message.php31
-rw-r--r--lib/private/Memcache/APCu.php27
-rw-r--r--lib/private/Memcache/ArrayCache.php24
-rw-r--r--lib/private/Memcache/CADTrait.php21
-rw-r--r--lib/private/Memcache/CASTrait.php21
-rw-r--r--lib/private/Memcache/Cache.php27
-rw-r--r--lib/private/Memcache/Factory.php43
-rw-r--r--lib/private/Memcache/LoggerWrapperCache.php33
-rw-r--r--lib/private/Memcache/Memcached.php31
-rw-r--r--lib/private/Memcache/NullCache.php26
-rw-r--r--lib/private/Memcache/ProfilerWrapperCache.php34
-rw-r--r--lib/private/Memcache/Redis.php76
-rw-r--r--lib/private/Memcache/WithLocalCache.php4
-rw-r--r--lib/private/MemoryInfo.php22
-rw-r--r--lib/private/Metadata/Capabilities.php44
-rw-r--r--lib/private/Metadata/FileEventListener.php110
-rw-r--r--lib/private/Metadata/FileMetadata.php51
-rw-r--r--lib/private/Metadata/FileMetadataMapper.php177
-rw-r--r--lib/private/Metadata/IMetadataManager.php35
-rw-r--r--lib/private/Metadata/IMetadataProvider.php41
-rw-r--r--lib/private/Metadata/MetadataManager.php100
-rw-r--r--lib/private/Metadata/Provider/ExifProvider.php142
-rw-r--r--lib/private/Migration/BackgroundRepair.php58
-rw-r--r--lib/private/Migration/ConsoleOutput.php44
-rw-r--r--lib/private/Migration/SimpleOutput.php43
-rw-r--r--lib/private/NaturalSort.php27
-rw-r--r--lib/private/NaturalSort_DefaultCollator.php24
-rw-r--r--lib/private/NavigationManager.php153
-rw-r--r--lib/private/NeedsUpdateException.php22
-rw-r--r--lib/private/Net/HostnameClassifier.php26
-rw-r--r--lib/private/Net/IpAddressClassifier.php26
-rw-r--r--lib/private/NotSquareException.php22
-rw-r--r--lib/private/Notification/Action.php100
-rw-r--r--lib/private/Notification/Manager.php135
-rw-r--r--lib/private/Notification/Notification.php329
-rw-r--r--lib/private/OCM/Model/OCMProvider.php217
-rw-r--r--lib/private/OCM/Model/OCMResource.php106
-rw-r--r--lib/private/OCM/OCMDiscoveryService.php120
-rw-r--r--lib/private/OCS/CoreCapabilities.php48
-rw-r--r--lib/private/OCS/DiscoveryService.php30
-rw-r--r--lib/private/OCS/Exception.php32
-rw-r--r--lib/private/OCS/Provider.php48
-rw-r--r--lib/private/OCS/Result.php68
-rw-r--r--lib/private/PhoneNumberUtil.php43
-rw-r--r--lib/private/Preview/BMP.php23
-rw-r--r--lib/private/Preview/BackgroundCleanupJob.php29
-rw-r--r--lib/private/Preview/Bitmap.php48
-rw-r--r--lib/private/Preview/Bundled.php21
-rw-r--r--lib/private/Preview/EMF.php16
-rw-r--r--lib/private/Preview/Font.php30
-rw-r--r--lib/private/Preview/GIF.php23
-rw-r--r--lib/private/Preview/Generator.php86
-rw-r--r--lib/private/Preview/GeneratorHelper.php24
-rw-r--r--lib/private/Preview/HEIC.php38
-rw-r--r--lib/private/Preview/IMagickSupport.php4
-rw-r--r--lib/private/Preview/Illustrator.php31
-rw-r--r--lib/private/Preview/Image.php30
-rw-r--r--lib/private/Preview/Imaginary.php50
-rw-r--r--lib/private/Preview/JPEG.php23
-rw-r--r--lib/private/Preview/Krita.php21
-rw-r--r--lib/private/Preview/MP3.php29
-rw-r--r--lib/private/Preview/MSOffice2003.php24
-rw-r--r--lib/private/Preview/MSOffice2007.php24
-rw-r--r--lib/private/Preview/MSOfficeDoc.php24
-rw-r--r--lib/private/Preview/MarkDown.php26
-rw-r--r--lib/private/Preview/MimeIconProvider.php24
-rw-r--r--lib/private/Preview/Movie.php32
-rw-r--r--lib/private/Preview/Office.php89
-rw-r--r--lib/private/Preview/OpenDocument.php25
-rw-r--r--lib/private/Preview/PDF.php31
-rw-r--r--lib/private/Preview/PNG.php23
-rw-r--r--lib/private/Preview/Photoshop.php31
-rw-r--r--lib/private/Preview/Postscript.php31
-rw-r--r--lib/private/Preview/Provider.php27
-rw-r--r--lib/private/Preview/ProviderV1Adapter.php22
-rw-r--r--lib/private/Preview/ProviderV2.php23
-rw-r--r--lib/private/Preview/SGI.php30
-rw-r--r--lib/private/Preview/SVG.php53
-rw-r--r--lib/private/Preview/StarOffice.php24
-rw-r--r--lib/private/Preview/Storage/Root.php22
-rw-r--r--lib/private/Preview/TGA.php30
-rw-r--r--lib/private/Preview/TIFF.php31
-rw-r--r--lib/private/Preview/TXT.php30
-rw-r--r--lib/private/Preview/Watcher.php24
-rw-r--r--lib/private/Preview/WatcherConnector.php23
-rw-r--r--lib/private/Preview/WebP.php21
-rw-r--r--lib/private/Preview/XBitmap.php23
-rw-r--r--lib/private/PreviewManager.php97
-rw-r--r--lib/private/PreviewNotAvailableException.php21
-rw-r--r--lib/private/Profile/Actions/EmailAction.php42
-rw-r--r--lib/private/Profile/Actions/FediverseAction.php37
-rw-r--r--lib/private/Profile/Actions/PhoneAction.php42
-rw-r--r--lib/private/Profile/Actions/TwitterAction.php44
-rw-r--r--lib/private/Profile/Actions/WebsiteAction.php42
-rw-r--r--lib/private/Profile/ProfileManager.php171
-rw-r--r--lib/private/Profile/TProfileHelper.php21
-rw-r--r--lib/private/Profiler/FileProfilerStorage.php40
-rw-r--r--lib/private/Profiler/Profile.php21
-rw-r--r--lib/private/Profiler/Profiler.php29
-rw-r--r--lib/private/Profiler/RoutingDataCollector.php23
-rw-r--r--lib/private/RedisFactory.php27
-rw-r--r--lib/private/Remote/Api/ApiBase.php21
-rw-r--r--lib/private/Remote/Api/ApiCollection.php21
-rw-r--r--lib/private/Remote/Api/ApiFactory.php21
-rw-r--r--lib/private/Remote/Api/NotFoundException.php21
-rw-r--r--lib/private/Remote/Api/OCS.php23
-rw-r--r--lib/private/Remote/Credentials.php21
-rw-r--r--lib/private/Remote/Instance.php21
-rw-r--r--lib/private/Remote/InstanceFactory.php21
-rw-r--r--lib/private/Remote/User.php24
-rw-r--r--lib/private/Repair.php82
-rw-r--r--lib/private/Repair/AddAppConfigLazyMigration.php45
-rw-r--r--lib/private/Repair/AddBruteForceCleanupJob.php21
-rw-r--r--lib/private/Repair/AddCleanupUpdaterBackupsJob.php21
-rw-r--r--lib/private/Repair/AddMetadataGenerationJob.php26
-rw-r--r--lib/private/Repair/AddRemoveOldTasksBackgroundJob.php29
-rw-r--r--lib/private/Repair/CleanTags.php27
-rw-r--r--lib/private/Repair/CleanUpAbandonedApps.php23
-rw-r--r--lib/private/Repair/ClearFrontendCaches.php25
-rw-r--r--lib/private/Repair/ClearGeneratedAvatarCache.php25
-rw-r--r--lib/private/Repair/ClearGeneratedAvatarCacheJob.php23
-rw-r--r--lib/private/Repair/Collation.php27
-rw-r--r--lib/private/Repair/Events/RepairAdvanceEvent.php20
-rw-r--r--lib/private/Repair/Events/RepairErrorEvent.php20
-rw-r--r--lib/private/Repair/Events/RepairFinishEvent.php20
-rw-r--r--lib/private/Repair/Events/RepairInfoEvent.php20
-rw-r--r--lib/private/Repair/Events/RepairStartEvent.php20
-rw-r--r--lib/private/Repair/Events/RepairStepEvent.php20
-rw-r--r--lib/private/Repair/Events/RepairWarningEvent.php20
-rw-r--r--lib/private/Repair/MoveUpdaterStepFile.php22
-rw-r--r--lib/private/Repair/NC11/FixMountStorages.php22
-rw-r--r--lib/private/Repair/NC13/AddLogRotateJob.php21
-rw-r--r--lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php21
-rw-r--r--lib/private/Repair/NC16/AddClenupLoginFlowV2BackgroundJob.php21
-rw-r--r--lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php22
-rw-r--r--lib/private/Repair/NC16/ClearCollectionsAccessCache.php21
-rw-r--r--lib/private/Repair/NC18/ResetGeneratedAvatarFlag.php23
-rw-r--r--lib/private/Repair/NC20/EncryptionLegacyCipher.php24
-rw-r--r--lib/private/Repair/NC20/EncryptionMigration.php24
-rw-r--r--lib/private/Repair/NC20/ShippedDashboardEnable.php21
-rw-r--r--lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php21
-rw-r--r--lib/private/Repair/NC21/ValidatePhoneNumber.php26
-rw-r--r--lib/private/Repair/NC22/LookupServerSendCheck.php22
-rw-r--r--lib/private/Repair/NC24/AddTokenCleanupJob.php21
-rw-r--r--lib/private/Repair/NC25/AddMissingSecretJob.php18
-rw-r--r--lib/private/Repair/OldGroupMembershipShares.php23
-rw-r--r--lib/private/Repair/Owncloud/CleanPreviews.php25
-rw-r--r--lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php70
-rw-r--r--lib/private/Repair/Owncloud/DropAccountTermsTable.php21
-rw-r--r--lib/private/Repair/Owncloud/MigrateOauthTables.php23
-rw-r--r--lib/private/Repair/Owncloud/MoveAvatars.php23
-rw-r--r--lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php56
-rw-r--r--lib/private/Repair/Owncloud/SaveAccountsTableData.php23
-rw-r--r--lib/private/Repair/Owncloud/UpdateLanguageCodes.php23
-rw-r--r--lib/private/Repair/RemoveLinkShares.php33
-rw-r--r--lib/private/Repair/RepairDavShares.php21
-rw-r--r--lib/private/Repair/RepairInvalidShares.php26
-rw-r--r--lib/private/Repair/RepairMimeTypes.php84
-rw-r--r--lib/private/Repair/SqliteAutoincrement.php100
-rw-r--r--lib/private/RepairException.php22
-rw-r--r--lib/private/RichObjectStrings/Validator.php25
-rw-r--r--lib/private/Route/CachingRouter.php31
-rw-r--r--lib/private/Route/Route.php29
-rw-r--r--lib/private/Route/Router.php184
-rw-r--r--lib/private/Search.php31
-rw-r--r--lib/private/Search/Filter/BooleanFilter.php29
-rw-r--r--lib/private/Search/Filter/DateTimeFilter.php29
-rw-r--r--lib/private/Search/Filter/FloatFilter.php28
-rw-r--r--lib/private/Search/Filter/GroupFilter.php34
-rw-r--r--lib/private/Search/Filter/IntegerFilter.php28
-rw-r--r--lib/private/Search/Filter/StringFilter.php27
-rw-r--r--lib/private/Search/Filter/StringsFilter.php34
-rw-r--r--lib/private/Search/Filter/UserFilter.php34
-rw-r--r--lib/private/Search/FilterCollection.php43
-rw-r--r--lib/private/Search/FilterFactory.php43
-rw-r--r--lib/private/Search/Provider/File.php30
-rw-r--r--lib/private/Search/Result/Audio.php24
-rw-r--r--lib/private/Search/Result/File.php27
-rw-r--r--lib/private/Search/Result/Folder.php24
-rw-r--r--lib/private/Search/Result/Image.php24
-rw-r--r--lib/private/Search/SearchComposer.php275
-rw-r--r--lib/private/Search/SearchQuery.php103
-rw-r--r--lib/private/Search/UnsupportedFilter.php17
-rw-r--r--lib/private/Security/Bruteforce/Backend/DatabaseBackend.php21
-rw-r--r--lib/private/Security/Bruteforce/Backend/IBackend.php21
-rw-r--r--lib/private/Security/Bruteforce/Backend/MemoryCacheBackend.php21
-rw-r--r--lib/private/Security/Bruteforce/Capabilities.php27
-rw-r--r--lib/private/Security/Bruteforce/CleanupJob.php32
-rw-r--r--lib/private/Security/Bruteforce/Throttler.php36
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicy.php139
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicyManager.php48
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php63
-rw-r--r--lib/private/Security/CSRF/CsrfToken.php39
-rw-r--r--lib/private/Security/CSRF/CsrfTokenGenerator.php35
-rw-r--r--lib/private/Security/CSRF/CsrfTokenManager.php52
-rw-r--r--lib/private/Security/CSRF/TokenStorage/SessionStorage.php51
-rw-r--r--lib/private/Security/Certificate.php73
-rw-r--r--lib/private/Security/CertificateManager.php59
-rw-r--r--lib/private/Security/CredentialsManager.php50
-rw-r--r--lib/private/Security/Crypto.php48
-rw-r--r--lib/private/Security/FeaturePolicy/FeaturePolicy.php21
-rw-r--r--lib/private/Security/FeaturePolicy/FeaturePolicyManager.php38
-rw-r--r--lib/private/Security/Hasher.php55
-rw-r--r--lib/private/Security/IdentityProof/Key.php22
-rw-r--r--lib/private/Security/IdentityProof/Manager.php25
-rw-r--r--lib/private/Security/IdentityProof/Signer.php27
-rw-r--r--lib/private/Security/Normalizer/IpAddress.php115
-rw-r--r--lib/private/Security/RateLimiting/Backend/DatabaseBackend.php23
-rw-r--r--lib/private/Security/RateLimiting/Backend/IBackend.php22
-rw-r--r--lib/private/Security/RateLimiting/Backend/MemoryCacheBackend.php26
-rw-r--r--lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php24
-rw-r--r--lib/private/Security/RateLimiting/Limiter.php25
-rw-r--r--lib/private/Security/RemoteHostValidator.php45
-rw-r--r--lib/private/Security/SecureRandom.php32
-rw-r--r--lib/private/Security/TrustedDomainHelper.php39
-rw-r--r--lib/private/Security/VerificationToken/CleanUpJob.php27
-rw-r--r--lib/private/Security/VerificationToken/VerificationToken.php23
-rw-r--r--lib/private/Server.php219
-rw-r--r--lib/private/ServerContainer.php24
-rw-r--r--lib/private/ServerNotAvailableException.php22
-rw-r--r--lib/private/ServiceUnavailableException.php23
-rw-r--r--lib/private/Session/CryptoSessionData.php58
-rw-r--r--lib/private/Session/CryptoWrapper.php32
-rw-r--r--lib/private/Session/Internal.php34
-rw-r--r--lib/private/Session/Memory.php28
-rw-r--r--lib/private/Session/Session.php28
-rw-r--r--lib/private/Settings/AuthorizedGroup.php22
-rw-r--r--lib/private/Settings/AuthorizedGroupMapper.php23
-rw-r--r--lib/private/Settings/DeclarativeManager.php386
-rw-r--r--lib/private/Settings/Manager.php70
-rw-r--r--lib/private/Settings/Section.php23
-rw-r--r--lib/private/Setup.php310
-rw-r--r--lib/private/Setup/AbstractDatabase.php46
-rw-r--r--lib/private/Setup/MySQL.php34
-rw-r--r--lib/private/Setup/OCI.php36
-rw-r--r--lib/private/Setup/PostgreSQL.php31
-rw-r--r--lib/private/Setup/Sqlite.php24
-rw-r--r--lib/private/SetupCheck/SetupCheckManager.php46
-rw-r--r--lib/private/Share/Constants.php27
-rw-r--r--lib/private/Share/Helper.php26
-rw-r--r--lib/private/Share/Share.php818
-rw-r--r--lib/private/Share20/DefaultShareProvider.php194
-rw-r--r--lib/private/Share20/Exception/BackendError.php21
-rw-r--r--lib/private/Share20/Exception/InvalidShare.php21
-rw-r--r--lib/private/Share20/Exception/ProviderException.php22
-rw-r--r--lib/private/Share20/Hooks.php28
-rw-r--r--lib/private/Share20/LegacyHooks.php25
-rw-r--r--lib/private/Share20/Manager.php468
-rw-r--r--lib/private/Share20/ProviderFactory.php54
-rw-r--r--lib/private/Share20/PublicShareTemplateFactory.php22
-rw-r--r--lib/private/Share20/Share.php81
-rw-r--r--lib/private/Share20/ShareAttributes.php21
-rw-r--r--lib/private/Share20/ShareDisableChecker.php85
-rw-r--r--lib/private/Share20/ShareHelper.php22
-rw-r--r--lib/private/Share20/UserRemovedListener.php21
-rw-r--r--lib/private/SpeechToText/SpeechToTextManager.php57
-rw-r--r--lib/private/SpeechToText/TranscriptionJob.php22
-rw-r--r--lib/private/StreamImage.php26
-rw-r--r--lib/private/Streamer.php32
-rw-r--r--lib/private/SubAdmin.php37
-rw-r--r--lib/private/Support/CrashReport/Registry.php22
-rw-r--r--lib/private/Support/Subscription/Assertion.php23
-rw-r--r--lib/private/Support/Subscription/Registry.php33
-rw-r--r--lib/private/SystemConfig.php42
-rw-r--r--lib/private/SystemTag/ManagerFactory.php40
-rw-r--r--lib/private/SystemTag/SystemTag.php78
-rw-r--r--lib/private/SystemTag/SystemTagManager.php44
-rw-r--r--lib/private/SystemTag/SystemTagObjectMapper.php31
-rw-r--r--lib/private/SystemTag/SystemTagsInFilesDetector.php27
-rw-r--r--lib/private/TagManager.php29
-rw-r--r--lib/private/Tagging/Tag.php24
-rw-r--r--lib/private/Tagging/TagMapper.php28
-rw-r--r--lib/private/Tags.php58
-rw-r--r--lib/private/Talk/Broker.php30
-rw-r--r--lib/private/Talk/ConversationOptions.php22
-rw-r--r--lib/private/TaskProcessing/Db/Task.php119
-rw-r--r--lib/private/TaskProcessing/Db/TaskMapper.php143
-rw-r--r--lib/private/TaskProcessing/Manager.php866
-rw-r--r--lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php79
-rw-r--r--lib/private/TaskProcessing/SynchronousBackgroundJob.php106
-rw-r--r--lib/private/Teams/TeamManager.php103
-rw-r--r--lib/private/TempManager.php32
-rw-r--r--lib/private/Template/Base.php30
-rw-r--r--lib/private/Template/CSSResourceLocator.php32
-rw-r--r--lib/private/Template/JSCombiner.php33
-rw-r--r--lib/private/Template/JSConfigHelper.php59
-rw-r--r--lib/private/Template/JSResourceLocator.php85
-rwxr-xr-xlib/private/Template/ResourceLocator.php30
-rw-r--r--lib/private/Template/ResourceNotFoundException.php23
-rw-r--r--lib/private/Template/TemplateFileLocator.php26
-rw-r--r--lib/private/TemplateLayout.php81
-rw-r--r--lib/private/TextProcessing/Db/Task.php30
-rw-r--r--lib/private/TextProcessing/Db/TaskMapper.php20
-rw-r--r--lib/private/TextProcessing/Manager.php120
-rw-r--r--lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php20
-rw-r--r--lib/private/TextProcessing/TaskBackgroundJob.php20
-rw-r--r--lib/private/TextToImage/Db/Task.php101
-rw-r--r--lib/private/TextToImage/Db/TaskMapper.php111
-rw-r--r--lib/private/TextToImage/Manager.php325
-rw-r--r--lib/private/TextToImage/RemoveOldTasksBackgroundJob.php62
-rw-r--r--lib/private/TextToImage/TaskBackgroundJob.php47
-rw-r--r--lib/private/Translation/TranslationManager.php38
-rw-r--r--lib/private/URLGenerator.php67
-rw-r--r--lib/private/Updater.php92
-rw-r--r--lib/private/Updater/Changes.php21
-rw-r--r--lib/private/Updater/ChangesCheck.php23
-rw-r--r--lib/private/Updater/ChangesMapper.php22
-rw-r--r--lib/private/Updater/VersionCheck.php43
-rw-r--r--lib/private/User/AvailabilityCoordinator.php122
-rw-r--r--lib/private/User/Backend.php25
-rw-r--r--lib/private/User/Database.php50
-rw-r--r--lib/private/User/DisplayNameCache.php21
-rw-r--r--lib/private/User/LazyUser.php19
-rw-r--r--lib/private/User/Listeners/BeforeUserDeletedListener.php28
-rw-r--r--lib/private/User/Listeners/UserChangedListener.php21
-rw-r--r--lib/private/User/LoginException.php22
-rw-r--r--lib/private/User/Manager.php129
-rw-r--r--lib/private/User/NoUserException.php23
-rw-r--r--lib/private/User/OutOfOfficeData.php58
-rw-r--r--lib/private/User/Session.php182
-rw-r--r--lib/private/User/User.php56
-rw-r--r--lib/private/UserStatus/ISettableProvider.php24
-rw-r--r--lib/private/UserStatus/Manager.php27
-rw-r--r--lib/private/legacy/OC_API.php35
-rw-r--r--lib/private/legacy/OC_App.php98
-rw-r--r--lib/private/legacy/OC_Defaults.php54
-rw-r--r--lib/private/legacy/OC_FileChunking.php31
-rw-r--r--lib/private/legacy/OC_Files.php63
-rw-r--r--lib/private/legacy/OC_Helper.php55
-rw-r--r--lib/private/legacy/OC_Hook.php31
-rw-r--r--lib/private/legacy/OC_Image.php155
-rw-r--r--lib/private/legacy/OC_JSON.php49
-rw-r--r--lib/private/legacy/OC_Response.php30
-rw-r--r--lib/private/legacy/OC_Template.php116
-rw-r--r--lib/private/legacy/OC_User.php72
-rw-r--r--lib/private/legacy/OC_Util.php97
-rw-r--r--lib/private/legacy/template/functions.php37
846 files changed, 18271 insertions, 26135 deletions
diff --git a/lib/private/Accounts/Account.php b/lib/private/Accounts/Account.php
index 22bbe3d11a0..946168d7755 100644
--- a/lib/private/Accounts/Account.php
+++ b/lib/private/Accounts/Account.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Accounts;
@@ -104,7 +85,7 @@ class Account implements IAccount {
}
}
- public function getFilteredProperties(string $scope = null, string $verified = null): array {
+ public function getFilteredProperties(?string $scope = null, ?string $verified = null): array {
$result = $incrementals = [];
/** @var IAccountProperty $obj */
foreach ($this->getAllProperties() as $obj) {
diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php
index 9865438161b..cc81a852cdf 100644
--- a/lib/private/Accounts/AccountManager.php
+++ b/lib/private/Accounts/AccountManager.php
@@ -1,61 +1,32 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Björn Schießle
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Accounts;
use Exception;
use InvalidArgumentException;
-use libphonenumber\NumberParseException;
-use libphonenumber\PhoneNumberFormat;
-use libphonenumber\PhoneNumberUtil;
use OC\Profile\TProfileHelper;
-use OCP\Accounts\UserUpdatedEvent;
-use OCP\Cache\CappedMemoryCache;
use OCA\Settings\BackgroundJobs\VerifyUserData;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
use OCP\Accounts\IAccountPropertyCollection;
use OCP\Accounts\PropertyDoesNotExistException;
+use OCP\Accounts\UserUpdatedEvent;
use OCP\BackgroundJob\IJobList;
+use OCP\Cache\CappedMemoryCache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Defaults;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
+use OCP\IPhoneNumberUtil;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\L10N\IFactory;
@@ -105,6 +76,7 @@ class AccountManager implements IAccountManager {
self::PROPERTY_ROLE => self::SCOPE_LOCAL,
self::PROPERTY_HEADLINE => self::SCOPE_LOCAL,
self::PROPERTY_BIOGRAPHY => self::SCOPE_LOCAL,
+ self::PROPERTY_BIRTHDATE => self::SCOPE_LOCAL,
];
public function __construct(
@@ -119,6 +91,7 @@ class AccountManager implements IAccountManager {
private IFactory $l10nFactory,
private IURLGenerator $urlGenerator,
private ICrypto $crypto,
+ private IPhoneNumberUtil $phoneNumberUtil,
) {
$this->internalCache = new CappedMemoryCache();
}
@@ -139,13 +112,9 @@ class AccountManager implements IAccountManager {
$defaultRegion = 'EN';
}
- $phoneUtil = PhoneNumberUtil::getInstance();
- try {
- $phoneNumber = $phoneUtil->parse($input, $defaultRegion);
- if ($phoneUtil->isValidNumber($phoneNumber)) {
- return $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
- }
- } catch (NumberParseException $e) {
+ $phoneNumber = $this->phoneNumberUtil->convertToStandardFormat($input, $defaultRegion);
+ if ($phoneNumber !== null) {
+ return $phoneNumber;
}
throw new InvalidArgumentException(self::PROPERTY_PHONE);
@@ -701,6 +670,12 @@ class AccountManager implements IAccountManager {
],
[
+ 'name' => self::PROPERTY_BIRTHDATE,
+ 'value' => '',
+ 'scope' => $scopes[self::PROPERTY_BIRTHDATE],
+ ],
+
+ [
'name' => self::PROPERTY_PROFILE_ENABLED,
'value' => $this->isProfileEnabledByDefault($this->config) ? '1' : '0',
],
diff --git a/lib/private/Accounts/AccountProperty.php b/lib/private/Accounts/AccountProperty.php
index 207dc1d139d..0c4ad568709 100644
--- a/lib/private/Accounts/AccountProperty.php
+++ b/lib/private/Accounts/AccountProperty.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Accounts;
@@ -32,6 +13,9 @@ use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
class AccountProperty implements IAccountProperty {
+ /**
+ * @var IAccountManager::SCOPE_*
+ */
private string $scope;
private string $locallyVerified = IAccountManager::NOT_VERIFIED;
diff --git a/lib/private/Accounts/AccountPropertyCollection.php b/lib/private/Accounts/AccountPropertyCollection.php
index 660a245714d..75eea76e686 100644
--- a/lib/private/Accounts/AccountPropertyCollection.php
+++ b/lib/private/Accounts/AccountPropertyCollection.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2021 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Accounts;
use InvalidArgumentException;
diff --git a/lib/private/Accounts/Hooks.php b/lib/private/Accounts/Hooks.php
index b449c41c1da..0235879e8e7 100644
--- a/lib/private/Accounts/Hooks.php
+++ b/lib/private/Accounts/Hooks.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Accounts;
diff --git a/lib/private/Accounts/TAccountsHelper.php b/lib/private/Accounts/TAccountsHelper.php
index f3be6523d29..69d25d9a933 100644
--- a/lib/private/Accounts/TAccountsHelper.php
+++ b/lib/private/Accounts/TAccountsHelper.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2021 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Accounts;
use OCP\Accounts\IAccountManager;
diff --git a/lib/private/Activity/ActivitySettingsAdapter.php b/lib/private/Activity/ActivitySettingsAdapter.php
index eba13ad0350..bc0e60c1acb 100644
--- a/lib/private/Activity/ActivitySettingsAdapter.php
+++ b/lib/private/Activity/ActivitySettingsAdapter.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Activity;
diff --git a/lib/private/Activity/Event.php b/lib/private/Activity/Event.php
index cc1135cf179..97ab7d1c935 100644
--- a/lib/private/Activity/Event.php
+++ b/lib/private/Activity/Event.php
@@ -3,31 +3,13 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Phil Davis <phil.davis@inf.org>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Activity;
+use OCP\Activity\Exceptions\InvalidValueException;
use OCP\Activity\IEvent;
use OCP\RichObjectStrings\InvalidObjectExeption;
use OCP\RichObjectStrings\IValidator;
@@ -89,16 +71,11 @@ class Event implements IEvent {
}
/**
- * Set the app of the activity
- *
- * @param string $app
- * @return IEvent
- * @throws \InvalidArgumentException if the app id is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setApp(string $app): IEvent {
if ($app === '' || isset($app[32])) {
- throw new \InvalidArgumentException('The given app is invalid');
+ throw new InvalidValueException('app');
}
$this->app = $app;
return $this;
@@ -112,16 +89,11 @@ class Event implements IEvent {
}
/**
- * Set the type of the activity
- *
- * @param string $type
- * @return IEvent
- * @throws \InvalidArgumentException if the type is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setType(string $type): IEvent {
if ($type === '' || isset($type[255])) {
- throw new \InvalidArgumentException('The given type is invalid');
+ throw new InvalidValueException('type');
}
$this->type = $type;
return $this;
@@ -135,16 +107,11 @@ class Event implements IEvent {
}
/**
- * Set the affected user of the activity
- *
- * @param string $affectedUser
- * @return IEvent
- * @throws \InvalidArgumentException if the affected user is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setAffectedUser(string $affectedUser): IEvent {
if ($affectedUser === '' || isset($affectedUser[64])) {
- throw new \InvalidArgumentException('The given affected user is invalid');
+ throw new InvalidValueException('affectedUser');
}
$this->affectedUser = $affectedUser;
return $this;
@@ -158,16 +125,11 @@ class Event implements IEvent {
}
/**
- * Set the author of the activity
- *
- * @param string $author
- * @return IEvent
- * @throws \InvalidArgumentException if the author is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setAuthor(string $author): IEvent {
if (isset($author[64])) {
- throw new \InvalidArgumentException('The given author user is invalid');
+ throw new InvalidValueException('author');
}
$this->author = $author;
return $this;
@@ -181,14 +143,12 @@ class Event implements IEvent {
}
/**
- * Set the timestamp of the activity
- *
- * @param int $timestamp
- * @return IEvent
- * @throws \InvalidArgumentException if the timestamp is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setTimestamp(int $timestamp): IEvent {
+ if ($timestamp < 0) {
+ throw new InvalidValueException('timestamp');
+ }
$this->timestamp = $timestamp;
return $this;
}
@@ -201,17 +161,11 @@ class Event implements IEvent {
}
/**
- * Set the subject of the activity
- *
- * @param string $subject
- * @param array $parameters
- * @return IEvent
- * @throws \InvalidArgumentException if the subject or parameters are invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setSubject(string $subject, array $parameters = []): IEvent {
if (isset($subject[255])) {
- throw new \InvalidArgumentException('The given subject is invalid');
+ throw new InvalidValueException('subject');
}
$this->subject = $subject;
$this->subjectParameters = $parameters;
@@ -233,14 +187,11 @@ class Event implements IEvent {
}
/**
- * @param string $subject
- * @return $this
- * @throws \InvalidArgumentException if the subject is invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setParsedSubject(string $subject): IEvent {
if ($subject === '') {
- throw new \InvalidArgumentException('The given parsed subject is invalid');
+ throw new InvalidValueException('parsedSubject');
}
$this->subjectParsed = $subject;
return $this;
@@ -255,21 +206,21 @@ class Event implements IEvent {
}
/**
- * @param string $subject
- * @param array $parameters
- * @return $this
- * @throws \InvalidArgumentException if the subject or parameters are invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setRichSubject(string $subject, array $parameters = []): IEvent {
if ($subject === '') {
- throw new \InvalidArgumentException('The given parsed subject is invalid');
+ throw new InvalidValueException('richSubject');
}
$this->subjectRich = $subject;
$this->subjectRichParameters = $parameters;
if ($this->subjectParsed === '') {
- $this->subjectParsed = $this->richToParsed($subject, $parameters);
+ try {
+ $this->subjectParsed = $this->richToParsed($subject, $parameters);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidValueException('richSubjectParameters', $e);
+ }
}
return $this;
@@ -316,17 +267,11 @@ class Event implements IEvent {
}
/**
- * Set the message of the activity
- *
- * @param string $message
- * @param array $parameters
- * @return IEvent
- * @throws \InvalidArgumentException if the message or parameters are invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setMessage(string $message, array $parameters = []): IEvent {
if (isset($message[255])) {
- throw new \InvalidArgumentException('The given message is invalid');
+ throw new InvalidValueException('message');
}
$this->message = $message;
$this->messageParameters = $parameters;
@@ -348,10 +293,7 @@ class Event implements IEvent {
}
/**
- * @param string $message
- * @return $this
- * @throws \InvalidArgumentException if the message is invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setParsedMessage(string $message): IEvent {
$this->messageParsed = $message;
@@ -367,18 +309,18 @@ class Event implements IEvent {
}
/**
- * @param string $message
- * @param array $parameters
- * @return $this
- * @throws \InvalidArgumentException if the subject or parameters are invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setRichMessage(string $message, array $parameters = []): IEvent {
$this->messageRich = $message;
$this->messageRichParameters = $parameters;
if ($this->messageParsed === '') {
- $this->messageParsed = $this->richToParsed($message, $parameters);
+ try {
+ $this->messageParsed = $this->richToParsed($message, $parameters);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidValueException('richMessageParameters', $e);
+ }
}
return $this;
@@ -401,21 +343,14 @@ class Event implements IEvent {
}
/**
- * Set the object of the activity
- *
- * @param string $objectType
- * @param int $objectId
- * @param string $objectName
- * @return IEvent
- * @throws \InvalidArgumentException if the object is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setObject(string $objectType, int $objectId, string $objectName = ''): IEvent {
if (isset($objectType[255])) {
- throw new \InvalidArgumentException('The given object type is invalid');
+ throw new InvalidValueException('objectType');
}
if (isset($objectName[4000])) {
- throw new \InvalidArgumentException('The given object name is invalid');
+ throw new InvalidValueException('objectName');
}
$this->objectType = $objectType;
$this->objectId = $objectId;
@@ -445,16 +380,11 @@ class Event implements IEvent {
}
/**
- * Set the link of the activity
- *
- * @param string $link
- * @return IEvent
- * @throws \InvalidArgumentException if the link is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setLink(string $link): IEvent {
if (isset($link[4000])) {
- throw new \InvalidArgumentException('The given link is invalid');
+ throw new InvalidValueException('link');
}
$this->link = $link;
return $this;
@@ -468,14 +398,11 @@ class Event implements IEvent {
}
/**
- * @param string $icon
- * @return $this
- * @throws \InvalidArgumentException if the icon is invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setIcon(string $icon): IEvent {
if (isset($icon[4000])) {
- throw new \InvalidArgumentException('The given icon is invalid');
+ throw new InvalidValueException('icon');
}
$this->icon = $icon;
return $this;
diff --git a/lib/private/Activity/EventMerger.php b/lib/private/Activity/EventMerger.php
index 9332d8b111a..504f9088f24 100644
--- a/lib/private/Activity/EventMerger.php
+++ b/lib/private/Activity/EventMerger.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Activity;
@@ -67,7 +48,7 @@ class EventMerger implements IEventMerger {
* @param IEvent|null $previousEvent
* @return IEvent
*/
- public function mergeEvents($mergeParameter, IEvent $event, IEvent $previousEvent = null) {
+ public function mergeEvents($mergeParameter, IEvent $event, ?IEvent $previousEvent = null) {
// No second event => can not combine
if (!$previousEvent instanceof IEvent) {
return $event;
diff --git a/lib/private/Activity/Manager.php b/lib/private/Activity/Manager.php
index a7d24510d53..8b60dc49ec9 100644
--- a/lib/private/Activity/Manager.php
+++ b/lib/private/Activity/Manager.php
@@ -1,34 +1,15 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Activity;
use OCP\Activity\ActivitySettings;
+use OCP\Activity\Exceptions\FilterNotFoundException;
+use OCP\Activity\Exceptions\IncompleteActivityException;
+use OCP\Activity\Exceptions\SettingNotFoundException;
use OCP\Activity\IConsumer;
use OCP\Activity\IEvent;
use OCP\Activity\IFilter;
@@ -70,11 +51,11 @@ class Manager implements IManager {
protected $l10n;
public function __construct(
- IRequest $request,
- IUserSession $session,
- IConfig $config,
- IValidator $validator,
- IL10N $l10n
+ IRequest $request,
+ IUserSession $session,
+ IConfig $config,
+ IValidator $validator,
+ IL10N $l10n
) {
$this->request = $request;
$this->session = $session;
@@ -127,16 +108,7 @@ class Manager implements IManager {
}
/**
- * Publish an event to the activity consumers
- *
- * Make sure to call at least the following methods before sending an Event:
- * - setApp()
- * - setType()
- * - setAffectedUser()
- * - setSubject()
- *
- * @param IEvent $event
- * @throws \BadMethodCallException if required values have not been set
+ * {@inheritDoc}
*/
public function publish(IEvent $event): void {
if ($event->getAuthor() === '') {
@@ -150,7 +122,7 @@ class Manager implements IManager {
}
if (!$event->isValid()) {
- throw new \BadMethodCallException('The given event is invalid');
+ throw new IncompleteActivityException('The given event is invalid');
}
foreach ($this->getConsumers() as $c) {
@@ -206,10 +178,7 @@ class Manager implements IManager {
}
/**
- * @param string $id
- * @return IFilter
- * @throws \InvalidArgumentException when the filter was not found
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getFilterById(string $id): IFilter {
$filters = $this->getFilters();
@@ -218,7 +187,7 @@ class Manager implements IManager {
return $filters[$id];
}
- throw new \InvalidArgumentException('Requested filter does not exist');
+ throw new FilterNotFoundException($id);
}
/** @var string[] */
@@ -294,10 +263,7 @@ class Manager implements IManager {
}
/**
- * @param string $id
- * @return ActivitySettings
- * @throws \InvalidArgumentException when the setting was not found
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getSettingById(string $id): ActivitySettings {
$settings = $this->getSettings();
@@ -306,7 +272,7 @@ class Manager implements IManager {
return $settings[$id];
}
- throw new \InvalidArgumentException('Requested setting does not exist');
+ throw new SettingNotFoundException($id);
}
@@ -346,12 +312,8 @@ class Manager implements IManager {
* Set the user we need to use
*
* @param string|null $currentUserId
- * @throws \UnexpectedValueException If the user is invalid
*/
- public function setCurrentUserId(string $currentUserId = null): void {
- if (!is_string($currentUserId) && $currentUserId !== null) {
- throw new \UnexpectedValueException('The given current user is invalid');
- }
+ public function setCurrentUserId(?string $currentUserId = null): void {
$this->currentUserId = $currentUserId;
}
diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php
index 2a0e8f53b14..d05fe440202 100644
--- a/lib/private/AllConfig.php
+++ b/lib/private/AllConfig.php
@@ -1,37 +1,12 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Loki3000 <github@labcms.ru>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author MichaIng <micha@dietpi.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
+use Doctrine\DBAL\Platforms\OraclePlatform;
use OCP\Cache\CappedMemoryCache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
@@ -42,7 +17,6 @@ use OCP\PreConditionNotMetException;
* Class to combine all the configuration options ownCloud offers
*/
class AllConfig implements IConfig {
- private SystemConfig $systemConfig;
private ?IDBConnection $connection = null;
/**
@@ -67,9 +41,10 @@ class AllConfig implements IConfig {
*/
private CappedMemoryCache $userCache;
- public function __construct(SystemConfig $systemConfig) {
+ public function __construct(
+ private SystemConfig $systemConfig
+ ) {
$this->userCache = new CappedMemoryCache();
- $this->systemConfig = $systemConfig;
}
/**
@@ -189,6 +164,7 @@ class AllConfig implements IConfig {
*
* @param string $appName the appName that we stored the value under
* @return string[] the keys stored for the app
+ * @deprecated 29.0.0 Use {@see IAppConfig} directly
*/
public function getAppKeys($appName) {
return \OC::$server->get(AppConfig::class)->getKeys($appName);
@@ -200,6 +176,7 @@ class AllConfig implements IConfig {
* @param string $appName the appName that we want to store the value under
* @param string $key the key of the value, under which will be saved
* @param string|float|int $value the value that should be stored
+ * @deprecated 29.0.0 Use {@see IAppConfig} directly
*/
public function setAppValue($appName, $key, $value) {
\OC::$server->get(AppConfig::class)->setValue($appName, $key, $value);
@@ -212,6 +189,7 @@ class AllConfig implements IConfig {
* @param string $key the key of the value, under which it was saved
* @param string $default the default value to be returned if the value isn't set
* @return string the saved value
+ * @deprecated 29.0.0 Use {@see IAppConfig} directly
*/
public function getAppValue($appName, $key, $default = '') {
return \OC::$server->get(AppConfig::class)->getValue($appName, $key, $default);
@@ -222,6 +200,7 @@ class AllConfig implements IConfig {
*
* @param string $appName the appName that we stored the value under
* @param string $key the key of the value, under which it was saved
+ * @deprecated 29.0.0 Use {@see IAppConfig} directly
*/
public function deleteAppValue($appName, $key) {
\OC::$server->get(AppConfig::class)->deleteKey($appName, $key);
@@ -231,6 +210,7 @@ class AllConfig implements IConfig {
* Removes all keys in appconfig belonging to the app
*
* @param string $appName the appName the configs are stored under
+ * @deprecated 29.0.0 Use {@see IAppConfig} directly
*/
public function deleteAppValues($appName) {
\OC::$server->get(AppConfig::class)->deleteApp($appName);
@@ -333,7 +313,7 @@ class AllConfig implements IConfig {
public function getUserKeys($userId, $appName) {
$data = $this->getAllUserValues($userId);
if (isset($data[$appName])) {
- return array_keys($data[$appName]);
+ return array_map('strval', array_keys($data[$appName]));
} else {
return [];
}
@@ -490,12 +470,15 @@ class AllConfig implements IConfig {
$this->fixDIInit();
$qb = $this->connection->getQueryBuilder();
+ $configValueColumn = ($this->connection->getDatabasePlatform() instanceof OraclePlatform)
+ ? $qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR)
+ : 'configvalue';
$result = $qb->select('userid')
->from('preferences')
->where($qb->expr()->eq('appid', $qb->createNamedParameter($appName, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq(
- $qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR),
+ $configValueColumn,
$qb->createNamedParameter($value, IQueryBuilder::PARAM_STR))
)->orderBy('userid')
->executeQuery();
@@ -524,13 +507,18 @@ class AllConfig implements IConfig {
// Email address is always stored lowercase in the database
return $this->getUsersForUserValue($appName, $key, strtolower($value));
}
+
$qb = $this->connection->getQueryBuilder();
+ $configValueColumn = ($this->connection->getDatabasePlatform() instanceof OraclePlatform)
+ ? $qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR)
+ : 'configvalue';
+
$result = $qb->select('userid')
->from('preferences')
->where($qb->expr()->eq('appid', $qb->createNamedParameter($appName, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq(
- $qb->func()->lower($qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR)),
+ $qb->func()->lower($configValueColumn),
$qb->createNamedParameter(strtolower($value), IQueryBuilder::PARAM_STR))
)->orderBy('userid')
->executeQuery();
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php
index 88044fbf7b6..99d1c913ced 100644
--- a/lib/private/App/AppManager.php
+++ b/lib/private/App/AppManager.php
@@ -1,43 +1,12 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Schaefer "christophł@wolkesicher.de"
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Daniel Rudolf <github.com@daniel-rudolf.de>
- * @author Greta Doci <gretadoci@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Haertl <jus@bitgrid.net>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Maxence Lange <maxence@artificial-owl.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tobia De Koninck <tobia@ledfan.be>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\App;
+use InvalidArgumentException;
use OC\AppConfig;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\ServerNotAvailableException;
@@ -47,14 +16,15 @@ use OCP\App\Events\AppDisableEvent;
use OCP\App\Events\AppEnableEvent;
use OCP\App\IAppManager;
use OCP\App\ManagerEvent;
-use OCP\EventDispatcher\IEventDispatcher;
use OCP\Collaboration\AutoComplete\IManager as IAutoCompleteManager;
use OCP\Collaboration\Collaborators\ISearch as ICollaboratorSearch;
use OCP\Diagnostics\IEventLogger;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
+use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Settings\IManager as ISettingsManager;
@@ -73,14 +43,6 @@ class AppManager implements IAppManager {
'prevent_group_restriction',
];
- private IUserSession $userSession;
- private IConfig $config;
- private AppConfig $appConfig;
- private IGroupManager $groupManager;
- private ICacheFactory $memCacheFactory;
- private IEventDispatcher $dispatcher;
- private LoggerInterface $logger;
-
/** @var string[] $appId => $enabled */
private array $installedAppsCache = [];
@@ -103,20 +65,57 @@ class AppManager implements IAppManager {
/** @var array<string, true> */
private array $loadedApps = [];
- public function __construct(IUserSession $userSession,
- IConfig $config,
- AppConfig $appConfig,
- IGroupManager $groupManager,
- ICacheFactory $memCacheFactory,
- IEventDispatcher $dispatcher,
- LoggerInterface $logger) {
- $this->userSession = $userSession;
- $this->config = $config;
- $this->appConfig = $appConfig;
- $this->groupManager = $groupManager;
- $this->memCacheFactory = $memCacheFactory;
- $this->dispatcher = $dispatcher;
- $this->logger = $logger;
+ private ?AppConfig $appConfig = null;
+ private ?IURLGenerator $urlGenerator = null;
+
+ /**
+ * Be extremely careful when injecting classes here. The AppManager is used by the installer,
+ * so it needs to work before installation. See how AppConfig and IURLGenerator are injected for reference
+ */
+ public function __construct(
+ private IUserSession $userSession,
+ private IConfig $config,
+ private IGroupManager $groupManager,
+ private ICacheFactory $memCacheFactory,
+ private IEventDispatcher $dispatcher,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ public function getAppIcon(string $appId, bool $dark = false): ?string {
+ $possibleIcons = $dark ? [$appId . '-dark.svg', 'app-dark.svg'] : [$appId . '.svg', 'app.svg'];
+ $icon = null;
+ foreach ($possibleIcons as $iconName) {
+ try {
+ $icon = $this->getUrlGenerator()->imagePath($appId, $iconName);
+ break;
+ } catch (\RuntimeException $e) {
+ // ignore
+ }
+ }
+ return $icon;
+ }
+
+ private function getAppConfig(): AppConfig {
+ if ($this->appConfig !== null) {
+ return $this->appConfig;
+ }
+ if (!$this->config->getSystemValueBool('installed', false)) {
+ throw new \Exception('Nextcloud is not installed yet, AppConfig is not available');
+ }
+ $this->appConfig = \OCP\Server::get(AppConfig::class);
+ return $this->appConfig;
+ }
+
+ private function getUrlGenerator(): IURLGenerator {
+ if ($this->urlGenerator !== null) {
+ return $this->urlGenerator;
+ }
+ if (!$this->config->getSystemValueBool('installed', false)) {
+ throw new \Exception('Nextcloud is not installed yet, AppConfig is not available');
+ }
+ $this->urlGenerator = \OCP\Server::get(IURLGenerator::class);
+ return $this->urlGenerator;
}
/**
@@ -124,7 +123,7 @@ class AppManager implements IAppManager {
*/
private function getInstalledAppsValues(): array {
if (!$this->installedAppsCache) {
- $values = $this->appConfig->getValues(false, 'enabled');
+ $values = $this->getAppConfig()->getValues(false, 'enabled');
$alwaysEnabledApps = $this->getAlwaysEnabledApps();
foreach ($alwaysEnabledApps as $appId) {
@@ -249,7 +248,7 @@ class AppManager implements IAppManager {
private function getAppTypes(string $app): array {
//load the cache
if (count($this->appTypes) === 0) {
- $this->appTypes = $this->appConfig->getValues(false, 'types') ?: [];
+ $this->appTypes = $this->getAppConfig()->getValues(false, 'types') ?: [];
}
if (isset($this->appTypes[$app])) {
@@ -288,7 +287,7 @@ class AppManager implements IAppManager {
* Check if an app is enabled for user
*
* @param string $appId
- * @param \OCP\IUser $user (optional) if not defined, the currently logged in user will be used
+ * @param \OCP\IUser|null $user (optional) if not defined, the currently logged in user will be used
* @return bool
*/
public function isEnabledForUser($appId, $user = null) {
@@ -537,7 +536,7 @@ class AppManager implements IAppManager {
}
$this->installedAppsCache[$appId] = 'yes';
- $this->appConfig->setValue($appId, 'enabled', 'yes');
+ $this->getAppConfig()->setValue($appId, 'enabled', 'yes');
$this->dispatcher->dispatchTyped(new AppEnableEvent($appId));
$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent(
ManagerEvent::EVENT_APP_ENABLE, $appId
@@ -591,7 +590,7 @@ class AppManager implements IAppManager {
}, $groups);
$this->installedAppsCache[$appId] = json_encode($groupIds);
- $this->appConfig->setValue($appId, 'enabled', json_encode($groupIds));
+ $this->getAppConfig()->setValue($appId, 'enabled', json_encode($groupIds));
$this->dispatcher->dispatchTyped(new AppEnableEvent($appId, $groupIds));
$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, new ManagerEvent(
ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, $appId, $groups
@@ -612,7 +611,7 @@ class AppManager implements IAppManager {
}
if ($automaticDisabled) {
- $previousSetting = $this->appConfig->getValue($appId, 'enabled', 'yes');
+ $previousSetting = $this->getAppConfig()->getValue($appId, 'enabled', 'yes');
if ($previousSetting !== 'yes' && $previousSetting !== 'no') {
$previousSetting = json_decode($previousSetting, true);
}
@@ -620,7 +619,7 @@ class AppManager implements IAppManager {
}
unset($this->installedAppsCache[$appId]);
- $this->appConfig->setValue($appId, 'enabled', 'no');
+ $this->getAppConfig()->setValue($appId, 'enabled', 'no');
// run uninstall steps
$appData = $this->getAppInfo($appId);
@@ -685,7 +684,7 @@ class AppManager implements IAppManager {
$apps = $this->getInstalledApps();
foreach ($apps as $appId) {
$appInfo = $this->getAppInfo($appId);
- $appDbVersion = $this->appConfig->getValue($appId, 'installed_version');
+ $appDbVersion = $this->getAppConfig()->getValue($appId, 'installed_version');
if ($appDbVersion
&& isset($appInfo['version'])
&& version_compare($appInfo['version'], $appDbVersion, '>')
@@ -701,10 +700,7 @@ class AppManager implements IAppManager {
/**
* Returns the app information from "appinfo/info.xml".
*
- * @param string $appId app id
- *
- * @param bool $path
- * @param null $lang
+ * @param string|null $lang
* @return array|null app info
*/
public function getAppInfo(string $appId, bool $path = false, $lang = null) {
@@ -816,22 +812,39 @@ class AppManager implements IAppManager {
/**
* @inheritdoc
*/
- public function getDefaultEnabledApps():array {
+ public function getDefaultEnabledApps(): array {
$this->loadShippedJson();
return $this->defaultEnabled;
}
- public function getDefaultAppForUser(?IUser $user = null): string {
+ public function getDefaultAppForUser(?IUser $user = null, bool $withFallbacks = true): string {
// Set fallback to always-enabled files app
- $appId = 'files';
- $defaultApps = explode(',', $this->config->getSystemValueString('defaultapp', 'dashboard,files'));
+ $appId = $withFallbacks ? 'files' : '';
+ $defaultApps = explode(',', $this->config->getSystemValueString('defaultapp', ''));
+ $defaultApps = array_filter($defaultApps);
$user ??= $this->userSession->getUser();
if ($user !== null) {
$userDefaultApps = explode(',', $this->config->getUserValue($user->getUID(), 'core', 'defaultapp'));
$defaultApps = array_filter(array_merge($userDefaultApps, $defaultApps));
+ if (empty($defaultApps) && $withFallbacks) {
+ /* Fallback on user defined apporder */
+ $customOrders = json_decode($this->config->getUserValue($user->getUID(), 'core', 'apporder', '[]'), true, flags:JSON_THROW_ON_ERROR);
+ if (!empty($customOrders)) {
+ // filter only entries with app key (when added using closures or NavigationManager::add the app is not guranteed to be set)
+ $customOrders = array_filter($customOrders, fn ($entry) => isset($entry['app']));
+ // sort apps by order
+ usort($customOrders, fn ($a, $b) => $a['order'] - $b['order']);
+ // set default apps to sorted apps
+ $defaultApps = array_map(fn ($entry) => $entry['app'], $customOrders);
+ }
+ }
+ }
+
+ if (empty($defaultApps) && $withFallbacks) {
+ $defaultApps = ['dashboard','files'];
}
// Find the first app that is enabled for the current user
@@ -845,4 +858,19 @@ class AppManager implements IAppManager {
return $appId;
}
+
+ public function getDefaultApps(): array {
+ return explode(',', $this->config->getSystemValueString('defaultapp', 'dashboard,files'));
+ }
+
+ public function setDefaultApps(array $defaultApps): void {
+ foreach ($defaultApps as $app) {
+ if (!$this->isInstalled($app)) {
+ $this->logger->debug('Can not set not installed app as default app', ['missing_app' => $app]);
+ throw new InvalidArgumentException('App is not installed');
+ }
+ }
+
+ $this->config->setSystemValue('defaultapp', join(',', $defaultApps));
+ }
}
diff --git a/lib/private/App/AppStore/Bundles/Bundle.php b/lib/private/App/AppStore/Bundles/Bundle.php
index dfc93fdfaa2..62f09b82f79 100644
--- a/lib/private/App/AppStore/Bundles/Bundle.php
+++ b/lib/private/App/AppStore/Bundles/Bundle.php
@@ -1,39 +1,19 @@
<?php
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
use OCP\IL10N;
abstract class Bundle {
- /** @var IL10N */
- protected $l10n;
-
/**
* @param IL10N $l10n
*/
- public function __construct(IL10N $l10n) {
- $this->l10n = $l10n;
+ public function __construct(
+ protected IL10N $l10n,
+ ) {
}
/**
diff --git a/lib/private/App/AppStore/Bundles/BundleFetcher.php b/lib/private/App/AppStore/Bundles/BundleFetcher.php
index 0d2bb61495f..01325699e2c 100644
--- a/lib/private/App/AppStore/Bundles/BundleFetcher.php
+++ b/lib/private/App/AppStore/Bundles/BundleFetcher.php
@@ -1,36 +1,16 @@
<?php
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
use OCP\IL10N;
class BundleFetcher {
- private IL10N $l10n;
-
- public function __construct(IL10N $l10n) {
- $this->l10n = $l10n;
+ public function __construct(
+ private IL10N $l10n,
+ ) {
}
/**
@@ -43,6 +23,7 @@ class BundleFetcher {
new GroupwareBundle($this->l10n),
new SocialSharingBundle($this->l10n),
new EducationBundle($this->l10n),
+ new PublicSectorBundle($this->l10n),
];
}
diff --git a/lib/private/App/AppStore/Bundles/EducationBundle.php b/lib/private/App/AppStore/Bundles/EducationBundle.php
index 58ffd4f83b8..a08d707b021 100644
--- a/lib/private/App/AppStore/Bundles/EducationBundle.php
+++ b/lib/private/App/AppStore/Bundles/EducationBundle.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
diff --git a/lib/private/App/AppStore/Bundles/EnterpriseBundle.php b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php
index bb64ec391ff..88a9ec60a00 100644
--- a/lib/private/App/AppStore/Bundles/EnterpriseBundle.php
+++ b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
diff --git a/lib/private/App/AppStore/Bundles/GroupwareBundle.php b/lib/private/App/AppStore/Bundles/GroupwareBundle.php
index 3a46ada52ad..7c7b74ff53d 100644
--- a/lib/private/App/AppStore/Bundles/GroupwareBundle.php
+++ b/lib/private/App/AppStore/Bundles/GroupwareBundle.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
diff --git a/lib/private/App/AppStore/Bundles/HubBundle.php b/lib/private/App/AppStore/Bundles/HubBundle.php
index d5d236a1855..354e01e25c2 100644
--- a/lib/private/App/AppStore/Bundles/HubBundle.php
+++ b/lib/private/App/AppStore/Bundles/HubBundle.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
diff --git a/lib/private/App/AppStore/Bundles/PublicSectorBundle.php b/lib/private/App/AppStore/Bundles/PublicSectorBundle.php
new file mode 100644
index 00000000000..edb86fb5ca7
--- /dev/null
+++ b/lib/private/App/AppStore/Bundles/PublicSectorBundle.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\App\AppStore\Bundles;
+
+class PublicSectorBundle extends Bundle {
+ /**
+ * {@inheritDoc}
+ */
+ public function getName(): string {
+ return $this->l10n->t('Public sector bundle');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getAppIdentifiers(): array {
+
+ return [
+ 'files_confidential',
+ 'forms',
+ 'collectives',
+ 'files_antivirus',
+ 'twofactor_nextcloud_notification',
+ 'tables',
+ 'richdocuments',
+ 'admin_audit',
+ 'files_retention',
+ ];
+ }
+
+}
diff --git a/lib/private/App/AppStore/Bundles/SocialSharingBundle.php b/lib/private/App/AppStore/Bundles/SocialSharingBundle.php
index f823792745b..7f925688ca3 100644
--- a/lib/private/App/AppStore/Bundles/SocialSharingBundle.php
+++ b/lib/private/App/AppStore/Bundles/SocialSharingBundle.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Bundles;
diff --git a/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php b/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php
new file mode 100644
index 00000000000..1174c7d240b
--- /dev/null
+++ b/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\App\AppStore\Fetcher;
+
+use DateTimeImmutable;
+use OC\App\CompareVersion;
+use OC\Files\AppData\Factory;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
+use OCP\Support\Subscription\IRegistry;
+use Psr\Log\LoggerInterface;
+
+class AppDiscoverFetcher extends Fetcher {
+
+ public const INVALIDATE_AFTER_SECONDS = 86400;
+
+ public function __construct(
+ Factory $appDataFactory,
+ IClientService $clientService,
+ ITimeFactory $timeFactory,
+ IConfig $config,
+ LoggerInterface $logger,
+ IRegistry $registry,
+ private CompareVersion $compareVersion,
+ ) {
+ parent::__construct(
+ $appDataFactory,
+ $clientService,
+ $timeFactory,
+ $config,
+ $logger,
+ $registry
+ );
+
+ $this->fileName = 'discover.json';
+ $this->endpointName = 'discover.json';
+ }
+
+ /**
+ * Get the app discover section entries
+ *
+ * @param bool $allowUnstable Include also upcoming entries
+ */
+ public function get($allowUnstable = false) {
+ $entries = parent::get(false);
+ $now = new DateTimeImmutable();
+
+ return array_filter($entries, function (array $entry) use ($now, $allowUnstable) {
+ // Always remove expired entries
+ if (isset($entry['expiryDate'])) {
+ try {
+ $expiryDate = new DateTimeImmutable($entry['expiryDate']);
+ if ($expiryDate < $now) {
+ return false;
+ }
+ } catch (\Throwable $e) {
+ // Invalid expiryDate format
+ return false;
+ }
+ }
+
+ // If not include upcoming entries, check for upcoming dates and remove those entries
+ if (!$allowUnstable && isset($entry['date'])) {
+ try {
+ $date = new DateTimeImmutable($entry['date']);
+ if ($date > $now) {
+ return false;
+ }
+ } catch (\Throwable $e) {
+ // Invalid date format
+ return false;
+ }
+ }
+ // Otherwise the entry is not time limited and should stay
+ return true;
+ });
+ }
+
+ public function getETag(): string|null {
+ $rootFolder = $this->appData->getFolder('/');
+
+ try {
+ $file = $rootFolder->getFile($this->fileName);
+ $jsonBlob = json_decode($file->getContent(), true);
+
+ if (is_array($jsonBlob) && isset($jsonBlob['ETag'])) {
+ return (string)$jsonBlob['ETag'];
+ }
+ } catch (\Throwable $e) {
+ // ignore
+ }
+ return null;
+ }
+}
diff --git a/lib/private/App/AppStore/Fetcher/AppFetcher.php b/lib/private/App/AppStore/Fetcher/AppFetcher.php
index 47bdece372d..508a5dae8f7 100644
--- a/lib/private/App/AppStore/Fetcher/AppFetcher.php
+++ b/lib/private/App/AppStore/Fetcher/AppFetcher.php
@@ -1,31 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Jakub Onderka <ahoj@jakubonderka.cz>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Fetcher;
@@ -39,22 +15,17 @@ use OCP\Support\Subscription\IRegistry;
use Psr\Log\LoggerInterface;
class AppFetcher extends Fetcher {
- /** @var CompareVersion */
- private $compareVersion;
-
- /** @var IRegistry */
- protected $registry;
-
/** @var bool */
private $ignoreMaxVersion;
public function __construct(Factory $appDataFactory,
- IClientService $clientService,
- ITimeFactory $timeFactory,
- IConfig $config,
- CompareVersion $compareVersion,
- LoggerInterface $logger,
- IRegistry $registry) {
+ IClientService $clientService,
+ ITimeFactory $timeFactory,
+ IConfig $config,
+ private CompareVersion $compareVersion,
+ LoggerInterface $logger,
+ protected IRegistry $registry,
+ ) {
parent::__construct(
$appDataFactory,
$clientService,
@@ -64,9 +35,6 @@ class AppFetcher extends Fetcher {
$registry
);
- $this->compareVersion = $compareVersion;
- $this->registry = $registry;
-
$this->fileName = 'apps.json';
$this->endpointName = 'apps.json';
$this->ignoreMaxVersion = true;
diff --git a/lib/private/App/AppStore/Fetcher/CategoryFetcher.php b/lib/private/App/AppStore/Fetcher/CategoryFetcher.php
index afe051e6281..d72f8fa7e24 100644
--- a/lib/private/App/AppStore/Fetcher/CategoryFetcher.php
+++ b/lib/private/App/AppStore/Fetcher/CategoryFetcher.php
@@ -1,28 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Fetcher;
@@ -34,12 +13,14 @@ use OCP\Support\Subscription\IRegistry;
use Psr\Log\LoggerInterface;
class CategoryFetcher extends Fetcher {
- public function __construct(Factory $appDataFactory,
- IClientService $clientService,
- ITimeFactory $timeFactory,
- IConfig $config,
- LoggerInterface $logger,
- IRegistry $registry) {
+ public function __construct(
+ Factory $appDataFactory,
+ IClientService $clientService,
+ ITimeFactory $timeFactory,
+ IConfig $config,
+ LoggerInterface $logger,
+ IRegistry $registry,
+ ) {
parent::__construct(
$appDataFactory,
$clientService,
diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php
index 095b026cb44..ad76befc5fa 100644
--- a/lib/private/App/AppStore/Fetcher/Fetcher.php
+++ b/lib/private/App/AppStore/Fetcher/Fetcher.php
@@ -1,32 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Steffen Lindner <mail@steffen-lindner.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Fetcher;
@@ -44,19 +19,10 @@ use Psr\Log\LoggerInterface;
abstract class Fetcher {
public const INVALIDATE_AFTER_SECONDS = 3600;
public const RETRY_AFTER_FAILURE_SECONDS = 300;
+ public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1';
/** @var IAppData */
protected $appData;
- /** @var IClientService */
- protected $clientService;
- /** @var ITimeFactory */
- protected $timeFactory;
- /** @var IConfig */
- protected $config;
- /** @var LoggerInterface */
- protected $logger;
- /** @var IRegistry */
- protected $registry;
/** @var string */
protected $fileName;
@@ -67,18 +33,15 @@ abstract class Fetcher {
/** @var ?string */
protected $channel = null;
- public function __construct(Factory $appDataFactory,
- IClientService $clientService,
- ITimeFactory $timeFactory,
- IConfig $config,
- LoggerInterface $logger,
- IRegistry $registry) {
+ public function __construct(
+ Factory $appDataFactory,
+ protected IClientService $clientService,
+ protected ITimeFactory $timeFactory,
+ protected IConfig $config,
+ protected LoggerInterface $logger,
+ protected IRegistry $registry,
+ ) {
$this->appData = $appDataFactory->get('appstore');
- $this->clientService = $clientService;
- $this->timeFactory = $timeFactory;
- $this->config = $config;
- $this->logger = $logger;
- $this->registry = $registry;
}
/**
@@ -109,10 +72,13 @@ abstract class Fetcher {
];
}
- // If we have a valid subscription key, send it to the appstore
- $subscriptionKey = $this->config->getAppValue('support', 'subscription_key');
- if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) {
- $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey;
+ if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) {
+ // If we have a valid subscription key, send it to the appstore
+ $subscriptionKey = $this->config->getAppValue('support', 'subscription_key');
+ if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) {
+ $options['headers'] ??= [];
+ $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey;
+ }
}
$client = $this->clientService->newClient();
@@ -142,7 +108,7 @@ abstract class Fetcher {
}
/**
- * Returns the array with the categories on the appstore server
+ * Returns the array with the entries on the appstore server
*
* @param bool [$allowUnstable] Allow unstable releases
* @return array
@@ -150,8 +116,9 @@ abstract class Fetcher {
public function get($allowUnstable = false) {
$appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true);
$internetavailable = $this->config->getSystemValueBool('has_internet_connection', true);
+ $isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL;
- if (!$appstoreenabled || !$internetavailable) {
+ if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) {
return [];
}
@@ -189,7 +156,7 @@ abstract class Fetcher {
try {
$responseJson = $this->fetch($ETag, $content, $allowUnstable);
- if (empty($responseJson)) {
+ if (empty($responseJson) || empty($responseJson['data'])) {
return [];
}
diff --git a/lib/private/App/AppStore/Version/Version.php b/lib/private/App/AppStore/Version/Version.php
index d41ca1770f0..b7e679d250a 100644
--- a/lib/private/App/AppStore/Version/Version.php
+++ b/lib/private/App/AppStore/Version/Version.php
@@ -1,40 +1,19 @@
<?php
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Version;
class Version {
- /** @var string */
- private $minVersion;
- /** @var string */
- private $maxVersion;
-
/**
* @param string $minVersion
* @param string $maxVersion
*/
- public function __construct($minVersion, $maxVersion) {
- $this->minVersion = $minVersion;
- $this->maxVersion = $maxVersion;
+ public function __construct(
+ private string $minVersion,
+ private string $maxVersion,
+ ) {
}
/**
diff --git a/lib/private/App/AppStore/Version/VersionParser.php b/lib/private/App/AppStore/Version/VersionParser.php
index 2b88399b9fd..59715c8d385 100644
--- a/lib/private/App/AppStore/Version/VersionParser.php
+++ b/lib/private/App/AppStore/Version/VersionParser.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App\AppStore\Version;
@@ -54,9 +35,9 @@ class VersionParser {
// Count the amount of =, if it is one then it's either maximum or minimum
// version. If it is two then it is maximum and minimum.
$versionElements = explode(' ', $versionSpec);
- $firstVersion = isset($versionElements[0]) ? $versionElements[0] : '';
+ $firstVersion = $versionElements[0] ?? '';
$firstVersionNumber = substr($firstVersion, 2);
- $secondVersion = isset($versionElements[1]) ? $versionElements[1] : '';
+ $secondVersion = $versionElements[1] ?? '';
$secondVersionNumber = substr($secondVersion, 2);
switch (count($versionElements)) {
diff --git a/lib/private/App/CompareVersion.php b/lib/private/App/CompareVersion.php
index a349c7aa6f2..7edc3e565b1 100644
--- a/lib/private/App/CompareVersion.php
+++ b/lib/private/App/CompareVersion.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\App;
diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php
index 3bdc551ea5a..d963c74de79 100644
--- a/lib/private/App/DependencyAnalyzer.php
+++ b/lib/private/App/DependencyAnalyzer.php
@@ -1,42 +1,14 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\App;
use OCP\IL10N;
class DependencyAnalyzer {
- /** @var Platform */
- private $platform;
- /** @var \OCP\IL10N */
- private $l;
/** @var array */
private $appInfo;
@@ -44,9 +16,10 @@ class DependencyAnalyzer {
* @param Platform $platform
* @param \OCP\IL10N $l
*/
- public function __construct(Platform $platform, IL10N $l) {
- $this->platform = $platform;
- $this->l = $l;
+ public function __construct(
+ private Platform $platform,
+ private IL10N $l,
+ ) {
}
/**
diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php
index 79d051fd2a1..d29b1d6596d 100644
--- a/lib/private/App/InfoParser.php
+++ b/lib/private/App/InfoParser.php
@@ -1,47 +1,21 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\App;
use OCP\ICache;
-use function libxml_disable_entity_loader;
use function simplexml_load_string;
class InfoParser {
- /** @var \OCP\ICache|null */
- private $cache;
-
/**
* @param ICache|null $cache
*/
- public function __construct(ICache $cache = null) {
- $this->cache = $cache;
+ public function __construct(
+ private ?ICache $cache = null,
+ ) {
}
/**
@@ -61,13 +35,7 @@ class InfoParser {
}
libxml_use_internal_errors(true);
- if ((PHP_VERSION_ID < 80000)) {
- $loadEntities = libxml_disable_entity_loader(false);
- $xml = simplexml_load_string(file_get_contents($file));
- libxml_disable_entity_loader($loadEntities);
- } else {
- $xml = simplexml_load_string(file_get_contents($file));
- }
+ $xml = simplexml_load_string(file_get_contents($file));
if ($xml === false) {
libxml_clear_errors();
@@ -272,7 +240,7 @@ class InfoParser {
} else {
$array[$element] = $data;
}
- // Just a value
+ // Just a value
} else {
if ($totalElement > 1) {
$array[$element][] = $this->xmlToArray($node);
diff --git a/lib/private/App/Platform.php b/lib/private/App/Platform.php
index 1cab740bebb..c2c059220c8 100644
--- a/lib/private/App/Platform.php
+++ b/lib/private/App/Platform.php
@@ -1,32 +1,13 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\App;
-use OCP\IConfig;
use OCP\IBinaryFinder;
+use OCP\IConfig;
/**
* Class Platform
@@ -36,10 +17,9 @@ use OCP\IBinaryFinder;
* @package OC\App
*/
class Platform {
- private IConfig $config;
-
- public function __construct(IConfig $config) {
- $this->config = $config;
+ public function __construct(
+ private IConfig $config,
+ ) {
}
public function getPhpVersion(): string {
diff --git a/lib/private/App/PlatformRepository.php b/lib/private/App/PlatformRepository.php
index 9b94c0b07bc..6d9a9cd011a 100644
--- a/lib/private/App/PlatformRepository.php
+++ b/lib/private/App/PlatformRepository.php
@@ -1,24 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\App;
@@ -154,7 +138,7 @@ class PlatformRepository {
*/
public function normalizeVersion(string $version, ?string $fullVersion = null): string {
$version = trim($version);
- if (null === $fullVersion) {
+ if ($fullVersion === null) {
$fullVersion = $version;
}
// ignore aliases and just assume the alias is required instead of the source
@@ -165,7 +149,7 @@ class PlatformRepository {
if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
return '9999999-dev';
}
- if ('dev-' === strtolower(substr($version, 0, 4))) {
+ if (strtolower(substr($version, 0, 4)) === 'dev-') {
return 'dev-' . substr($version, 4);
}
// match classical versioning
@@ -188,7 +172,7 @@ class PlatformRepository {
// add version modifiers if a version was matched
if (isset($index)) {
if (!empty($matches[$index])) {
- if ('stable' === $matches[$index]) {
+ if ($matches[$index] === 'stable') {
return $version;
}
$version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? $matches[$index + 1] : '');
diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php
index 84f0d5b9e5a..d046557e42c 100644
--- a/lib/private/AppConfig.php
+++ b/lib/private/AppConfig.php
@@ -1,383 +1,1356 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017, Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author michaelletzgus <michaelletzgus@users.noreply.github.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
+
namespace OC;
-use OC\DB\Connection;
-use OC\DB\OracleConnection;
+use InvalidArgumentException;
+use JsonException;
+use OCP\DB\Exception as DBException;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Exceptions\AppConfigIncorrectTypeException;
+use OCP\Exceptions\AppConfigTypeConflictException;
+use OCP\Exceptions\AppConfigUnknownKeyException;
use OCP\IAppConfig;
use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\Security\ICrypto;
+use Psr\Log\LoggerInterface;
/**
* This class provides an easy way for apps to store config values in the
* database.
+ *
+ * **Note:** since 29.0.0, it supports **lazy loading**
+ *
+ * ### What is lazy loading ?
+ * In order to avoid loading useless config values into memory for each request,
+ * only non-lazy values are now loaded.
+ *
+ * Once a value that is lazy is requested, all lazy values will be loaded.
+ *
+ * Similarly, some methods from this class are marked with a warning about ignoring
+ * lazy loading. Use them wisely and only on parts of the code that are called
+ * during specific requests or actions to avoid loading the lazy values all the time.
+ *
+ * @since 7.0.0
+ * @since 29.0.0 - Supporting types and lazy loading
*/
class AppConfig implements IAppConfig {
- /** @var array[] */
- protected $sensitiveValues = [
- 'circles' => [
- '/^key_pairs$/',
- '/^local_gskey$/',
- ],
- 'external' => [
- '/^sites$/',
- ],
- 'integration_discourse' => [
- '/^private_key$/',
- '/^public_key$/',
- ],
- 'integration_dropbox' => [
- '/^client_id$/',
- '/^client_secret$/',
- ],
- 'integration_github' => [
- '/^client_id$/',
- '/^client_secret$/',
- ],
- 'integration_gitlab' => [
- '/^client_id$/',
- '/^client_secret$/',
- '/^oauth_instance_url$/',
- ],
- 'integration_google' => [
- '/^client_id$/',
- '/^client_secret$/',
- ],
- 'integration_jira' => [
- '/^client_id$/',
- '/^client_secret$/',
- '/^forced_instance_url$/',
- ],
- 'integration_onedrive' => [
- '/^client_id$/',
- '/^client_secret$/',
- ],
- 'integration_openproject' => [
- '/^client_id$/',
- '/^client_secret$/',
- '/^oauth_instance_url$/',
- ],
- 'integration_reddit' => [
- '/^client_id$/',
- '/^client_secret$/',
- ],
- 'integration_suitecrm' => [
- '/^client_id$/',
- '/^client_secret$/',
- '/^oauth_instance_url$/',
- ],
- 'integration_twitter' => [
- '/^consumer_key$/',
- '/^consumer_secret$/',
- '/^followed_user$/',
- ],
- 'integration_zammad' => [
- '/^client_id$/',
- '/^client_secret$/',
- '/^oauth_instance_url$/',
- ],
- 'notify_push' => [
- '/^cookie$/',
- ],
- 'spreed' => [
- '/^bridge_bot_password$/',
- '/^hosted-signaling-server-(.*)$/',
- '/^recording_servers$/',
- '/^signaling_servers$/',
- '/^signaling_ticket_secret$/',
- '/^signaling_token_privkey_(.*)$/',
- '/^signaling_token_pubkey_(.*)$/',
- '/^sip_bridge_dialin_info$/',
- '/^sip_bridge_shared_secret$/',
- '/^stun_servers$/',
- '/^turn_servers$/',
- '/^turn_server_secret$/',
- ],
- 'support' => [
- '/^last_response$/',
- '/^potential_subscription_key$/',
- '/^subscription_key$/',
- ],
- 'theming' => [
- '/^imprintUrl$/',
- '/^privacyUrl$/',
- '/^slogan$/',
- '/^url$/',
- ],
- 'user_ldap' => [
- '/^(s..)?ldap_agent_password$/',
- ],
- 'user_saml' => [
- '/^idp-x509cert$/',
- ],
- ];
-
- /** @var Connection */
- protected $conn;
-
- /** @var array[] */
- private $cache = [];
-
- /** @var bool */
- private $configLoaded = false;
-
- /**
- * @param Connection $conn
- */
- public function __construct(Connection $conn) {
- $this->conn = $conn;
+ private const APP_MAX_LENGTH = 32;
+ private const KEY_MAX_LENGTH = 64;
+ private const ENCRYPTION_PREFIX = '$AppConfigEncryption$';
+ private const ENCRYPTION_PREFIX_LENGTH = 21; // strlen(self::ENCRYPTION_PREFIX)
+
+ /** @var array<string, array<string, mixed>> ['app_id' => ['config_key' => 'config_value']] */
+ private array $fastCache = []; // cache for normal config keys
+ /** @var array<string, array<string, mixed>> ['app_id' => ['config_key' => 'config_value']] */
+ private array $lazyCache = []; // cache for lazy config keys
+ /** @var array<string, array<string, int>> ['app_id' => ['config_key' => bitflag]] */
+ private array $valueTypes = []; // type for all config values
+ private bool $fastLoaded = false;
+ private bool $lazyLoaded = false;
+
+ /**
+ * $migrationCompleted is only needed to manage the previous structure
+ * of the database during the upgrading process to nc29.
+ *
+ * only when upgrading from a version prior 28.0.2
+ *
+ * @TODO: remove this value in Nextcloud 30+
+ */
+ private bool $migrationCompleted = true;
+
+ public function __construct(
+ protected IDBConnection $connection,
+ protected LoggerInterface $logger,
+ protected ICrypto $crypto,
+ ) {
}
/**
- * @param string $app
- * @return array
+ * @inheritDoc
+ *
+ * @return string[] list of app ids
+ * @since 7.0.0
+ */
+ public function getApps(): array {
+ $this->loadConfigAll();
+ $apps = array_merge(array_keys($this->fastCache), array_keys($this->lazyCache));
+ sort($apps);
+
+ return array_values(array_unique($apps));
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ *
+ * @return string[] list of stored config keys
+ * @since 29.0.0
+ */
+ public function getKeys(string $app): array {
+ $this->assertParams($app);
+ $this->loadConfigAll();
+ $keys = array_merge(array_keys($this->fastCache[$app] ?? []), array_keys($this->lazyCache[$app] ?? []));
+ sort($keys);
+
+ return array_values(array_unique($keys));
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param bool|null $lazy TRUE to search within lazy loaded config, NULL to search within all config
+ *
+ * @return bool TRUE if key exists
+ * @since 7.0.0
+ * @since 29.0.0 Added the $lazy argument
*/
- private function getAppValues($app) {
- $this->loadConfigValues();
+ public function hasKey(string $app, string $key, ?bool $lazy = false): bool {
+ $this->assertParams($app, $key);
+ $this->loadConfig($lazy);
- if (isset($this->cache[$app])) {
- return $this->cache[$app];
+ if ($lazy === null) {
+ $appCache = $this->getAllValues($app);
+ return isset($appCache[$key]);
}
- return [];
+ if ($lazy) {
+ return isset($this->lazyCache[$app][$key]);
+ }
+
+ return isset($this->fastCache[$app][$key]);
}
/**
- * Get all apps using the config
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param bool|null $lazy TRUE to search within lazy loaded config, NULL to search within all config
*
- * @return string[] an array of app ids
+ * @return bool
+ * @throws AppConfigUnknownKeyException if config key is not known
+ * @since 29.0.0
+ */
+ public function isSensitive(string $app, string $key, ?bool $lazy = false): bool {
+ $this->assertParams($app, $key);
+ $this->loadConfig($lazy);
+
+ if (!isset($this->valueTypes[$app][$key])) {
+ throw new AppConfigUnknownKeyException('unknown config key');
+ }
+
+ return $this->isTyped(self::VALUE_SENSITIVE, $this->valueTypes[$app][$key]);
+ }
+
+ /**
+ * @inheritDoc
*
- * This function returns a list of all apps that have at least one
- * entry in the appconfig table.
+ * @param string $app if of the app
+ * @param string $key config key
+ *
+ * @return bool TRUE if config is lazy loaded
+ * @throws AppConfigUnknownKeyException if config key is not known
+ * @see IAppConfig for details about lazy loading
+ * @since 29.0.0
*/
- public function getApps() {
- $this->loadConfigValues();
+ public function isLazy(string $app, string $key): bool {
+ // there is a huge probability the non-lazy config are already loaded
+ if ($this->hasKey($app, $key, false)) {
+ return false;
+ }
- return $this->getSortedKeys($this->cache);
+ // key not found, we search in the lazy config
+ if ($this->hasKey($app, $key, true)) {
+ return true;
+ }
+
+ throw new AppConfigUnknownKeyException('unknown config key');
}
+
/**
- * Get the available keys for an app
+ * @inheritDoc
*
- * @param string $app the app we are looking for
- * @return array an array of key names
+ * @param string $app id of the app
+ * @param string $prefix config keys prefix to search
+ * @param bool $filtered TRUE to hide sensitive config values. Value are replaced by {@see IConfig::SENSITIVE_VALUE}
*
- * This function gets all keys of an app. Please note that the values are
- * not returned.
+ * @return array<string, string|int|float|bool|array> [configKey => configValue]
+ * @since 29.0.0
*/
- public function getKeys($app) {
- $this->loadConfigValues();
+ public function getAllValues(string $app, string $prefix = '', bool $filtered = false): array {
+ $this->assertParams($app, $prefix);
+ // if we want to filter values, we need to get sensitivity
+ $this->loadConfigAll();
+ // array_merge() will remove numeric keys (here config keys), so addition arrays instead
+ $values = $this->formatAppValues($app, ($this->fastCache[$app] ?? []) + ($this->lazyCache[$app] ?? []));
+ $values = array_filter(
+ $values,
+ function (string $key) use ($prefix): bool {
+ return str_starts_with($key, $prefix); // filter values based on $prefix
+ }, ARRAY_FILTER_USE_KEY
+ );
- if (isset($this->cache[$app])) {
- return $this->getSortedKeys($this->cache[$app]);
+ if (!$filtered) {
+ return $values;
}
- return [];
+ /**
+ * Using the old (deprecated) list of sensitive values.
+ */
+ foreach ($this->getSensitiveKeys($app) as $sensitiveKeyExp) {
+ $sensitiveKeys = preg_grep($sensitiveKeyExp, array_keys($values));
+ foreach ($sensitiveKeys as $sensitiveKey) {
+ $this->valueTypes[$app][$sensitiveKey] = ($this->valueTypes[$app][$sensitiveKey] ?? 0) | self::VALUE_SENSITIVE;
+ }
+ }
+
+ $result = [];
+ foreach ($values as $key => $value) {
+ $result[$key] = $this->isTyped(self::VALUE_SENSITIVE, $this->valueTypes[$app][$key] ?? 0) ? IConfig::SENSITIVE_VALUE : $value;
+ }
+
+ return $result;
}
- public function getSortedKeys($data) {
- $keys = array_keys($data);
- sort($keys);
- return $keys;
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param bool $lazy search within lazy loaded config
+ * @param int|null $typedAs enforce type for the returned values ({@see self::VALUE_STRING} and others)
+ *
+ * @return array<string, string|int|float|bool|array> [appId => configValue]
+ * @since 29.0.0
+ */
+ public function searchValues(string $key, bool $lazy = false, ?int $typedAs = null): array {
+ $this->assertParams('', $key, true);
+ $this->loadConfig($lazy);
+
+ /** @var array<array-key, array<array-key, mixed>> $cache */
+ if ($lazy) {
+ $cache = $this->lazyCache;
+ } else {
+ $cache = $this->fastCache;
+ }
+
+ $values = [];
+ foreach (array_keys($cache) as $app) {
+ if (isset($cache[$app][$key])) {
+ $values[$app] = $this->convertTypedValue($cache[$app][$key], $typedAs ?? $this->getValueType((string)$app, $key, $lazy));
+ }
+ }
+
+ return $values;
}
+
/**
- * Gets the config value
+ * Get the config value as string.
+ * If the value does not exist the given default will be returned.
+ *
+ * Set lazy to `null` to ignore it and get the value from either source.
+ *
+ * **WARNING:** Method is internal and **SHOULD** not be used, as it is better to get the value with a type.
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param string $default config value
+ * @param null|bool $lazy get config as lazy loaded or not. can be NULL
*
- * @param string $app app
- * @param string $key key
- * @param string $default = null, default value if the key does not exist
* @return string the value or $default
+ * @internal
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ * @see getValueString()
+ * @see getValueInt()
+ * @see getValueFloat()
+ * @see getValueBool()
+ * @see getValueArray()
+ */
+ public function getValueMixed(
+ string $app,
+ string $key,
+ string $default = '',
+ ?bool $lazy = false
+ ): string {
+ try {
+ $lazy = ($lazy === null) ? $this->isLazy($app, $key) : $lazy;
+ } catch (AppConfigUnknownKeyException $e) {
+ return $default;
+ }
+
+ return $this->getTypedValue(
+ $app,
+ $key,
+ $default,
+ $lazy,
+ self::VALUE_MIXED
+ );
+ }
+
+ /**
+ * @inheritDoc
*
- * This function gets a value from the appconfig table. If the key does
- * not exist the default value will be returned
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param string $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return string stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
*/
- public function getValue($app, $key, $default = null) {
- $this->loadConfigValues();
+ public function getValueString(
+ string $app,
+ string $key,
+ string $default = '',
+ bool $lazy = false
+ ): string {
+ return $this->getTypedValue($app, $key, $default, $lazy, self::VALUE_STRING);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param int $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return int stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function getValueInt(
+ string $app,
+ string $key,
+ int $default = 0,
+ bool $lazy = false
+ ): int {
+ return (int)$this->getTypedValue($app, $key, (string)$default, $lazy, self::VALUE_INT);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param float $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return float stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function getValueFloat(string $app, string $key, float $default = 0, bool $lazy = false): float {
+ return (float)$this->getTypedValue($app, $key, (string)$default, $lazy, self::VALUE_FLOAT);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param bool $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return bool stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function getValueBool(string $app, string $key, bool $default = false, bool $lazy = false): bool {
+ $b = strtolower($this->getTypedValue($app, $key, $default ? 'true' : 'false', $lazy, self::VALUE_BOOL));
+ return in_array($b, ['1', 'true', 'yes', 'on']);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param array $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return array stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function getValueArray(
+ string $app,
+ string $key,
+ array $default = [],
+ bool $lazy = false
+ ): array {
+ try {
+ $defaultJson = json_encode($default, JSON_THROW_ON_ERROR);
+ $value = json_decode($this->getTypedValue($app, $key, $defaultJson, $lazy, self::VALUE_ARRAY), true, flags: JSON_THROW_ON_ERROR);
- if ($this->hasKey($app, $key)) {
- return $this->cache[$app][$key];
+ return is_array($value) ? $value : [];
+ } catch (JsonException) {
+ return [];
}
+ }
- return $default;
+ /**
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param string $default default value
+ * @param bool $lazy search within lazy loaded config
+ * @param int $type value type {@see VALUE_STRING} {@see VALUE_INT}{@see VALUE_FLOAT} {@see VALUE_BOOL} {@see VALUE_ARRAY}
+ *
+ * @return string
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @throws InvalidArgumentException
+ */
+ private function getTypedValue(
+ string $app,
+ string $key,
+ string $default,
+ bool $lazy,
+ int $type
+ ): string {
+ $this->assertParams($app, $key, valueType: $type);
+ $this->loadConfig($lazy);
+
+ /**
+ * We ignore check if mixed type is requested.
+ * If type of stored value is set as mixed, we don't filter.
+ * If type of stored value is defined, we compare with the one requested.
+ */
+ $knownType = $this->valueTypes[$app][$key] ?? 0;
+ if (!$this->isTyped(self::VALUE_MIXED, $type)
+ && $knownType > 0
+ && !$this->isTyped(self::VALUE_MIXED, $knownType)
+ && !$this->isTyped($type, $knownType)) {
+ $this->logger->warning('conflict with value type from database', ['app' => $app, 'key' => $key, 'type' => $type, 'knownType' => $knownType]);
+ throw new AppConfigTypeConflictException('conflict with value type from database');
+ }
+
+ /**
+ * - the pair $app/$key cannot exist in both array,
+ * - we should still return an existing non-lazy value even if current method
+ * is called with $lazy is true
+ *
+ * This way, lazyCache will be empty until the load for lazy config value is requested.
+ */
+ if (isset($this->lazyCache[$app][$key])) {
+ $value = $this->lazyCache[$app][$key];
+ } elseif (isset($this->fastCache[$app][$key])) {
+ $value = $this->fastCache[$app][$key];
+ } else {
+ return $default;
+ }
+
+ $sensitive = $this->isTyped(self::VALUE_SENSITIVE, $knownType);
+ if ($sensitive && str_starts_with($value, self::ENCRYPTION_PREFIX)) {
+ // Only decrypt values that are stored encrypted
+ $value = $this->crypto->decrypt(substr($value, self::ENCRYPTION_PREFIX_LENGTH));
+ }
+
+ return $value;
}
/**
- * check if a key is set in the appconfig
+ * @inheritDoc
*
- * @param string $app
- * @param string $key
- * @return bool
+ * @param string $app id of the app
+ * @param string $key config key
+ *
+ * @return int type of the value
+ * @throws AppConfigUnknownKeyException if config key is not known
+ * @since 29.0.0
+ * @see VALUE_STRING
+ * @see VALUE_INT
+ * @see VALUE_FLOAT
+ * @see VALUE_BOOL
+ * @see VALUE_ARRAY
+ */
+ public function getValueType(string $app, string $key, ?bool $lazy = null): int {
+ $this->assertParams($app, $key);
+ $this->loadConfig($lazy);
+
+ if (!isset($this->valueTypes[$app][$key])) {
+ throw new AppConfigUnknownKeyException('unknown config key');
+ }
+
+ $type = $this->valueTypes[$app][$key];
+ $type &= ~self::VALUE_SENSITIVE;
+ return $type;
+ }
+
+
+ /**
+ * Store a config key and its value in database as VALUE_MIXED
+ *
+ * **WARNING:** Method is internal and **MUST** not be used as it is best to set a real value type
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param string $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED
+ * @internal
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ * @see setValueString()
+ * @see setValueInt()
+ * @see setValueFloat()
+ * @see setValueBool()
+ * @see setValueArray()
*/
- public function hasKey($app, $key) {
- $this->loadConfigValues();
+ public function setValueMixed(
+ string $app,
+ string $key,
+ string $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->setTypedValue(
+ $app,
+ $key,
+ $value,
+ $lazy,
+ self::VALUE_MIXED | ($sensitive ? self::VALUE_SENSITIVE : 0)
+ );
+ }
- return isset($this->cache[$app][$key]);
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param string $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function setValueString(
+ string $app,
+ string $key,
+ string $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->setTypedValue(
+ $app,
+ $key,
+ $value,
+ $lazy,
+ self::VALUE_STRING | ($sensitive ? self::VALUE_SENSITIVE : 0)
+ );
}
/**
- * Sets a value. If the key did not exist before it will be created.
+ * @inheritDoc
*
- * @param string $app app
- * @param string $key key
- * @param string|float|int $value value
- * @return bool True if the value was inserted or updated, false if the value was the same
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param int $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
*/
- public function setValue($app, $key, $value) {
- if (!$this->hasKey($app, $key)) {
- $inserted = (bool) $this->conn->insertIfNotExist('*PREFIX*appconfig', [
- 'appid' => $app,
- 'configkey' => $key,
- 'configvalue' => $value,
- ], [
- 'appid',
- 'configkey',
- ]);
-
- if ($inserted) {
- if (!isset($this->cache[$app])) {
- $this->cache[$app] = [];
+ public function setValueInt(
+ string $app,
+ string $key,
+ int $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ if ($value > 2000000000) {
+ $this->logger->debug('You are trying to store an integer value around/above 2,147,483,647. This is a reminder that reaching this theoretical limit on 32 bits system will throw an exception.');
+ }
+
+ return $this->setTypedValue(
+ $app,
+ $key,
+ (string)$value,
+ $lazy,
+ self::VALUE_INT | ($sensitive ? self::VALUE_SENSITIVE : 0)
+ );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param float $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function setValueFloat(
+ string $app,
+ string $key,
+ float $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->setTypedValue(
+ $app,
+ $key,
+ (string)$value,
+ $lazy,
+ self::VALUE_FLOAT | ($sensitive ? self::VALUE_SENSITIVE : 0)
+ );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param bool $value config value
+ * @param bool $lazy set config as lazy loaded
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function setValueBool(
+ string $app,
+ string $key,
+ bool $value,
+ bool $lazy = false
+ ): bool {
+ return $this->setTypedValue(
+ $app,
+ $key,
+ ($value) ? '1' : '0',
+ $lazy,
+ self::VALUE_BOOL
+ );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param array $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @throws JsonException
+ * @since 29.0.0
+ * @see IAppConfig for explanation about lazy loading
+ */
+ public function setValueArray(
+ string $app,
+ string $key,
+ array $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ try {
+ return $this->setTypedValue(
+ $app,
+ $key,
+ json_encode($value, JSON_THROW_ON_ERROR),
+ $lazy,
+ self::VALUE_ARRAY | ($sensitive ? self::VALUE_SENSITIVE : 0)
+ );
+ } catch (JsonException $e) {
+ $this->logger->warning('could not setValueArray', ['app' => $app, 'key' => $key, 'exception' => $e]);
+ throw $e;
+ }
+ }
+
+ /**
+ * Store a config key and its value in database
+ *
+ * If config key is already known with the exact same config value and same sensitive/lazy status, the
+ * database is not updated. If config value was previously stored as sensitive, status will not be
+ * altered.
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param string $value config value
+ * @param bool $lazy config set as lazy loaded
+ * @param int $type value type {@see VALUE_STRING} {@see VALUE_INT} {@see VALUE_FLOAT} {@see VALUE_BOOL} {@see VALUE_ARRAY}
+ *
+ * @return bool TRUE if value was updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @see IAppConfig for explanation about lazy loading
+ */
+ private function setTypedValue(
+ string $app,
+ string $key,
+ string $value,
+ bool $lazy,
+ int $type
+ ): bool {
+ $this->assertParams($app, $key);
+ $this->loadConfig($lazy);
+
+ $sensitive = $this->isTyped(self::VALUE_SENSITIVE, $type);
+ $inserted = $refreshCache = false;
+
+ $origValue = $value;
+ if ($sensitive || ($this->hasKey($app, $key, $lazy) && $this->isSensitive($app, $key, $lazy))) {
+ $value = self::ENCRYPTION_PREFIX . $this->crypto->encrypt($value);
+ }
+
+ if ($this->hasKey($app, $key, $lazy)) {
+ /**
+ * no update if key is already known with set lazy status and value is
+ * not different, unless sensitivity is switched from false to true.
+ */
+ if ($origValue === $this->getTypedValue($app, $key, $value, $lazy, $type)
+ && (!$sensitive || $this->isSensitive($app, $key, $lazy))) {
+ return false;
+ }
+ } else {
+ /**
+ * if key is not known yet, we try to insert.
+ * It might fail if the key exists with a different lazy flag.
+ */
+ try {
+ $insert = $this->connection->getQueryBuilder();
+ $insert->insert('appconfig')
+ ->setValue('appid', $insert->createNamedParameter($app))
+ ->setValue('lazy', $insert->createNamedParameter(($lazy) ? 1 : 0, IQueryBuilder::PARAM_INT))
+ ->setValue('type', $insert->createNamedParameter($type, IQueryBuilder::PARAM_INT))
+ ->setValue('configkey', $insert->createNamedParameter($key))
+ ->setValue('configvalue', $insert->createNamedParameter($value));
+ $insert->executeStatement();
+ $inserted = true;
+ } catch (DBException $e) {
+ if ($e->getReason() !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
+ throw $e; // TODO: throw exception or just log and returns false !?
+ }
+ }
+ }
+
+ /**
+ * We cannot insert a new row, meaning we need to update an already existing one
+ */
+ if (!$inserted) {
+ $currType = $this->valueTypes[$app][$key] ?? 0;
+ if ($currType === 0) { // this might happen when switching lazy loading status
+ $this->loadConfigAll();
+ $currType = $this->valueTypes[$app][$key] ?? 0;
+ }
+
+ /**
+ * This should only happen during the upgrade process from 28 to 29.
+ * We only log a warning and set it to VALUE_MIXED.
+ */
+ if ($currType === 0) {
+ $this->logger->warning('Value type is set to zero (0) in database. This is fine only during the upgrade process from 28 to 29.', ['app' => $app, 'key' => $key]);
+ $currType = self::VALUE_MIXED;
+ }
+
+ /**
+ * we only accept a different type from the one stored in database
+ * if the one stored in database is not-defined (VALUE_MIXED)
+ */
+ if (!$this->isTyped(self::VALUE_MIXED, $currType) &&
+ ($type | self::VALUE_SENSITIVE) !== ($currType | self::VALUE_SENSITIVE)) {
+ try {
+ $currType = $this->convertTypeToString($currType);
+ $type = $this->convertTypeToString($type);
+ } catch (AppConfigIncorrectTypeException) {
+ // can be ignored, this was just needed for a better exception message.
}
+ throw new AppConfigTypeConflictException('conflict between new type (' . $type . ') and old type (' . $currType . ')');
+ }
+
+ // we fix $type if the stored value, or the new value as it might be changed, is set as sensitive
+ if ($sensitive || $this->isTyped(self::VALUE_SENSITIVE, $currType)) {
+ $type |= self::VALUE_SENSITIVE;
+ }
+
+ if ($lazy !== $this->isLazy($app, $key)) {
+ $refreshCache = true;
+ }
+
+ $update = $this->connection->getQueryBuilder();
+ $update->update('appconfig')
+ ->set('configvalue', $update->createNamedParameter($value))
+ ->set('lazy', $update->createNamedParameter(($lazy) ? 1 : 0, IQueryBuilder::PARAM_INT))
+ ->set('type', $update->createNamedParameter($type, IQueryBuilder::PARAM_INT))
+ ->where($update->expr()->eq('appid', $update->createNamedParameter($app)))
+ ->andWhere($update->expr()->eq('configkey', $update->createNamedParameter($key)));
+
+ $update->executeStatement();
+ }
+
+ if ($refreshCache) {
+ $this->clearCache();
+ return true;
+ }
+
+ // update local cache
+ if ($lazy) {
+ $this->lazyCache[$app][$key] = $value;
+ } else {
+ $this->fastCache[$app][$key] = $value;
+ }
+ $this->valueTypes[$app][$key] = $type;
- $this->cache[$app][$key] = $value;
- return true;
+ return true;
+ }
+
+ /**
+ * Change the type of config value.
+ *
+ * **WARNING:** Method is internal and **MUST** not be used as it may break things.
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param int $type value type {@see VALUE_STRING} {@see VALUE_INT} {@see VALUE_FLOAT} {@see VALUE_BOOL} {@see VALUE_ARRAY}
+ *
+ * @return bool TRUE if database update were necessary
+ * @throws AppConfigUnknownKeyException if $key is now known in database
+ * @throws AppConfigIncorrectTypeException if $type is not valid
+ * @internal
+ * @since 29.0.0
+ */
+ public function updateType(string $app, string $key, int $type = self::VALUE_MIXED): bool {
+ $this->assertParams($app, $key);
+ $this->loadConfigAll();
+ $lazy = $this->isLazy($app, $key);
+
+ // type can only be one type
+ if (!in_array($type, [self::VALUE_MIXED, self::VALUE_STRING, self::VALUE_INT, self::VALUE_FLOAT, self::VALUE_BOOL, self::VALUE_ARRAY])) {
+ throw new AppConfigIncorrectTypeException('Unknown value type');
+ }
+
+ $currType = $this->valueTypes[$app][$key];
+ if (($type | self::VALUE_SENSITIVE) === ($currType | self::VALUE_SENSITIVE)) {
+ return false;
+ }
+
+ // we complete with sensitive flag if the stored value is set as sensitive
+ if ($this->isTyped(self::VALUE_SENSITIVE, $currType)) {
+ $type = $type | self::VALUE_SENSITIVE;
+ }
+
+ $update = $this->connection->getQueryBuilder();
+ $update->update('appconfig')
+ ->set('type', $update->createNamedParameter($type, IQueryBuilder::PARAM_INT))
+ ->where($update->expr()->eq('appid', $update->createNamedParameter($app)))
+ ->andWhere($update->expr()->eq('configkey', $update->createNamedParameter($key)));
+ $update->executeStatement();
+ $this->valueTypes[$app][$key] = $type;
+
+ return true;
+ }
+
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param bool $sensitive TRUE to set as sensitive, FALSE to unset
+ *
+ * @return bool TRUE if entry was found in database and an update was necessary
+ * @since 29.0.0
+ */
+ public function updateSensitive(string $app, string $key, bool $sensitive): bool {
+ $this->assertParams($app, $key);
+ $this->loadConfigAll();
+
+ try {
+ if ($sensitive === $this->isSensitive($app, $key, null)) {
+ return false;
}
+ } catch (AppConfigUnknownKeyException $e) {
+ return false;
+ }
+
+ $lazy = $this->isLazy($app, $key);
+ if ($lazy) {
+ $cache = $this->lazyCache;
+ } else {
+ $cache = $this->fastCache;
}
- $sql = $this->conn->getQueryBuilder();
- $sql->update('appconfig')
- ->set('configvalue', $sql->createNamedParameter($value))
- ->where($sql->expr()->eq('appid', $sql->createNamedParameter($app)))
- ->andWhere($sql->expr()->eq('configkey', $sql->createNamedParameter($key)));
+ if (!isset($cache[$app][$key])) {
+ throw new AppConfigUnknownKeyException('unknown config key');
+ }
- /*
- * Only limit to the existing value for non-Oracle DBs:
- * http://docs.oracle.com/cd/E11882_01/server.112/e26088/conditions002.htm#i1033286
- * > Large objects (LOBs) are not supported in comparison conditions.
+ /**
+ * type returned by getValueType() is already cleaned from sensitive flag
+ * we just need to update it based on $sensitive and store it in database
*/
- if (!($this->conn instanceof OracleConnection)) {
- /*
- * Only update the value when it is not the same
- * Note that NULL requires some special handling. Since comparing
- * against null can have special results.
- */
+ $type = $this->getValueType($app, $key);
+ $value = $cache[$app][$key];
+ if ($sensitive) {
+ $type |= self::VALUE_SENSITIVE;
+ $value = self::ENCRYPTION_PREFIX . $this->crypto->encrypt($value);
+ } else {
+ $value = $this->crypto->decrypt(substr($value, self::ENCRYPTION_PREFIX_LENGTH));
+ }
+
+ $update = $this->connection->getQueryBuilder();
+ $update->update('appconfig')
+ ->set('type', $update->createNamedParameter($type, IQueryBuilder::PARAM_INT))
+ ->set('configvalue', $update->createNamedParameter($value))
+ ->where($update->expr()->eq('appid', $update->createNamedParameter($app)))
+ ->andWhere($update->expr()->eq('configkey', $update->createNamedParameter($key)));
+ $update->executeStatement();
+
+ $this->valueTypes[$app][$key] = $type;
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ * @param bool $lazy TRUE to set as lazy loaded, FALSE to unset
+ *
+ * @return bool TRUE if entry was found in database and an update was necessary
+ * @since 29.0.0
+ */
+ public function updateLazy(string $app, string $key, bool $lazy): bool {
+ $this->assertParams($app, $key);
+ $this->loadConfigAll();
+
+ try {
+ if ($lazy === $this->isLazy($app, $key)) {
+ return false;
+ }
+ } catch (AppConfigUnknownKeyException $e) {
+ return false;
+ }
+
+ $update = $this->connection->getQueryBuilder();
+ $update->update('appconfig')
+ ->set('lazy', $update->createNamedParameter($lazy ? 1 : 0, IQueryBuilder::PARAM_INT))
+ ->where($update->expr()->eq('appid', $update->createNamedParameter($app)))
+ ->andWhere($update->expr()->eq('configkey', $update->createNamedParameter($key)));
+ $update->executeStatement();
+
+ // At this point, it is a lot safer to clean cache
+ $this->clearCache();
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ *
+ * @return array
+ * @throws AppConfigUnknownKeyException if config key is not known in database
+ * @since 29.0.0
+ */
+ public function getDetails(string $app, string $key): array {
+ $this->assertParams($app, $key);
+ $this->loadConfigAll();
+ $lazy = $this->isLazy($app, $key);
+
+ if ($lazy) {
+ $cache = $this->lazyCache;
+ } else {
+ $cache = $this->fastCache;
+ }
+
+ $type = $this->getValueType($app, $key);
+ try {
+ $typeString = $this->convertTypeToString($type);
+ } catch (AppConfigIncorrectTypeException $e) {
+ $this->logger->warning('type stored in database is not correct', ['exception' => $e, 'type' => $type]);
+ $typeString = (string)$type;
+ }
+
+ if (!isset($cache[$app][$key])) {
+ throw new AppConfigUnknownKeyException('unknown config key');
+ }
+
+ $value = $cache[$app][$key];
+ $sensitive = $this->isSensitive($app, $key, null);
+ if ($sensitive && str_starts_with($value, self::ENCRYPTION_PREFIX)) {
+ $value = $this->crypto->decrypt(substr($value, self::ENCRYPTION_PREFIX_LENGTH));
+ }
+
+ return [
+ 'app' => $app,
+ 'key' => $key,
+ 'value' => $value,
+ 'type' => $type,
+ 'lazy' => $lazy,
+ 'typeString' => $typeString,
+ 'sensitive' => $sensitive
+ ];
+ }
+
+ /**
+ * @param string $type
+ *
+ * @return int
+ * @throws AppConfigIncorrectTypeException
+ * @since 29.0.0
+ */
+ public function convertTypeToInt(string $type): int {
+ return match (strtolower($type)) {
+ 'mixed' => IAppConfig::VALUE_MIXED,
+ 'string' => IAppConfig::VALUE_STRING,
+ 'integer' => IAppConfig::VALUE_INT,
+ 'float' => IAppConfig::VALUE_FLOAT,
+ 'boolean' => IAppConfig::VALUE_BOOL,
+ 'array' => IAppConfig::VALUE_ARRAY,
+ default => throw new AppConfigIncorrectTypeException('Unknown type ' . $type)
+ };
+ }
+
+ /**
+ * @param int $type
+ *
+ * @return string
+ * @throws AppConfigIncorrectTypeException
+ * @since 29.0.0
+ */
+ public function convertTypeToString(int $type): string {
+ $type &= ~self::VALUE_SENSITIVE;
+
+ return match ($type) {
+ IAppConfig::VALUE_MIXED => 'mixed',
+ IAppConfig::VALUE_STRING => 'string',
+ IAppConfig::VALUE_INT => 'integer',
+ IAppConfig::VALUE_FLOAT => 'float',
+ IAppConfig::VALUE_BOOL => 'boolean',
+ IAppConfig::VALUE_ARRAY => 'array',
+ default => throw new AppConfigIncorrectTypeException('Unknown numeric type ' . $type)
+ };
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ *
+ * @since 29.0.0
+ */
+ public function deleteKey(string $app, string $key): void {
+ $this->assertParams($app, $key);
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('appconfig')
+ ->where($qb->expr()->eq('appid', $qb->createNamedParameter($app)))
+ ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
+ $qb->executeStatement();
+
+ unset($this->lazyCache[$app][$key]);
+ unset($this->fastCache[$app][$key]);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ *
+ * @since 29.0.0
+ */
+ public function deleteApp(string $app): void {
+ $this->assertParams($app);
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('appconfig')
+ ->where($qb->expr()->eq('appid', $qb->createNamedParameter($app)));
+ $qb->executeStatement();
+
+ $this->clearCache();
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param bool $reload set to TRUE to refill cache instantly after clearing it
+ *
+ * @since 29.0.0
+ */
+ public function clearCache(bool $reload = false): void {
+ $this->lazyLoaded = $this->fastLoaded = false;
+ $this->lazyCache = $this->fastCache = $this->valueTypes = [];
+
+ if (!$reload) {
+ return;
+ }
+
+ $this->loadConfigAll();
+ }
+
+
+ /**
+ * For debug purpose.
+ * Returns the cached data.
+ *
+ * @return array
+ * @since 29.0.0
+ * @internal
+ */
+ public function statusCache(): array {
+ return [
+ 'fastLoaded' => $this->fastLoaded,
+ 'fastCache' => $this->fastCache,
+ 'lazyLoaded' => $this->lazyLoaded,
+ 'lazyCache' => $this->lazyCache,
+ ];
+ }
- if ($value === null) {
- $sql->andWhere(
- $sql->expr()->isNotNull('configvalue')
- );
+ /**
+ * @param int $needle bitflag to search
+ * @param int $type known value
+ *
+ * @return bool TRUE if bitflag $needle is set in $type
+ */
+ private function isTyped(int $needle, int $type): bool {
+ return (($needle & $type) !== 0);
+ }
+
+ /**
+ * Confirm the string set for app and key fit the database description
+ *
+ * @param string $app assert $app fit in database
+ * @param string $configKey assert config key fit in database
+ * @param bool $allowEmptyApp $app can be empty string
+ * @param int $valueType assert value type is only one type
+ *
+ * @throws InvalidArgumentException
+ */
+ private function assertParams(string $app = '', string $configKey = '', bool $allowEmptyApp = false, int $valueType = -1): void {
+ if (!$allowEmptyApp && $app === '') {
+ throw new InvalidArgumentException('app cannot be an empty string');
+ }
+ if (strlen($app) > self::APP_MAX_LENGTH) {
+ throw new InvalidArgumentException(
+ 'Value (' . $app . ') for app is too long (' . self::APP_MAX_LENGTH . ')'
+ );
+ }
+ if (strlen($configKey) > self::KEY_MAX_LENGTH) {
+ throw new InvalidArgumentException('Value (' . $configKey . ') for key is too long (' . self::KEY_MAX_LENGTH . ')');
+ }
+ if ($valueType > -1) {
+ $valueType &= ~self::VALUE_SENSITIVE;
+ if (!in_array($valueType, [self::VALUE_MIXED, self::VALUE_STRING, self::VALUE_INT, self::VALUE_FLOAT, self::VALUE_BOOL, self::VALUE_ARRAY])) {
+ throw new InvalidArgumentException('Unknown value type');
+ }
+ }
+ }
+
+ private function loadConfigAll(): void {
+ $this->loadConfig(null);
+ }
+
+ /**
+ * Load normal config or config set as lazy loaded
+ *
+ * @param bool|null $lazy set to TRUE to load config set as lazy loaded, set to NULL to load all config
+ */
+ private function loadConfig(?bool $lazy = false): void {
+ if ($this->isLoaded($lazy)) {
+ return;
+ }
+
+ if (($lazy ?? true) !== false) { // if lazy is null or true, we debug log
+ $this->logger->debug('The loading of lazy AppConfig values have been requested', ['exception' => new \RuntimeException('ignorable exception')]);
+ }
+
+ $qb = $this->connection->getQueryBuilder();
+ $qb->from('appconfig');
+
+ /**
+ * The use of $this->>migrationCompleted is only needed to manage the
+ * database during the upgrading process to nc29.
+ */
+ if (!$this->migrationCompleted) {
+ $qb->select('appid', 'configkey', 'configvalue');
+ } else {
+ // we only need value from lazy when loadConfig does not specify it
+ $qb->select('appid', 'configkey', 'configvalue', 'type');
+
+ if ($lazy !== null) {
+ $qb->where($qb->expr()->eq('lazy', $qb->createNamedParameter($lazy ? 1 : 0, IQueryBuilder::PARAM_INT)));
} else {
- $sql->andWhere(
- $sql->expr()->orX(
- $sql->expr()->isNull('configvalue'),
- $sql->expr()->neq('configvalue', $sql->createNamedParameter($value), IQueryBuilder::PARAM_STR)
- )
- );
+ $qb->addSelect('lazy');
}
}
- $changedRow = (bool) $sql->execute();
+ try {
+ $result = $qb->executeQuery();
+ } catch (DBException $e) {
+ /**
+ * in case of issue with field name, it means that migration is not completed.
+ * Falling back to a request without select on lazy.
+ * This whole try/catch and the migrationCompleted variable can be removed in NC30.
+ */
+ if ($e->getReason() !== DBException::REASON_INVALID_FIELD_NAME) {
+ throw $e;
+ }
+
+ $this->migrationCompleted = false;
+ $this->loadConfig($lazy);
- $this->cache[$app][$key] = $value;
+ return;
+ }
- return $changedRow;
+ $rows = $result->fetchAll();
+ foreach ($rows as $row) {
+ // most of the time, 'lazy' is not in the select because its value is already known
+ if (($row['lazy'] ?? ($lazy ?? 0) ? 1 : 0) === 1) {
+ $this->lazyCache[$row['appid']][$row['configkey']] = $row['configvalue'] ?? '';
+ } else {
+ $this->fastCache[$row['appid']][$row['configkey']] = $row['configvalue'] ?? '';
+ }
+ $this->valueTypes[$row['appid']][$row['configkey']] = (int)($row['type'] ?? 0);
+ }
+ $result->closeCursor();
+ $this->setAsLoaded($lazy);
}
/**
- * Deletes a key
+ * if $lazy is:
+ * - false: will returns true if fast config is loaded
+ * - true : will returns true if lazy config is loaded
+ * - null : will returns true if both config are loaded
*
- * @param string $app app
- * @param string $key key
- * @return boolean
+ * @param bool $lazy
+ *
+ * @return bool
*/
- public function deleteKey($app, $key) {
- $this->loadConfigValues();
+ private function isLoaded(?bool $lazy): bool {
+ if ($lazy === null) {
+ return $this->lazyLoaded && $this->fastLoaded;
+ }
+
+ return $lazy ? $this->lazyLoaded : $this->fastLoaded;
+ }
- $sql = $this->conn->getQueryBuilder();
- $sql->delete('appconfig')
- ->where($sql->expr()->eq('appid', $sql->createParameter('app')))
- ->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey')))
- ->setParameter('app', $app)
- ->setParameter('configkey', $key);
- $sql->execute();
+ /**
+ * if $lazy is:
+ * - false: set fast config as loaded
+ * - true : set lazy config as loaded
+ * - null : set both config as loaded
+ *
+ * @param bool $lazy
+ */
+ private function setAsLoaded(?bool $lazy): void {
+ if ($lazy === null) {
+ $this->fastLoaded = true;
+ $this->lazyLoaded = true;
+
+ return;
+ }
- unset($this->cache[$app][$key]);
- return false;
+ if ($lazy) {
+ $this->lazyLoaded = true;
+ } else {
+ $this->fastLoaded = true;
+ }
}
/**
- * Remove app from appconfig
+ * Gets the config value
*
* @param string $app app
- * @return boolean
+ * @param string $key key
+ * @param string $default = null, default value if the key does not exist
+ *
+ * @return string the value or $default
+ * @deprecated - use getValue*()
*
- * Removes all keys in appconfig belonging to the app.
+ * This function gets a value from the appconfig table. If the key does
+ * not exist the default value will be returned
*/
- public function deleteApp($app) {
- $this->loadConfigValues();
+ public function getValue($app, $key, $default = null) {
+ $this->loadConfig();
- $sql = $this->conn->getQueryBuilder();
- $sql->delete('appconfig')
- ->where($sql->expr()->eq('appid', $sql->createParameter('app')))
- ->setParameter('app', $app);
- $sql->execute();
+ return $this->fastCache[$app][$key] ?? $default;
+ }
- unset($this->cache[$app]);
- return false;
+ /**
+ * Sets a value. If the key did not exist before it will be created.
+ *
+ * @param string $app app
+ * @param string $key key
+ * @param string|float|int $value value
+ *
+ * @return bool True if the value was inserted or updated, false if the value was the same
+ * @throws AppConfigTypeConflictException
+ * @throws AppConfigUnknownKeyException
+ * @deprecated
+ */
+ public function setValue($app, $key, $value) {
+ /**
+ * TODO: would it be overkill, or decently improve performance, to catch
+ * call to this method with $key='enabled' and 'hide' config value related
+ * to $app when the app is disabled (by modifying entry in database: lazy=lazy+2)
+ * or enabled (lazy=lazy-2)
+ *
+ * this solution would remove the loading of config values from disabled app
+ * unless calling the method {@see loadConfigAll()}
+ */
+ return $this->setTypedValue($app, $key, (string)$value, false, self::VALUE_MIXED);
}
+
/**
* get multiple values, either the app or key can be used as wildcard by setting it to false
*
* @param string|false $app
* @param string|false $key
+ *
* @return array|false
+ * @deprecated 29.0.0 use {@see getAllValues()}
*/
public function getValues($app, $key) {
if (($app !== false) === ($key !== false)) {
return false;
}
- if ($key === false) {
- return $this->getAppValues($app);
+ $key = ($key === false) ? '' : $key;
+ if (!$app) {
+ return $this->searchValues($key, false, self::VALUE_MIXED);
} else {
- $appIds = $this->getApps();
- $values = array_map(function ($appId) use ($key) {
- return isset($this->cache[$appId][$key]) ? $this->cache[$appId][$key] : null;
- }, $appIds);
- $result = array_combine($appIds, $values);
-
- return array_filter($result);
+ return $this->getAllValues($app, $key);
}
}
@@ -385,58 +1358,184 @@ class AppConfig implements IAppConfig {
* get all values of the app or and filters out sensitive data
*
* @param string $app
+ *
* @return array
+ * @deprecated 29.0.0 use {@see getAllValues()}
*/
public function getFilteredValues($app) {
- $values = $this->getValues($app, false);
+ return $this->getAllValues($app, filtered: true);
+ }
- if (isset($this->sensitiveValues[$app])) {
- foreach ($this->sensitiveValues[$app] as $sensitiveKeyExp) {
- $sensitiveKeys = preg_grep($sensitiveKeyExp, array_keys($values));
- foreach ($sensitiveKeys as $sensitiveKey) {
- $values[$sensitiveKey] = IConfig::SENSITIVE_VALUE;
- }
+
+ /**
+ * **Warning:** avoid default NULL value for $lazy as this will
+ * load all lazy values from the database
+ *
+ * @param string $app
+ * @param array<string, string> $values ['key' => 'value']
+ * @param bool|null $lazy
+ *
+ * @return array<string, string|int|float|bool|array>
+ */
+ private function formatAppValues(string $app, array $values, ?bool $lazy = null): array {
+ foreach($values as $key => $value) {
+ try {
+ $type = $this->getValueType($app, $key, $lazy);
+ } catch (AppConfigUnknownKeyException $e) {
+ continue;
}
+
+ $values[$key] = $this->convertTypedValue($value, $type);
}
return $values;
}
/**
- * Load all the app config values
+ * convert string value to the expected type
+ *
+ * @param string $value
+ * @param int $type
+ *
+ * @return string|int|float|bool|array
*/
- protected function loadConfigValues() {
- if ($this->configLoaded) {
- return;
+ private function convertTypedValue(string $value, int $type): string|int|float|bool|array {
+ switch ($type) {
+ case self::VALUE_INT:
+ return (int)$value;
+ case self::VALUE_FLOAT:
+ return (float)$value;
+ case self::VALUE_BOOL:
+ return in_array(strtolower($value), ['1', 'true', 'yes', 'on']);
+ case self::VALUE_ARRAY:
+ try {
+ return json_decode($value, true, flags: JSON_THROW_ON_ERROR);
+ } catch (JsonException $e) {
+ // ignoreable
+ }
+ break;
}
+ return $value;
+ }
- $this->cache = [];
-
- $sql = $this->conn->getQueryBuilder();
- $sql->select('*')
- ->from('appconfig');
- $result = $sql->execute();
-
- // we are going to store the result in memory anyway
- $rows = $result->fetchAll();
- foreach ($rows as $row) {
- if (!isset($this->cache[$row['appid']])) {
- $this->cache[(string)$row['appid']] = [];
- }
-
- $this->cache[(string)$row['appid']][(string)$row['configkey']] = (string)$row['configvalue'];
- }
- $result->closeCursor();
+ /**
+ * @param string $app
+ *
+ * @return string[]
+ * @deprecated data sensitivity should be set when calling setValue*()
+ */
+ private function getSensitiveKeys(string $app): array {
+ $sensitiveValues = [
+ 'circles' => [
+ '/^key_pairs$/',
+ '/^local_gskey$/',
+ ],
+ 'external' => [
+ '/^sites$/',
+ ],
+ 'integration_discourse' => [
+ '/^private_key$/',
+ '/^public_key$/',
+ ],
+ 'integration_dropbox' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_github' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_gitlab' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'integration_google' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_jira' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^forced_instance_url$/',
+ ],
+ 'integration_onedrive' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_openproject' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'integration_reddit' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_suitecrm' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'integration_twitter' => [
+ '/^consumer_key$/',
+ '/^consumer_secret$/',
+ '/^followed_user$/',
+ ],
+ 'integration_zammad' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'notify_push' => [
+ '/^cookie$/',
+ ],
+ 'serverinfo' => [
+ '/^token$/',
+ ],
+ 'spreed' => [
+ '/^bridge_bot_password$/',
+ '/^hosted-signaling-server-(.*)$/',
+ '/^recording_servers$/',
+ '/^signaling_servers$/',
+ '/^signaling_ticket_secret$/',
+ '/^signaling_token_privkey_(.*)$/',
+ '/^signaling_token_pubkey_(.*)$/',
+ '/^sip_bridge_dialin_info$/',
+ '/^sip_bridge_shared_secret$/',
+ '/^stun_servers$/',
+ '/^turn_servers$/',
+ '/^turn_server_secret$/',
+ ],
+ 'support' => [
+ '/^last_response$/',
+ '/^potential_subscription_key$/',
+ '/^subscription_key$/',
+ ],
+ 'theming' => [
+ '/^imprintUrl$/',
+ '/^privacyUrl$/',
+ '/^slogan$/',
+ '/^url$/',
+ ],
+ 'user_ldap' => [
+ '/^(s..)?ldap_agent_password$/',
+ ],
+ 'user_saml' => [
+ '/^idp-x509cert$/',
+ ],
+ ];
- $this->configLoaded = true;
+ return $sensitiveValues[$app] ?? [];
}
-
/**
* Clear all the cached app config values
* New cache will be generated next time a config value is retrieved
+ *
+ * @deprecated use {@see clearCache()}
*/
public function clearCachedConfig(): void {
- $this->configLoaded = false;
+ $this->clearCache();
}
}
diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php
index ffd77da888e..9f9fb32dbcb 100644
--- a/lib/private/AppFramework/App.php
+++ b/lib/private/AppFramework/App.php
@@ -1,49 +1,26 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework;
use OC\AppFramework\DependencyInjection\DIContainer;
use OC\AppFramework\Http\Dispatcher;
use OC\AppFramework\Http\Request;
-use OCP\App\IAppManager;
-use OCP\Profiler\IProfiler;
use OC\Profiler\RoutingDataCollector;
-use OCP\AppFramework\QueryException;
+use OCP\App\IAppManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\ICallbackResponse;
use OCP\AppFramework\Http\IOutput;
+use OCP\AppFramework\QueryException;
use OCP\Diagnostics\IEventLogger;
use OCP\HintException;
use OCP\IRequest;
+use OCP\Profiler\IProfiler;
/**
* Entry point for every request in your app. You can consider this as your
@@ -116,7 +93,7 @@ class App {
* @param array $urlParams list of URL parameters (optional)
* @throws HintException
*/
- public static function main(string $controllerName, string $methodName, DIContainer $container, array $urlParams = null) {
+ public static function main(string $controllerName, string $methodName, DIContainer $container, ?array $urlParams = null) {
/** @var IProfiler $profiler */
$profiler = $container->get(IProfiler::class);
$eventLogger = $container->get(IEventLogger::class);
@@ -257,7 +234,7 @@ class App {
* @param DIContainer $container an instance of a pimple container.
*/
public static function part(string $controllerName, string $methodName, array $urlParams,
- DIContainer $container) {
+ DIContainer $container) {
$container['urlParams'] = $urlParams;
$controller = $container[$controllerName];
diff --git a/lib/private/AppFramework/Bootstrap/ARegistration.php b/lib/private/AppFramework/Bootstrap/ARegistration.php
index 797d7d2317b..37984667727 100644
--- a/lib/private/AppFramework/Bootstrap/ARegistration.php
+++ b/lib/private/AppFramework/Bootstrap/ARegistration.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
diff --git a/lib/private/AppFramework/Bootstrap/BootContext.php b/lib/private/AppFramework/Bootstrap/BootContext.php
index 8c37d00a419..b3da08adb07 100644
--- a/lib/private/AppFramework/Bootstrap/BootContext.php
+++ b/lib/private/AppFramework/Bootstrap/BootContext.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
diff --git a/lib/private/AppFramework/Bootstrap/Coordinator.php b/lib/private/AppFramework/Bootstrap/Coordinator.php
index f41b734a25b..4e78450fa04 100644
--- a/lib/private/AppFramework/Bootstrap/Coordinator.php
+++ b/lib/private/AppFramework/Bootstrap/Coordinator.php
@@ -3,67 +3,30 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
-use OCP\Diagnostics\IEventLogger;
-use function class_exists;
-use function class_implements;
-use function in_array;
-use OC_App;
use OC\Support\CrashReport\Registry;
+use OC_App;
+use OCP\App\AppPathNotFoundException;
+use OCP\App\IAppManager;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\QueryException;
use OCP\Dashboard\IManager;
+use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IServerContainer;
use Psr\Log\LoggerInterface;
use Throwable;
+use function class_exists;
+use function class_implements;
+use function in_array;
class Coordinator {
- /** @var IServerContainer */
- private $serverContainer;
-
- /** @var Registry */
- private $registry;
-
- /** @var IManager */
- private $dashboardManager;
-
- /** @var IEventDispatcher */
- private $eventDispatcher;
-
- /** @var IEventLogger */
- private $eventLogger;
-
- /** @var LoggerInterface */
- private $logger;
-
/** @var RegistrationContext|null */
private $registrationContext;
@@ -71,19 +34,14 @@ class Coordinator {
private $bootedApps = [];
public function __construct(
- IServerContainer $container,
- Registry $registry,
- IManager $dashboardManager,
- IEventDispatcher $eventListener,
- IEventLogger $eventLogger,
- LoggerInterface $logger
+ private IServerContainer $serverContainer,
+ private Registry $registry,
+ private IManager $dashboardManager,
+ private IEventDispatcher $eventDispatcher,
+ private IEventLogger $eventLogger,
+ private IAppManager $appManager,
+ private LoggerInterface $logger,
) {
- $this->serverContainer = $container;
- $this->registry = $registry;
- $this->dashboardManager = $dashboardManager;
- $this->eventDispatcher = $eventListener;
- $this->eventLogger = $eventLogger;
- $this->logger = $logger;
}
public function runInitialRegistration(): void {
@@ -108,11 +66,10 @@ class Coordinator {
$this->eventLogger->start("bootstrap:register_app:$appId:autoloader", "Setup autoloader for $appId");
/*
* First, we have to enable the app's autoloader
- *
- * @todo use $this->appManager->getAppPath($appId) here
*/
- $path = OC_App::getAppPath($appId);
- if ($path === false) {
+ try {
+ $path = $this->appManager->getAppPath($appId);
+ } catch (AppPathNotFoundException) {
// Ignore
continue;
}
diff --git a/lib/private/AppFramework/Bootstrap/EventListenerRegistration.php b/lib/private/AppFramework/Bootstrap/EventListenerRegistration.php
index 2ad410be26f..92955fc4123 100644
--- a/lib/private/AppFramework/Bootstrap/EventListenerRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/EventListenerRegistration.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
@@ -37,9 +20,9 @@ class EventListenerRegistration extends ServiceRegistration {
private $priority;
public function __construct(string $appId,
- string $event,
- string $service,
- int $priority) {
+ string $event,
+ string $service,
+ int $priority) {
parent::__construct($appId, $service);
$this->event = $event;
$this->priority = $priority;
diff --git a/lib/private/AppFramework/Bootstrap/FunctionInjector.php b/lib/private/AppFramework/Bootstrap/FunctionInjector.php
index 2f95906ab4c..973fc13aa2c 100644
--- a/lib/private/AppFramework/Bootstrap/FunctionInjector.php
+++ b/lib/private/AppFramework/Bootstrap/FunctionInjector.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
diff --git a/lib/private/AppFramework/Bootstrap/MiddlewareRegistration.php b/lib/private/AppFramework/Bootstrap/MiddlewareRegistration.php
index da226b311e0..d2ad6bbf0f6 100644
--- a/lib/private/AppFramework/Bootstrap/MiddlewareRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/MiddlewareRegistration.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
diff --git a/lib/private/AppFramework/Bootstrap/ParameterRegistration.php b/lib/private/AppFramework/Bootstrap/ParameterRegistration.php
index b501a757abd..cc9a4875e9a 100644
--- a/lib/private/AppFramework/Bootstrap/ParameterRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/ParameterRegistration.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
@@ -36,8 +19,8 @@ final class ParameterRegistration extends ARegistration {
private $value;
public function __construct(string $appId,
- string $name,
- $value) {
+ string $name,
+ $value) {
parent::__construct($appId);
$this->name = $name;
$this->value = $value;
diff --git a/lib/private/AppFramework/Bootstrap/PreviewProviderRegistration.php b/lib/private/AppFramework/Bootstrap/PreviewProviderRegistration.php
index 36c5cae7db3..7ecc4aac7f2 100644
--- a/lib/private/AppFramework/Bootstrap/PreviewProviderRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/PreviewProviderRegistration.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
@@ -34,8 +18,8 @@ class PreviewProviderRegistration extends ServiceRegistration {
private $mimeTypeRegex;
public function __construct(string $appId,
- string $service,
- string $mimeTypeRegex) {
+ string $service,
+ string $mimeTypeRegex) {
parent::__construct($appId, $service);
$this->mimeTypeRegex = $mimeTypeRegex;
}
diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
index 5aea2a7a744..df03d59ebfa 100644
--- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php
+++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
@@ -3,42 +3,13 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
use Closure;
-use OCP\Calendar\Resource\IBackend as IResourceBackend;
-use OCP\Calendar\Room\IBackend as IRoomBackend;
-use OCP\Collaboration\Reference\IReferenceProvider;
-use OCP\TextProcessing\IProvider as ITextProcessingProvider;
-use OCP\SpeechToText\ISpeechToTextProvider;
-use OCP\Talk\ITalkBackend;
-use OCP\Translation\ITranslationProvider;
-use RuntimeException;
-use function array_shift;
use OC\Support\CrashReport\Registry;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
@@ -46,7 +17,10 @@ use OCP\AppFramework\Middleware;
use OCP\AppFramework\Services\InitialStateProvider;
use OCP\Authentication\IAlternativeLogin;
use OCP\Calendar\ICalendarProvider;
+use OCP\Calendar\Resource\IBackend as IResourceBackend;
+use OCP\Calendar\Room\IBackend as IRoomBackend;
use OCP\Capabilities\ICapability;
+use OCP\Collaboration\Reference\IReferenceProvider;
use OCP\Dashboard\IManager;
use OCP\Dashboard\IWidget;
use OCP\EventDispatcher\IEventDispatcher;
@@ -55,11 +29,20 @@ use OCP\Http\WellKnown\IHandler;
use OCP\Notification\INotifier;
use OCP\Profile\ILinkAction;
use OCP\Search\IProvider;
+use OCP\Settings\IDeclarativeSettingsForm;
+use OCP\SetupCheck\ISetupCheck;
use OCP\Share\IPublicShareTemplateProvider;
+use OCP\SpeechToText\ISpeechToTextProvider;
use OCP\Support\CrashReport\IReporter;
+use OCP\Talk\ITalkBackend;
+use OCP\Teams\ITeamResourceProvider;
+use OCP\TextProcessing\IProvider as ITextProcessingProvider;
+use OCP\Translation\ITranslationProvider;
use OCP\UserMigration\IMigrator as IUserMigrator;
use Psr\Log\LoggerInterface;
+use RuntimeException;
use Throwable;
+use function array_shift;
class RegistrationContext {
/** @var ServiceRegistration<ICapability>[] */
@@ -137,8 +120,8 @@ class RegistrationContext {
/** @var ServiceRegistration<IReferenceProvider>[] */
private array $referenceProviders = [];
-
-
+ /** @var ServiceRegistration<\OCP\TextToImage\IProvider>[] */
+ private $textToImageProviders = [];
/** @var ParameterRegistration[] */
private $sensitiveMethods = [];
@@ -146,11 +129,25 @@ class RegistrationContext {
/** @var ServiceRegistration<IPublicShareTemplateProvider>[] */
private $publicShareTemplateProviders = [];
- /** @var LoggerInterface */
- private $logger;
+ private LoggerInterface $logger;
+
+ /** @var ServiceRegistration<ISetupCheck>[] */
+ private array $setupChecks = [];
/** @var PreviewProviderRegistration[] */
- private $previewProviders = [];
+ private array $previewProviders = [];
+
+ /** @var ServiceRegistration<IDeclarativeSettingsForm>[] */
+ private array $declarativeSettings = [];
+
+ /** @var ServiceRegistration<ITeamResourceProvider>[] */
+ private array $teamResourceProviders = [];
+
+ /** @var ServiceRegistration<\OCP\TaskProcessing\IProvider>[] */
+ private array $taskProcessingProviders = [];
+
+ /** @var ServiceRegistration<\OCP\TaskProcessing\ITaskType>[] */
+ private array $taskProcessingTaskTypes = [];
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
@@ -273,6 +270,13 @@ class RegistrationContext {
);
}
+ public function registerTextToImageProvider(string $providerClass): void {
+ $this->context->registerTextToImageProvider(
+ $this->appId,
+ $providerClass
+ );
+ }
+
public function registerTemplateProvider(string $providerClass): void {
$this->context->registerTemplateProvider(
$this->appId,
@@ -344,6 +348,13 @@ class RegistrationContext {
);
}
+ public function registerTeamResourceProvider(string $class) : void {
+ $this->context->registerTeamResourceProvider(
+ $this->appId,
+ $class
+ );
+ }
+
public function registerCalendarRoomBackend(string $class): void {
$this->context->registerCalendarRoomBackend(
$this->appId,
@@ -372,6 +383,34 @@ class RegistrationContext {
$class
);
}
+
+ public function registerSetupCheck(string $setupCheckClass): void {
+ $this->context->registerSetupCheck(
+ $this->appId,
+ $setupCheckClass
+ );
+ }
+
+ public function registerDeclarativeSettings(string $declarativeSettingsClass): void {
+ $this->context->registerDeclarativeSettings(
+ $this->appId,
+ $declarativeSettingsClass
+ );
+ }
+
+ public function registerTaskProcessingProvider(string $taskProcessingProviderClass): void {
+ $this->context->registerTaskProcessingProvider(
+ $this->appId,
+ $taskProcessingProviderClass
+ );
+ }
+
+ public function registerTaskProcessingTaskType(string $taskProcessingTaskTypeClass): void {
+ $this->context->registerTaskProcessingTaskType(
+ $this->appId,
+ $taskProcessingTaskTypeClass
+ );
+ }
};
}
@@ -383,14 +422,14 @@ class RegistrationContext {
}
/**
- * @psalm-param class-string<IReporter> $capability
+ * @psalm-param class-string<IReporter> $reporterClass
*/
public function registerCrashReporter(string $appId, string $reporterClass): void {
$this->crashReporters[] = new ServiceRegistration($appId, $reporterClass);
}
/**
- * @psalm-param class-string<IWidget> $capability
+ * @psalm-param class-string<IWidget> $panelClass
*/
public function registerDashboardPanel(string $appId, string $panelClass): void {
$this->dashboardPanels[] = new ServiceRegistration($appId, $panelClass);
@@ -443,6 +482,10 @@ class RegistrationContext {
$this->textProcessingProviders[] = new ServiceRegistration($appId, $class);
}
+ public function registerTextToImageProvider(string $appId, string $class): void {
+ $this->textToImageProviders[] = new ServiceRegistration($appId, $class);
+ }
+
public function registerTemplateProvider(string $appId, string $class): void {
$this->templateProviders[] = new ServiceRegistration($appId, $class);
}
@@ -508,6 +551,16 @@ class RegistrationContext {
}
/**
+ * @psalm-param class-string<ITeamResourceProvider> $class
+ */
+ public function registerTeamResourceProvider(string $appId, string $class) {
+ $this->teamResourceProviders[] = new ServiceRegistration(
+ $appId,
+ $class
+ );
+ }
+
+ /**
* @psalm-param class-string<IUserMigrator> $migratorClass
*/
public function registerUserMigrator(string $appId, string $migratorClass): void {
@@ -524,6 +577,34 @@ class RegistrationContext {
}
/**
+ * @psalm-param class-string<ISetupCheck> $setupCheckClass
+ */
+ public function registerSetupCheck(string $appId, string $setupCheckClass): void {
+ $this->setupChecks[] = new ServiceRegistration($appId, $setupCheckClass);
+ }
+
+ /**
+ * @psalm-param class-string<IDeclarativeSettingsForm> $declarativeSettingsClass
+ */
+ public function registerDeclarativeSettings(string $appId, string $declarativeSettingsClass): void {
+ $this->declarativeSettings[] = new ServiceRegistration($appId, $declarativeSettingsClass);
+ }
+
+ /**
+ * @psalm-param class-string<\OCP\TaskProcessing\IProvider> $declarativeSettingsClass
+ */
+ public function registerTaskProcessingProvider(string $appId, string $taskProcessingProviderClass): void {
+ $this->taskProcessingProviders[] = new ServiceRegistration($appId, $taskProcessingProviderClass);
+ }
+
+ /**
+ * @psalm-param class-string<\OCP\TaskProcessing\ITaskType> $declarativeSettingsClass
+ */
+ public function registerTaskProcessingTaskType(string $appId, string $taskProcessingTaskTypeClass) {
+ $this->taskProcessingTaskTypes[] = new ServiceRegistration($appId, $taskProcessingTaskTypeClass);
+ }
+
+ /**
* @param App[] $apps
*/
public function delegateCapabilityRegistrations(array $apps): void {
@@ -565,9 +646,6 @@ class RegistrationContext {
}
}
- /**
- * @param App[] $apps
- */
public function delegateDashboardPanelRegistrations(IManager $dashboardManager): void {
while (($panel = array_shift($this->dashboardPanels)) !== null) {
try {
@@ -729,6 +807,13 @@ class RegistrationContext {
}
/**
+ * @return ServiceRegistration<\OCP\TextToImage\IProvider>[]
+ */
+ public function getTextToImageProviders(): array {
+ return $this->textToImageProviders;
+ }
+
+ /**
* @return ServiceRegistration<ICustomTemplateProvider>[]
*/
public function getTemplateProviders(): array {
@@ -828,4 +913,39 @@ class RegistrationContext {
public function getPublicShareTemplateProviders(): array {
return $this->publicShareTemplateProviders;
}
+
+ /**
+ * @return ServiceRegistration<ISetupCheck>[]
+ */
+ public function getSetupChecks(): array {
+ return $this->setupChecks;
+ }
+
+ /**
+ * @return ServiceRegistration<ITeamResourceProvider>[]
+ */
+ public function getTeamResourceProviders(): array {
+ return $this->teamResourceProviders;
+ }
+
+ /**
+ * @return ServiceRegistration<IDeclarativeSettingsForm>[]
+ */
+ public function getDeclarativeSettings(): array {
+ return $this->declarativeSettings;
+ }
+
+ /**
+ * @return ServiceRegistration<\OCP\TaskProcessing\IProvider>[]
+ */
+ public function getTaskProcessingProviders(): array {
+ return $this->taskProcessingProviders;
+ }
+
+ /**
+ * @return ServiceRegistration<\OCP\TaskProcessing\ITaskType>[]
+ */
+ public function getTaskProcessingTaskTypes(): array {
+ return $this->taskProcessingTaskTypes;
+ }
}
diff --git a/lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php b/lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php
index e2b115e0353..aa3e38e4c46 100644
--- a/lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
@@ -46,8 +29,8 @@ class ServiceAliasRegistration extends ARegistration {
* @paslm-param string|class-string $target
*/
public function __construct(string $appId,
- string $alias,
- string $target) {
+ string $alias,
+ string $target) {
parent::__construct($appId);
$this->alias = $alias;
$this->target = $target;
diff --git a/lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php b/lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php
index b6658e55239..63e73410b5a 100644
--- a/lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
@@ -45,9 +28,9 @@ class ServiceFactoryRegistration extends ARegistration {
private $shared;
public function __construct(string $appId,
- string $alias,
- callable $target,
- bool $shared) {
+ string $alias,
+ callable $target,
+ bool $shared) {
parent::__construct($appId);
$this->name = $alias;
$this->factory = $target;
diff --git a/lib/private/AppFramework/Bootstrap/ServiceRegistration.php b/lib/private/AppFramework/Bootstrap/ServiceRegistration.php
index 6c89cdf9d71..6eda5e0196f 100644
--- a/lib/private/AppFramework/Bootstrap/ServiceRegistration.php
+++ b/lib/private/AppFramework/Bootstrap/ServiceRegistration.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Bootstrap;
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index a012d1e8ea6..9e3119d262a 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -1,35 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sebastian Wessalowski <sebastian@wessalowski.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\DependencyInjection;
@@ -96,7 +69,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
* @param array $urlParams
* @param ServerContainer|null $server
*/
- public function __construct(string $appName, array $urlParams = [], ServerContainer $server = null) {
+ public function __construct(string $appName, array $urlParams = [], ?ServerContainer $server = null) {
parent::__construct();
$this->appName = $appName;
$this['appName'] = $appName;
@@ -173,7 +146,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
});
$this->registerService('OC_Defaults', function (ContainerInterface $c) {
- return $c->get(IServerContainer::class)->getThemingDefaults();
+ return $c->get(IServerContainer::class)->get('ThemingDefaults');
});
$this->registerService('Protocol', function (ContainerInterface $c) {
@@ -302,7 +275,8 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$c->get(IRequest::class),
$c->get(IUserSession::class),
$c->get(IControllerMethodReflector::class),
- $c->get(OC\Security\RateLimiting\Limiter::class)
+ $c->get(OC\Security\RateLimiting\Limiter::class),
+ $c->get(ISession::class)
)
);
$dispatcher->registerMiddleware(
@@ -345,6 +319,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$this->registerService(IAppConfig::class, function (ContainerInterface $c) {
return new OC\AppFramework\Services\AppConfig(
$c->get(IConfig::class),
+ $c->get(\OCP\IAppConfig::class),
$c->get('AppName')
);
});
@@ -404,33 +379,6 @@ class DIContainer extends SimpleContainer implements IAppContainer {
}
/**
- * @deprecated use the ILogger instead
- * @param string $message
- * @param string $level
- * @return mixed
- */
- public function log($message, $level) {
- switch ($level) {
- case 'debug':
- $level = ILogger::DEBUG;
- break;
- case 'info':
- $level = ILogger::INFO;
- break;
- case 'warn':
- $level = ILogger::WARN;
- break;
- case 'fatal':
- $level = ILogger::FATAL;
- break;
- default:
- $level = ILogger::ERROR;
- break;
- }
- \OCP\Util::writeLog($this->getAppName(), $message, $level);
- }
-
- /**
* Register a capability
*
* @param string $serviceName e.g. 'OCA\Files\Capabilities'
diff --git a/lib/private/AppFramework/Http.php b/lib/private/AppFramework/Http.php
index 251c231fe65..3c3e19692bf 100644
--- a/lib/private/AppFramework/Http.php
+++ b/lib/private/AppFramework/Http.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework;
diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php
index 13b391eb287..bbb68972a41 100644
--- a/lib/private/AppFramework/Http/Dispatcher.php
+++ b/lib/private/AppFramework/Http/Dispatcher.php
@@ -1,34 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Http;
@@ -38,6 +14,7 @@ use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\DB\ConnectionAdapter;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\ParameterOutOfRangeException;
use OCP\AppFramework\Http\Response;
use OCP\Diagnostics\IEventLogger;
use OCP\IConfig;
@@ -88,14 +65,14 @@ class Dispatcher {
* @param IEventLogger $eventLogger
*/
public function __construct(Http $protocol,
- MiddlewareDispatcher $middlewareDispatcher,
- ControllerMethodReflector $reflector,
- IRequest $request,
- IConfig $config,
- ConnectionAdapter $connection,
- LoggerInterface $logger,
- IEventLogger $eventLogger,
- ContainerInterface $appContainer) {
+ MiddlewareDispatcher $middlewareDispatcher,
+ ControllerMethodReflector $reflector,
+ IRequest $request,
+ IConfig $config,
+ ConnectionAdapter $connection,
+ LoggerInterface $logger,
+ IEventLogger $eventLogger,
+ ContainerInterface $appContainer) {
$this->protocol = $protocol;
$this->middlewareDispatcher = $middlewareDispatcher;
$this->reflector = $reflector;
@@ -197,7 +174,7 @@ class Dispatcher {
private function executeController(Controller $controller, string $methodName): Response {
$arguments = [];
- // valid types that will be casted
+ // valid types that will be cast
$types = ['int', 'integer', 'bool', 'boolean', 'float', 'double'];
foreach ($this->reflector->getParameters() as $param => $default) {
@@ -219,6 +196,7 @@ class Dispatcher {
$value = false;
} elseif ($value !== null && \in_array($type, $types, true)) {
settype($value, $type);
+ $this->ensureParameterValueSatisfiesRange($param, $value);
} elseif ($value === null && $type !== null && $this->appContainer->has($type)) {
$value = $this->appContainer->get($type);
}
@@ -250,4 +228,22 @@ class Dispatcher {
return $response;
}
+
+ /**
+ * @psalm-param mixed $value
+ * @throws ParameterOutOfRangeException
+ */
+ private function ensureParameterValueSatisfiesRange(string $param, $value): void {
+ $rangeInfo = $this->reflector->getRange($param);
+ if ($rangeInfo) {
+ if ($value < $rangeInfo['min'] || $value > $rangeInfo['max']) {
+ throw new ParameterOutOfRangeException(
+ $param,
+ $value,
+ $rangeInfo['min'],
+ $rangeInfo['max'],
+ );
+ }
+ }
+ }
}
diff --git a/lib/private/AppFramework/Http/Output.php b/lib/private/AppFramework/Http/Output.php
index 963e01456e0..ff0ef1c15ca 100644
--- a/lib/private/AppFramework/Http/Output.php
+++ b/lib/private/AppFramework/Http/Output.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Http;
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index 408e88583a0..0bd430545d4 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -1,47 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author b108@volgograd "b108@volgograd"
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Juan Pablo Villafáñez <jvillafanez@solidgear.es>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Mitar <mitar.git@tnode.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Oliver Wegner <void1976@gmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Simon Leiner <simon@leiner.me>
- * @author Stanimir Bozhilov <stanimir@audriga.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Http;
@@ -57,17 +20,18 @@ use Symfony\Component\HttpFoundation\IpUtils;
* Class for accessing variables in the request.
* This class provides an immutable object with request variables.
*
- * @property mixed[] cookies
- * @property mixed[] env
- * @property mixed[] files
- * @property string method
- * @property mixed[] parameters
- * @property mixed[] server
+ * @property mixed[] $cookies
+ * @property mixed[] $env
+ * @property mixed[] $files
+ * @property string $method
+ * @property mixed[] $parameters
+ * @property mixed[] $server
+ * @template-implements \ArrayAccess<string,mixed>
*/
class Request implements \ArrayAccess, \Countable, IRequest {
public const USER_AGENT_IE = '/(MSIE)|(Trident)/';
// Microsoft Edge User Agent from https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
- public const USER_AGENT_MS_EDGE = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+ Edge\/[0-9.]+$/';
+ public const USER_AGENT_MS_EDGE = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+ Edge?\/[0-9.]+$/';
// Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
public const USER_AGENT_FIREFOX = '/^Mozilla\/5\.0 \([^)]+\) Gecko\/[0-9.]+ Firefox\/[0-9.]+$/';
// Chrome User Agent from https://developer.chrome.com/multidevice/user-agent
@@ -118,10 +82,10 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @see https://www.php.net/manual/en/reserved.variables.php
*/
public function __construct(array $vars,
- IRequestId $requestId,
- IConfig $config,
- CsrfTokenManager $csrfTokenManager = null,
- string $stream = 'php://input') {
+ IRequestId $requestId,
+ IConfig $config,
+ ?CsrfTokenManager $csrfTokenManager = null,
+ string $stream = 'php://input') {
$this->inputStream = $stream;
$this->items['params'] = [];
$this->requestId = $requestId;
@@ -193,9 +157,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset) {
- return isset($this->items['parameters'][$offset])
- ? $this->items['parameters'][$offset]
- : null;
+ return $this->items['parameters'][$offset] ?? null;
}
/**
@@ -255,9 +217,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
case 'cookies':
case 'urlParams':
case 'method':
- return isset($this->items[$name])
- ? $this->items[$name]
- : null;
+ return $this->items[$name] ?? null;
case 'parameters':
case 'params':
if ($this->isPutStreamContent()) {
@@ -435,8 +395,8 @@ class Request implements \ArrayAccess, \Countable, IRequest {
$this->items['post'] = $params;
}
}
- // Handle application/x-www-form-urlencoded for methods other than GET
- // or post correctly
+ // Handle application/x-www-form-urlencoded for methods other than GET
+ // or post correctly
} elseif ($this->method !== 'GET'
&& $this->method !== 'POST'
&& str_contains($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded')) {
@@ -577,7 +537,14 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise
*/
protected function isTrustedProxy($trustedProxies, $remoteAddress) {
- return IpUtils::checkIp($remoteAddress, $trustedProxies);
+ try {
+ return IpUtils::checkIp($remoteAddress, $trustedProxies);
+ } catch (\Throwable) {
+ // We can not log to our log here as the logger is using `getRemoteAddress` which uses the function, so we would have a cyclic dependency
+ // Reaching this line means `trustedProxies` is in invalid format.
+ error_log('Nextcloud trustedProxies has malformed entries');
+ return false;
+ }
}
/**
@@ -597,14 +564,25 @@ class Request implements \ArrayAccess, \Countable, IRequest {
// only have one default, so we cannot ship an insecure product out of the box
]);
- foreach ($forwardedForHeaders as $header) {
+ // Read the x-forwarded-for headers and values in reverse order as per
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#selecting_an_ip_address
+ foreach (array_reverse($forwardedForHeaders) as $header) {
if (isset($this->server[$header])) {
- foreach (explode(',', $this->server[$header]) as $IP) {
+ foreach (array_reverse(explode(',', $this->server[$header])) as $IP) {
$IP = trim($IP);
+ $colons = substr_count($IP, ':');
+ if ($colons > 1) {
+ // Extract IP from string with brackets and optional port
+ if (preg_match('/^\[(.+?)\](?::\d+)?$/', $IP, $matches) && isset($matches[1])) {
+ $IP = $matches[1];
+ }
+ } elseif ($colons === 1) {
+ // IPv4 with port
+ $IP = substr($IP, 0, strpos($IP, ':'));
+ }
- // remove brackets from IPv6 addresses
- if (str_starts_with($IP, '[') && str_ends_with($IP, ']')) {
- $IP = substr($IP, 1, -1);
+ if ($this->isTrustedProxy($trustedProxies, $IP)) {
+ continue;
}
if (filter_var($IP, FILTER_VALIDATE_IP) !== false) {
@@ -620,14 +598,12 @@ class Request implements \ArrayAccess, \Countable, IRequest {
/**
* Check overwrite condition
- * @param string $type
* @return bool
*/
- private function isOverwriteCondition(string $type = ''): bool {
+ private function isOverwriteCondition(): bool {
$regex = '/' . $this->config->getSystemValueString('overwritecondaddr', '') . '/';
$remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
- return $regex === '//' || preg_match($regex, $remoteAddr) === 1
- || $type !== 'protocol';
+ return $regex === '//' || preg_match($regex, $remoteAddr) === 1;
}
/**
@@ -637,7 +613,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*/
public function getServerProtocol(): string {
if ($this->config->getSystemValueString('overwriteprotocol') !== ''
- && $this->isOverwriteCondition('protocol')) {
+ && $this->isOverwriteCondition()) {
return $this->config->getSystemValueString('overwriteprotocol');
}
diff --git a/lib/private/AppFramework/Http/RequestId.php b/lib/private/AppFramework/Http/RequestId.php
index 70032873a75..c3a99c93591 100644
--- a/lib/private/AppFramework/Http/RequestId.php
+++ b/lib/private/AppFramework/Http/RequestId.php
@@ -2,24 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022, Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Http;
@@ -31,7 +15,7 @@ class RequestId implements IRequestId {
protected string $requestId;
public function __construct(string $uniqueId,
- ISecureRandom $secureRandom) {
+ ISecureRandom $secureRandom) {
$this->requestId = $uniqueId;
$this->secureRandom = $secureRandom;
}
diff --git a/lib/private/AppFramework/Logger.php b/lib/private/AppFramework/Logger.php
index cd70cead7e9..4ae4e6cae34 100644
--- a/lib/private/AppFramework/Logger.php
+++ b/lib/private/AppFramework/Logger.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework;
diff --git a/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php b/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php
index 64b1c7d2fcd..4f1c69b104f 100644
--- a/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php
+++ b/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware;
diff --git a/lib/private/AppFramework/Middleware/CompressionMiddleware.php b/lib/private/AppFramework/Middleware/CompressionMiddleware.php
index b1b89832b00..8bc56beb62e 100644
--- a/lib/private/AppFramework/Middleware/CompressionMiddleware.php
+++ b/lib/private/AppFramework/Middleware/CompressionMiddleware.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware;
diff --git a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
index 35eb0098eed..2b5acc8b75f 100644
--- a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
+++ b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
@@ -1,33 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware;
@@ -40,15 +17,15 @@ use OCP\AppFramework\Middleware;
*/
class MiddlewareDispatcher {
/**
- * @var array array containing all the middlewares
+ * @var Middleware[] array containing all the middlewares
*/
- private $middlewares;
+ private array $middlewares;
/**
* @var int counter which tells us what middleware was executed once an
* exception occurs
*/
- private $middlewareCounter;
+ private int $middlewareCounter;
/**
@@ -64,14 +41,14 @@ class MiddlewareDispatcher {
* Adds a new middleware
* @param Middleware $middleWare the middleware which will be added
*/
- public function registerMiddleware(Middleware $middleWare) {
+ public function registerMiddleware(Middleware $middleWare): void {
$this->middlewares[] = $middleWare;
}
/**
* returns an array with all middleware elements
- * @return array the middlewares
+ * @return Middleware[] the middlewares
*/
public function getMiddlewares(): array {
return $this->middlewares;
@@ -86,7 +63,7 @@ class MiddlewareDispatcher {
* @param string $methodName the name of the method that will be called on
* the controller
*/
- public function beforeController(Controller $controller, string $methodName) {
+ public function beforeController(Controller $controller, string $methodName): void {
// we need to count so that we know which middlewares we have to ask in
// case there is an exception
$middlewareCount = \count($this->middlewares);
diff --git a/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php b/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php
index 4ebdf10f403..17b423164f6 100644
--- a/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php
+++ b/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware;
diff --git a/lib/private/AppFramework/Middleware/OCSMiddleware.php b/lib/private/AppFramework/Middleware/OCSMiddleware.php
index 955b15f80c8..46612bf0d29 100644
--- a/lib/private/AppFramework/Middleware/OCSMiddleware.php
+++ b/lib/private/AppFramework/Middleware/OCSMiddleware.php
@@ -1,27 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware;
diff --git a/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php b/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php
index 8b568f06dd4..c80d06c90ae 100644
--- a/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php
+++ b/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\PublicShare\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php b/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php
index 7acb579938b..41cba1aacd3 100644
--- a/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php
+++ b/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\PublicShare;
diff --git a/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php b/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php
index 574e86a9ca2..4b4425517e0 100644
--- a/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php
@@ -3,28 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
diff --git a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php
index 8bdacf550b6..7b617b22e3c 100644
--- a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author korelstar <korelstar@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Stefan Weil <sw@weilnetz.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware\Security;
@@ -38,6 +19,7 @@ use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\IRequest;
+use OCP\ISession;
use OCP\Security\Bruteforce\IThrottler;
use ReflectionMethod;
@@ -58,9 +40,9 @@ class CORSMiddleware extends Middleware {
private $throttler;
public function __construct(IRequest $request,
- ControllerMethodReflector $reflector,
- Session $session,
- IThrottler $throttler) {
+ ControllerMethodReflector $reflector,
+ Session $session,
+ IThrottler $throttler) {
$this->request = $request;
$this->reflector = $reflector;
$this->session = $session;
@@ -91,6 +73,10 @@ class CORSMiddleware extends Middleware {
if ($this->request->passesCSRFCheck()) {
return;
}
+ // Skip CORS check for requests with AppAPI auth.
+ if ($this->session->getSession() instanceof ISession && $this->session->getSession()->get('app_api') === true) {
+ return;
+ }
$this->session->logout();
try {
if ($user === null || $pass === null || !$this->session->logClientIn($user, $pass, $this->request, $this->throttler)) {
diff --git a/lib/private/AppFramework/Middleware/Security/CSPMiddleware.php b/lib/private/AppFramework/Middleware/Security/CSPMiddleware.php
index ae0dc1f134e..2115c07c0fc 100644
--- a/lib/private/AppFramework/Middleware/Security/CSPMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/CSPMiddleware.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
@@ -44,8 +26,8 @@ class CSPMiddleware extends Middleware {
private $csrfTokenManager;
public function __construct(ContentSecurityPolicyManager $policyManager,
- ContentSecurityPolicyNonceManager $cspNonceManager,
- CsrfTokenManager $csrfTokenManager) {
+ ContentSecurityPolicyNonceManager $cspNonceManager,
+ CsrfTokenManager $csrfTokenManager) {
$this->contentSecurityPolicyManager = $policyManager;
$this->cspNonceManager = $cspNonceManager;
$this->csrfTokenManager = $csrfTokenManager;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php
index 2b9c5a2280b..646a5240bfc 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php
@@ -1,26 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php
index b30ebe58abd..0c6a28134ca 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php
index bbb8e746127..91f1dba874d 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php
index 1f1b9d6e501..6252c914ac1 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php
@@ -1,30 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php
index b466e9a4c7a..7e950f2c976 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php
index a0287c20435..e5a7853a64b 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/ReloadExecutionException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/ReloadExecutionException.php
index 3c65d5f5a88..d12ee96292e 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/ReloadExecutionException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/ReloadExecutionException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php
index 3232980b7e5..c8d70ad4f2b 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php
@@ -1,26 +1,10 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php
index 28092331a22..8ae20ab4e70 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security\Exceptions;
diff --git a/lib/private/AppFramework/Middleware/Security/FeaturePolicyMiddleware.php b/lib/private/AppFramework/Middleware/Security/FeaturePolicyMiddleware.php
index 418d4185184..921630e6326 100644
--- a/lib/private/AppFramework/Middleware/Security/FeaturePolicyMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/FeaturePolicyMiddleware.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
diff --git a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
index a72a7a40016..b95a69dc3e2 100644
--- a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
@@ -55,9 +37,9 @@ class PasswordConfirmationMiddleware extends Middleware {
* @param ITimeFactory $timeFactory
*/
public function __construct(ControllerMethodReflector $reflector,
- ISession $session,
- IUserSession $userSession,
- ITimeFactory $timeFactory) {
+ ISession $session,
+ IUserSession $userSession,
+ ITimeFactory $timeFactory) {
$this->reflector = $reflector;
$this->session = $session;
$this->userSession = $userSession;
diff --git a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php
index 6f84a0c94d0..d593bf5019f 100644
--- a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php
@@ -3,28 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
@@ -40,6 +20,7 @@ use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Middleware;
use OCP\IRequest;
+use OCP\ISession;
use OCP\IUserSession;
use ReflectionMethod;
@@ -70,6 +51,7 @@ class RateLimitingMiddleware extends Middleware {
protected IUserSession $userSession,
protected ControllerMethodReflector $reflector,
protected Limiter $limiter,
+ protected ISession $session,
) {
}
@@ -81,6 +63,11 @@ class RateLimitingMiddleware extends Middleware {
parent::beforeController($controller, $methodName);
$rateLimitIdentifier = get_class($controller) . '::' . $methodName;
+ if ($this->session->exists('app_api_system')) {
+ // Bypass rate limiting for app_api
+ return;
+ }
+
if ($this->userSession->isLoggedIn()) {
$rateLimit = $this->readLimitFromAnnotationOrAttribute($controller, $methodName, 'UserRateThrottle', UserRateLimit::class);
diff --git a/lib/private/AppFramework/Middleware/Security/ReloadExecutionMiddleware.php b/lib/private/AppFramework/Middleware/Security/ReloadExecutionMiddleware.php
index a6a07538345..e770fa4cbff 100644
--- a/lib/private/AppFramework/Middleware/Security/ReloadExecutionMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/ReloadExecutionMiddleware.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
diff --git a/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php
index e6d35dc66f2..e0bb96f132b 100644
--- a/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Middleware\Security;
@@ -38,7 +20,7 @@ class SameSiteCookieMiddleware extends Middleware {
private $reflector;
public function __construct(Request $request,
- ControllerMethodReflector $reflector) {
+ ControllerMethodReflector $reflector) {
$this->request = $request;
$this->reflector = $reflector;
}
diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
index db6c7a02c77..a38ad610fc6 100644
--- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
@@ -1,40 +1,11 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Holger Hees <holger.hees@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julien Veyssier <eneiluj@posteo.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\AppFramework\Middleware\Security;
use OC\AppFramework\Middleware\Security\Exceptions\AppNotEnabledException;
@@ -104,18 +75,18 @@ class SecurityMiddleware extends Middleware {
private $userSession;
public function __construct(IRequest $request,
- ControllerMethodReflector $reflector,
- INavigationManager $navigationManager,
- IURLGenerator $urlGenerator,
- LoggerInterface $logger,
- string $appName,
- bool $isLoggedIn,
- bool $isAdminUser,
- bool $isSubAdmin,
- IAppManager $appManager,
- IL10N $l10n,
- AuthorizedGroupMapper $mapper,
- IUserSession $userSession
+ ControllerMethodReflector $reflector,
+ INavigationManager $navigationManager,
+ IURLGenerator $urlGenerator,
+ LoggerInterface $logger,
+ string $appName,
+ bool $isLoggedIn,
+ bool $isAdminUser,
+ bool $isSubAdmin,
+ IAppManager $appManager,
+ IL10N $l10n,
+ AuthorizedGroupMapper $mapper,
+ IUserSession $userSession
) {
$this->navigationManager = $navigationManager;
$this->request = $request;
@@ -180,20 +151,20 @@ class SecurityMiddleware extends Middleware {
}
}
if (!$authorized) {
- throw new NotAdminException($this->l10n->t('Logged in user must be an admin, a sub admin or gotten special right to access this setting'));
+ throw new NotAdminException($this->l10n->t('Logged in account must be an admin, a sub admin or gotten special right to access this setting'));
}
}
if ($this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class)
&& !$this->isSubAdmin
&& !$this->isAdminUser
&& !$authorized) {
- throw new NotAdminException($this->l10n->t('Logged in user must be an admin or sub admin'));
+ throw new NotAdminException($this->l10n->t('Logged in account must be an admin or sub admin'));
}
if (!$this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class)
&& !$this->hasAnnotationOrAttribute($reflectionMethod, 'NoAdminRequired', NoAdminRequired::class)
&& !$this->isAdminUser
&& !$authorized) {
- throw new NotAdminException($this->l10n->t('Logged in user must be an admin'));
+ throw new NotAdminException($this->l10n->t('Logged in account must be an admin'));
}
}
diff --git a/lib/private/AppFramework/Middleware/SessionMiddleware.php b/lib/private/AppFramework/Middleware/SessionMiddleware.php
index 39f85915901..b7b0fb118c2 100644
--- a/lib/private/AppFramework/Middleware/SessionMiddleware.php
+++ b/lib/private/AppFramework/Middleware/SessionMiddleware.php
@@ -1,30 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Middleware;
@@ -44,7 +24,7 @@ class SessionMiddleware extends Middleware {
private $session;
public function __construct(ControllerMethodReflector $reflector,
- ISession $session) {
+ ISession $session) {
$this->reflector = $reflector;
$this->session = $session;
}
diff --git a/lib/private/AppFramework/OCS/BaseResponse.php b/lib/private/AppFramework/OCS/BaseResponse.php
index 123b73d302c..2e685de856b 100644
--- a/lib/private/AppFramework/OCS/BaseResponse.php
+++ b/lib/private/AppFramework/OCS/BaseResponse.php
@@ -1,29 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Kate Döen <kate.doeen@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\OCS;
@@ -64,10 +42,10 @@ abstract class BaseResponse extends Response {
* @param int|null $itemsPerPage
*/
public function __construct(DataResponse $dataResponse,
- $format = 'xml',
- $statusMessage = null,
- $itemsCount = null,
- $itemsPerPage = null) {
+ $format = 'xml',
+ $statusMessage = null,
+ $itemsCount = null,
+ $itemsPerPage = null) {
parent::__construct();
$this->format = $format;
@@ -159,6 +137,10 @@ abstract class BaseResponse extends Response {
$writer->startElement($k);
$this->toXML($v, $writer);
$writer->endElement();
+ } elseif ($v instanceof \JsonSerializable) {
+ $writer->startElement($k);
+ $this->toXML($v->jsonSerialize(), $writer);
+ $writer->endElement();
} else {
$writer->writeElement($k, $v);
}
diff --git a/lib/private/AppFramework/OCS/V1Response.php b/lib/private/AppFramework/OCS/V1Response.php
index e6b01652789..c56aa9cf478 100644
--- a/lib/private/AppFramework/OCS/V1Response.php
+++ b/lib/private/AppFramework/OCS/V1Response.php
@@ -1,27 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Kate Döen <kate.doeen@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\OCS;
diff --git a/lib/private/AppFramework/OCS/V2Response.php b/lib/private/AppFramework/OCS/V2Response.php
index 1e81a3c7d93..caa8302a673 100644
--- a/lib/private/AppFramework/OCS/V2Response.php
+++ b/lib/private/AppFramework/OCS/V2Response.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Kate Döen <kate.doeen@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\OCS;
diff --git a/lib/private/AppFramework/Routing/RouteActionHandler.php b/lib/private/AppFramework/Routing/RouteActionHandler.php
index 4682d2e9e7e..ec38105a5a0 100644
--- a/lib/private/AppFramework/Routing/RouteActionHandler.php
+++ b/lib/private/AppFramework/Routing/RouteActionHandler.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Routing;
diff --git a/lib/private/AppFramework/Routing/RouteConfig.php b/lib/private/AppFramework/Routing/RouteConfig.php
index 6e3e49e8d99..bdeae93c7c8 100644
--- a/lib/private/AppFramework/Routing/RouteConfig.php
+++ b/lib/private/AppFramework/Routing/RouteConfig.php
@@ -1,32 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Routing;
@@ -136,7 +114,13 @@ class RouteConfig {
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($action);
- $routeName = $routeNamePrefix . $this->appName . '.' . $controller . '.' . $action . $postfix;
+ /*
+ * The route name has to be lowercase, for symfony to match it correctly.
+ * This is required because smyfony allows mixed casing for controller names in the routes.
+ * To avoid breaking all the existing route names, registering and matching will only use the lowercase names.
+ * This is also safe on the PHP side because class and method names collide regardless of the casing.
+ */
+ $routeName = strtolower($routeNamePrefix . $this->appName . '.' . $controller . '.' . $action . $postfix);
$router = $this->router->create($routeName, $url)
->method($verb);
diff --git a/lib/private/AppFramework/Routing/RouteParser.php b/lib/private/AppFramework/Routing/RouteParser.php
index 1b3a6c1255a..49a50852bf3 100644
--- a/lib/private/AppFramework/Routing/RouteParser.php
+++ b/lib/private/AppFramework/Routing/RouteParser.php
@@ -1,26 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Routing;
@@ -100,7 +84,13 @@ class RouteParser {
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($action);
- $routeName = $routeNamePrefix . $appName . '.' . $controller . '.' . $action . $postfix;
+ /*
+ * The route name has to be lowercase, for symfony to match it correctly.
+ * This is required because smyfony allows mixed casing for controller names in the routes.
+ * To avoid breaking all the existing route names, registering and matching will only use the lowercase names.
+ * This is also safe on the PHP side because class and method names collide regardless of the casing.
+ */
+ $routeName = strtolower($routeNamePrefix . $appName . '.' . $controller . '.' . $action . $postfix);
$routeObject = new Route($url);
$routeObject->method($verb);
diff --git a/lib/private/AppFramework/ScopedPsrLogger.php b/lib/private/AppFramework/ScopedPsrLogger.php
index 4ed91cdb6c0..2eaabdbedd7 100644
--- a/lib/private/AppFramework/ScopedPsrLogger.php
+++ b/lib/private/AppFramework/ScopedPsrLogger.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework;
@@ -37,7 +19,7 @@ class ScopedPsrLogger implements LoggerInterface {
private $appId;
public function __construct(LoggerInterface $inner,
- string $appId) {
+ string $appId) {
$this->inner = $inner;
$this->appId = $appId;
}
diff --git a/lib/private/AppFramework/Services/AppConfig.php b/lib/private/AppFramework/Services/AppConfig.php
index 1fc07bc22b0..e47bbc429d0 100644
--- a/lib/private/AppFramework/Services/AppConfig.php
+++ b/lib/private/AppFramework/Services/AppConfig.php
@@ -3,62 +3,327 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Services;
+use InvalidArgumentException;
+use JsonException;
use OCP\AppFramework\Services\IAppConfig;
+use OCP\Exceptions\AppConfigTypeConflictException;
+use OCP\Exceptions\AppConfigUnknownKeyException;
use OCP\IConfig;
class AppConfig implements IAppConfig {
- /** @var IConfig */
- private $config;
+ public function __construct(
+ private IConfig $config,
+ /** @var \OC\AppConfig */
+ private \OCP\IAppConfig $appConfig,
+ private string $appName,
+ ) {
+ }
- /** @var string */
- private $appName;
+ /**
+ * @inheritDoc
+ *
+ * @return string[] list of stored config keys
+ * @since 20.0.0
+ */
+ public function getAppKeys(): array {
+ return $this->appConfig->getKeys($this->appName);
+ }
- public function __construct(IConfig $config, string $appName) {
- $this->config = $config;
- $this->appName = $appName;
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param bool|null $lazy TRUE to search within lazy loaded config, NULL to search within all config
+ *
+ * @return bool TRUE if key exists
+ * @since 29.0.0
+ */
+ public function hasAppKey(string $key, ?bool $lazy = false): bool {
+ return $this->appConfig->hasKey($this->appName, $key, $lazy);
}
- public function getAppKeys(): array {
- return $this->config->getAppKeys($this->appName);
+ /**
+ * @param string $key config key
+ * @param bool|null $lazy TRUE to search within lazy loaded config, NULL to search within all config
+ *
+ * @return bool
+ * @throws AppConfigUnknownKeyException if config key is not known
+ * @since 29.0.0
+ */
+ public function isSensitive(string $key, ?bool $lazy = false): bool {
+ return $this->appConfig->isSensitive($this->appName, $key, $lazy);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ *
+ * @return bool TRUE if config is lazy loaded
+ * @throws AppConfigUnknownKeyException if config key is not known
+ * @see \OCP\IAppConfig for details about lazy loading
+ * @since 29.0.0
+ */
+ public function isLazy(string $key): bool {
+ return $this->appConfig->isLazy($this->appName, $key);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config keys prefix to search
+ * @param bool $filtered TRUE to hide sensitive config values. Value are replaced by {@see IConfig::SENSITIVE_VALUE}
+ *
+ * @return array<string, string|int|float|bool|array> [configKey => configValue]
+ * @since 29.0.0
+ */
+ public function getAllAppValues(string $key = '', bool $filtered = false): array {
+ return $this->appConfig->getAllValues($this->appName, $key, $filtered);
}
+ /**
+ * @inheritDoc
+ *
+ * @param string $key the key of the value, under which will be saved
+ * @param string $value the value that should be stored
+ * @since 20.0.0
+ * @deprecated 29.0.0 use {@see setAppValueString()}
+ */
public function setAppValue(string $key, string $value): void {
- $this->config->setAppValue($this->appName, $key, $value);
+ /** @psalm-suppress InternalMethod */
+ $this->appConfig->setValueMixed($this->appName, $key, $value);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param string $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function setAppValueString(
+ string $key,
+ string $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->appConfig->setValueString($this->appName, $key, $value, $lazy, $sensitive);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param int $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function setAppValueInt(
+ string $key,
+ int $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->appConfig->setValueInt($this->appName, $key, $value, $lazy, $sensitive);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param float $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function setAppValueFloat(
+ string $key,
+ float $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->appConfig->setValueFloat($this->appName, $key, $value, $lazy, $sensitive);
}
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param bool $value config value
+ * @param bool $lazy set config as lazy loaded
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function setAppValueBool(
+ string $key,
+ bool $value,
+ bool $lazy = false
+ ): bool {
+ return $this->appConfig->setValueBool($this->appName, $key, $value, $lazy);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param array $value config value
+ * @param bool $lazy set config as lazy loaded
+ * @param bool $sensitive if TRUE value will be hidden when listing config values.
+ *
+ * @return bool TRUE if value was different, therefor updated in database
+ * @throws AppConfigTypeConflictException if type from database is not VALUE_MIXED and different from the requested one
+ * @throws JsonException
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function setAppValueArray(
+ string $key,
+ array $value,
+ bool $lazy = false,
+ bool $sensitive = false
+ ): bool {
+ return $this->appConfig->setValueArray($this->appName, $key, $value, $lazy, $sensitive);
+ }
+
+ /**
+ * @param string $key
+ * @param string $default
+ *
+ * @since 20.0.0
+ * @deprecated 29.0.0 use {@see getAppValueString()}
+ * @return string
+ */
public function getAppValue(string $key, string $default = ''): string {
- return $this->config->getAppValue($this->appName, $key, $default);
+ /** @psalm-suppress InternalMethod */
+ /** @psalm-suppress UndefinedInterfaceMethod */
+ return $this->appConfig->getValueMixed($this->appName, $key, $default);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param string $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return string stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function getAppValueString(string $key, string $default = '', bool $lazy = false): string {
+ return $this->appConfig->getValueString($this->appName, $key, $default, $lazy);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param int $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return int stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function getAppValueInt(string $key, int $default = 0, bool $lazy = false): int {
+ return $this->appConfig->getValueInt($this->appName, $key, $default, $lazy);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param float $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return float stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function getAppValueFloat(string $key, float $default = 0, bool $lazy = false): float {
+ return $this->appConfig->getValueFloat($this->appName, $key, $default, $lazy);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param bool $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return bool stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function getAppValueBool(string $key, bool $default = false, bool $lazy = false): bool {
+ return $this->appConfig->getValueBool($this->appName, $key, $default, $lazy);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $key config key
+ * @param array $default default value
+ * @param bool $lazy search within lazy loaded config
+ *
+ * @return array stored config value or $default if not set in database
+ * @throws InvalidArgumentException if one of the argument format is invalid
+ * @throws AppConfigTypeConflictException in case of conflict with the value type set in database
+ * @since 29.0.0
+ * @see \OCP\IAppConfig for explanation about lazy loading
+ */
+ public function getAppValueArray(string $key, array $default = [], bool $lazy = false): array {
+ return $this->appConfig->getValueArray($this->appName, $key, $default, $lazy);
}
+ /**
+ * @inheritDoc
+ *
+ * @param string $key the key of the value, under which it was saved
+ * @since 20.0.0
+ */
public function deleteAppValue(string $key): void {
- $this->config->deleteAppValue($this->appName, $key);
+ $this->appConfig->deleteKey($this->appName, $key);
}
+ /**
+ * @inheritDoc
+ *
+ * @since 20.0.0
+ */
public function deleteAppValues(): void {
- $this->config->deleteAppValues($this->appName);
+ $this->appConfig->deleteApp($this->appName);
}
public function setUserValue(string $userId, string $key, string $value, ?string $preCondition = null): void {
diff --git a/lib/private/AppFramework/Services/InitialState.php b/lib/private/AppFramework/Services/InitialState.php
index 9a44db606ea..da225b612cf 100644
--- a/lib/private/AppFramework/Services/InitialState.php
+++ b/lib/private/AppFramework/Services/InitialState.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Services;
diff --git a/lib/private/AppFramework/Utility/ControllerMethodReflector.php b/lib/private/AppFramework/Utility/ControllerMethodReflector.php
index b76b3c33c42..9c08f58b384 100644
--- a/lib/private/AppFramework/Utility/ControllerMethodReflector.php
+++ b/lib/private/AppFramework/Utility/ControllerMethodReflector.php
@@ -1,35 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Utility;
@@ -42,6 +17,7 @@ class ControllerMethodReflector implements IControllerMethodReflector {
public $annotations = [];
private $types = [];
private $parameters = [];
+ private array $ranges = [];
/**
* @param object $object an object or classname
@@ -54,26 +30,38 @@ class ControllerMethodReflector implements IControllerMethodReflector {
if ($docs !== false) {
// extract everything prefixed by @ and first letter uppercase
preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
- foreach ($matches['annotation'] as $key => $annontation) {
- $annontation = strtolower($annontation);
+ foreach ($matches['annotation'] as $key => $annotation) {
+ $annotation = strtolower($annotation);
$annotationValue = $matches['parameter'][$key];
- if (isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[\strlen($annotationValue) - 1] === ')') {
+ if (str_starts_with($annotationValue, '(') && str_ends_with($annotationValue, ')')) {
$cutString = substr($annotationValue, 1, -1);
$cutString = str_replace(' ', '', $cutString);
- $splittedArray = explode(',', $cutString);
- foreach ($splittedArray as $annotationValues) {
+ $splitArray = explode(',', $cutString);
+ foreach ($splitArray as $annotationValues) {
[$key, $value] = explode('=', $annotationValues);
- $this->annotations[$annontation][$key] = $value;
+ $this->annotations[$annotation][$key] = $value;
}
continue;
}
- $this->annotations[$annontation] = [$annotationValue];
+ $this->annotations[$annotation] = [$annotationValue];
}
// extract type parameter information
preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
$this->types = array_combine($matches['var'], $matches['type']);
+ preg_match_all('/@psalm-param\h+(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>\h+\$(?P<var>\w+)/', $docs, $matches);
+ foreach ($matches['var'] as $index => $varName) {
+ if ($matches['type'][$index] !== 'int') {
+ // only int ranges are possible at the moment
+ // @see https://psalm.dev/docs/annotating_code/type_syntax/scalar_types
+ continue;
+ }
+ $this->ranges[$varName] = [
+ 'min' => $matches['rangeMin'][$index] === 'min' ? PHP_INT_MIN : (int)$matches['rangeMin'][$index],
+ 'max' => $matches['rangeMax'][$index] === 'max' ? PHP_INT_MAX : (int)$matches['rangeMax'][$index],
+ ];
+ }
}
foreach ($reflection->getParameters() as $param) {
@@ -106,6 +94,14 @@ class ControllerMethodReflector implements IControllerMethodReflector {
return null;
}
+ public function getRange(string $parameter): ?array {
+ if (array_key_exists($parameter, $this->ranges)) {
+ return $this->ranges[$parameter];
+ }
+
+ return null;
+ }
+
/**
* @return array the arguments of the method with key => default value
*/
diff --git a/lib/private/AppFramework/Utility/QueryNotFoundException.php b/lib/private/AppFramework/Utility/QueryNotFoundException.php
index 04faaa51a4b..4d2df14ebc8 100644
--- a/lib/private/AppFramework/Utility/QueryNotFoundException.php
+++ b/lib/private/AppFramework/Utility/QueryNotFoundException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023, Ferdinand Thiessen <rpm@fthiessen.de>
- *
- * @author Ferdinand Thiessen <rpm@fthiessen.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\AppFramework\Utility;
diff --git a/lib/private/AppFramework/Utility/SimpleContainer.php b/lib/private/AppFramework/Utility/SimpleContainer.php
index 7aa5cb83926..bf0ef36d13c 100644
--- a/lib/private/AppFramework/Utility/SimpleContainer.php
+++ b/lib/private/AppFramework/Utility/SimpleContainer.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Utility;
@@ -37,8 +15,8 @@ use Pimple\Container;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionException;
-use ReflectionParameter;
use ReflectionNamedType;
+use ReflectionParameter;
use function class_exists;
/**
@@ -60,7 +38,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
* @psalm-param S $id
* @psalm-return (S is class-string<T> ? T : mixed)
*/
- public function get(string $id) {
+ public function get(string $id): mixed {
return $this->query($id);
}
@@ -105,6 +83,11 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
try {
return $this->query($resolveName);
} catch (QueryException $e2) {
+ // Pass null if typed and nullable
+ if ($parameter->allowsNull() && ($parameterType instanceof ReflectionNamedType)) {
+ return null;
+ }
+
// don't lose the error we got while trying to query by type
throw new QueryException($e->getMessage(), (int) $e->getCode(), $e);
}
@@ -223,8 +206,8 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
/**
* @deprecated 20.0.0 use \OCP\IContainer::registerService
*/
- public function offsetSet($id, $service): void {
- $this->container->offsetSet($id, $service);
+ public function offsetSet($offset, $value): void {
+ $this->container->offsetSet($offset, $value);
}
/**
diff --git a/lib/private/AppFramework/Utility/TimeFactory.php b/lib/private/AppFramework/Utility/TimeFactory.php
index 1e4655dd1cd..0584fd05ef9 100644
--- a/lib/private/AppFramework/Utility/TimeFactory.php
+++ b/lib/private/AppFramework/Utility/TimeFactory.php
@@ -1,30 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2022, Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\Utility;
@@ -34,7 +14,7 @@ use OCP\AppFramework\Utility\ITimeFactory;
* Use this to get a timestamp or DateTime object in code to remain testable
*
* @since 8.0.0
- * @since 26.0.0 Extends the \Psr\Clock\ClockInterface interface
+ * @since 27.0.0 Implements the \Psr\Clock\ClockInterface interface
* @ref https://www.php-fig.org/psr/psr-20/#21-clockinterface
*/
class TimeFactory implements ITimeFactory {
@@ -60,7 +40,7 @@ class TimeFactory implements ITimeFactory {
* @since 15.0.0
* @deprecated 26.0.0 {@see ITimeFactory::now()}
*/
- public function getDateTime(string $time = 'now', \DateTimeZone $timezone = null): \DateTime {
+ public function getDateTime(string $time = 'now', ?\DateTimeZone $timezone = null): \DateTime {
return new \DateTime($time, $timezone);
}
@@ -73,4 +53,11 @@ class TimeFactory implements ITimeFactory {
return $clone;
}
+
+ public function getTimeZone(?string $timezone = null): \DateTimeZone {
+ if ($timezone !== null) {
+ return new \DateTimeZone($timezone);
+ }
+ return $this->timezone;
+ }
}
diff --git a/lib/private/AppScriptDependency.php b/lib/private/AppScriptDependency.php
index 35878e85b49..380816f21ac 100644
--- a/lib/private/AppScriptDependency.php
+++ b/lib/private/AppScriptDependency.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2021, Jonas Meurer <jonas@freesources.org>
- *
- * @author Jonas Meurer <jonas@freesources.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/AppScriptSort.php b/lib/private/AppScriptSort.php
index c42d02d485d..eda41e97445 100644
--- a/lib/private/AppScriptSort.php
+++ b/lib/private/AppScriptSort.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2021, Jonas Meurer <jonas@freesources.org>
- *
- * @author Jonas Meurer <jonas@freesources.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
@@ -46,10 +29,10 @@ class AppScriptSort {
* @param array $sortedScriptDeps
*/
private function topSortVisit(
- AppScriptDependency $app,
- array &$parents,
- array &$scriptDeps,
- array &$sortedScriptDeps): void {
+ AppScriptDependency $app,
+ array &$parents,
+ array &$scriptDeps,
+ array &$sortedScriptDeps): void {
// Detect and log circular dependencies
if (isset($parents[$app->getId()])) {
$this->logger->error('Circular dependency in app scripts at app ' . $app->getId());
diff --git a/lib/private/Archive/Archive.php b/lib/private/Archive/Archive.php
index ff6456113f8..26b940be410 100644
--- a/lib/private/Archive/Archive.php
+++ b/lib/private/Archive/Archive.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Archive;
diff --git a/lib/private/Archive/TAR.php b/lib/private/Archive/TAR.php
index 9dc906384e0..e08720a75a5 100644
--- a/lib/private/Archive/TAR.php
+++ b/lib/private/Archive/TAR.php
@@ -1,34 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Remco Brenninkmeijer <requist1@starmail.nl>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Archive;
@@ -48,15 +23,9 @@ class TAR extends Archive {
*/
private $cachedHeaders = false;
- /**
- * @var \Archive_Tar
- */
- private $tar = null;
+ private \Archive_Tar $tar;
- /**
- * @var string
- */
- private $path;
+ private string $path;
public function __construct(string $source) {
$types = [null, 'gz', 'bz2'];
@@ -137,7 +106,7 @@ class TAR extends Archive {
$tmp = \OC::$server->getTempManager()->getTemporaryFolder();
$this->tar->extract($tmp);
rename($tmp . $source, $tmp . $dest);
- $this->tar = null;
+ $this->tar->_close();
unlink($this->path);
$types = [null, 'gz', 'bz'];
$this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
@@ -197,7 +166,7 @@ class TAR extends Archive {
if ($pos = strpos($result, '/')) {
$result = substr($result, 0, $pos + 1);
}
- if (array_search($result, $folderContent) === false) {
+ if (!in_array($result, $folderContent)) {
$folderContent[] = $result;
}
}
@@ -209,11 +178,16 @@ class TAR extends Archive {
* get all files in the archive
*/
public function getFiles(): array {
- if ($this->fileList) {
+ if ($this->fileList !== false) {
return $this->fileList;
}
- if (!$this->cachedHeaders) {
- $this->cachedHeaders = $this->tar->listContent();
+ if ($this->cachedHeaders === false) {
+ $headers = $this->tar->listContent();
+ if (is_array($headers)) {
+ $this->cachedHeaders = $headers;
+ } else {
+ return [];
+ }
}
$files = [];
foreach ($this->cachedHeaders as $header) {
@@ -230,6 +204,7 @@ class TAR extends Archive {
*/
public function getFile(string $path) {
$string = $this->tar->extractInString($path);
+ /** @var ?string $string */
if (is_string($string)) {
return $string;
} else {
@@ -269,7 +244,7 @@ class TAR extends Archive {
*/
public function fileExists(string $path): bool {
$files = $this->getFiles();
- if ((array_search($path, $files) !== false) or (array_search($path . '/', $files) !== false)) {
+ if ((in_array($path, $files)) or (in_array($path . '/', $files))) {
return true;
} else {
$folderPath = rtrim($path, '/') . '/';
@@ -300,7 +275,6 @@ class TAR extends Archive {
$tmp = \OC::$server->getTempManager()->getTemporaryFolder();
$this->tar->extract($tmp);
\OCP\Files::rmdirr($tmp . $path);
- $this->tar = null;
unlink($this->path);
$this->reopen();
$this->tar->createModify([$tmp], '', $tmp);
@@ -347,10 +321,7 @@ class TAR extends Archive {
* reopen the archive to ensure everything is written
*/
private function reopen(): void {
- if ($this->tar) {
- $this->tar->_close();
- $this->tar = null;
- }
+ $this->tar->_close();
$types = [null, 'gz', 'bz'];
$this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
}
@@ -359,7 +330,7 @@ class TAR extends Archive {
* Get error object from archive_tar.
*/
public function getError(): ?\PEAR_Error {
- if ($this->tar instanceof \Archive_Tar && $this->tar->error_object instanceof \PEAR_Error) {
+ if ($this->tar->error_object instanceof \PEAR_Error) {
return $this->tar->error_object;
}
return null;
diff --git a/lib/private/Archive/ZIP.php b/lib/private/Archive/ZIP.php
index f98009ecc3a..52352f9505e 100644
--- a/lib/private/Archive/ZIP.php
+++ b/lib/private/Archive/ZIP.php
@@ -1,33 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Archive;
diff --git a/lib/private/Authentication/Events/ARemoteWipeEvent.php b/lib/private/Authentication/Events/ARemoteWipeEvent.php
index e36b7d1087b..ba1e93d26ae 100644
--- a/lib/private/Authentication/Events/ARemoteWipeEvent.php
+++ b/lib/private/Authentication/Events/ARemoteWipeEvent.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Events/AppPasswordCreatedEvent.php b/lib/private/Authentication/Events/AppPasswordCreatedEvent.php
index a90abd25026..bf502ade0cc 100644
--- a/lib/private/Authentication/Events/AppPasswordCreatedEvent.php
+++ b/lib/private/Authentication/Events/AppPasswordCreatedEvent.php
@@ -3,38 +3,19 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
-use OC\Authentication\Token\IToken;
+use OCP\Authentication\Token\IToken;
use OCP\EventDispatcher\Event;
class AppPasswordCreatedEvent extends Event {
- /** @var IToken */
- private $token;
-
- public function __construct(IToken $token) {
+ public function __construct(
+ private IToken $token,
+ ) {
parent::__construct();
- $this->token = $token;
}
public function getToken(): IToken {
diff --git a/lib/private/Authentication/Events/LoginFailed.php b/lib/private/Authentication/Events/LoginFailed.php
index ef702e40a59..23eeaef87ad 100644
--- a/lib/private/Authentication/Events/LoginFailed.php
+++ b/lib/private/Authentication/Events/LoginFailed.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Events/RemoteWipeFinished.php b/lib/private/Authentication/Events/RemoteWipeFinished.php
index 10e72de096c..9704ebff3f5 100644
--- a/lib/private/Authentication/Events/RemoteWipeFinished.php
+++ b/lib/private/Authentication/Events/RemoteWipeFinished.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Events/RemoteWipeStarted.php b/lib/private/Authentication/Events/RemoteWipeStarted.php
index 273a319b1fb..ad0f72f0e09 100644
--- a/lib/private/Authentication/Events/RemoteWipeStarted.php
+++ b/lib/private/Authentication/Events/RemoteWipeStarted.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Exceptions/ExpiredTokenException.php b/lib/private/Authentication/Exceptions/ExpiredTokenException.php
index 0dc92b45920..eed2358d29d 100644
--- a/lib/private/Authentication/Exceptions/ExpiredTokenException.php
+++ b/lib/private/Authentication/Exceptions/ExpiredTokenException.php
@@ -3,41 +3,26 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
use OC\Authentication\Token\IToken;
-class ExpiredTokenException extends InvalidTokenException {
- /** @var IToken */
- private $token;
-
- public function __construct(IToken $token) {
- parent::__construct();
-
- $this->token = $token;
+/**
+ * @deprecated 28.0.0 use {@see \OCP\Authentication\Exceptions\ExpiredTokenException} instead
+ */
+class ExpiredTokenException extends \OCP\Authentication\Exceptions\ExpiredTokenException {
+ public function __construct(
+ IToken $token,
+ ) {
+ parent::__construct($token);
}
public function getToken(): IToken {
- return $this->token;
+ $token = parent::getToken();
+ /** @var IToken $token We know that we passed OC interface from constructor */
+ return $token;
}
}
diff --git a/lib/private/Authentication/Exceptions/InvalidProviderException.php b/lib/private/Authentication/Exceptions/InvalidProviderException.php
index 86b44e4d0e2..9dbf3a7782a 100644
--- a/lib/private/Authentication/Exceptions/InvalidProviderException.php
+++ b/lib/private/Authentication/Exceptions/InvalidProviderException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
@@ -29,7 +12,7 @@ use Exception;
use Throwable;
class InvalidProviderException extends Exception {
- public function __construct(string $providerId, Throwable $previous = null) {
+ public function __construct(string $providerId, ?Throwable $previous = null) {
parent::__construct("The provider '$providerId' does not exist'", 0, $previous);
}
}
diff --git a/lib/private/Authentication/Exceptions/InvalidTokenException.php b/lib/private/Authentication/Exceptions/InvalidTokenException.php
index acaabff6b88..d23f767e69b 100644
--- a/lib/private/Authentication/Exceptions/InvalidTokenException.php
+++ b/lib/private/Authentication/Exceptions/InvalidTokenException.php
@@ -1,30 +1,15 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
-use Exception;
-
-class InvalidTokenException extends Exception {
+/**
+ * @deprecated 28.0.0 use OCP version instead
+ */
+class InvalidTokenException extends \OCP\Authentication\Exceptions\InvalidTokenException {
}
diff --git a/lib/private/Authentication/Exceptions/LoginRequiredException.php b/lib/private/Authentication/Exceptions/LoginRequiredException.php
index cc3e8636214..d18ec4f1fbf 100644
--- a/lib/private/Authentication/Exceptions/LoginRequiredException.php
+++ b/lib/private/Authentication/Exceptions/LoginRequiredException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
index 28829390f70..ec833a5a3d0 100644
--- a/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
+++ b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/PasswordlessTokenException.php b/lib/private/Authentication/Exceptions/PasswordlessTokenException.php
index c974cc3d6fd..a11e9a5f8d5 100644
--- a/lib/private/Authentication/Exceptions/PasswordlessTokenException.php
+++ b/lib/private/Authentication/Exceptions/PasswordlessTokenException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php b/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php
index 7710673ce7c..aa331f31fd0 100644
--- a/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php
+++ b/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php b/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php
index 9733c4547b4..8873b2c9f85 100644
--- a/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php
+++ b/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php b/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php
index 520372f3087..257f59772fc 100644
--- a/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php
+++ b/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/WipeTokenException.php b/lib/private/Authentication/Exceptions/WipeTokenException.php
index 1c60ab9da78..6bf0565434a 100644
--- a/lib/private/Authentication/Exceptions/WipeTokenException.php
+++ b/lib/private/Authentication/Exceptions/WipeTokenException.php
@@ -3,41 +3,26 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
use OC\Authentication\Token\IToken;
-class WipeTokenException extends InvalidTokenException {
- /** @var IToken */
- private $token;
-
- public function __construct(IToken $token) {
- parent::__construct();
-
- $this->token = $token;
+/**
+ * @deprecated 28.0.0 use {@see \OCP\Authentication\Exceptions\WipeTokenException} instead
+ */
+class WipeTokenException extends \OCP\Authentication\Exceptions\WipeTokenException {
+ public function __construct(
+ IToken $token,
+ ) {
+ parent::__construct($token);
}
public function getToken(): IToken {
- return $this->token;
+ $token = parent::getToken();
+ /** @var IToken $token We know that we passed OC interface from constructor */
+ return $token;
}
}
diff --git a/lib/private/Authentication/Listeners/LoginFailedListener.php b/lib/private/Authentication/Listeners/LoginFailedListener.php
index d2971e07b55..0358887bb86 100644
--- a/lib/private/Authentication/Listeners/LoginFailedListener.php
+++ b/lib/private/Authentication/Listeners/LoginFailedListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
diff --git a/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php b/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
index edebb2a2641..457630eff27 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -46,7 +28,7 @@ class RemoteWipeActivityListener implements IEventListener {
private $logger;
public function __construct(IActvityManager $activityManager,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->activityManager = $activityManager;
$this->logger = $logger;
}
diff --git a/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php b/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
index cba2b183589..96878c44123 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -57,9 +39,9 @@ class RemoteWipeEmailListener implements IEventListener {
private $logger;
public function __construct(IMailer $mailer,
- IUserManager $userManager,
- IL10nFactory $l10nFactory,
- LoggerInterface $logger) {
+ IUserManager $userManager,
+ IL10nFactory $l10nFactory,
+ LoggerInterface $logger) {
$this->mailer = $mailer;
$this->userManager = $userManager;
$this->l10n = $l10nFactory->get('core');
diff --git a/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php b/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
index 81feab32746..d95bcd98cf9 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -45,7 +27,7 @@ class RemoteWipeNotificationsListener implements IEventListener {
private $timeFactory;
public function __construct(INotificationManager $notificationManager,
- ITimeFactory $timeFactory) {
+ ITimeFactory $timeFactory) {
$this->notificationManager = $notificationManager;
$this->timeFactory = $timeFactory;
}
diff --git a/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
index 5e657be0763..697aea71c6d 100644
--- a/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -34,6 +17,7 @@ use OCP\Files\Storage\IStorage;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\UserDeletedEvent;
+/** @template-implements IEventListener<BeforeUserDeletedEvent|UserDeletedEvent> */
class UserDeletedFilesCleanupListener implements IEventListener {
/** @var array<string,IStorage> */
private $homeStorageCache = [];
@@ -55,7 +39,7 @@ class UserDeletedFilesCleanupListener implements IEventListener {
$userHome = $this->mountProviderCollection->getHomeMountForUser($event->getUser());
$storage = $userHome->getStorage();
if (!$storage) {
- throw new \Exception("User has no home storage");
+ throw new \Exception("Account has no home storage");
}
// remove all wrappers, so we do the delete directly on the home storage bypassing any wrapper
diff --git a/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
index e478c21239f..5f21c640780 100644
--- a/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
diff --git a/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
index a09a08568d5..3631c04432c 100644
--- a/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -44,7 +26,7 @@ class UserDeletedTokenCleanupListener implements IEventListener {
private $logger;
public function __construct(Manager $manager,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->manager = $manager;
$this->logger = $logger;
}
diff --git a/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php
index 4927c3ac7f9..67f8ff7cfcd 100644
--- a/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -31,6 +14,7 @@ use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\User\Events\UserDeletedEvent;
+/** @template-implements IEventListener<UserDeletedEvent> */
class UserDeletedWebAuthnCleanupListener implements IEventListener {
/** @var PublicKeyCredentialMapper */
private $credentialMapper;
diff --git a/lib/private/Authentication/Listeners/UserLoggedInListener.php b/lib/private/Authentication/Listeners/UserLoggedInListener.php
index df030c44749..a8d4baeafa1 100644
--- a/lib/private/Authentication/Listeners/UserLoggedInListener.php
+++ b/lib/private/Authentication/Listeners/UserLoggedInListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
diff --git a/lib/private/Authentication/Login/ALoginCommand.php b/lib/private/Authentication/Login/ALoginCommand.php
index 7944eac1b62..a9f51f0da9e 100644
--- a/lib/private/Authentication/Login/ALoginCommand.php
+++ b/lib/private/Authentication/Login/ALoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/Chain.php b/lib/private/Authentication/Login/Chain.php
index 3c3179472c4..abd24287a6c 100644
--- a/lib/private/Authentication/Login/Chain.php
+++ b/lib/private/Authentication/Login/Chain.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -63,17 +46,17 @@ class Chain {
private $finishRememberedLoginCommand;
public function __construct(PreLoginHookCommand $preLoginHookCommand,
- UserDisabledCheckCommand $userDisabledCheckCommand,
- UidLoginCommand $uidLoginCommand,
- EmailLoginCommand $emailLoginCommand,
- LoggedInCheckCommand $loggedInCheckCommand,
- CompleteLoginCommand $completeLoginCommand,
- CreateSessionTokenCommand $createSessionTokenCommand,
- ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
- UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
- SetUserTimezoneCommand $setUserTimezoneCommand,
- TwoFactorCommand $twoFactorCommand,
- FinishRememberedLoginCommand $finishRememberedLoginCommand
+ UserDisabledCheckCommand $userDisabledCheckCommand,
+ UidLoginCommand $uidLoginCommand,
+ EmailLoginCommand $emailLoginCommand,
+ LoggedInCheckCommand $loggedInCheckCommand,
+ CompleteLoginCommand $completeLoginCommand,
+ CreateSessionTokenCommand $createSessionTokenCommand,
+ ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
+ UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
+ SetUserTimezoneCommand $setUserTimezoneCommand,
+ TwoFactorCommand $twoFactorCommand,
+ FinishRememberedLoginCommand $finishRememberedLoginCommand
) {
$this->preLoginHookCommand = $preLoginHookCommand;
$this->userDisabledCheckCommand = $userDisabledCheckCommand;
diff --git a/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php b/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php
index 1643b5af1d5..40369c383ac 100644
--- a/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php
+++ b/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/CompleteLoginCommand.php b/lib/private/Authentication/Login/CompleteLoginCommand.php
index 46f7f1a3fa7..ec6fdf75f40 100644
--- a/lib/private/Authentication/Login/CompleteLoginCommand.php
+++ b/lib/private/Authentication/Login/CompleteLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/CreateSessionTokenCommand.php b/lib/private/Authentication/Login/CreateSessionTokenCommand.php
index ba237dfbf20..7619ad90d93 100644
--- a/lib/private/Authentication/Login/CreateSessionTokenCommand.php
+++ b/lib/private/Authentication/Login/CreateSessionTokenCommand.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -39,7 +20,7 @@ class CreateSessionTokenCommand extends ALoginCommand {
private $userSession;
public function __construct(IConfig $config,
- Session $userSession) {
+ Session $userSession) {
$this->config = $config;
$this->userSession = $userSession;
}
diff --git a/lib/private/Authentication/Login/EmailLoginCommand.php b/lib/private/Authentication/Login/EmailLoginCommand.php
index 315fe450697..96cb39277fd 100644
--- a/lib/private/Authentication/Login/EmailLoginCommand.php
+++ b/lib/private/Authentication/Login/EmailLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/FinishRememberedLoginCommand.php b/lib/private/Authentication/Login/FinishRememberedLoginCommand.php
index 56ea042a662..3eb1f8f1a65 100644
--- a/lib/private/Authentication/Login/FinishRememberedLoginCommand.php
+++ b/lib/private/Authentication/Login/FinishRememberedLoginCommand.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/LoggedInCheckCommand.php b/lib/private/Authentication/Login/LoggedInCheckCommand.php
index dc1a4d2d883..b6b59ced6ce 100644
--- a/lib/private/Authentication/Login/LoggedInCheckCommand.php
+++ b/lib/private/Authentication/Login/LoggedInCheckCommand.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -39,7 +20,7 @@ class LoggedInCheckCommand extends ALoginCommand {
private $dispatcher;
public function __construct(LoggerInterface $logger,
- IEventDispatcher $dispatcher) {
+ IEventDispatcher $dispatcher) {
$this->logger = $logger;
$this->dispatcher = $dispatcher;
}
diff --git a/lib/private/Authentication/Login/LoginData.php b/lib/private/Authentication/Login/LoginData.php
index 240a1dc6476..1ad97a9d559 100644
--- a/lib/private/Authentication/Login/LoginData.php
+++ b/lib/private/Authentication/Login/LoginData.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -55,11 +37,11 @@ class LoginData {
private $rememberLogin = true;
public function __construct(IRequest $request,
- string $username,
- ?string $password,
- string $redirectUrl = null,
- string $timeZone = '',
- string $timeZoneOffset = '') {
+ string $username,
+ ?string $password,
+ ?string $redirectUrl = null,
+ string $timeZone = '',
+ string $timeZoneOffset = '') {
$this->request = $request;
$this->username = $username;
$this->password = $password;
diff --git a/lib/private/Authentication/Login/LoginResult.php b/lib/private/Authentication/Login/LoginResult.php
index dec012c2fc9..95e87b520e3 100644
--- a/lib/private/Authentication/Login/LoginResult.php
+++ b/lib/private/Authentication/Login/LoginResult.php
@@ -3,28 +3,13 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
+use OC\Core\Controller\LoginController;
+
class LoginResult {
/** @var bool */
private $success;
@@ -59,7 +44,10 @@ class LoginResult {
return $result;
}
- public static function failure(LoginData $data, string $msg = null): LoginResult {
+ /**
+ * @param LoginController::LOGIN_MSG_*|null $msg
+ */
+ public static function failure(LoginData $data, ?string $msg = null): LoginResult {
$result = new static(false, $data);
if ($msg !== null) {
$result->setErrorMessage($msg);
diff --git a/lib/private/Authentication/Login/PreLoginHookCommand.php b/lib/private/Authentication/Login/PreLoginHookCommand.php
index 21c97433f5a..d5aa174094d 100644
--- a/lib/private/Authentication/Login/PreLoginHookCommand.php
+++ b/lib/private/Authentication/Login/PreLoginHookCommand.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/SetUserTimezoneCommand.php b/lib/private/Authentication/Login/SetUserTimezoneCommand.php
index f68fce1771e..90bc444ae7d 100644
--- a/lib/private/Authentication/Login/SetUserTimezoneCommand.php
+++ b/lib/private/Authentication/Login/SetUserTimezoneCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -36,7 +19,7 @@ class SetUserTimezoneCommand extends ALoginCommand {
private $session;
public function __construct(IConfig $config,
- ISession $session) {
+ ISession $session) {
$this->config = $config;
$this->session = $session;
}
diff --git a/lib/private/Authentication/Login/TwoFactorCommand.php b/lib/private/Authentication/Login/TwoFactorCommand.php
index 256d88ffa81..fc5285221a2 100644
--- a/lib/private/Authentication/Login/TwoFactorCommand.php
+++ b/lib/private/Authentication/Login/TwoFactorCommand.php
@@ -3,35 +3,17 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
-use function array_pop;
-use function count;
use OC\Authentication\TwoFactorAuth\Manager;
use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\IURLGenerator;
+use function array_pop;
+use function count;
class TwoFactorCommand extends ALoginCommand {
/** @var Manager */
@@ -44,8 +26,8 @@ class TwoFactorCommand extends ALoginCommand {
private $urlGenerator;
public function __construct(Manager $twoFactorManager,
- MandatoryTwoFactor $mandatoryTwoFactor,
- IURLGenerator $urlGenerator) {
+ MandatoryTwoFactor $mandatoryTwoFactor,
+ IURLGenerator $urlGenerator) {
$this->twoFactorManager = $twoFactorManager;
$this->mandatoryTwoFactor = $mandatoryTwoFactor;
$this->urlGenerator = $urlGenerator;
diff --git a/lib/private/Authentication/Login/UidLoginCommand.php b/lib/private/Authentication/Login/UidLoginCommand.php
index d3216b6aad8..511b5f61e0e 100644
--- a/lib/private/Authentication/Login/UidLoginCommand.php
+++ b/lib/private/Authentication/Login/UidLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php b/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php
index 571ea931d8a..0582239e9de 100644
--- a/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php
+++ b/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/UserDisabledCheckCommand.php b/lib/private/Authentication/Login/UserDisabledCheckCommand.php
index 7cf4c7235ec..8777aa6dcea 100644
--- a/lib/private/Authentication/Login/UserDisabledCheckCommand.php
+++ b/lib/private/Authentication/Login/UserDisabledCheckCommand.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -38,7 +20,7 @@ class UserDisabledCheckCommand extends ALoginCommand {
private $logger;
public function __construct(IUserManager $userManager,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->userManager = $userManager;
$this->logger = $logger;
}
diff --git a/lib/private/Authentication/Login/WebAuthnChain.php b/lib/private/Authentication/Login/WebAuthnChain.php
index f3ebc313a44..c31e39de28c 100644
--- a/lib/private/Authentication/Login/WebAuthnChain.php
+++ b/lib/private/Authentication/Login/WebAuthnChain.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -57,15 +40,15 @@ class WebAuthnChain {
private $webAuthnLoginCommand;
public function __construct(UserDisabledCheckCommand $userDisabledCheckCommand,
- WebAuthnLoginCommand $webAuthnLoginCommand,
- LoggedInCheckCommand $loggedInCheckCommand,
- CompleteLoginCommand $completeLoginCommand,
- CreateSessionTokenCommand $createSessionTokenCommand,
- ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
- UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
- SetUserTimezoneCommand $setUserTimezoneCommand,
- TwoFactorCommand $twoFactorCommand,
- FinishRememberedLoginCommand $finishRememberedLoginCommand
+ WebAuthnLoginCommand $webAuthnLoginCommand,
+ LoggedInCheckCommand $loggedInCheckCommand,
+ CompleteLoginCommand $completeLoginCommand,
+ CreateSessionTokenCommand $createSessionTokenCommand,
+ ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
+ UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
+ SetUserTimezoneCommand $setUserTimezoneCommand,
+ TwoFactorCommand $twoFactorCommand,
+ FinishRememberedLoginCommand $finishRememberedLoginCommand
) {
$this->userDisabledCheckCommand = $userDisabledCheckCommand;
$this->webAuthnLoginCommand = $webAuthnLoginCommand;
diff --git a/lib/private/Authentication/Login/WebAuthnLoginCommand.php b/lib/private/Authentication/Login/WebAuthnLoginCommand.php
index 478a579853c..8f14e5b3f6d 100644
--- a/lib/private/Authentication/Login/WebAuthnLoginCommand.php
+++ b/lib/private/Authentication/Login/WebAuthnLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/LoginCredentials/Credentials.php b/lib/private/Authentication/LoginCredentials/Credentials.php
index 69bfc2ba198..2d7ed3adfd0 100644
--- a/lib/private/Authentication/LoginCredentials/Credentials.php
+++ b/lib/private/Authentication/LoginCredentials/Credentials.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\LoginCredentials;
diff --git a/lib/private/Authentication/LoginCredentials/Store.php b/lib/private/Authentication/LoginCredentials/Store.php
index 3a09e983ee8..bd39dd11460 100644
--- a/lib/private/Authentication/LoginCredentials/Store.php
+++ b/lib/private/Authentication/LoginCredentials/Store.php
@@ -3,33 +3,15 @@
declare(strict_types=1);
/**
- * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\LoginCredentials;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
use OC\Authentication\Token\IProvider;
use OCP\Authentication\Exceptions\CredentialsUnavailableException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
use OCP\Authentication\LoginCredentials\ICredentials;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\ISession;
@@ -48,8 +30,8 @@ class Store implements IStore {
private $tokenProvider;
public function __construct(ISession $session,
- LoggerInterface $logger,
- IProvider $tokenProvider = null) {
+ LoggerInterface $logger,
+ ?IProvider $tokenProvider = null) {
$this->session = $session;
$this->logger = $logger;
$this->tokenProvider = $tokenProvider;
diff --git a/lib/private/Authentication/Notifications/Notifier.php b/lib/private/Authentication/Notifications/Notifier.php
index 8cf5d653771..3b6c9b3e610 100644
--- a/lib/private/Authentication/Notifications/Notifier.php
+++ b/lib/private/Authentication/Notifications/Notifier.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Notifications;
diff --git a/lib/private/Authentication/Token/INamedToken.php b/lib/private/Authentication/Token/INamedToken.php
index 96a7719fb41..9a90cfc7d76 100644
--- a/lib/private/Authentication/Token/INamedToken.php
+++ b/lib/private/Authentication/Token/INamedToken.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Daniel Kesselberg (mail@danielkesselberg.de)
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php
index a12d3ba34d9..dfb17301ab3 100644
--- a/lib/private/Authentication/Token/IProvider.php
+++ b/lib/private/Authentication/Token/IProvider.php
@@ -3,36 +3,17 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Marcel Waldvogel <marcel.waldvogel@uni-konstanz.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Token;
-use OC\Authentication\Exceptions\ExpiredTokenException;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
-use OC\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Exceptions\ExpiredTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Token\IToken as OCPIToken;
interface IProvider {
/**
@@ -45,16 +26,16 @@ interface IProvider {
* @param string $name Name will be trimmed to 120 chars when longer
* @param int $type token type
* @param int $remember whether the session token should be used for remember-me
- * @return IToken
+ * @return OCPIToken
* @throws \RuntimeException when OpenSSL reports a problem
*/
public function generateToken(string $token,
- string $uid,
- string $loginName,
- ?string $password,
- string $name,
- int $type = IToken::TEMPORARY_TOKEN,
- int $remember = IToken::DO_NOT_REMEMBER): IToken;
+ string $uid,
+ string $loginName,
+ ?string $password,
+ string $name,
+ int $type = OCPIToken::TEMPORARY_TOKEN,
+ int $remember = OCPIToken::DO_NOT_REMEMBER): OCPIToken;
/**
* Get a token by token id
@@ -63,9 +44,9 @@ interface IProvider {
* @throws InvalidTokenException
* @throws ExpiredTokenException
* @throws WipeTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function getToken(string $tokenId): IToken;
+ public function getToken(string $tokenId): OCPIToken;
/**
* Get a token by token id
@@ -74,9 +55,9 @@ interface IProvider {
* @throws InvalidTokenException
* @throws ExpiredTokenException
* @throws WipeTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function getTokenById(int $tokenId): IToken;
+ public function getTokenById(int $tokenId): OCPIToken;
/**
* Duplicate an existing session token
@@ -85,9 +66,9 @@ interface IProvider {
* @param string $sessionId
* @throws InvalidTokenException
* @throws \RuntimeException when OpenSSL reports a problem
- * @return IToken The new token
+ * @return OCPIToken The new token
*/
- public function renewSessionToken(string $oldSessionId, string $sessionId): IToken;
+ public function renewSessionToken(string $oldSessionId, string $sessionId): OCPIToken;
/**
* Invalidate (delete) the given session token
@@ -117,16 +98,16 @@ interface IProvider {
/**
* Save the updated token
*
- * @param IToken $token
+ * @param OCPIToken $token
*/
- public function updateToken(IToken $token);
+ public function updateToken(OCPIToken $token);
/**
* Update token activity timestamp
*
- * @param IToken $token
+ * @param OCPIToken $token
*/
- public function updateTokenActivity(IToken $token);
+ public function updateTokenActivity(OCPIToken $token);
/**
* Get all tokens of a user
@@ -135,49 +116,49 @@ interface IProvider {
* where a high number of (session) tokens is generated
*
* @param string $uid
- * @return IToken[]
+ * @return OCPIToken[]
*/
public function getTokenByUser(string $uid): array;
/**
* Get the (unencrypted) password of the given token
*
- * @param IToken $savedToken
+ * @param OCPIToken $savedToken
* @param string $tokenId
* @throws InvalidTokenException
* @throws PasswordlessTokenException
* @return string
*/
- public function getPassword(IToken $savedToken, string $tokenId): string;
+ public function getPassword(OCPIToken $savedToken, string $tokenId): string;
/**
* Encrypt and set the password of the given token
*
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $tokenId
* @param string $password
* @throws InvalidTokenException
*/
- public function setPassword(IToken $token, string $tokenId, string $password);
+ public function setPassword(OCPIToken $token, string $tokenId, string $password);
/**
* Rotate the token. Useful for for example oauth tokens
*
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $oldTokenId
* @param string $newTokenId
- * @return IToken
+ * @return OCPIToken
* @throws \RuntimeException when OpenSSL reports a problem
*/
- public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken;
+ public function rotate(OCPIToken $token, string $oldTokenId, string $newTokenId): OCPIToken;
/**
* Marks a token as having an invalid password.
*
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $tokenId
*/
- public function markPasswordInvalid(IToken $token, string $tokenId);
+ public function markPasswordInvalid(OCPIToken $token, string $tokenId);
/**
* Update all the passwords of $uid if required
diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php
index 5ca4eaea843..2028a0b328c 100644
--- a/lib/private/Authentication/Token/IToken.php
+++ b/lib/private/Authentication/Token/IToken.php
@@ -1,134 +1,17 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Token;
-use JsonSerializable;
-
-interface IToken extends JsonSerializable {
- public const TEMPORARY_TOKEN = 0;
- public const PERMANENT_TOKEN = 1;
- public const WIPE_TOKEN = 2;
- public const DO_NOT_REMEMBER = 0;
- public const REMEMBER = 1;
-
- /**
- * Get the token ID
- *
- * @return int
- */
- public function getId(): int;
-
- /**
- * Get the user UID
- *
- * @return string
- */
- public function getUID(): string;
-
- /**
- * Get the login name used when generating the token
- *
- * @return string
- */
- public function getLoginName(): string;
-
- /**
- * Get the (encrypted) login password
- *
- * @return string|null
- */
- public function getPassword();
-
- /**
- * Get the timestamp of the last password check
- *
- * @return int
- */
- public function getLastCheck(): int;
-
- /**
- * Set the timestamp of the last password check
- *
- * @param int $time
- */
- public function setLastCheck(int $time);
-
- /**
- * Get the authentication scope for this token
- *
- * @return string
- */
- public function getScope(): string;
+use OCP\Authentication\Token\IToken as OCPIToken;
- /**
- * Get the authentication scope for this token
- *
- * @return array
- */
- public function getScopeAsArray(): array;
-
- /**
- * Set the authentication scope for this token
- *
- * @param array $scope
- */
- public function setScope($scope);
-
- /**
- * Get the name of the token
- * @return string
- */
- public function getName(): string;
-
- /**
- * Get the remember state of the token
- *
- * @return int
- */
- public function getRemember(): int;
-
- /**
- * Set the token
- *
- * @param string $token
- */
- public function setToken(string $token);
-
- /**
- * Set the password
- *
- * @param string $password
- */
- public function setPassword(string $password);
-
- /**
- * Set the expiration time of the token
- *
- * @param int|null $expires
- */
- public function setExpires($expires);
+/**
+ * @deprecated 28.0.0 use {@see \OCP\Authentication\Token\IToken} instead
+ */
+interface IToken extends OCPIToken {
}
diff --git a/lib/private/Authentication/Token/IWipeableToken.php b/lib/private/Authentication/Token/IWipeableToken.php
index 5ba994e0d5e..fc1476785cd 100644
--- a/lib/private/Authentication/Token/IWipeableToken.php
+++ b/lib/private/Authentication/Token/IWipeableToken.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
diff --git a/lib/private/Authentication/Token/Manager.php b/lib/private/Authentication/Token/Manager.php
index 6a1c7d4c1e7..37ed6083d82 100644
--- a/lib/private/Authentication/Token/Manager.php
+++ b/lib/private/Authentication/Token/Manager.php
@@ -1,38 +1,20 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
-use OC\Authentication\Exceptions\ExpiredTokenException;
-use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Exceptions\InvalidTokenException as OcInvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
-use OC\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Exceptions\ExpiredTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
use OCP\Authentication\Token\IProvider as OCPIProvider;
+use OCP\Authentication\Token\IToken as OCPIToken;
class Manager implements IProvider, OCPIProvider {
/** @var PublicKeyTokenProvider */
@@ -52,15 +34,15 @@ class Manager implements IProvider, OCPIProvider {
* @param string $name Name will be trimmed to 120 chars when longer
* @param int $type token type
* @param int $remember whether the session token should be used for remember-me
- * @return IToken
+ * @return OCPIToken
*/
public function generateToken(string $token,
- string $uid,
- string $loginName,
- $password,
- string $name,
- int $type = IToken::TEMPORARY_TOKEN,
- int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type = OCPIToken::TEMPORARY_TOKEN,
+ int $remember = OCPIToken::DO_NOT_REMEMBER): OCPIToken {
if (mb_strlen($name) > 128) {
$name = mb_substr($name, 0, 120) . '…';
}
@@ -93,10 +75,10 @@ class Manager implements IProvider, OCPIProvider {
/**
* Save the updated token
*
- * @param IToken $token
+ * @param OCPIToken $token
* @throws InvalidTokenException
*/
- public function updateToken(IToken $token) {
+ public function updateToken(OCPIToken $token) {
$provider = $this->getProvider($token);
$provider->updateToken($token);
}
@@ -105,16 +87,16 @@ class Manager implements IProvider, OCPIProvider {
* Update token activity timestamp
*
* @throws InvalidTokenException
- * @param IToken $token
+ * @param OCPIToken $token
*/
- public function updateTokenActivity(IToken $token) {
+ public function updateTokenActivity(OCPIToken $token) {
$provider = $this->getProvider($token);
$provider->updateTokenActivity($token);
}
/**
* @param string $uid
- * @return IToken[]
+ * @return OCPIToken[]
*/
public function getTokenByUser(string $uid): array {
return $this->publicKeyTokenProvider->getTokenByUser($uid);
@@ -126,9 +108,9 @@ class Manager implements IProvider, OCPIProvider {
* @param string $tokenId
* @throws InvalidTokenException
* @throws \RuntimeException when OpenSSL reports a problem
- * @return IToken
+ * @return OCPIToken
*/
- public function getToken(string $tokenId): IToken {
+ public function getToken(string $tokenId): OCPIToken {
try {
return $this->publicKeyTokenProvider->getToken($tokenId);
} catch (WipeTokenException $e) {
@@ -145,9 +127,9 @@ class Manager implements IProvider, OCPIProvider {
*
* @param int $tokenId
* @throws InvalidTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function getTokenById(int $tokenId): IToken {
+ public function getTokenById(int $tokenId): OCPIToken {
try {
return $this->publicKeyTokenProvider->getTokenById($tokenId);
} catch (ExpiredTokenException $e) {
@@ -163,9 +145,9 @@ class Manager implements IProvider, OCPIProvider {
* @param string $oldSessionId
* @param string $sessionId
* @throws InvalidTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function renewSessionToken(string $oldSessionId, string $sessionId): IToken {
+ public function renewSessionToken(string $oldSessionId, string $sessionId): OCPIToken {
try {
return $this->publicKeyTokenProvider->renewSessionToken($oldSessionId, $sessionId);
} catch (ExpiredTokenException $e) {
@@ -176,18 +158,18 @@ class Manager implements IProvider, OCPIProvider {
}
/**
- * @param IToken $savedToken
+ * @param OCPIToken $savedToken
* @param string $tokenId session token
* @throws InvalidTokenException
* @throws PasswordlessTokenException
* @return string
*/
- public function getPassword(IToken $savedToken, string $tokenId): string {
+ public function getPassword(OCPIToken $savedToken, string $tokenId): string {
$provider = $this->getProvider($savedToken);
return $provider->getPassword($savedToken, $tokenId);
}
- public function setPassword(IToken $token, string $tokenId, string $password) {
+ public function setPassword(OCPIToken $token, string $tokenId, string $password) {
$provider = $this->getProvider($token);
$provider->setPassword($token, $tokenId, $password);
}
@@ -209,35 +191,37 @@ class Manager implements IProvider, OCPIProvider {
}
/**
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $oldTokenId
* @param string $newTokenId
- * @return IToken
+ * @return OCPIToken
* @throws InvalidTokenException
* @throws \RuntimeException when OpenSSL reports a problem
*/
- public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
+ public function rotate(OCPIToken $token, string $oldTokenId, string $newTokenId): OCPIToken {
if ($token instanceof PublicKeyToken) {
return $this->publicKeyTokenProvider->rotate($token, $oldTokenId, $newTokenId);
}
- throw new InvalidTokenException();
+ /** @psalm-suppress DeprecatedClass We have to throw the OC version so both OC and OCP catches catch it */
+ throw new OcInvalidTokenException();
}
/**
- * @param IToken $token
+ * @param OCPIToken $token
* @return IProvider
* @throws InvalidTokenException
*/
- private function getProvider(IToken $token): IProvider {
+ private function getProvider(OCPIToken $token): IProvider {
if ($token instanceof PublicKeyToken) {
return $this->publicKeyTokenProvider;
}
- throw new InvalidTokenException();
+ /** @psalm-suppress DeprecatedClass We have to throw the OC version so both OC and OCP catches catch it */
+ throw new OcInvalidTokenException();
}
- public function markPasswordInvalid(IToken $token, string $tokenId) {
+ public function markPasswordInvalid(OCPIToken $token, string $tokenId) {
$this->getProvider($token)->markPasswordInvalid($token, $tokenId);
}
diff --git a/lib/private/Authentication/Token/PublicKeyToken.php b/lib/private/Authentication/Token/PublicKeyToken.php
index 45335e17c31..0b7a2589f3e 100644
--- a/lib/private/Authentication/Token/PublicKeyToken.php
+++ b/lib/private/Authentication/Token/PublicKeyToken.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
@@ -137,10 +118,8 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
/**
* Get the (encrypted) login password
- *
- * @return string|null
*/
- public function getPassword() {
+ public function getPassword(): ?string {
return parent::getPassword();
}
@@ -165,10 +144,8 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
/**
* Get the timestamp of the last password check
- *
- * @param int $time
*/
- public function setLastCheck(int $time) {
+ public function setLastCheck(int $time): void {
parent::setLastCheck($time);
}
@@ -191,7 +168,7 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
return $scope;
}
- public function setScope($scope) {
+ public function setScope(array|string|null $scope): void {
if (is_array($scope)) {
parent::setScope(json_encode($scope));
} else {
@@ -211,15 +188,15 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
return parent::getRemember();
}
- public function setToken(string $token) {
+ public function setToken(string $token): void {
parent::setToken($token);
}
- public function setPassword(string $password = null) {
+ public function setPassword(?string $password = null): void {
parent::setPassword($password);
}
- public function setExpires($expires) {
+ public function setExpires($expires): void {
parent::setExpires($expires);
}
diff --git a/lib/private/Authentication/Token/PublicKeyTokenMapper.php b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
index 855639dd907..0db5c4f53e7 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenMapper.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
@@ -3,32 +3,14 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
+use OCP\Authentication\Token\IToken;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
@@ -42,8 +24,6 @@ class PublicKeyTokenMapper extends QBMapper {
/**
* Invalidate (delete) a given token
- *
- * @param string $token
*/
public function invalidate(string $token) {
/* @var $qb IQueryBuilder */
@@ -150,14 +130,15 @@ class PublicKeyTokenMapper extends QBMapper {
return $entities;
}
- public function deleteById(string $uid, int $id) {
+ public function getTokenByUserAndId(string $uid, int $id): ?string {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $qb->delete($this->tableName)
+ $qb->select('token')
+ ->from($this->tableName)
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
- $qb->execute();
+ return $qb->executeQuery()->fetchOne() ?: null;
}
/**
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
index 3fb11611076..5363b82df69 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
@@ -1,43 +1,23 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use OC\Authentication\Exceptions\ExpiredTokenException;
use OC\Authentication\Exceptions\InvalidTokenException;
-use OC\Authentication\Exceptions\TokenPasswordExpiredException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
+use OC\Authentication\Exceptions\TokenPasswordExpiredException;
use OC\Authentication\Exceptions\WipeTokenException;
-use OCP\AppFramework\Db\TTransactional;
-use OCP\Cache\CappedMemoryCache;
use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\TTransactional;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Token\IToken as OCPIToken;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
@@ -47,6 +27,8 @@ use Psr\Log\LoggerInterface;
class PublicKeyTokenProvider implements IProvider {
public const TOKEN_MIN_LENGTH = 22;
+ /** Token cache TTL in seconds */
+ private const TOKEN_CACHE_TTL = 10;
use TTransactional;
@@ -67,18 +49,20 @@ class PublicKeyTokenProvider implements IProvider {
/** @var ITimeFactory */
private $time;
- /** @var CappedMemoryCache */
+ /** @var ICache */
private $cache;
- private IHasher $hasher;
+ /** @var IHasher */
+ private $hasher;
public function __construct(PublicKeyTokenMapper $mapper,
- ICrypto $crypto,
- IConfig $config,
- IDBConnection $db,
- LoggerInterface $logger,
- ITimeFactory $time,
- IHasher $hasher) {
+ ICrypto $crypto,
+ IConfig $config,
+ IDBConnection $db,
+ LoggerInterface $logger,
+ ITimeFactory $time,
+ IHasher $hasher,
+ ICacheFactory $cacheFactory) {
$this->mapper = $mapper;
$this->crypto = $crypto;
$this->config = $config;
@@ -86,7 +70,9 @@ class PublicKeyTokenProvider implements IProvider {
$this->logger = $logger;
$this->time = $time;
- $this->cache = new CappedMemoryCache();
+ $this->cache = $cacheFactory->isLocalCacheAvailable()
+ ? $cacheFactory->createLocal('authtoken_')
+ : $cacheFactory->createInMemory();
$this->hasher = $hasher;
}
@@ -94,12 +80,12 @@ class PublicKeyTokenProvider implements IProvider {
* {@inheritDoc}
*/
public function generateToken(string $token,
- string $uid,
- string $loginName,
- ?string $password,
- string $name,
- int $type = IToken::TEMPORARY_TOKEN,
- int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ string $uid,
+ string $loginName,
+ ?string $password,
+ string $name,
+ int $type = OCPIToken::TEMPORARY_TOKEN,
+ int $remember = OCPIToken::DO_NOT_REMEMBER): OCPIToken {
if (strlen($token) < self::TOKEN_MIN_LENGTH) {
$exception = new InvalidTokenException('Token is too short, minimum of ' . self::TOKEN_MIN_LENGTH . ' characters is required, ' . strlen($token) . ' characters given');
$this->logger->error('Invalid token provided when generating new token', ['exception' => $exception]);
@@ -128,12 +114,12 @@ class PublicKeyTokenProvider implements IProvider {
}
// Add the token to the cache
- $this->cache[$dbToken->getToken()] = $dbToken;
+ $this->cacheToken($dbToken);
return $dbToken;
}
- public function getToken(string $tokenId): IToken {
+ public function getToken(string $tokenId): OCPIToken {
/**
* Token length: 72
* @see \OC\Core\Controller\ClientFlowLoginController::generateAppPassword
@@ -156,57 +142,76 @@ class PublicKeyTokenProvider implements IProvider {
}
$tokenHash = $this->hashToken($tokenId);
+ if ($token = $this->getTokenFromCache($tokenHash)) {
+ $this->checkToken($token);
+ return $token;
+ }
- if (isset($this->cache[$tokenHash])) {
- if ($this->cache[$tokenHash] instanceof DoesNotExistException) {
- $ex = $this->cache[$tokenHash];
- throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
- }
- $token = $this->cache[$tokenHash];
- } else {
+ try {
+ $token = $this->mapper->getToken($tokenHash);
+ $this->cacheToken($token);
+ } catch (DoesNotExistException $ex) {
try {
- $token = $this->mapper->getToken($tokenHash);
- $this->cache[$token->getToken()] = $token;
- } catch (DoesNotExistException $ex) {
- try {
- $token = $this->mapper->getToken($this->hashTokenWithEmptySecret($tokenId));
- $this->cache[$token->getToken()] = $token;
- $this->rotate($token, $tokenId, $tokenId);
- } catch (DoesNotExistException $ex2) {
- $this->cache[$tokenHash] = $ex2;
- throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
- }
+ $token = $this->mapper->getToken($this->hashTokenWithEmptySecret($tokenId));
+ $this->rotate($token, $tokenId, $tokenId);
+ } catch (DoesNotExistException) {
+ $this->cacheInvalidHash($tokenHash);
+ throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
}
}
- if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
- throw new ExpiredTokenException($token);
- }
+ $this->checkToken($token);
- if ($token->getType() === IToken::WIPE_TOKEN) {
- throw new WipeTokenException($token);
+ return $token;
+ }
+
+ /**
+ * @throws InvalidTokenException when token doesn't exist
+ */
+ private function getTokenFromCache(string $tokenHash): ?PublicKeyToken {
+ $serializedToken = $this->cache->get($tokenHash);
+ if ($serializedToken === false) {
+ throw new InvalidTokenException('Token does not exist: ' . $tokenHash);
}
- if ($token->getPasswordInvalid() === true) {
- //The password is invalid we should throw an TokenPasswordExpiredException
- throw new TokenPasswordExpiredException($token);
+ if ($serializedToken === null) {
+ return null;
}
- return $token;
+ $token = unserialize($serializedToken, [
+ 'allowed_classes' => [PublicKeyToken::class],
+ ]);
+
+ return $token instanceof PublicKeyToken ? $token : null;
+ }
+
+ private function cacheToken(PublicKeyToken $token): void {
+ $this->cache->set($token->getToken(), serialize($token), self::TOKEN_CACHE_TTL);
+ }
+
+ private function cacheInvalidHash(string $tokenHash): void {
+ // Invalid entries can be kept longer in cache since it’s unlikely to reuse them
+ $this->cache->set($tokenHash, false, self::TOKEN_CACHE_TTL * 2);
}
- public function getTokenById(int $tokenId): IToken {
+ public function getTokenById(int $tokenId): OCPIToken {
try {
$token = $this->mapper->getTokenById($tokenId);
} catch (DoesNotExistException $ex) {
throw new InvalidTokenException("Token with ID $tokenId does not exist: " . $ex->getMessage(), 0, $ex);
}
+ $this->checkToken($token);
+
+ return $token;
+ }
+
+ private function checkToken($token): void {
if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
throw new ExpiredTokenException($token);
}
- if ($token->getType() === IToken::WIPE_TOKEN) {
+ if ($token->getType() === OCPIToken::WIPE_TOKEN) {
throw new WipeTokenException($token);
}
@@ -214,13 +219,9 @@ class PublicKeyTokenProvider implements IProvider {
//The password is invalid we should throw an TokenPasswordExpiredException
throw new TokenPasswordExpiredException($token);
}
-
- return $token;
}
- public function renewSessionToken(string $oldSessionId, string $sessionId): IToken {
- $this->cache->clear();
-
+ public function renewSessionToken(string $oldSessionId, string $sessionId): OCPIToken {
return $this->atomic(function () use ($oldSessionId, $sessionId) {
$token = $this->getToken($oldSessionId);
@@ -239,10 +240,12 @@ class PublicKeyTokenProvider implements IProvider {
$token->getLoginName(),
$password,
$token->getName(),
- IToken::TEMPORARY_TOKEN,
+ OCPIToken::TEMPORARY_TOKEN,
$token->getRemember()
);
+ $this->cacheToken($newToken);
+ $this->cacheInvalidHash($token->getToken());
$this->mapper->delete($token);
return $newToken;
@@ -250,47 +253,44 @@ class PublicKeyTokenProvider implements IProvider {
}
public function invalidateToken(string $token) {
- $this->cache->clear();
-
+ $tokenHash = $this->hashToken($token);
$this->mapper->invalidate($this->hashToken($token));
$this->mapper->invalidate($this->hashTokenWithEmptySecret($token));
+ $this->cacheInvalidHash($tokenHash);
}
public function invalidateTokenById(string $uid, int $id) {
- $this->cache->clear();
+ $token = $this->mapper->getTokenById($id);
+ if ($token->getUID() !== $uid) {
+ return;
+ }
+ $this->mapper->invalidate($token->getToken());
+ $this->cacheInvalidHash($token->getToken());
- $this->mapper->deleteById($uid, $id);
}
public function invalidateOldTokens() {
- $this->cache->clear();
-
$olderThan = $this->time->getTime() - $this->config->getSystemValueInt('session_lifetime', 60 * 60 * 24);
$this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']);
- $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
+ $this->mapper->invalidateOld($olderThan, OCPIToken::DO_NOT_REMEMBER);
$rememberThreshold = $this->time->getTime() - $this->config->getSystemValueInt('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
$this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']);
- $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
+ $this->mapper->invalidateOld($rememberThreshold, OCPIToken::REMEMBER);
}
public function invalidateLastUsedBefore(string $uid, int $before): void {
- $this->cache->clear();
-
$this->mapper->invalidateLastUsedBefore($uid, $before);
}
- public function updateToken(IToken $token) {
- $this->cache->clear();
-
+ public function updateToken(OCPIToken $token) {
if (!($token instanceof PublicKeyToken)) {
throw new InvalidTokenException("Invalid token type");
}
$this->mapper->update($token);
+ $this->cacheToken($token);
}
- public function updateTokenActivity(IToken $token) {
- $this->cache->clear();
-
+ public function updateTokenActivity(OCPIToken $token) {
if (!($token instanceof PublicKeyToken)) {
throw new InvalidTokenException("Invalid token type");
}
@@ -303,6 +303,7 @@ class PublicKeyTokenProvider implements IProvider {
if ($token->getLastActivity() < ($now - $activityInterval)) {
$token->setLastActivity($now);
$this->mapper->updateActivity($token, $now);
+ $this->cacheToken($token);
}
}
@@ -310,7 +311,7 @@ class PublicKeyTokenProvider implements IProvider {
return $this->mapper->getTokenByUser($uid);
}
- public function getPassword(IToken $savedToken, string $tokenId): string {
+ public function getPassword(OCPIToken $savedToken, string $tokenId): string {
if (!($savedToken instanceof PublicKeyToken)) {
throw new InvalidTokenException("Invalid token type");
}
@@ -326,9 +327,7 @@ class PublicKeyTokenProvider implements IProvider {
return $this->decryptPassword($savedToken->getPassword(), $privateKey);
}
- public function setPassword(IToken $token, string $tokenId, string $password) {
- $this->cache->clear();
-
+ public function setPassword(OCPIToken $token, string $tokenId, string $password) {
if (!($token instanceof PublicKeyToken)) {
throw new InvalidTokenException("Invalid token type");
}
@@ -353,9 +352,7 @@ class PublicKeyTokenProvider implements IProvider {
return $this->hasher->hash(sha1($password) . $password);
}
- public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
- $this->cache->clear();
-
+ public function rotate(OCPIToken $token, string $oldTokenId, string $newTokenId): OCPIToken {
if (!($token instanceof PublicKeyToken)) {
throw new InvalidTokenException("Invalid token type");
}
@@ -425,12 +422,12 @@ class PublicKeyTokenProvider implements IProvider {
* @throws \RuntimeException when OpenSSL reports a problem
*/
private function newToken(string $token,
- string $uid,
- string $loginName,
- $password,
- string $name,
- int $type,
- int $remember): PublicKeyToken {
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type,
+ int $remember): PublicKeyToken {
$dbToken = new PublicKeyToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);
@@ -478,20 +475,17 @@ class PublicKeyTokenProvider implements IProvider {
return $dbToken;
}
- public function markPasswordInvalid(IToken $token, string $tokenId) {
- $this->cache->clear();
-
+ public function markPasswordInvalid(OCPIToken $token, string $tokenId) {
if (!($token instanceof PublicKeyToken)) {
throw new InvalidTokenException("Invalid token type");
}
$token->setPasswordInvalid(true);
$this->mapper->update($token);
+ $this->cacheToken($token);
}
public function updatePasswords(string $uid, string $password) {
- $this->cache->clear();
-
// prevent setting an empty pw as result of pw-less-login
if ($password === '' || !$this->config->getSystemValueBool('auth.storeCryptedPassword', true)) {
return;
diff --git a/lib/private/Authentication/Token/RemoteWipe.php b/lib/private/Authentication/Token/RemoteWipe.php
index 5fd01cfbe87..43c2bd060d1 100644
--- a/lib/private/Authentication/Token/RemoteWipe.php
+++ b/lib/private/Authentication/Token/RemoteWipe.php
@@ -3,38 +3,19 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
-use Psr\Log\LoggerInterface;
-use function array_filter;
use OC\Authentication\Events\RemoteWipeFinished;
use OC\Authentication\Events\RemoteWipeStarted;
-use OC\Authentication\Exceptions\InvalidTokenException;
-use OC\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
+use Psr\Log\LoggerInterface;
+use function array_filter;
class RemoteWipe {
/** @var IProvider */
@@ -47,8 +28,8 @@ class RemoteWipe {
private $logger;
public function __construct(IProvider $tokenProvider,
- IEventDispatcher $eventDispatcher,
- LoggerInterface $logger) {
+ IEventDispatcher $eventDispatcher,
+ LoggerInterface $logger) {
$this->tokenProvider = $tokenProvider;
$this->eventDispatcher = $eventDispatcher;
$this->logger = $logger;
diff --git a/lib/private/Authentication/Token/TokenCleanupJob.php b/lib/private/Authentication/Token/TokenCleanupJob.php
index 292f8f310e8..041d2e8a5e2 100644
--- a/lib/private/Authentication/Token/TokenCleanupJob.php
+++ b/lib/private/Authentication/Token/TokenCleanupJob.php
@@ -1,23 +1,7 @@
<?php
/**
- * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
- *
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Token;
diff --git a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
index 4817c6b8de0..c84b7f1af20 100644
--- a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
+++ b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
@@ -3,30 +3,11 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth\Db;
-use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
-use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use function array_map;
@@ -59,7 +40,7 @@ class ProviderUserAssignmentDao {
$result = $query->execute();
$providers = [];
foreach ($result->fetchAll() as $row) {
- $providers[(string)$row['provider_id']] = 1 === (int)$row['enabled'];
+ $providers[(string)$row['provider_id']] = (int)$row['enabled'] === 1;
}
$result->closeCursor();
@@ -70,32 +51,29 @@ class ProviderUserAssignmentDao {
* Persist a new/updated (provider_id, uid, enabled) tuple
*/
public function persist(string $providerId, string $uid, int $enabled): void {
- $qb = $this->conn->getQueryBuilder();
-
- try {
- // Insert a new entry
- $insertQuery = $qb->insert(self::TABLE_NAME)->values([
- 'provider_id' => $qb->createNamedParameter($providerId),
- 'uid' => $qb->createNamedParameter($uid),
- 'enabled' => $qb->createNamedParameter($enabled, IQueryBuilder::PARAM_INT),
- ]);
-
- $insertQuery->execute();
- } catch (UniqueConstraintViolationException $ex) {
- // There is already an entry -> update it
- $updateQuery = $qb->update(self::TABLE_NAME)
- ->set('enabled', $qb->createNamedParameter($enabled))
- ->where($qb->expr()->eq('provider_id', $qb->createNamedParameter($providerId)))
- ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
- $updateQuery->execute();
+ $conn = $this->conn;
+
+ // Insert a new entry
+ if ($conn->insertIgnoreConflict(self::TABLE_NAME, [
+ 'provider_id' => $providerId,
+ 'uid' => $uid,
+ 'enabled' => $enabled,
+ ])) {
+ return;
}
+
+ // There is already an entry -> update it
+ $qb = $conn->getQueryBuilder();
+ $updateQuery = $qb->update(self::TABLE_NAME)
+ ->set('enabled', $qb->createNamedParameter($enabled))
+ ->where($qb->expr()->eq('provider_id', $qb->createNamedParameter($providerId)))
+ ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
+ $updateQuery->executeStatement();
}
/**
* Delete all provider states of a user and return the provider IDs
*
- * @param string $uid
- *
* @return list<array{provider_id: string, uid: string, enabled: bool}>
*/
public function deleteByUser(string $uid): array {
@@ -103,7 +81,7 @@ class ProviderUserAssignmentDao {
$selectQuery = $qb1->select('*')
->from(self::TABLE_NAME)
->where($qb1->expr()->eq('uid', $qb1->createNamedParameter($uid)));
- $selectResult = $selectQuery->execute();
+ $selectResult = $selectQuery->executeQuery();
$rows = $selectResult->fetchAll();
$selectResult->closeCursor();
@@ -111,15 +89,15 @@ class ProviderUserAssignmentDao {
$deleteQuery = $qb2
->delete(self::TABLE_NAME)
->where($qb2->expr()->eq('uid', $qb2->createNamedParameter($uid)));
- $deleteQuery->execute();
+ $deleteQuery->executeStatement();
- return array_map(function (array $row) {
+ return array_values(array_map(function (array $row) {
return [
- 'provider_id' => $row['provider_id'],
- 'uid' => $row['uid'],
- 'enabled' => 1 === (int) $row['enabled'],
+ 'provider_id' => (string)$row['provider_id'],
+ 'uid' => (string)$row['uid'],
+ 'enabled' => ((int) $row['enabled']) === 1,
];
- }, $rows);
+ }, $rows));
}
public function deleteAll(string $providerId): void {
diff --git a/lib/private/Authentication/TwoFactorAuth/EnforcementState.php b/lib/private/Authentication/TwoFactorAuth/EnforcementState.php
index b95128c1e0f..e02064bc8f7 100644
--- a/lib/private/Authentication/TwoFactorAuth/EnforcementState.php
+++ b/lib/private/Authentication/TwoFactorAuth/EnforcementState.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
@@ -45,8 +28,8 @@ class EnforcementState implements JsonSerializable {
* @param string[] $excludedGroups
*/
public function __construct(bool $enforced,
- array $enforcedGroups = [],
- array $excludedGroups = []) {
+ array $enforcedGroups = [],
+ array $excludedGroups = []) {
$this->enforced = $enforced;
$this->enforcedGroups = $enforcedGroups;
$this->excludedGroups = $excludedGroups;
diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php
index ff0c33445a2..2585646c998 100644
--- a/lib/private/Authentication/TwoFactorAuth/Manager.php
+++ b/lib/private/Authentication/TwoFactorAuth/Manager.php
@@ -1,38 +1,19 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\TwoFactorAuth;
use BadMethodCallException;
use Exception;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\IProvider as TokenProvider;
use OCP\Activity\IManager;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Exceptions\InvalidTokenException;
use OCP\Authentication\TwoFactorAuth\IActivatableAtLogin;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Authentication\TwoFactorAuth\IRegistry;
@@ -89,15 +70,15 @@ class Manager {
private $userIsTwoFactorAuthenticated = [];
public function __construct(ProviderLoader $providerLoader,
- IRegistry $providerRegistry,
- MandatoryTwoFactor $mandatoryTwoFactor,
- ISession $session,
- IConfig $config,
- IManager $activityManager,
- LoggerInterface $logger,
- TokenProvider $tokenProvider,
- ITimeFactory $timeFactory,
- IEventDispatcher $eventDispatcher) {
+ IRegistry $providerRegistry,
+ MandatoryTwoFactor $mandatoryTwoFactor,
+ ISession $session,
+ IConfig $config,
+ IManager $activityManager,
+ LoggerInterface $logger,
+ TokenProvider $tokenProvider,
+ ITimeFactory $timeFactory,
+ IEventDispatcher $eventDispatcher) {
$this->providerLoader = $providerLoader;
$this->providerRegistry = $providerRegistry;
$this->mandatoryTwoFactor = $mandatoryTwoFactor;
@@ -313,13 +294,13 @@ class Manager {
* @param IUser $user the currently logged in user
* @return boolean
*/
- public function needsSecondFactor(IUser $user = null): bool {
+ public function needsSecondFactor(?IUser $user = null): bool {
if ($user === null) {
return false;
}
- // If we are authenticated using an app password skip all this
- if ($this->session->exists('app_password')) {
+ // If we are authenticated using an app password or AppAPI Auth, skip all this
+ if ($this->session->exists('app_password') || $this->session->get('app_api') === true) {
return false;
}
diff --git a/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php b/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php
index 3bfbd77941b..37c9d3fc550 100644
--- a/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php
+++ b/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php b/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
index efd92f8ba30..b9a0a97bec4 100644
--- a/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderManager.php b/lib/private/Authentication/TwoFactorAuth/ProviderManager.php
index c7c075bdab3..5ce4c598154 100644
--- a/lib/private/Authentication/TwoFactorAuth/ProviderManager.php
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderManager.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderSet.php b/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
index af270fb83c8..15b82be6dec 100644
--- a/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
@@ -3,31 +3,14 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
-use function array_filter;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\Authentication\TwoFactorAuth\IProvider;
+use function array_filter;
/**
* Contains all two-factor provider information for the two-factor login challenge
diff --git a/lib/private/Authentication/TwoFactorAuth/Registry.php b/lib/private/Authentication/TwoFactorAuth/Registry.php
index 482c025e144..544f60c4f97 100644
--- a/lib/private/Authentication/TwoFactorAuth/Registry.php
+++ b/lib/private/Authentication/TwoFactorAuth/Registry.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
@@ -45,7 +27,7 @@ class Registry implements IRegistry {
private $dispatcher;
public function __construct(ProviderUserAssignmentDao $assignmentDao,
- IEventDispatcher $dispatcher) {
+ IEventDispatcher $dispatcher) {
$this->assignmentDao = $assignmentDao;
$this->dispatcher = $dispatcher;
}
diff --git a/lib/private/Authentication/WebAuthn/CredentialRepository.php b/lib/private/Authentication/WebAuthn/CredentialRepository.php
index e5c3fcf1618..f32136f9594 100644
--- a/lib/private/Authentication/WebAuthn/CredentialRepository.php
+++ b/lib/private/Authentication/WebAuthn/CredentialRepository.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn;
@@ -61,7 +44,7 @@ class CredentialRepository implements PublicKeyCredentialSourceRepository {
}, $entities);
}
- public function saveAndReturnCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, string $name = null): PublicKeyCredentialEntity {
+ public function saveAndReturnCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, ?string $name = null): PublicKeyCredentialEntity {
$oldEntity = null;
try {
@@ -87,7 +70,7 @@ class CredentialRepository implements PublicKeyCredentialSourceRepository {
return $this->credentialMapper->insertOrUpdate($entity);
}
- public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, string $name = null): void {
+ public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, ?string $name = null): void {
$this->saveAndReturnCredentialSource($publicKeyCredentialSource, $name);
}
}
diff --git a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php
index 6f97ded483d..443a7985cae 100644
--- a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php
+++ b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn\Db;
diff --git a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php
index 72c557eb53a..fa7304157c8 100644
--- a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php
+++ b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn\Db;
diff --git a/lib/private/Authentication/WebAuthn/Manager.php b/lib/private/Authentication/WebAuthn/Manager.php
index 744a3fa354a..007be245992 100644
--- a/lib/private/Authentication/WebAuthn/Manager.php
+++ b/lib/private/Authentication/WebAuthn/Manager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn;
@@ -83,15 +64,15 @@ class Manager {
public function startRegistration(IUser $user, string $serverHost): PublicKeyCredentialCreationOptions {
$rpEntity = new PublicKeyCredentialRpEntity(
'Nextcloud', //Name
- $this->stripPort($serverHost), //ID
+ $this->stripPort($serverHost), //ID
null //Icon
);
$userEntity = new PublicKeyCredentialUserEntity(
- $user->getUID(), //Name
- $user->getUID(), //ID
- $user->getDisplayName() //Display name
-// 'https://foo.example.co/avatar/123e4567-e89b-12d3-a456-426655440000' //Icon
+ $user->getUID(), // Name
+ $user->getUID(), // ID
+ $user->getDisplayName() // Display name
+ // 'https://foo.example.co/avatar/123e4567-e89b-12d3-a456-426655440000' //Icon
);
$challenge = random_bytes(32);
@@ -108,8 +89,9 @@ class Manager {
$authenticatorSelectionCriteria = new AuthenticatorSelectionCriteria(
null,
+ AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED,
+ null,
false,
- AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED
);
return new PublicKeyCredentialCreationOptions(
@@ -117,11 +99,10 @@ class Manager {
$userEntity,
$challenge,
$publicKeyCredentialParametersList,
- $timeout,
- $excludedPublicKeyDescriptors,
$authenticatorSelectionCriteria,
PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE,
- null
+ $excludedPublicKeyDescriptors,
+ $timeout,
);
}
@@ -149,7 +130,7 @@ class Manager {
try {
// Load the data
$publicKeyCredential = $publicKeyCredentialLoader->load($data);
- $response = $publicKeyCredential->getResponse();
+ $response = $publicKeyCredential->response;
// Check if the response is an Authenticator Attestation Response
if (!$response instanceof AuthenticatorAttestationResponse) {
@@ -162,7 +143,9 @@ class Manager {
$publicKeyCredentialSource = $authenticatorAttestationResponseValidator->check(
$response,
$publicKeyCredentialCreationOptions,
- $request);
+ $request,
+ ['localhost'],
+ );
} catch (\Throwable $exception) {
throw $exception;
}
@@ -180,18 +163,18 @@ class Manager {
$registeredPublicKeyCredentialDescriptors = array_map(function (PublicKeyCredentialEntity $entity) {
$credential = $entity->toPublicKeyCredentialSource();
return new PublicKeyCredentialDescriptor(
- $credential->getType(),
- $credential->getPublicKeyCredentialId()
+ $credential->type,
+ $credential->publicKeyCredentialId,
);
}, $this->credentialMapper->findAllForUid($uid));
// Public Key Credential Request Options
return new PublicKeyCredentialRequestOptions(
- random_bytes(32), // Challenge
- 60000, // Timeout
- $this->stripPort($serverHost), // Relying Party ID
- $registeredPublicKeyCredentialDescriptors, // Registered PublicKeyCredentialDescriptor classes
- AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED
+ random_bytes(32), // Challenge
+ $this->stripPort($serverHost), // Relying Party ID
+ $registeredPublicKeyCredentialDescriptors, // Registered PublicKeyCredentialDescriptor classes
+ AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED,
+ 60000, // Timeout
);
}
@@ -213,16 +196,15 @@ class Manager {
$tokenBindingHandler,
$extensionOutputCheckerHandler,
$algorithmManager,
- null,
- $this->logger,
);
+ $authenticatorAssertionResponseValidator->setLogger($this->logger);
try {
$this->logger->debug('Loading publickey credentials from: ' . $data);
// Load the data
$publicKeyCredential = $publicKeyCredentialLoader->load($data);
- $response = $publicKeyCredential->getResponse();
+ $response = $publicKeyCredential->response;
// Check if the response is an Authenticator Attestation Response
if (!$response instanceof AuthenticatorAssertionResponse) {
@@ -233,18 +215,17 @@ class Manager {
$request = ServerRequest::fromGlobals();
$publicKeyCredentialSource = $authenticatorAssertionResponseValidator->check(
- $publicKeyCredential->getRawId(),
+ $publicKeyCredential->rawId,
$response,
$publicKeyCredentialRequestOptions,
$request,
- $uid
+ $uid,
+ ['localhost'],
);
} catch (\Throwable $e) {
throw $e;
}
-
-
return true;
}
diff --git a/lib/private/Avatar/Avatar.php b/lib/private/Avatar/Avatar.php
index 69bf9bacfcf..1ad70001f13 100644
--- a/lib/private/Avatar/Avatar.php
+++ b/lib/private/Avatar/Avatar.php
@@ -3,36 +3,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright 2018 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sergey Shliakhov <husband.sergey@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Avatar;
@@ -151,6 +124,7 @@ abstract class Avatar implements IAvatar {
/**
* Generate png avatar with GD
+ * @throws \Exception when an error occurs in gd calls
*/
protected function generateAvatar(string $userDisplayName, int $size, bool $darkTheme): string {
$text = $this->getAvatarText();
@@ -158,6 +132,9 @@ abstract class Avatar implements IAvatar {
$backgroundColor = $textColor->alphaBlending(0.1, $darkTheme ? new Color(0, 0, 0) : new Color(255, 255, 255));
$im = imagecreatetruecolor($size, $size);
+ if ($im === false) {
+ throw new \Exception('Failed to create avatar image');
+ }
$background = imagecolorallocate(
$im,
$backgroundColor->red(),
@@ -169,6 +146,9 @@ abstract class Avatar implements IAvatar {
$textColor->green(),
$textColor->blue()
);
+ if ($background === false || $textColor === false) {
+ throw new \Exception('Failed to create avatar image color');
+ }
imagefilledrectangle($im, 0, 0, $size, $size, $background);
$font = __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf';
@@ -191,7 +171,7 @@ abstract class Avatar implements IAvatar {
/**
* Calculate real image ttf center
*
- * @param resource $image
+ * @param \GdImage $image
* @param string $text text string
* @param string $font font path
* @param int $size font size
diff --git a/lib/private/Avatar/AvatarManager.php b/lib/private/Avatar/AvatarManager.php
index 4125c8eb0a8..f8ce4d5b656 100644
--- a/lib/private/Avatar/AvatarManager.php
+++ b/lib/private/Avatar/AvatarManager.php
@@ -1,37 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Avatar;
@@ -55,71 +28,42 @@ use Psr\Log\LoggerInterface;
* This class implements methods to access Avatar functionality
*/
class AvatarManager implements IAvatarManager {
- /** @var IUserSession */
- private $userSession;
-
- /** @var Manager */
- private $userManager;
-
- /** @var IAppData */
- private $appData;
-
- /** @var IL10N */
- private $l;
-
- /** @var LoggerInterface */
- private $logger;
-
- /** @var IConfig */
- private $config;
-
- /** @var IAccountManager */
- private $accountManager;
-
- /** @var KnownUserService */
- private $knownUserService;
-
public function __construct(
- IUserSession $userSession,
- Manager $userManager,
- IAppData $appData,
- IL10N $l,
- LoggerInterface $logger,
- IConfig $config,
- IAccountManager $accountManager,
- KnownUserService $knownUserService
+ private IUserSession $userSession,
+ private Manager $userManager,
+ private IAppData $appData,
+ private IL10N $l,
+ private LoggerInterface $logger,
+ private IConfig $config,
+ private IAccountManager $accountManager,
+ private KnownUserService $knownUserService,
) {
- $this->userSession = $userSession;
- $this->userManager = $userManager;
- $this->appData = $appData;
- $this->l = $l;
- $this->logger = $logger;
- $this->config = $config;
- $this->accountManager = $accountManager;
- $this->knownUserService = $knownUserService;
}
/**
* return a user specific instance of \OCP\IAvatar
+ *
+ * If the user is disabled a guest avatar will be returned
+ *
* @see \OCP\IAvatar
* @param string $userId the ownCloud user id
- * @return \OCP\IAvatar
* @throws \Exception In case the username is potentially dangerous
* @throws NotFoundException In case there is no user folder yet
*/
- public function getAvatar(string $userId) : IAvatar {
+ public function getAvatar(string $userId): IAvatar {
$user = $this->userManager->get($userId);
if ($user === null) {
throw new \Exception('user does not exist');
}
+ if (!$user->isEnabled()) {
+ return $this->getGuestAvatar($userId);
+ }
+
// sanitize userID - fixes casing issue (needed for the filesystem stuff that is done below)
$userId = $user->getUID();
- $requestingUser = null;
- if ($this->userSession !== null) {
- $requestingUser = $this->userSession->getUser();
- }
+ $requestingUser = $this->userSession->getUser();
try {
$folder = $this->appData->getFolder($userId);
@@ -157,7 +101,7 @@ class AvatarManager implements IAvatarManager {
/**
* Clear generated avatars
*/
- public function clearCachedAvatars() {
+ public function clearCachedAvatars(): void {
$users = $this->config->getUsersForUserValue('avatar', 'generated', 'true');
foreach ($users as $userId) {
// This also bumps the avatar version leading to cache invalidation in browsers
@@ -174,7 +118,7 @@ class AvatarManager implements IAvatarManager {
} catch (NotPermittedException | StorageNotAvailableException $e) {
$this->logger->error("Unable to delete user avatars for $userId. gnoring avatar deletion");
} catch (NoUserException $e) {
- $this->logger->debug("User $userId not found. gnoring avatar deletion");
+ $this->logger->debug("Account $userId not found. Ignoring avatar deletion");
}
$this->config->deleteUserValue($userId, 'avatar', 'generated');
}
@@ -183,7 +127,6 @@ class AvatarManager implements IAvatarManager {
* Returns a GuestAvatar.
*
* @param string $name The guest name, e.g. "Albert".
- * @return IAvatar
*/
public function getGuestAvatar(string $name): IAvatar {
return new GuestAvatar($name, $this->logger);
diff --git a/lib/private/Avatar/GuestAvatar.php b/lib/private/Avatar/GuestAvatar.php
index 083deb4108f..7ae633f1260 100644
--- a/lib/private/Avatar/GuestAvatar.php
+++ b/lib/private/Avatar/GuestAvatar.php
@@ -3,31 +3,13 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Michael Weimann <mail@michael-weimann.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Avatar;
-use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\InMemoryFile;
+use OCP\Files\SimpleFS\ISimpleFile;
use Psr\Log\LoggerInterface;
/**
@@ -35,18 +17,15 @@ use Psr\Log\LoggerInterface;
*/
class GuestAvatar extends Avatar {
/**
- * Holds the guest user display name.
- */
- private string $userDisplayName;
-
- /**
* GuestAvatar constructor.
*
* @param string $userDisplayName The guest user display name
*/
- public function __construct(string $userDisplayName, LoggerInterface $logger) {
+ public function __construct(
+ private string $userDisplayName,
+ LoggerInterface $logger,
+ ) {
parent::__construct($logger);
- $this->userDisplayName = $userDisplayName;
}
/**
@@ -68,7 +47,6 @@ class GuestAvatar extends Avatar {
* Setting avatars isn't implemented for guests.
*
* @param \OCP\IImage|resource|string $data
- * @return void
*/
public function set($data): void {
// unimplemented for guest user avatars
diff --git a/lib/private/Avatar/PlaceholderAvatar.php b/lib/private/Avatar/PlaceholderAvatar.php
index e7ca89f4d30..07c54f62713 100644
--- a/lib/private/Avatar/PlaceholderAvatar.php
+++ b/lib/private/Avatar/PlaceholderAvatar.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Avatar;
@@ -32,9 +14,7 @@ use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
-use OCP\IConfig;
use OCP\IImage;
-use OCP\IL10N;
use Psr\Log\LoggerInterface;
/**
@@ -44,26 +24,12 @@ use Psr\Log\LoggerInterface;
* for faster retrieval, unlike the GuestAvatar.
*/
class PlaceholderAvatar extends Avatar {
- private ISimpleFolder $folder;
- private User $user;
-
- /**
- * UserAvatar constructor.
- *
- * @param IConfig $config The configuration
- * @param ISimpleFolder $folder The avatar files folder
- * @param IL10N $l The localization helper
- * @param User $user The user this class manages the avatar for
- * @param LoggerInterface $logger The logger
- */
public function __construct(
- ISimpleFolder $folder,
- $user,
- LoggerInterface $logger) {
+ private ISimpleFolder $folder,
+ private User $user,
+ LoggerInterface $logger,
+ ) {
parent::__construct($logger);
-
- $this->folder = $folder;
- $this->user = $user;
}
/**
@@ -80,7 +46,6 @@ class PlaceholderAvatar extends Avatar {
* @throws \Exception if the provided file is not a jpg or png image
* @throws \Exception if the provided image is not valid
* @throws NotSquareException if the image is not square
- * @return void
*/
public function set($data): void {
// unimplemented for placeholder avatars
@@ -102,8 +67,6 @@ class PlaceholderAvatar extends Avatar {
*
* If there is no avatar file yet, one is generated.
*
- * @param int $size
- * @return ISimpleFile
* @throws NotFoundException
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\PreConditionNotMetException
diff --git a/lib/private/Avatar/UserAvatar.php b/lib/private/Avatar/UserAvatar.php
index 6d39d5f067d..ce604394c4e 100644
--- a/lib/private/Avatar/UserAvatar.php
+++ b/lib/private/Avatar/UserAvatar.php
@@ -3,29 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Michael Weimann <mail@michael-weimann.eu>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Avatar;
@@ -44,31 +23,14 @@ use Psr\Log\LoggerInterface;
* This class represents a registered user's avatar.
*/
class UserAvatar extends Avatar {
- private IConfig $config;
- private ISimpleFolder $folder;
- private IL10N $l;
- private User $user;
-
- /**
- * UserAvatar constructor.
- *
- * @param IConfig $config The configuration
- * @param ISimpleFolder $folder The avatar files folder
- * @param IL10N $l The localization helper
- * @param User $user The user this class manages the avatar for
- * @param LoggerInterface $logger The logger
- */
public function __construct(
- ISimpleFolder $folder,
- IL10N $l,
- User $user,
+ private ISimpleFolder $folder,
+ private IL10N $l,
+ private User $user,
LoggerInterface $logger,
- IConfig $config) {
+ private IConfig $config,
+ ) {
parent::__construct($logger);
- $this->folder = $folder;
- $this->l = $l;
- $this->user = $user;
- $this->config = $config;
}
/**
@@ -85,7 +47,6 @@ class UserAvatar extends Avatar {
* @throws \Exception if the provided file is not a jpg or png image
* @throws \Exception if the provided image is not valid
* @throws NotSquareException if the image is not square
- * @return void
*/
public function set($data): void {
$img = $this->getAvatarImage($data);
@@ -113,7 +74,6 @@ class UserAvatar extends Avatar {
* Returns an image from several sources.
*
* @param IImage|resource|string|\GdImage $data An image object, imagedata or path to the avatar
- * @return IImage
*/
private function getAvatarImage($data): IImage {
if ($data instanceof IImage) {
@@ -229,8 +189,6 @@ class UserAvatar extends Avatar {
*
* If there is no avatar file yet, one is generated.
*
- * @param int $size
- * @return ISimpleFile
* @throws NotFoundException
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\PreConditionNotMetException
diff --git a/lib/private/BackgroundJob/Job.php b/lib/private/BackgroundJob/Job.php
deleted file mode 100644
index ffcaaf8c36d..00000000000
--- a/lib/private/BackgroundJob/Job.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Noveen Sachdeva <noveen.sachdeva@research.iiit.ac.in>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\BackgroundJob;
-
-use OCP\BackgroundJob\IJob;
-use OCP\BackgroundJob\IJobList;
-use OCP\ILogger;
-
-/**
- * @deprecated internal class, use \OCP\BackgroundJob\Job
- */
-abstract class Job implements IJob {
- /** @var int */
- protected $id;
-
- /** @var int */
- protected $lastRun;
-
- /** @var mixed */
- protected $argument;
-
- public function execute(IJobList $jobList, ILogger $logger = null) {
- $jobList->setLastRun($this);
- if ($logger === null) {
- $logger = \OC::$server->getLogger();
- }
-
- try {
- $jobStartTime = time();
- $logger->debug('Run ' . get_class($this) . ' job with ID ' . $this->getId(), ['app' => 'cron']);
- $this->run($this->argument);
- $timeTaken = time() - $jobStartTime;
-
- $logger->debug('Finished ' . get_class($this) . ' job with ID ' . $this->getId() . ' in ' . $timeTaken . ' seconds', ['app' => 'cron']);
- $jobList->setExecutionTime($this, $timeTaken);
- } catch (\Throwable $e) {
- if ($logger) {
- $logger->logException($e, [
- 'app' => 'core',
- 'message' => 'Error while running background job (class: ' . get_class($this) . ', arguments: ' . print_r($this->argument, true) . ')'
- ]);
- }
- }
- }
-
- public function start(IJobList $jobList): void {
- $this->execute($jobList);
- }
-
- abstract protected function run($argument);
-
- public function setId(int $id) {
- $this->id = $id;
- }
-
- public function setLastRun(int $lastRun) {
- $this->lastRun = $lastRun;
- }
-
- public function setArgument($argument) {
- $this->argument = $argument;
- }
-
- public function getId() {
- return $this->id;
- }
-
- public function getLastRun() {
- return $this->lastRun;
- }
-
- public function getArgument() {
- return $this->argument;
- }
-}
diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php
index 36cccbd4eab..3df9be7558c 100644
--- a/lib/private/BackgroundJob/JobList.php
+++ b/lib/private/BackgroundJob/JobList.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Noveen Sachdeva <noveen.sachdeva@research.iiit.ac.in>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\BackgroundJob;
@@ -41,6 +19,10 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection;
use Psr\Log\LoggerInterface;
+use function get_class;
+use function json_encode;
+use function md5;
+use function strlen;
class JobList implements IJobList {
protected IDBConnection $connection;
@@ -55,11 +37,10 @@ class JobList implements IJobList {
$this->logger = $logger;
}
- /**
- * @param IJob|class-string<IJob> $job
- * @param mixed $argument
- */
- public function add($job, $argument = null): void {
+ public function add($job, $argument = null, ?int $firstCheck = null): void {
+ if ($firstCheck === null) {
+ $firstCheck = $this->timeFactory->getTime();
+ }
if ($job instanceof IJob) {
$class = get_class($job);
} else {
@@ -79,18 +60,23 @@ class JobList implements IJobList {
'argument' => $query->createNamedParameter($argumentJson),
'argument_hash' => $query->createNamedParameter(md5($argumentJson)),
'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT),
- 'last_checked' => $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT),
+ 'last_checked' => $query->createNamedParameter($firstCheck, IQueryBuilder::PARAM_INT),
]);
} else {
$query->update('jobs')
->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT))
- ->set('last_checked', $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT))
+ ->set('last_checked', $query->createNamedParameter($firstCheck, IQueryBuilder::PARAM_INT))
+ ->set('last_run', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('class', $query->createNamedParameter($class)))
->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(md5($argumentJson))));
}
$query->executeStatement();
}
+ public function scheduleAfter(string $job, int $runAfter, $argument = null): void {
+ $this->add($job, $argument, $runAfter);
+ }
+
/**
* @param IJob|string $job
* @param mixed $argument
@@ -203,10 +189,9 @@ class JobList implements IJobList {
}
/**
- * Get the next job in the list
- * @return ?IJob the next job to run. Beware that this object may be a singleton and may be modified by the next call to buildJob.
+ * @inheritDoc
*/
- public function getNext(bool $onlyTimeSensitive = false): ?IJob {
+ public function getNext(bool $onlyTimeSensitive = false, ?array $jobClasses = null): ?IJob {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs')
@@ -219,6 +204,14 @@ class JobList implements IJobList {
$query->andWhere($query->expr()->eq('time_sensitive', $query->createNamedParameter(IJob::TIME_SENSITIVE, IQueryBuilder::PARAM_INT)));
}
+ if ($jobClasses !== null && count($jobClasses) > 0) {
+ $orClasses = $query->expr()->orx();
+ foreach ($jobClasses as $jobClass) {
+ $orClasses->add($query->expr()->eq('class', $query->createNamedParameter($jobClass, IQueryBuilder::PARAM_STR)));
+ }
+ $query->andWhere($orClasses);
+ }
+
$result = $query->executeQuery();
$row = $result->fetch();
$result->closeCursor();
@@ -253,7 +246,7 @@ class JobList implements IJobList {
if ($count === 0) {
// Background job already executed elsewhere, try again.
- return $this->getNext($onlyTimeSensitive);
+ return $this->getNext($onlyTimeSensitive, $jobClasses);
}
if ($job === null) {
@@ -266,7 +259,7 @@ class JobList implements IJobList {
$reset->executeStatement();
// Background job from disabled app, try again.
- return $this->getNext($onlyTimeSensitive);
+ return $this->getNext($onlyTimeSensitive, $jobClasses);
}
return $job;
@@ -384,6 +377,7 @@ class JobList implements IJobList {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
->set('execution_duration', $query->createNamedParameter($timeTaken, IQueryBuilder::PARAM_INT))
+ ->set('reserved_at', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
$query->executeStatement();
}
@@ -406,7 +400,7 @@ class JobList implements IJobList {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs')
- ->where($query->expr()->neq('reserved_at', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
+ ->where($query->expr()->gt('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 6 * 3600, IQueryBuilder::PARAM_INT)))
->setMaxResults(1);
if ($className !== null) {
@@ -423,4 +417,26 @@ class JobList implements IJobList {
return false;
}
}
+
+ public function countByClass(): array {
+ $query = $this->connection->getQueryBuilder();
+ $query->select('class')
+ ->selectAlias($query->func()->count('id'), 'count')
+ ->from('jobs')
+ ->orderBy('count')
+ ->groupBy('class');
+
+ $result = $query->executeQuery();
+
+ $jobs = [];
+
+ while (($row = $result->fetch()) !== false) {
+ /**
+ * @var array{count:int, class:class-string} $row
+ */
+ $jobs[] = $row;
+ }
+
+ return $jobs;
+ }
}
diff --git a/lib/private/BackgroundJob/QueuedJob.php b/lib/private/BackgroundJob/QueuedJob.php
deleted file mode 100644
index 28d86481e62..00000000000
--- a/lib/private/BackgroundJob/QueuedJob.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\BackgroundJob;
-
-use OCP\ILogger;
-
-/**
- * Class QueuedJob
- *
- * create a background job that is to be executed once
- *
- * @package OC\BackgroundJob
- *
- * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob
- */
-abstract class QueuedJob extends Job {
- /**
- * run the job, then remove it from the joblist
- *
- * @param JobList $jobList
- * @param ILogger|null $logger
- */
- public function execute($jobList, ILogger $logger = null) {
- $jobList->remove($this, $this->argument);
- parent::execute($jobList, $logger);
- }
-}
diff --git a/lib/private/BackgroundJob/TimedJob.php b/lib/private/BackgroundJob/TimedJob.php
deleted file mode 100644
index 0f0951e1aec..00000000000
--- a/lib/private/BackgroundJob/TimedJob.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\BackgroundJob;
-
-use OCP\BackgroundJob\IJobList;
-use OCP\ILogger;
-
-/**
- * Class QueuedJob
- *
- * create a background job that is to be executed at an interval
- *
- * @package OC\BackgroundJob
- *
- * @deprecated internal class, use \OCP\BackgroundJob\TimedJob
- */
-abstract class TimedJob extends Job {
- protected $interval = 0;
-
- /**
- * set the interval for the job
- *
- * @param int $interval
- */
- public function setInterval($interval) {
- $this->interval = $interval;
- }
-
- /**
- * run the job if
- *
- * @param IJobList $jobList
- * @param ILogger|null $logger
- */
- public function execute($jobList, ILogger $logger = null) {
- if ((time() - $this->lastRun) > $this->interval) {
- parent::execute($jobList, $logger);
- }
- }
-}
diff --git a/lib/private/BinaryFinder.php b/lib/private/BinaryFinder.php
index a7ef55237db..f7ac7a5195c 100644
--- a/lib/private/BinaryFinder.php
+++ b/lib/private/BinaryFinder.php
@@ -2,29 +2,15 @@
declare(strict_types = 1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
+use OCP\IBinaryFinder;
use OCP\ICache;
use OCP\ICacheFactory;
-use OCP\IBinaryFinder;
use Symfony\Component\Process\ExecutableFinder;
/**
diff --git a/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php b/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php
new file mode 100644
index 00000000000..61ace449453
--- /dev/null
+++ b/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php
@@ -0,0 +1,153 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Blurhash\Listener;
+
+use GdImage;
+use kornrunner\Blurhash\Blurhash;
+use OC\Files\Node\File;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\GenericFileException;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\FilesMetadata\AMetadataEvent;
+use OCP\FilesMetadata\Event\MetadataBackgroundEvent;
+use OCP\FilesMetadata\Event\MetadataLiveEvent;
+use OCP\IPreview;
+use OCP\Lock\LockedException;
+
+/**
+ * Generate a Blurhash string as metadata when image file is uploaded/edited.
+ *
+ * @template-implements IEventListener<AMetadataEvent>
+ */
+class GenerateBlurhashMetadata implements IEventListener {
+ private const RESIZE_BOXSIZE = 300;
+
+ private const COMPONENTS_X = 4;
+ private const COMPONENTS_Y = 3;
+
+ public function __construct(
+ private IPreview $preview,
+ ) {
+ }
+
+ /**
+ * @throws NotPermittedException
+ * @throws GenericFileException
+ * @throws LockedException
+ */
+ public function handle(Event $event): void {
+ if (!($event instanceof MetadataLiveEvent)
+ && !($event instanceof MetadataBackgroundEvent)) {
+ return;
+ }
+
+ $file = $event->getNode();
+ if (!($file instanceof File)) {
+ return;
+ }
+
+ $currentEtag = $file->getEtag();
+ $metadata = $event->getMetadata();
+ if ($metadata->getEtag('blurhash') === $currentEtag) {
+ return;
+ }
+
+ // too heavy to run on the live thread, request a rerun as a background job
+ if ($event instanceof MetadataLiveEvent) {
+ $event->requestBackgroundJob();
+ return;
+ }
+
+ $image = false;
+ try {
+ // using preview image to generate the blurhash
+ $preview = $this->preview->getPreview($file, 256, 256);
+ $image = @imagecreatefromstring($preview->getContent());
+ } catch (NotFoundException $e) {
+ // https://github.com/nextcloud/server/blob/9d70fd3e64b60a316a03fb2b237891380c310c58/lib/private/legacy/OC_Image.php#L668
+ // The preview system can fail on huge picture, in that case we use our own image resizer.
+ if (str_starts_with($file->getMimetype(), 'image/')) {
+ $image = $this->resizedImageFromFile($file);
+ }
+ }
+
+ if ($image === false) {
+ return;
+ }
+
+ $metadata->setString('blurhash', $this->generateBlurHash($image))
+ ->setEtag('blurhash', $currentEtag);
+ }
+
+ /**
+ * @param File $file
+ *
+ * @return GdImage|false
+ * @throws GenericFileException
+ * @throws NotPermittedException
+ * @throws LockedException
+ */
+ private function resizedImageFromFile(File $file): GdImage|false {
+ $image = @imagecreatefromstring($file->getContent());
+ if ($image === false) {
+ return false;
+ }
+
+ $currX = imagesx($image);
+ $currY = imagesy($image);
+
+ if ($currX > $currY) {
+ $newX = self::RESIZE_BOXSIZE;
+ $newY = intval($currY * $newX / $currX);
+ } else {
+ $newY = self::RESIZE_BOXSIZE;
+ $newX = intval($currX * $newY / $currY);
+ }
+
+ $newImage = imagescale($image, $newX, $newY);
+ return ($newImage !== false) ? $newImage : $image;
+ }
+
+ /**
+ * @param GdImage $image
+ *
+ * @return string
+ */
+ public function generateBlurHash(GdImage $image): string {
+ $width = imagesx($image);
+ $height = imagesy($image);
+
+ $pixels = [];
+ for ($y = 0; $y < $height; ++$y) {
+ $row = [];
+ for ($x = 0; $x < $width; ++$x) {
+ $index = imagecolorat($image, $x, $y);
+ $colors = imagecolorsforindex($image, $index);
+ $row[] = [$colors['red'], $colors['green'], $colors['blue']];
+ }
+
+ $pixels[] = $row;
+ }
+
+ return Blurhash::encode($pixels, self::COMPONENTS_X, self::COMPONENTS_Y);
+ }
+
+ /**
+ * @param IEventDispatcher $eventDispatcher
+ *
+ * @return void
+ */
+ public static function loadListeners(IEventDispatcher $eventDispatcher): void {
+ $eventDispatcher->addServiceListener(MetadataLiveEvent::class, self::class);
+ $eventDispatcher->addServiceListener(MetadataBackgroundEvent::class, self::class);
+ }
+}
diff --git a/lib/private/Broadcast/Events/BroadcastEvent.php b/lib/private/Broadcast/Events/BroadcastEvent.php
index de950ac9371..d6c2cf49904 100644
--- a/lib/private/Broadcast/Events/BroadcastEvent.php
+++ b/lib/private/Broadcast/Events/BroadcastEvent.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Broadcast\Events;
diff --git a/lib/private/Cache/CappedMemoryCache.php b/lib/private/Cache/CappedMemoryCache.php
index 31e8ef3e720..2c2eab3209a 100644
--- a/lib/private/Cache/CappedMemoryCache.php
+++ b/lib/private/Cache/CappedMemoryCache.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Cache;
diff --git a/lib/private/Cache/File.php b/lib/private/Cache/File.php
index 72fc95a802b..33fa1c00e98 100644
--- a/lib/private/Cache/File.php
+++ b/lib/private/Cache/File.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sebastian Wessalowski <sebastian@wessalowski.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Cache;
@@ -60,7 +38,7 @@ class File implements ICache {
$this->storage = new View('/' . $user->getUID() . '/cache');
return $this->storage;
} else {
- \OC::$server->get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
+ \OCP\Server::get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
}
}
@@ -192,11 +170,11 @@ class File implements ICache {
}
} catch (\OCP\Lock\LockedException $e) {
// ignore locked chunks
- \OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
+ \OCP\Server::get(LoggerInterface::class)->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
} catch (\OCP\Files\ForbiddenException $e) {
- \OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
+ \OCP\Server::get(LoggerInterface::class)->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
} catch (\OCP\Files\LockNotAcquiredException $e) {
- \OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
+ \OCP\Server::get(LoggerInterface::class)->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
}
}
}
diff --git a/lib/private/Calendar/CalendarQuery.php b/lib/private/Calendar/CalendarQuery.php
index 3d37d9dc467..4eb4a4cd636 100644
--- a/lib/private/Calendar/CalendarQuery.php
+++ b/lib/private/Calendar/CalendarQuery.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Anna Larch <anna.larch@gmx.net>
- *
- * @author Anna Larch <anna.larch@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Calendar;
diff --git a/lib/private/Calendar/Manager.php b/lib/private/Calendar/Manager.php
index dc4801c69ce..7ae577c9d7f 100644
--- a/lib/private/Calendar/Manager.php
+++ b/lib/private/Calendar/Manager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2017, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Anna Larch <anna.larch@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Calendar;
diff --git a/lib/private/Calendar/Resource/Manager.php b/lib/private/Calendar/Resource/Manager.php
index 88e733f3f24..870409c9ba5 100644
--- a/lib/private/Calendar/Resource/Manager.php
+++ b/lib/private/Calendar/Resource/Manager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Calendar\Resource;
diff --git a/lib/private/Calendar/Room/Manager.php b/lib/private/Calendar/Room/Manager.php
index d7ecdfd8b36..e5a60765919 100644
--- a/lib/private/Calendar/Room/Manager.php
+++ b/lib/private/Calendar/Room/Manager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Calendar\Room;
diff --git a/lib/private/CapabilitiesManager.php b/lib/private/CapabilitiesManager.php
index 7885a98869d..bb84ebb65e8 100644
--- a/lib/private/CapabilitiesManager.php
+++ b/lib/private/CapabilitiesManager.php
@@ -1,37 +1,17 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
use OCP\AppFramework\QueryException;
use OCP\Capabilities\ICapability;
-use OCP\Capabilities\IPublicCapability;
use OCP\Capabilities\IInitialStateExcludedCapability;
+use OCP\Capabilities\IPublicCapability;
use Psr\Log\LoggerInterface;
class CapabilitiesManager {
diff --git a/lib/private/Collaboration/AutoComplete/Manager.php b/lib/private/Collaboration/AutoComplete/Manager.php
index cab15baf535..d7298d9deef 100644
--- a/lib/private/Collaboration/AutoComplete/Manager.php
+++ b/lib/private/Collaboration/AutoComplete/Manager.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\AutoComplete;
@@ -29,47 +11,46 @@ use OCP\IServerContainer;
class Manager implements IManager {
/** @var string[] */
- protected $sorters = [];
+ protected array $sorters = [];
/** @var ISorter[] */
- protected $sorterInstances = [];
- /** @var IServerContainer */
- private $c;
+ protected array $sorterInstances = [];
- public function __construct(IServerContainer $container) {
- $this->c = $container;
+ public function __construct(
+ private IServerContainer $container,
+ ) {
}
- public function runSorters(array $sorters, array &$sortArray, array $context) {
+ public function runSorters(array $sorters, array &$sortArray, array $context): void {
$sorterInstances = $this->getSorters();
while ($sorter = array_shift($sorters)) {
if (isset($sorterInstances[$sorter])) {
$sorterInstances[$sorter]->sort($sortArray, $context);
} else {
- $this->c->getLogger()->warning('No sorter for ID "{id}", skipping', [
+ $this->container->getLogger()->warning('No sorter for ID "{id}", skipping', [
'app' => 'core', 'id' => $sorter
]);
}
}
}
- public function registerSorter($className) {
+ public function registerSorter($className): void {
$this->sorters[] = $className;
}
- protected function getSorters() {
+ protected function getSorters(): array {
if (count($this->sorterInstances) === 0) {
foreach ($this->sorters as $sorter) {
/** @var ISorter $instance */
- $instance = $this->c->resolve($sorter);
+ $instance = $this->container->resolve($sorter);
if (!$instance instanceof ISorter) {
- $this->c->getLogger()->notice('Skipping sorter which is not an instance of ISorter. Class name: {class}',
+ $this->container->getLogger()->notice('Skipping sorter which is not an instance of ISorter. Class name: {class}',
['app' => 'core', 'class' => $sorter]);
continue;
}
$sorterId = trim($instance->getId());
if (trim($sorterId) === '') {
- $this->c->getLogger()->notice('Skipping sorter with empty ID. Class name: {class}',
+ $this->container->getLogger()->notice('Skipping sorter with empty ID. Class name: {class}',
['app' => 'core', 'class' => $sorter]);
continue;
}
diff --git a/lib/private/Collaboration/Collaborators/GroupPlugin.php b/lib/private/Collaboration/Collaborators/GroupPlugin.php
index 75e52c19e0b..a7b84b72199 100644
--- a/lib/private/Collaboration/Collaborators/GroupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/GroupPlugin.php
@@ -1,29 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -37,34 +15,31 @@ use OCP\IUserSession;
use OCP\Share\IShare;
class GroupPlugin implements ISearchPlugin {
- /** @var bool */
- protected $shareeEnumeration;
- /** @var bool */
- protected $shareWithGroupOnly;
- /** @var bool */
- protected $shareeEnumerationInGroupOnly;
- /** @var bool */
- protected $groupSharingDisabled;
-
- /** @var IGroupManager */
- private $groupManager;
- /** @var IConfig */
- private $config;
- /** @var IUserSession */
- private $userSession;
-
- public function __construct(IConfig $config, IGroupManager $groupManager, IUserSession $userSession) {
- $this->groupManager = $groupManager;
- $this->config = $config;
- $this->userSession = $userSession;
+ protected bool $shareeEnumeration;
+ protected bool $shareWithGroupOnly;
+
+ protected bool $shareeEnumerationInGroupOnly;
+
+ protected bool $groupSharingDisabled;
+
+ public function __construct(
+ private IConfig $config,
+ private IGroupManager $groupManager,
+ private IUserSession $userSession,
+ private mixed $shareWithGroupOnlyExcludeGroupsList = [],
+ ) {
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$this->groupSharingDisabled = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'no';
+
+ if ($this->shareWithGroupOnly) {
+ $this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
+ }
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
if ($this->groupSharingDisabled) {
return false;
}
@@ -89,6 +64,9 @@ class GroupPlugin implements ISearchPlugin {
return $group->getGID();
}, $userGroups);
$groupIds = array_intersect($groupIds, $userGroups);
+
+ // ShareWithGroupOnly filtering
+ $groupIds = array_diff($groupIds, $this->shareWithGroupOnlyExcludeGroupsList);
}
$lowerSearch = strtolower($search);
diff --git a/lib/private/Collaboration/Collaborators/LookupPlugin.php b/lib/private/Collaboration/Collaborators/LookupPlugin.php
index 86ac70ab970..3cc4e93a486 100644
--- a/lib/private/Collaboration/Collaborators/LookupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/LookupPlugin.php
@@ -1,29 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -38,31 +16,21 @@ use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
class LookupPlugin implements ISearchPlugin {
- /** @var IConfig */
- private $config;
- /** @var IClientService */
- private $clientService;
/** @var string remote part of the current user's cloud id */
- private $currentUserRemote;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var LoggerInterface */
- private $logger;
+ private string $currentUserRemote;
- public function __construct(IConfig $config,
- IClientService $clientService,
- IUserSession $userSession,
- ICloudIdManager $cloudIdManager,
- LoggerInterface $logger) {
- $this->config = $config;
- $this->clientService = $clientService;
- $this->cloudIdManager = $cloudIdManager;
+ public function __construct(
+ private IConfig $config,
+ private IClientService $clientService,
+ IUserSession $userSession,
+ private ICloudIdManager $cloudIdManager,
+ private LoggerInterface $logger,
+ ) {
$currentUserCloudId = $userSession->getUser()->getCloudId();
$this->currentUserRemote = $cloudIdManager->resolveCloudId($currentUserCloudId)->getRemote();
- $this->logger = $logger;
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$isGlobalScaleEnabled = $this->config->getSystemValueBool('gs.enabled', false);
$isLookupServerEnabled = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes') === 'yes';
$hasInternetConnection = $this->config->getSystemValueBool('has_internet_connection', true);
@@ -103,7 +71,7 @@ class LookupPlugin implements ISearchPlugin {
if ($this->currentUserRemote === $remote) {
continue;
}
- $name = isset($lookup['name']['value']) ? $lookup['name']['value'] : '';
+ $name = $lookup['name']['value'] ?? '';
$label = empty($name) ? $lookup['federationId'] : $name . ' (' . $lookup['federationId'] . ')';
$result[] = [
'label' => $label,
diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php
index aa317ec1720..134970518bc 100644
--- a/lib/private/Collaboration/Collaborators/MailPlugin.php
+++ b/lib/private/Collaboration/Collaborators/MailPlugin.php
@@ -1,28 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Tobia De Koninck <tobia@ledfan.be>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -37,66 +16,48 @@ use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
-use OCP\Share\IShare;
use OCP\Mail\IMailer;
+use OCP\Share\IShare;
class MailPlugin implements ISearchPlugin {
- /* @var bool */
- protected $shareWithGroupOnly;
- /* @var bool */
- protected $shareeEnumeration;
- /* @var bool */
- protected $shareeEnumerationInGroupOnly;
- /* @var bool */
- protected $shareeEnumerationPhone;
- /* @var bool */
- protected $shareeEnumerationFullMatch;
- /* @var bool */
- protected $shareeEnumerationFullMatchEmail;
+ protected bool $shareWithGroupOnly;
+
+ protected bool $shareeEnumeration;
+
+ protected bool $shareeEnumerationInGroupOnly;
- /** @var IManager */
- private $contactsManager;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var IConfig */
- private $config;
+ protected bool $shareeEnumerationPhone;
- /** @var IGroupManager */
- private $groupManager;
- /** @var KnownUserService */
- private $knownUserService;
- /** @var IUserSession */
- private $userSession;
- /** @var IMailer */
- private $mailer;
+ protected bool $shareeEnumerationFullMatch;
- public function __construct(IManager $contactsManager,
- ICloudIdManager $cloudIdManager,
- IConfig $config,
- IGroupManager $groupManager,
- KnownUserService $knownUserService,
- IUserSession $userSession,
- IMailer $mailer) {
- $this->contactsManager = $contactsManager;
- $this->cloudIdManager = $cloudIdManager;
- $this->config = $config;
- $this->groupManager = $groupManager;
- $this->knownUserService = $knownUserService;
- $this->userSession = $userSession;
- $this->mailer = $mailer;
+ protected bool $shareeEnumerationFullMatchEmail;
+ public function __construct(
+ private IManager $contactsManager,
+ private ICloudIdManager $cloudIdManager,
+ private IConfig $config,
+ private IGroupManager $groupManager,
+ private KnownUserService $knownUserService,
+ private IUserSession $userSession,
+ private IMailer $mailer,
+ private mixed $shareWithGroupOnlyExcludeGroupsList = [],
+ ) {
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
$this->shareeEnumerationFullMatch = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
$this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
+
+ if ($this->shareWithGroupOnly) {
+ $this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
+ }
}
/**
* {@inheritdoc}
*/
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
if ($this->shareeEnumerationFullMatch && !$this->shareeEnumerationFullMatchEmail) {
return false;
}
@@ -120,8 +81,8 @@ class MailPlugin implements ISearchPlugin {
[
'limit' => $limit,
'offset' => $offset,
- 'enumeration' => (bool) $this->shareeEnumeration,
- 'fullmatch' => (bool) $this->shareeEnumerationFullMatch,
+ 'enumeration' => $this->shareeEnumeration,
+ 'fullmatch' => $this->shareeEnumerationFullMatch,
]
);
$lowerSearch = strtolower($search);
@@ -150,6 +111,10 @@ class MailPlugin implements ISearchPlugin {
* Check if the user may share with the user associated with the e-mail of the just found contact
*/
$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
+
+ // ShareWithGroupOnly filtering
+ $userGroups = array_diff($userGroups, $this->shareWithGroupOnlyExcludeGroupsList);
+
$found = false;
foreach ($userGroups as $userGroup) {
if ($this->groupManager->isInGroup($contact['UID'], $userGroup)) {
@@ -163,7 +128,7 @@ class MailPlugin implements ISearchPlugin {
}
if ($exactEmailMatch && $this->shareeEnumerationFullMatch) {
try {
- $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
+ $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0] ?? '');
} catch (\InvalidArgumentException $e) {
continue;
}
@@ -188,7 +153,7 @@ class MailPlugin implements ISearchPlugin {
if ($this->shareeEnumeration) {
try {
- $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
+ $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0] ?? '');
} catch (\InvalidArgumentException $e) {
continue;
}
@@ -286,6 +251,6 @@ class MailPlugin implements ISearchPlugin {
public function isCurrentUser(ICloudId $cloud): bool {
$currentUser = $this->userSession->getUser();
- return $currentUser instanceof IUser ? $currentUser->getUID() === $cloud->getUser() : false;
+ return $currentUser instanceof IUser && $currentUser->getUID() === $cloud->getUser();
}
}
diff --git a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
index 413799e52c6..89d5c4e4f79 100644
--- a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -33,14 +14,12 @@ use OCP\Share;
use OCP\Share\IShare;
class RemoteGroupPlugin implements ISearchPlugin {
- protected $shareeEnumeration;
+ private bool $enabled = false;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var bool */
- private $enabled = false;
-
- public function __construct(ICloudFederationProviderManager $cloudFederationProviderManager, ICloudIdManager $cloudIdManager) {
+ public function __construct(
+ ICloudFederationProviderManager $cloudFederationProviderManager,
+ private ICloudIdManager $cloudIdManager,
+ ) {
try {
$fileSharingProvider = $cloudFederationProviderManager->getCloudFederationProvider('file');
$supportedShareTypes = $fileSharingProvider->getSupportedShareTypes();
@@ -50,10 +29,9 @@ class RemoteGroupPlugin implements ISearchPlugin {
} catch (\Exception $e) {
// do nothing, just don't enable federated group shares
}
- $this->cloudIdManager = $cloudIdManager;
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$resultType = new SearchResultType('remote_groups');
@@ -83,7 +61,7 @@ class RemoteGroupPlugin implements ISearchPlugin {
* @return array [user, remoteURL]
* @throws \InvalidArgumentException
*/
- public function splitGroupRemote($address) {
+ public function splitGroupRemote($address): array {
try {
$cloudId = $this->cloudIdManager->resolveCloudId($address);
return [$cloudId->getUser(), $cloudId->getRemote()];
diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php
index 7d7a013a38c..e46b71eb710 100644
--- a/lib/private/Collaboration/Collaborators/RemotePlugin.php
+++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php
@@ -1,28 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -37,32 +16,22 @@ use OCP\IUserSession;
use OCP\Share\IShare;
class RemotePlugin implements ISearchPlugin {
- protected $shareeEnumeration;
+ protected bool $shareeEnumeration;
- /** @var IManager */
- private $contactsManager;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var IConfig */
- private $config;
- /** @var IUserManager */
- private $userManager;
- /** @var string */
- private $userId = '';
+ private string $userId;
- public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IUserManager $userManager, IUserSession $userSession) {
- $this->contactsManager = $contactsManager;
- $this->cloudIdManager = $cloudIdManager;
- $this->config = $config;
- $this->userManager = $userManager;
- $user = $userSession->getUser();
- if ($user !== null) {
- $this->userId = $user->getUID();
- }
+ public function __construct(
+ private IManager $contactsManager,
+ private ICloudIdManager $cloudIdManager,
+ private IConfig $config,
+ private IUserManager $userManager,
+ IUserSession $userSession,
+ ) {
+ $this->userId = $userSession->getUser()?->getUID() ?? '';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$resultType = new SearchResultType('remotes');
@@ -185,7 +154,7 @@ class RemotePlugin implements ISearchPlugin {
* @return array [user, remoteURL]
* @throws \InvalidArgumentException
*/
- public function splitUserRemote($address) {
+ public function splitUserRemote(string $address): array {
try {
$cloudId = $this->cloudIdManager->resolveCloudId($address);
return [$cloudId->getUser(), $cloudId->getRemote()];
diff --git a/lib/private/Collaboration/Collaborators/Search.php b/lib/private/Collaboration/Collaborators/Search.php
index 8d99ed42fcd..78b57b52400 100644
--- a/lib/private/Collaboration/Collaborators/Search.php
+++ b/lib/private/Collaboration/Collaborators/Search.php
@@ -1,29 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author onehappycat <one.happy.cat@gmx.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -35,32 +13,28 @@ use OCP\IContainer;
use OCP\Share;
class Search implements ISearch {
- /** @var IContainer */
- private $c;
+ protected array $pluginList = [];
- protected $pluginList = [];
-
- public function __construct(IContainer $c) {
- $this->c = $c;
+ public function __construct(
+ private IContainer $container,
+ ) {
}
/**
* @param string $search
- * @param array $shareTypes
* @param bool $lookup
* @param int|null $limit
* @param int|null $offset
- * @return array
* @throws \OCP\AppFramework\QueryException
*/
- public function search($search, array $shareTypes, $lookup, $limit, $offset) {
+ public function search($search, array $shareTypes, $lookup, $limit, $offset): array {
$hasMoreResults = false;
// Trim leading and trailing whitespace characters, e.g. when query is copy-pasted
$search = trim($search);
/** @var ISearchResult $searchResult */
- $searchResult = $this->c->resolve(SearchResult::class);
+ $searchResult = $this->container->resolve(SearchResult::class);
foreach ($shareTypes as $type) {
if (!isset($this->pluginList[$type])) {
@@ -68,14 +42,14 @@ class Search implements ISearch {
}
foreach ($this->pluginList[$type] as $plugin) {
/** @var ISearchPlugin $searchPlugin */
- $searchPlugin = $this->c->resolve($plugin);
+ $searchPlugin = $this->container->resolve($plugin);
$hasMoreResults = $searchPlugin->search($search, $limit, $offset, $searchResult) || $hasMoreResults;
}
}
// Get from lookup server, not a separate share type
if ($lookup) {
- $searchPlugin = $this->c->resolve(LookupPlugin::class);
+ $searchPlugin = $this->container->resolve(LookupPlugin::class);
$hasMoreResults = $searchPlugin->search($search, $limit, $offset, $searchResult) || $hasMoreResults;
}
@@ -105,7 +79,7 @@ class Search implements ISearch {
return [$searchResult->asArray(), $hasMoreResults];
}
- public function registerPlugin(array $pluginInfo) {
+ public function registerPlugin(array $pluginInfo): void {
$shareType = constant(Share::class . '::' . $pluginInfo['shareType']);
if ($shareType === null) {
throw new \InvalidArgumentException('Provided ShareType is invalid');
diff --git a/lib/private/Collaboration/Collaborators/SearchResult.php b/lib/private/Collaboration/Collaborators/SearchResult.php
index 76d78c9c231..73c0fed41e0 100644
--- a/lib/private/Collaboration/Collaborators/SearchResult.php
+++ b/lib/private/Collaboration/Collaborators/SearchResult.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -28,13 +9,13 @@ use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
class SearchResult implements ISearchResult {
- protected $result = [
+ protected array $result = [
'exact' => [],
];
- protected $exactIdMatches = [];
+ protected array $exactIdMatches = [];
- public function addResultSet(SearchResultType $type, array $matches, array $exactMatches = null) {
+ public function addResultSet(SearchResultType $type, array $matches, ?array $exactMatches = null): void {
$type = $type->getLabel();
if (!isset($this->result[$type])) {
$this->result[$type] = [];
@@ -47,15 +28,15 @@ class SearchResult implements ISearchResult {
}
}
- public function markExactIdMatch(SearchResultType $type) {
+ public function markExactIdMatch(SearchResultType $type): void {
$this->exactIdMatches[$type->getLabel()] = 1;
}
- public function hasExactIdMatch(SearchResultType $type) {
+ public function hasExactIdMatch(SearchResultType $type): bool {
return isset($this->exactIdMatches[$type->getLabel()]);
}
- public function hasResult(SearchResultType $type, $collaboratorId) {
+ public function hasResult(SearchResultType $type, $collaboratorId): bool {
$type = $type->getLabel();
if (!isset($this->result[$type])) {
return false;
@@ -73,11 +54,11 @@ class SearchResult implements ISearchResult {
return false;
}
- public function asArray() {
+ public function asArray(): array {
return $this->result;
}
- public function unsetResult(SearchResultType $type) {
+ public function unsetResult(SearchResultType $type): void {
$type = $type->getLabel();
$this->result[$type] = [];
if (isset($this->result['exact'][$type])) {
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php
index 9beecdaa6cb..b4cb77ad5b8 100644
--- a/lib/private/Collaboration/Collaborators/UserPlugin.php
+++ b/lib/private/Collaboration/Collaborators/UserPlugin.php
@@ -1,33 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -44,50 +18,31 @@ use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
class UserPlugin implements ISearchPlugin {
- /* @var bool */
- protected $shareWithGroupOnly;
- /* @var bool */
- protected $shareeEnumeration;
- /* @var bool */
- protected $shareeEnumerationInGroupOnly;
- /* @var bool */
- protected $shareeEnumerationPhone;
- /* @var bool */
- protected $shareeEnumerationFullMatch;
- /* @var bool */
- protected $shareeEnumerationFullMatchUserId;
- /* @var bool */
- protected $shareeEnumerationFullMatchEmail;
- /* @var bool */
- protected $shareeEnumerationFullMatchIgnoreSecondDisplayName;
-
- /** @var IConfig */
- private $config;
- /** @var IGroupManager */
- private $groupManager;
- /** @var IUserSession */
- private $userSession;
- /** @var IUserManager */
- private $userManager;
- /** @var KnownUserService */
- private $knownUserService;
- /** @var IUserStatusManager */
- private $userStatusManager;
-
- public function __construct(IConfig $config,
- IUserManager $userManager,
- IGroupManager $groupManager,
- IUserSession $userSession,
- KnownUserService $knownUserService,
- IUserStatusManager $userStatusManager) {
- $this->config = $config;
-
- $this->groupManager = $groupManager;
- $this->userSession = $userSession;
- $this->userManager = $userManager;
- $this->knownUserService = $knownUserService;
- $this->userStatusManager = $userStatusManager;
+ protected bool $shareWithGroupOnly;
+ protected bool $shareeEnumeration;
+
+ protected bool $shareeEnumerationInGroupOnly;
+
+ protected bool $shareeEnumerationPhone;
+
+ protected bool $shareeEnumerationFullMatch;
+
+ protected bool $shareeEnumerationFullMatchUserId;
+
+ protected bool $shareeEnumerationFullMatchEmail;
+
+ protected bool $shareeEnumerationFullMatchIgnoreSecondDisplayName;
+
+ public function __construct(
+ private IConfig $config,
+ private IUserManager $userManager,
+ private IGroupManager $groupManager,
+ private IUserSession $userSession,
+ private KnownUserService $knownUserService,
+ private IUserStatusManager $userStatusManager,
+ private mixed $shareWithGroupOnlyExcludeGroupsList = [],
+ ) {
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
@@ -96,15 +51,23 @@ class UserPlugin implements ISearchPlugin {
$this->shareeEnumerationFullMatchUserId = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes') === 'yes';
$this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
$this->shareeEnumerationFullMatchIgnoreSecondDisplayName = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes';
+
+ if ($this->shareWithGroupOnly) {
+ $this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
+ }
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$users = [];
$hasMoreResults = false;
$currentUserId = $this->userSession->getUser()->getUID();
$currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
+
+ // ShareWithGroupOnly filtering
+ $currentUserGroups = array_diff($currentUserGroups, $this->shareWithGroupOnlyExcludeGroupsList);
+
if ($this->shareWithGroupOnly || $this->shareeEnumerationInGroupOnly) {
// Search in all the groups this user is part of
foreach ($currentUserGroups as $userGroupId) {
@@ -282,8 +245,6 @@ class UserPlugin implements ISearchPlugin {
}
}
-
-
$type = new SearchResultType('users');
$searchResult->addResultSet($type, $result['wide'], $result['exact']);
if (count($result['exact'])) {
@@ -293,7 +254,7 @@ class UserPlugin implements ISearchPlugin {
return $hasMoreResults;
}
- public function takeOutCurrentUser(array &$users) {
+ public function takeOutCurrentUser(array &$users): void {
$currentUser = $this->userSession->getUser();
if (!is_null($currentUser)) {
if (isset($users[$currentUser->getUID()])) {
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php
index 1dbe8e3bc35..e468ad4eb4c 100644
--- a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php
+++ b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php
@@ -2,24 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Reference\File;
@@ -36,10 +20,9 @@ use OCP\Share\Events\ShareDeletedEvent;
/** @template-implements IEventListener<Event|NodeDeletedEvent|ShareDeletedEvent|ShareCreatedEvent> */
class FileReferenceEventListener implements IEventListener {
- private IReferenceManager $manager;
-
- public function __construct(IReferenceManager $manager) {
- $this->manager = $manager;
+ public function __construct(
+ private IReferenceManager $manager,
+ ) {
}
public static function register(IEventDispatcher $eventDispatcher): void {
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
index d423a830495..3cb174d9607 100644
--- a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
+++ b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
@@ -2,24 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Reference\File;
@@ -31,7 +15,6 @@ use OCP\Collaboration\Reference\Reference;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\InvalidPathException;
use OCP\Files\IRootFolder;
-use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IL10N;
@@ -41,26 +24,18 @@ use OCP\IUserSession;
use OCP\L10N\IFactory;
class FileReferenceProvider extends ADiscoverableReferenceProvider {
- private IURLGenerator $urlGenerator;
- private IRootFolder $rootFolder;
private ?string $userId;
- private IPreview $previewManager;
- private IMimeTypeDetector $mimeTypeDetector;
private IL10N $l10n;
public function __construct(
- IURLGenerator $urlGenerator,
- IRootFolder $rootFolder,
+ private IURLGenerator $urlGenerator,
+ private IRootFolder $rootFolder,
IUserSession $userSession,
- IMimeTypeDetector $mimeTypeDetector,
- IPreview $previewManager,
- IFactory $l10n
+ private IMimeTypeDetector $mimeTypeDetector,
+ private IPreview $previewManager,
+ IFactory $l10n,
) {
- $this->urlGenerator = $urlGenerator;
- $this->rootFolder = $rootFolder;
- $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
- $this->previewManager = $previewManager;
- $this->mimeTypeDetector = $mimeTypeDetector;
+ $this->userId = $userSession->getUser()?->getUID();
$this->l10n = $l10n->get('files');
}
@@ -129,15 +104,12 @@ class FileReferenceProvider extends ADiscoverableReferenceProvider {
try {
$userFolder = $this->rootFolder->getUserFolder($this->userId);
- $files = $userFolder->getById($fileId);
+ $file = $userFolder->getFirstNodeById($fileId);
- if (empty($files)) {
+ if (!$file) {
throw new NotFoundException();
}
- /** @var Node $file */
- $file = array_shift($files);
-
$reference->setTitle($file->getName());
$reference->setDescription($file->getMimetype());
$reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId));
diff --git a/lib/private/Collaboration/Reference/LinkReferenceProvider.php b/lib/private/Collaboration/Reference/LinkReferenceProvider.php
index dbdab75abcb..5af23bf633d 100644
--- a/lib/private/Collaboration/Reference/LinkReferenceProvider.php
+++ b/lib/private/Collaboration/Reference/LinkReferenceProvider.php
@@ -2,190 +2,14 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Reference;
-use Fusonic\OpenGraph\Consumer;
-use GuzzleHttp\Exception\GuzzleException;
-use GuzzleHttp\Psr7\LimitStream;
-use GuzzleHttp\Psr7\Utils;
-use OC\Security\RateLimiting\Exception\RateLimitExceededException;
-use OC\Security\RateLimiting\Limiter;
-use OC\SystemConfig;
-use OCP\Collaboration\Reference\IReference;
-use OCP\Collaboration\Reference\IReferenceProvider;
-use OCP\Collaboration\Reference\Reference;
-use OCP\Files\AppData\IAppDataFactory;
-use OCP\Files\NotFoundException;
-use OCP\Http\Client\IClientService;
-use OCP\IRequest;
-use OCP\IURLGenerator;
-use OCP\IUserSession;
-use Psr\Log\LoggerInterface;
+use OCP\Collaboration\Reference\LinkReferenceProvider as OCPLinkReferenceProvider;
-class LinkReferenceProvider implements IReferenceProvider {
- public const MAX_PREVIEW_SIZE = 1024 * 1024;
-
- public const ALLOWED_CONTENT_TYPES = [
- 'image/png',
- 'image/jpg',
- 'image/jpeg',
- 'image/gif',
- 'image/svg+xml',
- 'image/webp'
- ];
-
- private IClientService $clientService;
- private LoggerInterface $logger;
- private SystemConfig $systemConfig;
- private IAppDataFactory $appDataFactory;
- private IURLGenerator $urlGenerator;
- private Limiter $limiter;
- private IUserSession $userSession;
- private IRequest $request;
-
- public function __construct(IClientService $clientService, LoggerInterface $logger, SystemConfig $systemConfig, IAppDataFactory $appDataFactory, IURLGenerator $urlGenerator, Limiter $limiter, IUserSession $userSession, IRequest $request) {
- $this->clientService = $clientService;
- $this->logger = $logger;
- $this->systemConfig = $systemConfig;
- $this->appDataFactory = $appDataFactory;
- $this->urlGenerator = $urlGenerator;
- $this->limiter = $limiter;
- $this->userSession = $userSession;
- $this->request = $request;
- }
-
- public function matchReference(string $referenceText): bool {
- if ($this->systemConfig->getValue('reference_opengraph', true) !== true) {
- return false;
- }
-
- return (bool)preg_match(IURLGenerator::URL_REGEX, $referenceText);
- }
-
- public function resolveReference(string $referenceText): ?IReference {
- if ($this->matchReference($referenceText)) {
- $reference = new Reference($referenceText);
- $this->fetchReference($reference);
- return $reference;
- }
-
- return null;
- }
-
- private function fetchReference(Reference $reference): void {
- try {
- $user = $this->userSession->getUser();
- if ($user) {
- $this->limiter->registerUserRequest('opengraph', 10, 120, $user);
- } else {
- $this->limiter->registerAnonRequest('opengraph', 10, 120, $this->request->getRemoteAddress());
- }
- } catch (RateLimitExceededException $e) {
- return;
- }
-
- $client = $this->clientService->newClient();
- try {
- $headResponse = $client->head($reference->getId(), [ 'timeout' => 10 ]);
- } catch (\Exception $e) {
- $this->logger->debug('Failed to perform HEAD request to get target metadata', ['exception' => $e]);
- return;
- }
- $linkContentLength = $headResponse->getHeader('Content-Length');
- if (is_numeric($linkContentLength) && (int) $linkContentLength > 5 * 1024 * 1024) {
- $this->logger->debug('Skip resolving links pointing to content length > 5 MB');
- return;
- }
- $linkContentType = $headResponse->getHeader('Content-Type');
- $expectedContentType = 'text/html';
- $suffixedExpectedContentType = $expectedContentType . ';';
- $startsWithSuffixed = substr($linkContentType, 0, strlen($suffixedExpectedContentType)) === $suffixedExpectedContentType;
- // check the header begins with the expected content type
- if ($linkContentType !== $expectedContentType && !$startsWithSuffixed) {
- $this->logger->debug('Skip resolving links pointing to content type that is not "text/html"');
- return;
- }
- try {
- $response = $client->get($reference->getId(), [ 'timeout' => 10 ]);
- } catch (\Exception $e) {
- $this->logger->debug('Failed to fetch link for obtaining open graph data', ['exception' => $e]);
- return;
- }
-
- $responseBody = (string)$response->getBody();
-
- // OpenGraph handling
- $consumer = new Consumer();
- $consumer->useFallbackMode = true;
- $object = $consumer->loadHtml($responseBody);
-
- $reference->setUrl($reference->getId());
-
- if ($object->title) {
- $reference->setTitle($object->title);
- }
-
- if ($object->description) {
- $reference->setDescription($object->description);
- }
-
- if ($object->images) {
- try {
- $host = parse_url($object->images[0]->url, PHP_URL_HOST);
- if ($host === false || $host === null) {
- $this->logger->warning('Could not detect host of open graph image URI for ' . $reference->getId());
- } else {
- $appData = $this->appDataFactory->get('core');
- try {
- $folder = $appData->getFolder('opengraph');
- } catch (NotFoundException $e) {
- $folder = $appData->newFolder('opengraph');
- }
- $response = $client->get($object->images[0]->url, ['timeout' => 10]);
- $contentType = $response->getHeader('Content-Type');
- $contentLength = $response->getHeader('Content-Length');
-
- if (in_array($contentType, self::ALLOWED_CONTENT_TYPES, true) && $contentLength < self::MAX_PREVIEW_SIZE) {
- $stream = Utils::streamFor($response->getBody());
- $bodyStream = new LimitStream($stream, self::MAX_PREVIEW_SIZE, 0);
- $reference->setImageContentType($contentType);
- $folder->newFile(md5($reference->getId()), $bodyStream->getContents());
- $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Reference.preview', ['referenceId' => md5($reference->getId())]));
- }
- }
- } catch (GuzzleException $e) {
- $this->logger->info('Failed to fetch and store the open graph image for ' . $reference->getId(), ['exception' => $e]);
- } catch (\Throwable $e) {
- $this->logger->error('Failed to fetch and store the open graph image for ' . $reference->getId(), ['exception' => $e]);
- }
- }
- }
-
- public function getCachePrefix(string $referenceId): string {
- return $referenceId;
- }
-
- public function getCacheKey(string $referenceId): ?string {
- return null;
- }
+/** @deprecated 29.0.0 Use OCP\Collaboration\Reference\LinkReferenceProvider instead */
+class LinkReferenceProvider extends OCPLinkReferenceProvider {
}
diff --git a/lib/private/Collaboration/Reference/ReferenceManager.php b/lib/private/Collaboration/Reference/ReferenceManager.php
index 2897410f5d6..208c50a074b 100644
--- a/lib/private/Collaboration/Reference/ReferenceManager.php
+++ b/lib/private/Collaboration/Reference/ReferenceManager.php
@@ -2,24 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Reference;
@@ -46,33 +30,22 @@ class ReferenceManager implements IReferenceManager {
/** @var IReferenceProvider[]|null */
private ?array $providers = null;
private ICache $cache;
- private Coordinator $coordinator;
- private ContainerInterface $container;
- private LinkReferenceProvider $linkReferenceProvider;
- private LoggerInterface $logger;
- private IConfig $config;
- private IUserSession $userSession;
-
- public function __construct(LinkReferenceProvider $linkReferenceProvider,
- ICacheFactory $cacheFactory,
- Coordinator $coordinator,
- ContainerInterface $container,
- LoggerInterface $logger,
- IConfig $config,
- IUserSession $userSession) {
- $this->linkReferenceProvider = $linkReferenceProvider;
+
+ public function __construct(
+ private LinkReferenceProvider $linkReferenceProvider,
+ ICacheFactory $cacheFactory,
+ private Coordinator $coordinator,
+ private ContainerInterface $container,
+ private LoggerInterface $logger,
+ private IConfig $config,
+ private IUserSession $userSession,
+ ) {
$this->cache = $cacheFactory->createDistributed('reference');
- $this->coordinator = $coordinator;
- $this->container = $container;
- $this->logger = $logger;
- $this->config = $config;
- $this->userSession = $userSession;
}
/**
* Extract a list of URLs from a text
*
- * @param string $text
* @return string[]
*/
public function extractReferences(string $text): array {
@@ -85,9 +58,6 @@ class ReferenceManager implements IReferenceManager {
/**
* Try to get a cached reference object from a reference string
- *
- * @param string $referenceId
- * @return IReference|null
*/
public function getReferenceFromCache(string $referenceId): ?IReference {
$matchedProvider = $this->getMatchedProvider($referenceId);
@@ -102,9 +72,6 @@ class ReferenceManager implements IReferenceManager {
/**
* Try to get a cached reference object from a full cache key
- *
- * @param string $cacheKey
- * @return IReference|null
*/
public function getReferenceByCacheKey(string $cacheKey): ?IReference {
$cached = $this->cache->get($cacheKey);
@@ -118,9 +85,6 @@ class ReferenceManager implements IReferenceManager {
/**
* Get a reference object from a reference string with a matching provider
* Use a cached reference if possible
- *
- * @param string $referenceId
- * @return IReference|null
*/
public function resolveReference(string $referenceId): ?IReference {
$matchedProvider = $this->getMatchedProvider($referenceId);
@@ -137,6 +101,11 @@ class ReferenceManager implements IReferenceManager {
$reference = $matchedProvider->resolveReference($referenceId);
if ($reference) {
+ $cachePrefix = $matchedProvider->getCachePrefix($referenceId);
+ if ($cachePrefix !== '') {
+ // If a prefix is used we set an additional key to know when we need to delete by prefix during invalidateCache()
+ $this->cache->set('hasPrefix-' . md5($cachePrefix), true, self::CACHE_TTL);
+ }
$this->cache->set($cacheKey, Reference::toCache($reference), self::CACHE_TTL);
return $reference;
}
@@ -148,7 +117,6 @@ class ReferenceManager implements IReferenceManager {
* Try to match a reference string with all the registered providers
* Fallback to the link reference provider (using OpenGraph)
*
- * @param string $referenceId
* @return IReferenceProvider|null the first matching provider
*/
private function getMatchedProvider(string $referenceId): ?IReferenceProvider {
@@ -169,10 +137,6 @@ class ReferenceManager implements IReferenceManager {
/**
* Get a hashed full cache key from a key and prefix given by a provider
- *
- * @param IReferenceProvider $provider
- * @param string $referenceId
- * @return string
*/
private function getFullCacheKey(IReferenceProvider $provider, string $referenceId): string {
$cacheKey = $provider->getCacheKey($referenceId);
@@ -183,14 +147,14 @@ class ReferenceManager implements IReferenceManager {
/**
* Remove a specific cache entry from its key+prefix
- *
- * @param string $cachePrefix
- * @param string|null $cacheKey
- * @return void
*/
public function invalidateCache(string $cachePrefix, ?string $cacheKey = null): void {
if ($cacheKey === null) {
- $this->cache->clear(md5($cachePrefix));
+ // clear might be a heavy operation, so we only do it if there have actually been keys set
+ if ($this->cache->remove('hasPrefix-' . md5($cachePrefix))) {
+ $this->cache->clear(md5($cachePrefix));
+ }
+
return;
}
diff --git a/lib/private/Collaboration/Reference/RenderReferenceEventListener.php b/lib/private/Collaboration/Reference/RenderReferenceEventListener.php
index dc2c5612666..9e6192314cb 100644
--- a/lib/private/Collaboration/Reference/RenderReferenceEventListener.php
+++ b/lib/private/Collaboration/Reference/RenderReferenceEventListener.php
@@ -2,24 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Julien Veyssier <eneiluj@posteo.net>
- *
- * @author Julien Veyssier <eneiluj@posteo.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Reference;
@@ -34,12 +18,10 @@ use OCP\IInitialStateService;
/** @template-implements IEventListener<Event|RenderReferenceEvent> */
class RenderReferenceEventListener implements IEventListener {
- private IReferenceManager $manager;
- private IInitialStateService $initialStateService;
-
- public function __construct(IReferenceManager $manager, IInitialStateService $initialStateService) {
- $this->manager = $manager;
- $this->initialStateService = $initialStateService;
+ public function __construct(
+ private IReferenceManager $manager,
+ private IInitialStateService $initialStateService,
+ ) {
}
public static function register(IEventDispatcher $eventDispatcher): void {
diff --git a/lib/private/Collaboration/Resources/Collection.php b/lib/private/Collaboration/Resources/Collection.php
index e34c38a80cd..2c5cc28ef28 100644
--- a/lib/private/Collaboration/Resources/Collection.php
+++ b/lib/private/Collaboration/Resources/Collection.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Resources;
@@ -37,46 +18,21 @@ use OCP\IDBConnection;
use OCP\IUser;
class Collection implements ICollection {
- /** @var Manager */
- protected $manager;
-
- /** @var IDBConnection */
- protected $connection;
-
- /** @var int */
- protected $id;
-
- /** @var string */
- protected $name;
-
- /** @var IUser|null */
- protected $userForAccess;
-
- /** @var bool|null */
- protected $access;
-
/** @var IResource[] */
- protected $resources;
+ protected array $resources = [];
public function __construct(
- IManager $manager,
- IDBConnection $connection,
- int $id,
- string $name,
- ?IUser $userForAccess = null,
- ?bool $access = null
+ /** @var Manager $manager */
+ protected IManager $manager,
+ protected IDBConnection $connection,
+ protected int $id,
+ protected string $name,
+ protected ?IUser $userForAccess = null,
+ protected ?bool $access = null
) {
- $this->manager = $manager;
- $this->connection = $connection;
- $this->id = $id;
- $this->name = $name;
- $this->userForAccess = $userForAccess;
- $this->access = $access;
- $this->resources = [];
}
/**
- * @return int
* @since 16.0.0
*/
public function getId(): int {
@@ -84,7 +40,6 @@ class Collection implements ICollection {
}
/**
- * @return string
* @since 16.0.0
*/
public function getName(): string {
@@ -92,7 +47,6 @@ class Collection implements ICollection {
}
/**
- * @param string $name
* @since 16.0.0
*/
public function setName(string $name): void {
@@ -120,7 +74,6 @@ class Collection implements ICollection {
/**
* Adds a resource to a collection
*
- * @param IResource $resource
* @throws ResourceException when the resource is already part of the collection
* @since 16.0.0
*/
@@ -153,7 +106,6 @@ class Collection implements ICollection {
/**
* Removes a resource from a collection
*
- * @param IResource $resource
* @since 16.0.0
*/
public function removeResource(IResource $resource): void {
@@ -178,8 +130,6 @@ class Collection implements ICollection {
/**
* Can a user/guest access the collection
*
- * @param IUser|null $user
- * @return bool
* @since 16.0.0
*/
public function canAccess(?IUser $user): bool {
diff --git a/lib/private/Collaboration/Resources/Listener.php b/lib/private/Collaboration/Resources/Listener.php
index 4330f3570bc..dfdde24d78e 100644
--- a/lib/private/Collaboration/Resources/Listener.php
+++ b/lib/private/Collaboration/Resources/Listener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Resources;
diff --git a/lib/private/Collaboration/Resources/Manager.php b/lib/private/Collaboration/Resources/Manager.php
index fc8804e69b4..6c9b77d41c5 100644
--- a/lib/private/Collaboration/Resources/Manager.php
+++ b/lib/private/Collaboration/Resources/Manager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com>
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Resources;
@@ -45,26 +26,17 @@ class Manager implements IManager {
public const TABLE_RESOURCES = 'collres_resources';
public const TABLE_ACCESS_CACHE = 'collres_accesscache';
- /** @var IDBConnection */
- protected $connection;
- /** @var IProviderManager */
- protected $providerManager;
- /** @var LoggerInterface */
- protected $logger;
-
/** @var string[] */
- protected $providers = [];
-
+ protected array $providers = [];
- public function __construct(IDBConnection $connection, IProviderManager $providerManager, LoggerInterface $logger) {
- $this->connection = $connection;
- $this->providerManager = $providerManager;
- $this->logger = $logger;
+ public function __construct(
+ protected IDBConnection $connection,
+ protected IProviderManager $providerManager,
+ protected LoggerInterface $logger,
+ ) {
}
/**
- * @param int $id
- * @return ICollection
* @throws CollectionException when the collection could not be found
* @since 16.0.0
*/
@@ -85,9 +57,6 @@ class Manager implements IManager {
}
/**
- * @param int $id
- * @param IUser|null $user
- * @return ICollection
* @throws CollectionException when the collection could not be found
* @since 16.0.0
*/
@@ -122,10 +91,6 @@ class Manager implements IManager {
}
/**
- * @param IUser $user
- * @param string $filter
- * @param int $limit
- * @param int $start
* @return ICollection[]
* @since 16.0.0
*/
@@ -173,8 +138,6 @@ class Manager implements IManager {
}
/**
- * @param string $name
- * @return ICollection
* @since 16.0.0
*/
public function newCollection(string $name): ICollection {
@@ -189,9 +152,6 @@ class Manager implements IManager {
}
/**
- * @param string $type
- * @param string $id
- * @return IResource
* @since 16.0.0
*/
public function createResource(string $type, string $id): IResource {
@@ -199,10 +159,6 @@ class Manager implements IManager {
}
/**
- * @param string $type
- * @param string $id
- * @param IUser|null $user
- * @return IResource
* @throws ResourceException
* @since 16.0.0
*/
@@ -239,8 +195,6 @@ class Manager implements IManager {
}
/**
- * @param ICollection $collection
- * @param IUser|null $user
* @return IResource[]
* @since 16.0.0
*/
@@ -274,8 +228,6 @@ class Manager implements IManager {
/**
* Get the rich object data of a resource
*
- * @param IResource $resource
- * @return array
* @since 16.0.0
*/
public function getResourceRichObject(IResource $resource): array {
@@ -294,9 +246,6 @@ class Manager implements IManager {
/**
* Can a user/guest access the collection
*
- * @param IResource $resource
- * @param IUser|null $user
- * @return bool
* @since 16.0.0
*/
public function canAccessResource(IResource $resource, ?IUser $user): bool {
@@ -325,9 +274,6 @@ class Manager implements IManager {
/**
* Can a user/guest access the collection
*
- * @param ICollection $collection
- * @param IUser|null $user
- * @return bool
* @since 16.0.0
*/
public function canAccessCollection(ICollection $collection, ?IUser $user): bool {
@@ -505,9 +451,6 @@ class Manager implements IManager {
$query->execute();
}
- /**
- * @param string $provider
- */
public function registerResourceProvider(string $provider): void {
$this->logger->debug('\OC\Collaboration\Resources\Manager::registerResourceProvider is deprecated', ['provider' => $provider]);
$this->providerManager->registerResourceProvider($provider);
@@ -516,7 +459,6 @@ class Manager implements IManager {
/**
* Get the resource type of the provider
*
- * @return string
* @since 16.0.0
*/
public function getType(): string {
diff --git a/lib/private/Collaboration/Resources/ProviderManager.php b/lib/private/Collaboration/Resources/ProviderManager.php
index 4f5ed53b162..0ce4ae7155a 100644
--- a/lib/private/Collaboration/Resources/ProviderManager.php
+++ b/lib/private/Collaboration/Resources/ProviderManager.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Resources;
@@ -34,20 +16,15 @@ use Psr\Log\LoggerInterface;
class ProviderManager implements IProviderManager {
/** @var string[] */
- protected $providers = [];
+ protected array $providers = [];
/** @var IProvider[] */
- protected $providerInstances = [];
+ protected array $providerInstances = [];
- /** @var IServerContainer */
- protected $serverContainer;
-
- /** @var LoggerInterface */
- protected $logger;
-
- public function __construct(IServerContainer $serverContainer, LoggerInterface $logger) {
- $this->serverContainer = $serverContainer;
- $this->logger = $logger;
+ public function __construct(
+ protected IServerContainer $serverContainer,
+ protected LoggerInterface $logger,
+ ) {
}
public function getResourceProviders(): array {
diff --git a/lib/private/Collaboration/Resources/Resource.php b/lib/private/Collaboration/Resources/Resource.php
index b5e0215cb39..ae011e319de 100644
--- a/lib/private/Collaboration/Resources/Resource.php
+++ b/lib/private/Collaboration/Resources/Resource.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Resources;
@@ -33,45 +15,19 @@ use OCP\IDBConnection;
use OCP\IUser;
class Resource implements IResource {
- /** @var IManager */
- protected $manager;
-
- /** @var IDBConnection */
- protected $connection;
-
- /** @var string */
- protected $type;
-
- /** @var string */
- protected $id;
-
- /** @var IUser|null */
- protected $userForAccess;
-
- /** @var bool|null */
- protected $access;
-
- /** @var array|null */
- protected $data;
+ protected ?array $data = null;
public function __construct(
- IManager $manager,
- IDBConnection $connection,
- string $type,
- string $id,
- ?IUser $userForAccess = null,
- ?bool $access = null
+ protected IManager $manager,
+ protected IDBConnection $connection,
+ protected string $type,
+ protected string $id,
+ protected ?IUser $userForAccess = null,
+ protected ?bool $access = null
) {
- $this->manager = $manager;
- $this->connection = $connection;
- $this->type = $type;
- $this->id = $id;
- $this->userForAccess = $userForAccess;
- $this->access = $access;
}
/**
- * @return string
* @since 16.0.0
*/
public function getType(): string {
@@ -79,7 +35,6 @@ class Resource implements IResource {
}
/**
- * @return string
* @since 16.0.0
*/
public function getId(): string {
@@ -87,7 +42,6 @@ class Resource implements IResource {
}
/**
- * @return array
* @since 16.0.0
*/
public function getRichObject(): array {
@@ -101,8 +55,6 @@ class Resource implements IResource {
/**
* Can a user/guest access the resource
*
- * @param IUser|null $user
- * @return bool
* @since 16.0.0
*/
public function canAccess(?IUser $user): bool {
diff --git a/lib/private/Color.php b/lib/private/Color.php
index 91b9b63c009..e96d6fd23bd 100644
--- a/lib/private/Color.php
+++ b/lib/private/Color.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/Command/AsyncBus.php b/lib/private/Command/AsyncBus.php
index ec6fbc91f68..fb7860c9dd8 100644
--- a/lib/private/Command/AsyncBus.php
+++ b/lib/private/Command/AsyncBus.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Command;
@@ -82,7 +68,7 @@ abstract class AsyncBus implements IBus {
private function canRunAsync($command) {
$traits = $this->getTraits($command);
foreach ($traits as $trait) {
- if (array_search($trait, $this->syncTraits) !== false) {
+ if (in_array($trait, $this->syncTraits)) {
return false;
}
}
diff --git a/lib/private/Command/CallableJob.php b/lib/private/Command/CallableJob.php
index 8bb3c76c9af..8744977a81e 100644
--- a/lib/private/Command/CallableJob.php
+++ b/lib/private/Command/CallableJob.php
@@ -1,27 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Command;
-use OC\BackgroundJob\QueuedJob;
+use OCP\BackgroundJob\QueuedJob;
class CallableJob extends QueuedJob {
protected function run($serializedCallable) {
diff --git a/lib/private/Command/ClosureJob.php b/lib/private/Command/ClosureJob.php
index 5639852e4db..58fe9696437 100644
--- a/lib/private/Command/ClosureJob.php
+++ b/lib/private/Command/ClosureJob.php
@@ -1,34 +1,18 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Command;
-use OC\BackgroundJob\QueuedJob;
use Laravel\SerializableClosure\SerializableClosure as LaravelClosure;
-use Opis\Closure\SerializableClosure as OpisClosure;
+use OCP\BackgroundJob\QueuedJob;
class ClosureJob extends QueuedJob {
- protected function run($serializedCallable) {
- $callable = unserialize($serializedCallable, [LaravelClosure::class, OpisClosure::class]);
+ protected function run($argument) {
+ $callable = unserialize($argument, [LaravelClosure::class]);
$callable = $callable->getClosure();
if (is_callable($callable)) {
$callable();
diff --git a/lib/private/Command/CommandJob.php b/lib/private/Command/CommandJob.php
index 5b267162c81..41ca3a9cb40 100644
--- a/lib/private/Command/CommandJob.php
+++ b/lib/private/Command/CommandJob.php
@@ -1,36 +1,21 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Command;
-use OC\BackgroundJob\QueuedJob;
+use OCP\BackgroundJob\QueuedJob;
use OCP\Command\ICommand;
/**
* Wrap a command in the background job interface
*/
class CommandJob extends QueuedJob {
- protected function run($serializedCommand) {
- $command = unserialize($serializedCommand);
+ protected function run($argument) {
+ $command = unserialize($argument);
if ($command instanceof ICommand) {
$command->handle();
} else {
diff --git a/lib/private/Command/CronBus.php b/lib/private/Command/CronBus.php
index 8749ad0bff5..1ff9bb7099a 100644
--- a/lib/private/Command/CronBus.php
+++ b/lib/private/Command/CronBus.php
@@ -1,56 +1,30 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Command;
-use OCP\Command\ICommand;
use Laravel\SerializableClosure\SerializableClosure;
+use OCP\BackgroundJob\IJob;
+use OCP\BackgroundJob\IJobList;
+use OCP\Command\ICommand;
class CronBus extends AsyncBus {
- /**
- * @var \OCP\BackgroundJob\IJobList
- */
- private $jobList;
-
-
- /**
- * @param \OCP\BackgroundJob\IJobList $jobList
- */
- public function __construct($jobList) {
- $this->jobList = $jobList;
+ public function __construct(
+ private IJobList $jobList,
+ ) {
}
- protected function queueCommand($command) {
+ protected function queueCommand($command): void {
$this->jobList->add($this->getJobClass($command), $this->serializeCommand($command));
}
/**
- * @param \OCP\Command\ICommand | callable $command
- * @return string
+ * @param ICommand|callable $command
+ * @return class-string<IJob>
*/
- private function getJobClass($command) {
+ private function getJobClass($command): string {
if ($command instanceof \Closure) {
return ClosureJob::class;
} elseif (is_callable($command)) {
@@ -63,10 +37,10 @@ class CronBus extends AsyncBus {
}
/**
- * @param \OCP\Command\ICommand | callable $command
+ * @param ICommand|callable $command
* @return string
*/
- private function serializeCommand($command) {
+ private function serializeCommand($command): string {
if ($command instanceof \Closure) {
return serialize(new SerializableClosure($command));
} elseif (is_callable($command) or $command instanceof ICommand) {
diff --git a/lib/private/Command/FileAccess.php b/lib/private/Command/FileAccess.php
index 584e61696c3..1af1591492d 100644
--- a/lib/private/Command/FileAccess.php
+++ b/lib/private/Command/FileAccess.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Command;
diff --git a/lib/private/Command/QueueBus.php b/lib/private/Command/QueueBus.php
index b2ceea744bc..ed7d43b38b6 100644
--- a/lib/private/Command/QueueBus.php
+++ b/lib/private/Command/QueueBus.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Command;
diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php
index 35e88c74438..422e29c084d 100644
--- a/lib/private/Comments/Comment.php
+++ b/lib/private/Comments/Comment.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Comments;
@@ -42,6 +24,7 @@ class Comment implements IComment {
'objectType' => '',
'objectId' => '',
'referenceId' => null,
+ 'metaData' => null,
'creationDT' => null,
'latestChildDT' => null,
'reactions' => null,
@@ -54,7 +37,7 @@ class Comment implements IComment {
* @param array $data optional, array with keys according to column names from
* the comments database scheme
*/
- public function __construct(array $data = null) {
+ public function __construct(?array $data = null) {
if (is_array($data)) {
$this->fromArray($data);
}
@@ -219,7 +202,7 @@ class Comment implements IComment {
*
*/
public function getMentions(): array {
- $ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@(\"guest\/[a-f0-9]+\"|\"group\/[a-z0-9_\-@\.\' ]+\"|\"[a-z0-9_\-@\.\' ]+\"|[a-z0-9_\-@\.\']+)/i", $this->getMessage(), $mentions);
+ $ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@(\"guest\/[a-f0-9]+\"|\"(?:federated_)?(?:group|team|user){1}\/[a-z0-9_\-@\.\' \/:]+\"|\"[a-z0-9_\-@\.\' ]+\"|[a-z0-9_\-@\.\']+)/i", $this->getMessage(), $mentions);
if (!$ok || !isset($mentions[0])) {
return [];
}
@@ -229,11 +212,21 @@ class Comment implements IComment {
});
$result = [];
foreach ($mentionIds as $mentionId) {
+ // Cut-off the @ and remove wrapping double-quotes
$cleanId = trim(substr($mentionId, 1), '"');
+
if (str_starts_with($cleanId, 'guest/')) {
$result[] = ['type' => 'guest', 'id' => $cleanId];
+ } elseif (str_starts_with($cleanId, 'federated_group/')) {
+ $result[] = ['type' => 'federated_group', 'id' => substr($cleanId, 16)];
} elseif (str_starts_with($cleanId, 'group/')) {
$result[] = ['type' => 'group', 'id' => substr($cleanId, 6)];
+ } elseif (str_starts_with($cleanId, 'federated_team/')) {
+ $result[] = ['type' => 'federated_team', 'id' => substr($cleanId, 15)];
+ } elseif (str_starts_with($cleanId, 'team/')) {
+ $result[] = ['type' => 'team', 'id' => substr($cleanId, 5)];
+ } elseif (str_starts_with($cleanId, 'federated_user/')) {
+ $result[] = ['type' => 'federated_user', 'id' => substr($cleanId, 15)];
} else {
$result[] = ['type' => 'user', 'id' => $cleanId];
}
@@ -403,6 +396,34 @@ class Comment implements IComment {
/**
* @inheritDoc
*/
+ public function getMetaData(): ?array {
+ if ($this->data['metaData'] === null) {
+ return null;
+ }
+
+ try {
+ $metaData = json_decode($this->data['metaData'], true, flags: JSON_THROW_ON_ERROR);
+ } catch (\JsonException $e) {
+ return null;
+ }
+ return is_array($metaData) ? $metaData : null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function setMetaData(?array $metaData): IComment {
+ if ($metaData === null) {
+ $this->data['metaData'] = null;
+ } else {
+ $this->data['metaData'] = json_encode($metaData, JSON_THROW_ON_ERROR);
+ }
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
+ */
public function getReactions(): array {
return $this->data['reactions'] ?? [];
}
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index af4fda277d6..e3d40f2d965 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -1,35 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Simounet <contact@simounet.net>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Comments;
use Doctrine\DBAL\Exception\DriverException;
-use Doctrine\DBAL\Exception\InvalidFieldNameException;
+use OCA\DAV\Connector\Sabre\File;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\CommentsEvent;
use OCP\Comments\IComment;
@@ -37,22 +16,19 @@ use OCP\Comments\ICommentsEventHandler;
use OCP\Comments\ICommentsManager;
use OCP\Comments\NotFoundException;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Files\FileInfo;
+use OCP\Files\Folder;
+use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IEmojiHelper;
-use OCP\IUser;
use OCP\IInitialStateService;
+use OCP\IUser;
use OCP\PreConditionNotMetException;
use OCP\Util;
use Psr\Log\LoggerInterface;
class Manager implements ICommentsManager {
- protected IDBConnection $dbConn;
- protected LoggerInterface $logger;
- protected IConfig $config;
- protected ITimeFactory $timeFactory;
- protected IEmojiHelper $emojiHelper;
- protected IInitialStateService $initialStateService;
/** @var IComment[] */
protected array $commentsCache = [];
@@ -65,18 +41,15 @@ class Manager implements ICommentsManager {
/** @var \Closure[] */
protected array $displayNameResolvers = [];
- public function __construct(IDBConnection $dbConn,
- LoggerInterface $logger,
- IConfig $config,
- ITimeFactory $timeFactory,
- IEmojiHelper $emojiHelper,
- IInitialStateService $initialStateService) {
- $this->dbConn = $dbConn;
- $this->logger = $logger;
- $this->config = $config;
- $this->timeFactory = $timeFactory;
- $this->emojiHelper = $emojiHelper;
- $this->initialStateService = $initialStateService;
+ public function __construct(
+ protected IDBConnection $dbConn,
+ protected LoggerInterface $logger,
+ protected IConfig $config,
+ protected ITimeFactory $timeFactory,
+ protected IEmojiHelper $emojiHelper,
+ protected IInitialStateService $initialStateService,
+ protected IRootFolder $rootFolder,
+ ) {
}
/**
@@ -97,7 +70,8 @@ class Manager implements ICommentsManager {
$data['expire_date'] = new \DateTime($data['expire_date']);
}
$data['children_count'] = (int)$data['children_count'];
- $data['reference_id'] = $data['reference_id'] ?? null;
+ $data['reference_id'] = $data['reference_id'];
+ $data['meta_data'] = json_decode($data['meta_data'], true);
if ($this->supportReactions()) {
if ($data['reactions'] !== null) {
$list = json_decode($data['reactions'], true);
@@ -344,7 +318,7 @@ class Manager implements ICommentsManager {
$objectId,
$limit = 0,
$offset = 0,
- \DateTime $notOlderThan = null
+ ?\DateTime $notOlderThan = null
) {
$comments = [];
@@ -501,6 +475,22 @@ class Manager implements ICommentsManager {
)
);
}
+ } elseif ($lastKnownCommentId > 0) {
+ // We didn't find the "$lastKnownComment" but we still use the ID as an offset.
+ // This is required as a fall-back for expired messages in talk and deleted comments in other apps.
+ if ($sortDirection === 'desc') {
+ if ($includeLastKnown) {
+ $query->andWhere($query->expr()->lte('id', $query->createNamedParameter($lastKnownCommentId)));
+ } else {
+ $query->andWhere($query->expr()->lt('id', $query->createNamedParameter($lastKnownCommentId)));
+ }
+ } else {
+ if ($includeLastKnown) {
+ $query->andWhere($query->expr()->gte('id', $query->createNamedParameter($lastKnownCommentId)));
+ } else {
+ $query->andWhere($query->expr()->gt('id', $query->createNamedParameter($lastKnownCommentId)));
+ }
+ }
}
$resultStatement = $query->execute();
@@ -520,8 +510,8 @@ class Manager implements ICommentsManager {
* @param int $id the comment to look for
*/
protected function getLastKnownComment(string $objectType,
- string $objectId,
- int $id): ?IComment {
+ string $objectId,
+ int $id): ?IComment {
$query = $this->dbConn->getQueryBuilder();
$query->select('*')
->from('comments')
@@ -621,7 +611,7 @@ class Manager implements ICommentsManager {
* @return Int
* @since 9.0.0
*/
- public function getNumberOfCommentsForObject($objectType, $objectId, \DateTime $notOlderThan = null, $verb = '') {
+ public function getNumberOfCommentsForObject($objectType, $objectId, ?\DateTime $notOlderThan = null, $verb = '') {
$qb = $this->dbConn->getQueryBuilder();
$query = $qb->select($qb->func()->count('id'))
->from('comments')
@@ -804,54 +794,25 @@ class Manager implements ICommentsManager {
/**
* Get the number of unread comments for all files in a folder
*
+ * This is unused since 8bd39fccf411195839f2dadee085fad18ec52c23
+ *
* @param int $folderId
* @param IUser $user
* @return array [$fileId => $unreadCount]
*/
public function getNumberOfUnreadCommentsForFolder($folderId, IUser $user) {
- $qb = $this->dbConn->getQueryBuilder();
-
- $query = $qb->select('f.fileid')
- ->addSelect($qb->func()->count('c.id', 'num_ids'))
- ->from('filecache', 'f')
- ->leftJoin('f', 'comments', 'c', $qb->expr()->andX(
- $qb->expr()->eq('f.fileid', $qb->expr()->castColumn('c.object_id', IQueryBuilder::PARAM_INT)),
- $qb->expr()->eq('c.object_type', $qb->createNamedParameter('files'))
- ))
- ->leftJoin('c', 'comments_read_markers', 'm', $qb->expr()->andX(
- $qb->expr()->eq('c.object_id', 'm.object_id'),
- $qb->expr()->eq('m.object_type', $qb->createNamedParameter('files'))
- ))
- ->where(
- $qb->expr()->andX(
- $qb->expr()->eq('f.parent', $qb->createNamedParameter($folderId)),
- $qb->expr()->orX(
- $qb->expr()->eq('c.object_type', $qb->createNamedParameter('files')),
- $qb->expr()->isNull('c.object_type')
- ),
- $qb->expr()->orX(
- $qb->expr()->eq('m.object_type', $qb->createNamedParameter('files')),
- $qb->expr()->isNull('m.object_type')
- ),
- $qb->expr()->orX(
- $qb->expr()->eq('m.user_id', $qb->createNamedParameter($user->getUID())),
- $qb->expr()->isNull('m.user_id')
- ),
- $qb->expr()->orX(
- $qb->expr()->gt('c.creation_timestamp', 'm.marker_datetime'),
- $qb->expr()->isNull('m.marker_datetime')
- )
- )
- )->groupBy('f.fileid');
-
- $resultStatement = $query->execute();
-
- $results = [];
- while ($row = $resultStatement->fetch()) {
- $results[$row['fileid']] = (int) $row['num_ids'];
+ $directory = $this->rootFolder->getFirstNodeById($folderId);
+ if (!$directory instanceof Folder) {
+ return [];
}
- $resultStatement->closeCursor();
- return $results;
+ $children = $directory->getDirectoryListing();
+ $ids = array_map(fn (FileInfo $child) => (string) $child->getId(), $children);
+
+ $ids[] = (string) $directory->getId();
+ $counts = $this->getNumberOfUnreadCommentsForObjects('files', $ids, $user);
+ return array_filter($counts, function (int $count) {
+ return $count > 0;
+ });
}
/**
@@ -1134,22 +1095,6 @@ class Manager implements ICommentsManager {
* @return bool
*/
protected function insert(IComment $comment): bool {
- try {
- $result = $this->insertQuery($comment, true);
- } catch (InvalidFieldNameException $e) {
- // The reference id field was only added in Nextcloud 19.
- // In order to not cause too long waiting times on the update,
- // it was decided to only add it lazy, as it is also not a critical
- // feature, but only helps to have a better experience while commenting.
- // So in case the reference_id field is missing,
- // we simply save the comment without that field.
- $result = $this->insertQuery($comment, false);
- }
-
- return $result;
- }
-
- protected function insertQuery(IComment $comment, bool $tryWritingReferenceId): bool {
$qb = $this->dbConn->getQueryBuilder();
$values = [
@@ -1165,12 +1110,10 @@ class Manager implements ICommentsManager {
'object_type' => $qb->createNamedParameter($comment->getObjectType()),
'object_id' => $qb->createNamedParameter($comment->getObjectId()),
'expire_date' => $qb->createNamedParameter($comment->getExpireDate(), 'datetime'),
+ 'reference_id' => $qb->createNamedParameter($comment->getReferenceId()),
+ 'meta_data' => $qb->createNamedParameter(json_encode($comment->getMetaData())),
];
- if ($tryWritingReferenceId) {
- $values['reference_id'] = $qb->createNamedParameter($comment->getReferenceId());
- }
-
$affectedRows = $qb->insert('comments')
->values($values)
->execute();
@@ -1273,12 +1216,7 @@ class Manager implements ICommentsManager {
$this->sendEvent(CommentsEvent::EVENT_PRE_UPDATE, $this->get($comment->getId()));
$this->uncache($comment->getId());
- try {
- $result = $this->updateQuery($comment, true);
- } catch (InvalidFieldNameException $e) {
- // See function insert() for explanation
- $result = $this->updateQuery($comment, false);
- }
+ $result = $this->updateQuery($comment);
if ($comment->getVerb() === 'reaction_deleted') {
$this->deleteReaction($comment);
@@ -1289,7 +1227,7 @@ class Manager implements ICommentsManager {
return $result;
}
- protected function updateQuery(IComment $comment, bool $tryWritingReferenceId): bool {
+ protected function updateQuery(IComment $comment): bool {
$qb = $this->dbConn->getQueryBuilder();
$qb
->update('comments')
@@ -1304,14 +1242,11 @@ class Manager implements ICommentsManager {
->set('latest_child_timestamp', $qb->createNamedParameter($comment->getLatestChildDateTime(), 'datetime'))
->set('object_type', $qb->createNamedParameter($comment->getObjectType()))
->set('object_id', $qb->createNamedParameter($comment->getObjectId()))
- ->set('expire_date', $qb->createNamedParameter($comment->getExpireDate(), 'datetime'));
-
- if ($tryWritingReferenceId) {
- $qb->set('reference_id', $qb->createNamedParameter($comment->getReferenceId()));
- }
-
- $affectedRows = $qb->where($qb->expr()->eq('id', $qb->createNamedParameter($comment->getId())))
- ->execute();
+ ->set('expire_date', $qb->createNamedParameter($comment->getExpireDate(), 'datetime'))
+ ->set('reference_id', $qb->createNamedParameter($comment->getReferenceId()))
+ ->set('meta_data', $qb->createNamedParameter(json_encode($comment->getMetaData())))
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($comment->getId())));
+ $affectedRows = $qb->executeStatement();
if ($affectedRows === 0) {
throw new NotFoundException('Comment to update does ceased to exist');
diff --git a/lib/private/Comments/ManagerFactory.php b/lib/private/Comments/ManagerFactory.php
index 2b59a284b61..2436ca74c66 100644
--- a/lib/private/Comments/ManagerFactory.php
+++ b/lib/private/Comments/ManagerFactory.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Comments;
diff --git a/lib/private/Config.php b/lib/private/Config.php
index 3ea822101df..ee30b8efc5e 100644
--- a/lib/private/Config.php
+++ b/lib/private/Config.php
@@ -1,40 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Adam Williamson <awilliam@redhat.com>
- * @author Aldo "xoen" Giambelluca <xoen@xoen.org>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Philipp Schaffrath <github@philipp.schaffrath.email>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -153,8 +122,6 @@ class Config {
* @throws HintException
*/
protected function set($key, $value) {
- $this->checkReadOnly();
-
if (!isset($this->cache[$key]) || $this->cache[$key] !== $value) {
// Add change
$this->cache[$key] = $value;
@@ -185,8 +152,6 @@ class Config {
* @throws HintException
*/
protected function delete($key) {
- $this->checkReadOnly();
-
if (isset($this->cache[$key])) {
// Delete key from cache
unset($this->cache[$key]);
@@ -215,13 +180,24 @@ class Config {
// Include file and merge config
foreach ($configFiles as $file) {
- $fileExistsAndIsReadable = file_exists($file) && is_readable($file);
- $filePointer = $fileExistsAndIsReadable ? fopen($file, 'r') : false;
- if ($file === $this->configFilePath &&
- $filePointer === false) {
- // Opening the main config might not be possible, e.g. if the wrong
- // permissions are set (likely on a new installation)
- continue;
+ unset($CONFIG);
+
+ // Invalidate opcache (only if the timestamp changed)
+ if (function_exists('opcache_invalidate')) {
+ opcache_invalidate($file, false);
+ }
+
+ $filePointer = @fopen($file, 'r');
+ if ($filePointer === false) {
+ // e.g. wrong permissions are set
+ if ($file === $this->configFilePath) {
+ // opening the main config file might not be possible
+ // (likely on a new installation)
+ continue;
+ }
+
+ http_response_code(500);
+ die(sprintf('FATAL: Could not open the config file %s', $file));
}
// Try to acquire a file lock
@@ -229,8 +205,14 @@ class Config {
throw new \Exception(sprintf('Could not acquire a shared lock on the config file %s', $file));
}
- unset($CONFIG);
- include $file;
+ try {
+ include $file;
+ } finally {
+ // Close the file pointer and release the lock
+ flock($filePointer, LOCK_UN);
+ fclose($filePointer);
+ }
+
if (!defined('PHPUNIT_RUN') && headers_sent()) {
// syntax issues in the config file like leading spaces causing PHP to send output
$errorMessage = sprintf('Config file has leading content, please remove everything before "<?php" in %s', basename($file));
@@ -242,10 +224,6 @@ class Config {
if (isset($CONFIG) && is_array($CONFIG)) {
$this->cache = array_merge($this->cache, $CONFIG);
}
-
- // Close the file pointer and release the lock
- flock($filePointer, LOCK_UN);
- fclose($filePointer);
}
$this->envCache = getenv();
diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php
index 113f0507ef5..14baa528940 100644
--- a/lib/private/Console/Application.php
+++ b/lib/private/Console/Application.php
@@ -1,38 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Console;
use OC\MemoryInfo;
use OC\NeedsUpdateException;
-use OC_App;
+use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\Console\ConsoleEvent;
use OCP\EventDispatcher\IEventDispatcher;
@@ -47,35 +24,21 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Application {
- /** @var IConfig */
- private $config;
private SymfonyApplication $application;
- /** @var IEventDispatcher */
- private $dispatcher;
- /** @var IRequest */
- private $request;
- /** @var LoggerInterface */
- private $logger;
- /** @var MemoryInfo */
- private $memoryInfo;
- public function __construct(IConfig $config,
- IEventDispatcher $dispatcher,
- IRequest $request,
- LoggerInterface $logger,
- MemoryInfo $memoryInfo) {
- $defaults = \OC::$server->getThemingDefaults();
- $this->config = $config;
+ public function __construct(
+ private IConfig $config,
+ private IEventDispatcher $dispatcher,
+ private IRequest $request,
+ private LoggerInterface $logger,
+ private MemoryInfo $memoryInfo,
+ private IAppManager $appManager,
+ ) {
+ $defaults = \OC::$server->get('ThemingDefaults');
$this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
- $this->dispatcher = $dispatcher;
- $this->request = $request;
- $this->logger = $logger;
- $this->memoryInfo = $memoryInfo;
}
/**
- * @param InputInterface $input
- * @param ConsoleOutputInterface $output
* @throws \Exception
*/
public function loadCommands(
@@ -118,17 +81,24 @@ class Application {
} elseif ($this->config->getSystemValueBool('maintenance')) {
$this->writeMaintenanceModeInfo($input, $output);
} else {
- OC_App::loadApps();
- $appManager = \OCP\Server::get(IAppManager::class);
- foreach ($appManager->getInstalledApps() as $app) {
- $appPath = \OC_App::getAppPath($app);
- if ($appPath === false) {
+ $this->appManager->loadApps();
+ foreach ($this->appManager->getInstalledApps() as $app) {
+ try {
+ $appPath = $this->appManager->getAppPath($app);
+ } catch (AppPathNotFoundException) {
continue;
}
// load commands using info.xml
- $info = $appManager->getAppInfo($app);
+ $info = $this->appManager->getAppInfo($app);
if (isset($info['commands'])) {
- $this->loadCommandsFromInfoXml($info['commands']);
+ try {
+ $this->loadCommandsFromInfoXml($info['commands']);
+ } catch (\Throwable $e) {
+ $output->writeln("<error>" . $e->getMessage() . "</error>");
+ $this->logger->error($e->getMessage(), [
+ 'exception' => $e,
+ ]);
+ }
}
// load from register_command.php
\OC_App::registerAutoloading($app, $appPath);
@@ -203,7 +173,7 @@ class Application {
* @return int
* @throws \Exception
*/
- public function run(InputInterface $input = null, OutputInterface $output = null) {
+ public function run(?InputInterface $input = null, ?OutputInterface $output = null) {
$event = new ConsoleEvent(
ConsoleEvent::EVENT_RUN,
$this->request->server['argv']
diff --git a/lib/private/Console/TimestampFormatter.php b/lib/private/Console/TimestampFormatter.php
index 8d74c28e94f..de0675cc5df 100644
--- a/lib/private/Console/TimestampFormatter.php
+++ b/lib/private/Console/TimestampFormatter.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Console;
@@ -27,17 +12,17 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyleInterface;
class TimestampFormatter implements OutputFormatterInterface {
- /** @var IConfig */
+ /** @var ?IConfig */
protected $config;
/** @var OutputFormatterInterface */
protected $formatter;
/**
- * @param IConfig $config
+ * @param ?IConfig $config
* @param OutputFormatterInterface $formatter
*/
- public function __construct(IConfig $config, OutputFormatterInterface $formatter) {
+ public function __construct(?IConfig $config, OutputFormatterInterface $formatter) {
$this->config = $config;
$this->formatter = $formatter;
}
@@ -104,11 +89,16 @@ class TimestampFormatter implements OutputFormatterInterface {
return $this->formatter->format($message);
}
- $timeZone = $this->config->getSystemValue('logtimezone', 'UTC');
- $timeZone = $timeZone !== null ? new \DateTimeZone($timeZone) : null;
+ if ($this->config instanceof IConfig) {
+ $timeZone = $this->config->getSystemValue('logtimezone', 'UTC');
+ $timeZone = $timeZone !== null ? new \DateTimeZone($timeZone) : null;
- $time = new \DateTime('now', $timeZone);
- $timestampInfo = $time->format($this->config->getSystemValue('logdateformat', \DateTimeInterface::ATOM));
+ $time = new \DateTime('now', $timeZone);
+ $timestampInfo = $time->format($this->config->getSystemValue('logdateformat', \DateTimeInterface::ATOM));
+ } else {
+ $time = new \DateTime('now');
+ $timestampInfo = $time->format(\DateTimeInterface::ATOM);
+ }
return $timestampInfo . ' ' . $this->formatter->format($message);
}
diff --git a/lib/private/Contacts/ContactsMenu/ActionFactory.php b/lib/private/Contacts/ContactsMenu/ActionFactory.php
index 739c43d0bce..71ebe575fdd 100644
--- a/lib/private/Contacts/ContactsMenu/ActionFactory.php
+++ b/lib/private/Contacts/ContactsMenu/ActionFactory.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu;
diff --git a/lib/private/Contacts/ContactsMenu/ActionProviderStore.php b/lib/private/Contacts/ContactsMenu/ActionProviderStore.php
index 7ba5db4bb33..b760de03a04 100644
--- a/lib/private/Contacts/ContactsMenu/ActionProviderStore.php
+++ b/lib/private/Contacts/ContactsMenu/ActionProviderStore.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu;
@@ -33,6 +15,7 @@ use OC\Contacts\ContactsMenu\Providers\EMailProvider;
use OC\Contacts\ContactsMenu\Providers\LocalTimeProvider;
use OC\Contacts\ContactsMenu\Providers\ProfileProvider;
use OCP\AppFramework\QueryException;
+use OCP\Contacts\ContactsMenu\IBulkProvider;
use OCP\Contacts\ContactsMenu\IProvider;
use OCP\IServerContainer;
use OCP\IUser;
@@ -47,18 +30,26 @@ class ActionProviderStore {
}
/**
- * @return IProvider[]
+ * @return list<IProvider|IBulkProvider>
* @throws Exception
*/
public function getProviders(IUser $user): array {
$appClasses = $this->getAppProviderClasses($user);
$providerClasses = $this->getServerProviderClasses();
$allClasses = array_merge($providerClasses, $appClasses);
+ /** @var list<IProvider|IBulkProvider> $providers */
$providers = [];
foreach ($allClasses as $class) {
try {
- $providers[] = $this->serverContainer->get($class);
+ $provider = $this->serverContainer->get($class);
+ if ($provider instanceof IProvider || $provider instanceof IBulkProvider) {
+ $providers[] = $provider;
+ } else {
+ $this->logger->warning('Ignoring invalid contacts menu provider', [
+ 'class' => $class,
+ ]);
+ }
} catch (QueryException $ex) {
$this->logger->error(
'Could not load contacts menu action provider ' . $class,
diff --git a/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php b/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php
index e0d3515f421..0d4cc9b9b01 100644
--- a/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php
+++ b/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu\Actions;
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index c692b486ae4..d7cdb5efebf 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -1,38 +1,16 @@
<?php
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- * @copyright 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tobia De Koninck <tobia@ledfan.be>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu;
use OC\KnownUser\KnownUserService;
use OC\Profile\ProfileManager;
+use OCA\UserStatus\Db\UserStatus;
+use OCA\UserStatus\Service\StatusService;
use OCP\Contacts\ContactsMenu\IContactsStore;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\IManager;
@@ -42,10 +20,17 @@ use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\L10N\IFactory as IL10NFactory;
+use function array_column;
+use function array_fill_keys;
+use function array_filter;
+use function array_key_exists;
+use function array_merge;
+use function count;
class ContactsStore implements IContactsStore {
public function __construct(
private IManager $contactsManager,
+ private ?StatusService $userStatusService,
private IConfig $config,
private ProfileManager $profileManager,
private IUserManager $userManager,
@@ -70,15 +55,75 @@ class ContactsStore implements IContactsStore {
if ($offset !== null) {
$options['offset'] = $offset;
}
+ // Status integration only works without pagination and filters
+ if ($offset === null && ($filter === null || $filter === '')) {
+ $recentStatuses = $this->userStatusService?->findAllRecentStatusChanges($limit, $offset) ?? [];
+ } else {
+ $recentStatuses = [];
+ }
- $allContacts = $this->contactsManager->search(
- $filter ?? '',
- [
- 'FN',
- 'EMAIL'
- ],
- $options
- );
+ // Search by status if there is no filter and statuses are available
+ if (!empty($recentStatuses)) {
+ $allContacts = array_filter(array_map(function (UserStatus $userStatus) use ($options) {
+ // UID is ambiguous with federation. We have to use the federated cloud ID to an exact match of
+ // A local user
+ $user = $this->userManager->get($userStatus->getUserId());
+ if ($user === null) {
+ return null;
+ }
+
+ $contact = $this->contactsManager->search(
+ $user->getCloudId(),
+ [
+ 'CLOUD',
+ ],
+ array_merge(
+ $options,
+ [
+ 'limit' => 1,
+ 'offset' => 0,
+ ],
+ ),
+ )[0] ?? null;
+ if ($contact !== null) {
+ $contact[Entry::PROPERTY_STATUS_MESSAGE_TIMESTAMP] = $userStatus->getStatusMessageTimestamp();
+ }
+ return $contact;
+ }, $recentStatuses));
+ if ($limit !== null && count($allContacts) < $limit) {
+ // More contacts were requested
+ $fromContacts = $this->contactsManager->search(
+ $filter ?? '',
+ [
+ 'FN',
+ 'EMAIL'
+ ],
+ array_merge(
+ $options,
+ [
+ 'limit' => $limit - count($allContacts),
+ ],
+ ),
+ );
+
+ // Create hash map of all status contacts
+ $existing = array_fill_keys(array_column($allContacts, 'URI'), null);
+ // Append the ones that are new
+ $allContacts = array_merge(
+ $allContacts,
+ array_filter($fromContacts, fn (array $contact): bool => !array_key_exists($contact['URI'], $existing))
+ );
+ }
+ } else {
+ $allContacts = $this->contactsManager->search(
+ $filter ?? '',
+ [
+ 'FN',
+ 'EMAIL'
+ ],
+ $options
+ );
+ }
$userId = $user->getUID();
$contacts = array_filter($allContacts, function ($contact) use ($userId) {
@@ -108,6 +153,9 @@ class ContactsStore implements IContactsStore {
* 3. if the `shareapi_only_share_with_group_members` config option is
* enabled it will filter all users which doesn't have a common group
* with the current user.
+ * If enabled, the 'shareapi_only_share_with_group_members_exclude_group_list'
+ * config option may specify some groups excluded from the principle of
+ * belonging to the same group.
*
* @param Entry[] $entries
* @return Entry[] the filtered contacts
@@ -121,7 +169,7 @@ class ContactsStore implements IContactsStore {
$restrictEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$restrictEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
$allowEnumerationFullMatch = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
- $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes';
+ $excludeGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no');
// whether to filter out local users
$skipLocal = false;
@@ -130,17 +178,32 @@ class ContactsStore implements IContactsStore {
$selfGroups = $this->groupManager->getUserGroupIds($self);
- if ($excludedGroups) {
+ if ($excludeGroups && $excludeGroups !== 'no') {
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$decodedExcludeGroups = json_decode($excludedGroups, true);
$excludeGroupsList = $decodedExcludeGroups ?? [];
- if (count(array_intersect($excludeGroupsList, $selfGroups)) !== 0) {
- // a group of the current user is excluded -> filter all local users
+ if ($excludeGroups != 'allow') {
+ if (count(array_intersect($excludeGroupsList, $selfGroups)) !== 0) {
+ // a group of the current user is excluded -> filter all local users
+ $skipLocal = true;
+ }
+ } else {
$skipLocal = true;
+ if (count(array_intersect($excludeGroupsList, $selfGroups)) !== 0) {
+ // a group of the current user is allowed -> do not filter all local users
+ $skipLocal = false;
+ }
}
}
+ // ownGroupsOnly : some groups may be excluded
+ if ($ownGroupsOnly) {
+ $excludeGroupsFromOwnGroups = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
+ $excludeGroupsFromOwnGroupsList = json_decode($excludeGroupsFromOwnGroups, true) ?? [];
+ $selfGroups = array_diff($selfGroups, $excludeGroupsFromOwnGroupsList);
+ }
+
$selfUID = $self->getUID();
return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $allowEnumerationFullMatch, $filter) {
@@ -265,36 +328,39 @@ class ContactsStore implements IContactsStore {
private function contactArrayToEntry(array $contact): Entry {
$entry = new Entry();
- if (isset($contact['UID'])) {
+ if (!empty($contact['UID'])) {
$uid = $contact['UID'];
$entry->setId($uid);
+ $entry->setProperty('isUser', false);
+ // overloaded usage so leaving as-is for now
if (isset($contact['isLocalSystemBook'])) {
$avatar = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $uid, 'size' => 64]);
- } elseif (isset($contact['FN'])) {
- $avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => $contact['FN'], 'size' => 64]);
+ $entry->setProperty('isUser', true);
+ } elseif (!empty($contact['FN'])) {
+ $avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => str_replace('/', ' ', $contact['FN']), 'size' => 64]);
} else {
- $avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => $uid, 'size' => 64]);
+ $avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => str_replace('/', ' ', $uid), 'size' => 64]);
}
$entry->setAvatar($avatar);
}
- if (isset($contact['FN'])) {
+ if (!empty($contact['FN'])) {
$entry->setFullName($contact['FN']);
}
$avatarPrefix = "VALUE=uri:";
- if (isset($contact['PHOTO']) && str_starts_with($contact['PHOTO'], $avatarPrefix)) {
+ if (!empty($contact['PHOTO']) && str_starts_with($contact['PHOTO'], $avatarPrefix)) {
$entry->setAvatar(substr($contact['PHOTO'], strlen($avatarPrefix)));
}
- if (isset($contact['EMAIL'])) {
+ if (!empty($contact['EMAIL'])) {
foreach ($contact['EMAIL'] as $email) {
$entry->addEMailAddress($email);
}
}
// Provide profile parameters for core/src/OC/contactsmenu/contact.handlebars template
- if (isset($contact['UID']) && isset($contact['FN'])) {
+ if (!empty($contact['UID']) && !empty($contact['FN'])) {
$targetUserId = $contact['UID'];
$targetUser = $this->userManager->get($targetUserId);
if (!empty($targetUser)) {
diff --git a/lib/private/Contacts/ContactsMenu/Entry.php b/lib/private/Contacts/ContactsMenu/Entry.php
index f1cb4f9c52f..d4f2dc7bf90 100644
--- a/lib/private/Contacts/ContactsMenu/Entry.php
+++ b/lib/private/Contacts/ContactsMenu/Entry.php
@@ -3,34 +3,19 @@
declare(strict_types=1);
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu;
use OCP\Contacts\ContactsMenu\IAction;
use OCP\Contacts\ContactsMenu\IEntry;
+use function array_merge;
class Entry implements IEntry {
+ public const PROPERTY_STATUS_MESSAGE_TIMESTAMP = 'statusMessageTimestamp';
+
/** @var string|int|null */
private $id = null;
@@ -50,6 +35,11 @@ class Entry implements IEntry {
private array $properties = [];
+ private ?string $status = null;
+ private ?string $statusMessage = null;
+ private ?int $statusMessageTimestamp = null;
+ private ?string $statusIcon = null;
+
public function setId(string $id): void {
$this->id = $id;
}
@@ -102,6 +92,16 @@ class Entry implements IEntry {
$this->sortActions();
}
+ public function setStatus(string $status,
+ ?string $statusMessage = null,
+ ?int $statusMessageTimestamp = null,
+ ?string $icon = null): void {
+ $this->status = $status;
+ $this->statusMessage = $statusMessage;
+ $this->statusMessageTimestamp = $statusMessageTimestamp;
+ $this->statusIcon = $icon;
+ }
+
/**
* @return IAction[]
*/
@@ -127,11 +127,15 @@ class Entry implements IEntry {
});
}
+ public function setProperty(string $propertyName, mixed $value) {
+ $this->properties[$propertyName] = $value;
+ }
+
/**
- * @param array $contact key-value array containing additional properties
+ * @param array $properties key-value array containing additional properties
*/
- public function setProperties(array $contact): void {
- $this->properties = $contact;
+ public function setProperties(array $properties): void {
+ $this->properties = array_merge($this->properties, $properties);
}
public function getProperty(string $key): mixed {
@@ -142,7 +146,7 @@ class Entry implements IEntry {
}
/**
- * @return array{id: int|string|null, fullName: string, avatar: string|null, topAction: mixed, actions: array, lastMessage: '', emailAddresses: string[], profileTitle: string|null, profileUrl: string|null}
+ * @return array{id: int|string|null, fullName: string, avatar: string|null, topAction: mixed, actions: array, lastMessage: '', emailAddresses: string[], profileTitle: string|null, profileUrl: string|null, status: string|null, statusMessage: null|string, statusMessageTimestamp: null|int, statusIcon: null|string, isUser: bool, uid: mixed}
*/
public function jsonSerialize(): array {
$topAction = !empty($this->actions) ? $this->actions[0]->jsonSerialize() : null;
@@ -160,6 +164,20 @@ class Entry implements IEntry {
'emailAddresses' => $this->getEMailAddresses(),
'profileTitle' => $this->profileTitle,
'profileUrl' => $this->profileUrl,
+ 'status' => $this->status,
+ 'statusMessage' => $this->statusMessage,
+ 'statusMessageTimestamp' => $this->statusMessageTimestamp,
+ 'statusIcon' => $this->statusIcon,
+ 'isUser' => $this->getProperty('isUser') === true,
+ 'uid' => $this->getProperty('UID'),
];
}
+
+ public function getStatusMessage(): ?string {
+ return $this->statusMessage;
+ }
+
+ public function getStatusMessageTimestamp(): ?int {
+ return $this->statusMessageTimestamp;
+ }
}
diff --git a/lib/private/Contacts/ContactsMenu/Manager.php b/lib/private/Contacts/ContactsMenu/Manager.php
index 490cf602283..65a2c4469ea 100644
--- a/lib/private/Contacts/ContactsMenu/Manager.php
+++ b/lib/private/Contacts/ContactsMenu/Manager.php
@@ -1,34 +1,16 @@
<?php
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu;
use Exception;
use OCP\App\IAppManager;
use OCP\Constants;
+use OCP\Contacts\ContactsMenu\IBulkProvider;
use OCP\Contacts\ContactsMenu\IEntry;
+use OCP\Contacts\ContactsMenu\IProvider;
use OCP\IConfig;
use OCP\IUser;
@@ -80,8 +62,19 @@ class Manager {
* @return IEntry[]
*/
private function sortEntries(array $entries): array {
- usort($entries, function (IEntry $entryA, IEntry $entryB) {
- return strcasecmp($entryA->getFullName(), $entryB->getFullName());
+ usort($entries, function (Entry $entryA, Entry $entryB) {
+ $aStatusTimestamp = $entryA->getProperty(Entry::PROPERTY_STATUS_MESSAGE_TIMESTAMP);
+ $bStatusTimestamp = $entryB->getProperty(Entry::PROPERTY_STATUS_MESSAGE_TIMESTAMP);
+ if (!$aStatusTimestamp && !$bStatusTimestamp) {
+ return strcasecmp($entryA->getFullName(), $entryB->getFullName());
+ }
+ if ($aStatusTimestamp === null) {
+ return 1;
+ }
+ if ($bStatusTimestamp === null) {
+ return -1;
+ }
+ return $bStatusTimestamp - $aStatusTimestamp;
});
return $entries;
}
@@ -92,9 +85,14 @@ class Manager {
*/
private function processEntries(array $entries, IUser $user): void {
$providers = $this->actionProviderStore->getProviders($user);
- foreach ($entries as $entry) {
- foreach ($providers as $provider) {
- $provider->process($entry);
+
+ foreach ($providers as $provider) {
+ if ($provider instanceof IBulkProvider && !($provider instanceof IProvider)) {
+ $provider->process($entries);
+ } elseif ($provider instanceof IProvider && !($provider instanceof IBulkProvider)) {
+ foreach ($entries as $entry) {
+ $provider->process($entry);
+ }
}
}
}
diff --git a/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php b/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php
index 145c30a2ce7..c852fc90b9e 100644
--- a/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php
+++ b/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu\Providers;
diff --git a/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php b/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php
index 32e1280ff0f..a5d911a03b1 100644
--- a/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php
+++ b/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023, Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu\Providers;
diff --git a/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php b/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
index 6b36b9fff0e..d099e2c620d 100644
--- a/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
+++ b/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
@@ -1,25 +1,8 @@
<?php
/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Contacts\ContactsMenu\Providers;
diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php
index c39f7c715cc..f67cb196eef 100644
--- a/lib/private/ContactsManager.php
+++ b/lib/private/ContactsManager.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tobia De Koninck <tobia@ledfan.be>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -91,20 +71,20 @@ class ContactsManager implements IManager {
* This function can be used to delete the contact identified by the given id
*
* @param int $id the unique identifier to a contact
- * @param string $address_book_key identifier of the address book in which the contact shall be deleted
+ * @param string $addressBookKey identifier of the address book in which the contact shall be deleted
* @return bool successful or not
*/
- public function delete($id, $address_book_key) {
- $addressBook = $this->getAddressBook($address_book_key);
+ public function delete($id, $addressBookKey) {
+ $addressBook = $this->getAddressBook($addressBookKey);
if (!$addressBook) {
- return null;
+ return false;
}
if ($addressBook->getPermissions() & Constants::PERMISSION_DELETE) {
return $addressBook->delete($id);
}
- return null;
+ return false;
}
/**
@@ -112,11 +92,11 @@ class ContactsManager implements IManager {
* Otherwise the contact will be updated by replacing the entire data set.
*
* @param array $properties this array if key-value-pairs defines a contact
- * @param string $address_book_key identifier of the address book in which the contact shall be created or updated
- * @return array representing the contact just created or updated
+ * @param string $addressBookKey identifier of the address book in which the contact shall be created or updated
+ * @return ?array representing the contact just created or updated
*/
- public function createOrUpdate($properties, $address_book_key) {
- $addressBook = $this->getAddressBook($address_book_key);
+ public function createOrUpdate($properties, $addressBookKey) {
+ $addressBook = $this->getAddressBook($addressBookKey);
if (!$addressBook) {
return null;
}
@@ -133,7 +113,7 @@ class ContactsManager implements IManager {
*
* @return bool true if enabled, false if not
*/
- public function isEnabled() {
+ public function isEnabled(): bool {
return !empty($this->addressBooks) || !empty($this->addressBookLoaders);
}
@@ -192,11 +172,8 @@ class ContactsManager implements IManager {
/**
* Get (and load when needed) the address book for $key
- *
- * @param string $addressBookKey
- * @return IAddressBook
*/
- protected function getAddressBook($addressBookKey) {
+ protected function getAddressBook(string $addressBookKey): ?IAddressBook {
$this->loadAddressBooks();
if (!array_key_exists($addressBookKey, $this->addressBooks)) {
return null;
diff --git a/lib/private/DB/Adapter.php b/lib/private/DB/Adapter.php
index acaa529c0e2..b5be14e5dc6 100644
--- a/lib/private/DB/Adapter.php
+++ b/lib/private/DB/Adapter.php
@@ -1,35 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jonny007-MKD <1-23-4-5@web.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Ole Ostergaard <ole.c.ostergaard@gmail.com>
- * @author Ole Ostergaard <ole.ostergaard@knime.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
+use OC\DB\Exceptions\DbalException;
/**
* This handles the way we use to write queries, into something that can be
@@ -99,7 +79,7 @@ class Adapter {
* @throws Exception
* @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
*/
- public function insertIfNotExist($table, $input, array $compare = null) {
+ public function insertIfNotExist($table, $input, ?array $compare = null) {
if (empty($compare)) {
$compare = array_keys($input);
}
@@ -142,9 +122,12 @@ class Adapter {
foreach ($values as $key => $value) {
$builder->setValue($key, $builder->createNamedParameter($value));
}
- return $builder->execute();
- } catch (UniqueConstraintViolationException $e) {
- return 0;
+ return $builder->executeStatement();
+ } catch (DbalException $e) {
+ if ($e->getReason() === \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
+ return 0;
+ }
+ throw $e;
}
}
}
diff --git a/lib/private/DB/AdapterMySQL.php b/lib/private/DB/AdapterMySQL.php
index 295783616b6..8e854769e1f 100644
--- a/lib/private/DB/AdapterMySQL.php
+++ b/lib/private/DB/AdapterMySQL.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/AdapterOCI8.php b/lib/private/DB/AdapterOCI8.php
index d8e6fabe745..0a509090bca 100644
--- a/lib/private/DB/AdapterOCI8.php
+++ b/lib/private/DB/AdapterOCI8.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/AdapterPgSql.php b/lib/private/DB/AdapterPgSql.php
index 9045aa7f879..847ea3052b7 100644
--- a/lib/private/DB/AdapterPgSql.php
+++ b/lib/private/DB/AdapterPgSql.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Ole Ostergaard <ole.c.ostergaard@gmail.com>
- * @author Ole Ostergaard <ole.ostergaard@knime.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/AdapterSqlite.php b/lib/private/DB/AdapterSqlite.php
index 27c700bce7f..e84f62e8d80 100644
--- a/lib/private/DB/AdapterSqlite.php
+++ b/lib/private/DB/AdapterSqlite.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
@@ -63,7 +44,7 @@ class AdapterSqlite extends Adapter {
* @throws \Doctrine\DBAL\Exception
* @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
*/
- public function insertIfNotExist($table, $input, array $compare = null) {
+ public function insertIfNotExist($table, $input, ?array $compare = null) {
if (empty($compare)) {
$compare = array_keys($input);
}
diff --git a/lib/private/DB/BacktraceDebugStack.php b/lib/private/DB/BacktraceDebugStack.php
index 6a19be89225..4afd3ce6a13 100644
--- a/lib/private/DB/BacktraceDebugStack.php
+++ b/lib/private/DB/BacktraceDebugStack.php
@@ -2,23 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index 85c6a72dfdb..8d300123a40 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -1,62 +1,40 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Ole Ostergaard <ole.c.ostergaard@gmail.com>
- * @author Ole Ostergaard <ole.ostergaard@knime.com>
- * @author Philipp Schaffrath <github@philipp.schaffrath.email>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Configuration;
+use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception;
+use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
-use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Result;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Statement;
+use OC\DB\QueryBuilder\QueryBuilder;
+use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Diagnostics\IEventLogger;
use OCP\IRequestId;
use OCP\PreConditionNotMetException;
use OCP\Profiler\IProfiler;
-use OC\DB\QueryBuilder\QueryBuilder;
-use OC\SystemConfig;
+use OCP\Server;
+use Psr\Clock\ClockInterface;
use Psr\Log\LoggerInterface;
+use function count;
+use function in_array;
-class Connection extends \Doctrine\DBAL\Connection {
+class Connection extends PrimaryReadReplicaConnection {
/** @var string */
protected $tablePrefix;
@@ -66,6 +44,8 @@ class Connection extends \Doctrine\DBAL\Connection {
/** @var SystemConfig */
private $systemConfig;
+ private ClockInterface $clock;
+
private LoggerInterface $logger;
protected $lockedTable = null;
@@ -78,6 +58,15 @@ class Connection extends \Doctrine\DBAL\Connection {
/** @var DbDataCollector|null */
protected $dbDataCollector = null;
+ private array $lastConnectionCheck = [];
+
+ protected ?float $transactionActiveSince = null;
+
+ /** @var array<string, int> */
+ protected $tableDirtyWrites = [];
+
+ protected bool $logRequestId;
+ protected string $requestId;
/**
* Initializes a new instance of the Connection class.
@@ -85,7 +74,7 @@ class Connection extends \Doctrine\DBAL\Connection {
* @throws \Exception
*/
public function __construct(
- array $params,
+ private array $params,
Driver $driver,
?Configuration $config = null,
?EventManager $eventManager = null
@@ -104,10 +93,14 @@ class Connection extends \Doctrine\DBAL\Connection {
$this->tablePrefix = $params['tablePrefix'];
$this->systemConfig = \OC::$server->getSystemConfig();
- $this->logger = \OC::$server->get(LoggerInterface::class);
+ $this->clock = Server::get(ClockInterface::class);
+ $this->logger = Server::get(LoggerInterface::class);
+
+ $this->logRequestId = $this->systemConfig->getValue('db.log_request_id', false);
+ $this->requestId = Server::get(IRequestId::class)->getId();
/** @var \OCP\Profiler\IProfiler */
- $profiler = \OC::$server->get(IProfiler::class);
+ $profiler = Server::get(IProfiler::class);
if ($profiler->isEnabled()) {
$this->dbDataCollector = new DbDataCollector($this);
$profiler->add($this->dbDataCollector);
@@ -115,20 +108,25 @@ class Connection extends \Doctrine\DBAL\Connection {
$this->dbDataCollector->setDebugStack($debugStack);
$this->_config->setSQLLogger($debugStack);
}
+
+ $this->setNestTransactionsWithSavepoints(true);
}
/**
* @throws Exception
*/
- public function connect() {
+ public function connect($connectionName = null) {
try {
if ($this->_conn) {
+ $this->reconnectIfNeeded();
/** @psalm-suppress InternalMethod */
return parent::connect();
}
+ $this->lastConnectionCheck[$this->getConnectionName()] = time();
+
// Only trigger the event logger for the initial connect call
- $eventLogger = \OC::$server->get(IEventLogger::class);
+ $eventLogger = Server::get(IEventLogger::class);
$eventLogger->start('connect:db', 'db connection opened');
/** @psalm-suppress InternalMethod */
$status = parent::connect();
@@ -141,6 +139,15 @@ class Connection extends \Doctrine\DBAL\Connection {
}
}
+ protected function performConnect(?string $connectionName = null): bool {
+ if (($connectionName ?? 'replica') === 'replica'
+ && count($this->params['replica']) === 1
+ && $this->params['primary'] === $this->params['replica'][0]) {
+ return parent::performConnect('primary');
+ }
+ return parent::performConnect($connectionName);
+ }
+
public function getStats(): array {
return [
'built' => $this->queriesBuilt,
@@ -220,7 +227,7 @@ class Connection extends \Doctrine\DBAL\Connection {
* @return Statement The prepared statement.
* @throws Exception
*/
- public function prepare($statement, $limit = null, $offset = null): Statement {
+ public function prepare($sql, $limit = null, $offset = null): Statement {
if ($limit === -1 || $limit === null) {
$limit = null;
} else {
@@ -231,10 +238,9 @@ class Connection extends \Doctrine\DBAL\Connection {
}
if (!is_null($limit)) {
$platform = $this->getDatabasePlatform();
- $statement = $platform->modifyLimitQuery($statement, $limit, $offset);
+ $sql = $platform->modifyLimitQuery($sql, $limit, $offset);
}
- $statement = $this->replaceTablePrefix($statement);
- $statement = $this->adapter->fixupStatement($statement);
+ $statement = $this->finishQuery($sql);
return parent::prepare($statement);
}
@@ -254,20 +260,64 @@ class Connection extends \Doctrine\DBAL\Connection {
*
* @throws \Doctrine\DBAL\Exception
*/
- public function executeQuery(string $sql, array $params = [], $types = [], QueryCacheProfile $qcp = null): Result {
- $sql = $this->replaceTablePrefix($sql);
- $sql = $this->adapter->fixupStatement($sql);
+ public function executeQuery(string $sql, array $params = [], $types = [], ?QueryCacheProfile $qcp = null): Result {
+ $tables = $this->getQueriedTables($sql);
+ $now = $this->clock->now()->getTimestamp();
+ $dirtyTableWrites = [];
+ foreach ($tables as $table) {
+ $lastAccess = $this->tableDirtyWrites[$table] ?? 0;
+ // Only very recent writes are considered dirty
+ if ($lastAccess >= ($now - 3)) {
+ $dirtyTableWrites[] = $table;
+ }
+ }
+ if ($this->isTransactionActive()) {
+ // Transacted queries go to the primary. The consistency of the primary guarantees that we can not run
+ // into a dirty read.
+ } elseif (count($dirtyTableWrites) === 0) {
+ // No tables read that could have been written already in the same request and no transaction active
+ // so we can switch back to the replica for reading as long as no writes happen that switch back to the primary
+ // We cannot log here as this would log too early in the server boot process
+ $this->ensureConnectedToReplica();
+ } else {
+ // Read to a table that has been written to previously
+ // While this might not necessarily mean that we did a read after write it is an indication for a code path to check
+ $this->logger->log(
+ (int) ($this->systemConfig->getValue('loglevel_dirty_database_queries', null) ?? 0),
+ 'dirty table reads: ' . $sql,
+ [
+ 'tables' => array_keys($this->tableDirtyWrites),
+ 'reads' => $tables,
+ 'exception' => new \Exception('dirty table reads: ' . $sql),
+ ],
+ );
+ // To prevent a dirty read on a replica that is slightly out of sync, we
+ // switch back to the primary. This is detrimental for performance but
+ // safer for consistency.
+ $this->ensureConnectedToPrimary();
+ }
+
+ $sql = $this->finishQuery($sql);
$this->queriesExecuted++;
$this->logQueryToFile($sql);
return parent::executeQuery($sql, $params, $types, $qcp);
}
/**
+ * Helper function to get the list of tables affected by a given query
+ * used to track dirty tables that received a write with the current request
+ */
+ private function getQueriedTables(string $sql): array {
+ $re = '/(\*PREFIX\*\w+)/mi';
+ preg_match_all($re, $sql, $matches);
+ return array_map([$this, 'replaceTablePrefix'], $matches[0] ?? []);
+ }
+
+ /**
* @throws Exception
*/
public function executeUpdate(string $sql, array $params = [], array $types = []): int {
- $sql = $this->replaceTablePrefix($sql);
- $sql = $this->adapter->fixupStatement($sql);
+ $sql = $this->finishQuery($sql);
$this->queriesExecuted++;
$this->logQueryToFile($sql);
return parent::executeUpdate($sql, $params, $types);
@@ -288,8 +338,11 @@ class Connection extends \Doctrine\DBAL\Connection {
* @throws \Doctrine\DBAL\Exception
*/
public function executeStatement($sql, array $params = [], array $types = []): int {
- $sql = $this->replaceTablePrefix($sql);
- $sql = $this->adapter->fixupStatement($sql);
+ $tables = $this->getQueriedTables($sql);
+ foreach ($tables as $table) {
+ $this->tableDirtyWrites[$table] = $this->clock->now()->getTimestamp();
+ }
+ $sql = $this->finishQuery($sql);
$this->queriesExecuted++;
$this->logQueryToFile($sql);
return (int)parent::executeStatement($sql, $params, $types);
@@ -300,12 +353,23 @@ class Connection extends \Doctrine\DBAL\Connection {
if ($logFile !== '' && is_writable(dirname($logFile)) && (!file_exists($logFile) || is_writable($logFile))) {
$prefix = '';
if ($this->systemConfig->getValue('query_log_file_requestid') === 'yes') {
- $prefix .= \OC::$server->get(IRequestId::class)->getId() . "\t";
+ $prefix .= Server::get(IRequestId::class)->getId() . "\t";
}
+ $postfix = '';
+ if ($this->systemConfig->getValue('query_log_file_backtrace') === 'yes') {
+ $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+ array_pop($trace);
+ $postfix .= '; ' . json_encode($trace);
+ }
+
+ // FIXME: Improve to log the actual target db host
+ $isPrimary = $this->connections['primary'] === $this->_conn;
+ $prefix .= ' ' . ($isPrimary === true ? 'primary' : 'replica') . ' ';
+ $prefix .= ' ' . $this->getTransactionNestingLevel() . ' ';
file_put_contents(
$this->systemConfig->getValue('query_log_file', ''),
- $prefix . $sql . "\n",
+ $prefix . $sql . $postfix . "\n",
FILE_APPEND
);
}
@@ -321,14 +385,14 @@ class Connection extends \Doctrine\DBAL\Connection {
*
* @param string $seqName Name of the sequence object from which the ID should be returned.
*
- * @return string the last inserted ID.
+ * @return int the last inserted ID.
* @throws Exception
*/
- public function lastInsertId($seqName = null) {
- if ($seqName) {
- $seqName = $this->replaceTablePrefix($seqName);
+ public function lastInsertId($name = null): int {
+ if ($name) {
+ $name = $this->replaceTablePrefix($name);
}
- return $this->adapter->lastInsertId($seqName);
+ return $this->adapter->lastInsertId($name);
}
/**
@@ -353,7 +417,7 @@ class Connection extends \Doctrine\DBAL\Connection {
* @throws \Doctrine\DBAL\Exception
* @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
*/
- public function insertIfNotExist($table, $input, array $compare = null) {
+ public function insertIfNotExist($table, $input, ?array $compare = null) {
return $this->adapter->insertIfNotExist($table, $input, $compare);
}
@@ -516,6 +580,16 @@ class Connection extends \Doctrine\DBAL\Connection {
return $schema->tablesExist([$table]);
}
+ protected function finishQuery(string $statement): string {
+ $statement = $this->replaceTablePrefix($statement);
+ $statement = $this->adapter->fixupStatement($statement);
+ if ($this->logRequestId) {
+ return $statement . " /* reqid: " . $this->requestId . " */";
+ } else {
+ return $statement;
+ }
+ }
+
// internal use
/**
* @param string $statement
@@ -595,17 +669,66 @@ class Connection extends \Doctrine\DBAL\Connection {
$random = \OC::$server->getSecureRandom();
$platform = $this->getDatabasePlatform();
$config = \OC::$server->getConfig();
- $dispatcher = \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class);
+ $dispatcher = Server::get(\OCP\EventDispatcher\IEventDispatcher::class);
if ($platform instanceof SqlitePlatform) {
return new SQLiteMigrator($this, $config, $dispatcher);
} elseif ($platform instanceof OraclePlatform) {
return new OracleMigrator($this, $config, $dispatcher);
- } elseif ($platform instanceof MySQLPlatform) {
- return new MySQLMigrator($this, $config, $dispatcher);
- } elseif ($platform instanceof PostgreSQL94Platform) {
- return new PostgreSqlMigrator($this, $config, $dispatcher);
} else {
return new Migrator($this, $config, $dispatcher);
}
}
+
+ public function beginTransaction() {
+ if (!$this->inTransaction()) {
+ $this->transactionActiveSince = microtime(true);
+ }
+ return parent::beginTransaction();
+ }
+
+ public function commit() {
+ $result = parent::commit();
+ if ($this->getTransactionNestingLevel() === 0) {
+ $timeTook = microtime(true) - $this->transactionActiveSince;
+ $this->transactionActiveSince = null;
+ if ($timeTook > 1) {
+ $this->logger->debug('Transaction took ' . $timeTook . 's', ['exception' => new \Exception('Transaction took ' . $timeTook . 's')]);
+ }
+ }
+ return $result;
+ }
+
+ public function rollBack() {
+ $result = parent::rollBack();
+ if ($this->getTransactionNestingLevel() === 0) {
+ $timeTook = microtime(true) - $this->transactionActiveSince;
+ $this->transactionActiveSince = null;
+ if ($timeTook > 1) {
+ $this->logger->debug('Transaction rollback took longer than 1s: ' . $timeTook, ['exception' => new \Exception('Long running transaction rollback')]);
+ }
+ }
+ return $result;
+ }
+
+ private function reconnectIfNeeded(): void {
+ if (
+ !isset($this->lastConnectionCheck[$this->getConnectionName()]) ||
+ time() <= $this->lastConnectionCheck[$this->getConnectionName()] + 30 ||
+ $this->isTransactionActive()
+ ) {
+ return;
+ }
+
+ try {
+ $this->_conn->query($this->getDriver()->getDatabasePlatform()->getDummySelectSQL());
+ $this->lastConnectionCheck[$this->getConnectionName()] = time();
+ } catch (ConnectionLost|\Exception $e) {
+ $this->logger->warning('Exception during connectivity check, closing and reconnecting', ['exception' => $e]);
+ $this->close();
+ }
+ }
+
+ private function getConnectionName(): string {
+ return $this->isConnectedToPrimary() ? 'primary' : 'replica';
+ }
}
diff --git a/lib/private/DB/ConnectionAdapter.php b/lib/private/DB/ConnectionAdapter.php
index a53c7ecd994..86a901a7de3 100644
--- a/lib/private/DB/ConnectionAdapter.php
+++ b/lib/private/DB/ConnectionAdapter.php
@@ -3,30 +3,17 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\AbstractPlatform;
+use Doctrine\DBAL\Platforms\MySQLPlatform;
+use Doctrine\DBAL\Platforms\OraclePlatform;
+use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
+use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use OC\DB\Exceptions\DbalException;
use OCP\DB\IPreparedStatement;
@@ -87,13 +74,13 @@ class ConnectionAdapter implements IDBConnection {
public function lastInsertId(string $table): int {
try {
- return (int)$this->inner->lastInsertId($table);
+ return $this->inner->lastInsertId($table);
} catch (Exception $e) {
throw DbalException::wrap($e);
}
}
- public function insertIfNotExist(string $table, array $input, array $compare = null) {
+ public function insertIfNotExist(string $table, array $input, ?array $compare = null) {
try {
return $this->inner->insertIfNotExist($table, $input, $compare);
} catch (Exception $e) {
@@ -242,4 +229,19 @@ class ConnectionAdapter implements IDBConnection {
public function getInner(): Connection {
return $this->inner;
}
+
+ public function getDatabaseProvider(): string {
+ $platform = $this->inner->getDatabasePlatform();
+ if ($platform instanceof MySQLPlatform) {
+ return IDBConnection::PLATFORM_MYSQL;
+ } elseif ($platform instanceof OraclePlatform) {
+ return IDBConnection::PLATFORM_ORACLE;
+ } elseif ($platform instanceof PostgreSQLPlatform) {
+ return IDBConnection::PLATFORM_POSTGRES;
+ } elseif ($platform instanceof SqlitePlatform) {
+ return IDBConnection::PLATFORM_SQLITE;
+ } else {
+ throw new \Exception('Database ' . $platform::class . ' not supported');
+ }
+ }
}
diff --git a/lib/private/DB/ConnectionFactory.php b/lib/private/DB/ConnectionFactory.php
index 1b0ac436364..5e50d01538a 100644
--- a/lib/private/DB/ConnectionFactory.php
+++ b/lib/private/DB/ConnectionFactory.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
@@ -32,7 +11,6 @@ use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
-use Doctrine\DBAL\Event\Listeners\SQLSessionInit;
use OC\SystemConfig;
/**
@@ -127,11 +105,17 @@ class ConnectionFactory {
$normalizedType = $this->normalizeType($type);
$eventManager = new EventManager();
$eventManager->addEventSubscriber(new SetTransactionIsolationLevel());
+ $additionalConnectionParams = array_merge($this->createConnectionParams(), $additionalConnectionParams);
switch ($normalizedType) {
- case 'mysql':
- $eventManager->addEventSubscriber(
- new SQLSessionInit("SET SESSION AUTOCOMMIT=1"));
+ case 'pgsql':
+ // pg_connect used by Doctrine DBAL does not support URI notation (enclosed in brackets)
+ $matches = [];
+ if (preg_match('/^\[([^\]]+)\]$/', $additionalConnectionParams['host'], $matches)) {
+ // Host variable carries a port or socket.
+ $additionalConnectionParams['host'] = $matches[1];
+ }
break;
+
case 'oci':
$eventManager->addEventSubscriber(new OracleSessionInit);
// the driverOptions are unused in dbal and need to be mapped to the parameters
@@ -139,7 +123,7 @@ class ConnectionFactory {
$additionalConnectionParams = array_merge($additionalConnectionParams, $additionalConnectionParams['driverOptions']);
}
$host = $additionalConnectionParams['host'];
- $port = isset($additionalConnectionParams['port']) ? $additionalConnectionParams['port'] : null;
+ $port = $additionalConnectionParams['port'] ?? null;
$dbName = $additionalConnectionParams['dbname'];
// we set the connect string as dbname and unset the host to coerce doctrine into using it as connect string
@@ -159,7 +143,7 @@ class ConnectionFactory {
}
/** @var Connection $connection */
$connection = DriverManager::getConnection(
- array_merge($this->getDefaultConnectionParams($type), $additionalConnectionParams),
+ $additionalConnectionParams,
new Configuration(),
$eventManager
);
@@ -195,10 +179,10 @@ class ConnectionFactory {
public function createConnectionParams(string $configPrefix = '') {
$type = $this->config->getValue('dbtype', 'sqlite');
- $connectionParams = [
+ $connectionParams = array_merge($this->getDefaultConnectionParams($type), [
'user' => $this->config->getValue($configPrefix . 'dbuser', $this->config->getValue('dbuser', '')),
'password' => $this->config->getValue($configPrefix . 'dbpassword', $this->config->getValue('dbpassword', '')),
- ];
+ ]);
$name = $this->config->getValue($configPrefix . 'dbname', $this->config->getValue('dbname', self::DEFAULT_DBNAME));
if ($this->normalizeType($type) === 'sqlite3') {
@@ -237,7 +221,11 @@ class ConnectionFactory {
$connectionParams['persistent'] = true;
}
- return $connectionParams;
+ $replica = $this->config->getValue($configPrefix . 'dbreplica', $this->config->getValue('dbreplica', [])) ?: [$connectionParams];
+ return array_merge($connectionParams, [
+ 'primary' => $connectionParams,
+ 'replica' => $replica,
+ ]);
}
/**
diff --git a/lib/private/DB/DbDataCollector.php b/lib/private/DB/DbDataCollector.php
index 60e3dbe797d..fcaa74daeab 100644
--- a/lib/private/DB/DbDataCollector.php
+++ b/lib/private/DB/DbDataCollector.php
@@ -2,25 +2,8 @@
declare(strict_types = 1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
@@ -48,7 +31,7 @@ class DbDataCollector extends \OCP\DataCollector\AbstractDataCollector {
/**
* @inheritDoc
*/
- public function collect(Request $request, Response $response, \Throwable $exception = null): void {
+ public function collect(Request $request, Response $response, ?\Throwable $exception = null): void {
$queries = $this->sanitizeQueries($this->debugStack->queries);
$this->data = [
@@ -75,7 +58,7 @@ class DbDataCollector extends \OCP\DataCollector\AbstractDataCollector {
private function sanitizeQuery(array $query): array {
$query['explainable'] = true;
$query['runnable'] = true;
- if (null === $query['params']) {
+ if ($query['params'] === null) {
$query['params'] = [];
}
if (!\is_array($query['params'])) {
diff --git a/lib/private/DB/Exceptions/DbalException.php b/lib/private/DB/Exceptions/DbalException.php
index 2b860a50ff3..05ea9e22a5d 100644
--- a/lib/private/DB/Exceptions/DbalException.php
+++ b/lib/private/DB/Exceptions/DbalException.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\Exceptions;
@@ -35,6 +17,7 @@ use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
+use Doctrine\DBAL\Exception\LockWaitTimeoutException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\RetryableException;
@@ -100,6 +83,9 @@ class DbalException extends Exception {
/**
* Other server errors
*/
+ if ($this->original instanceof LockWaitTimeoutException) {
+ return parent::REASON_LOCK_WAIT_TIMEOUT;
+ }
if ($this->original instanceof DatabaseObjectExistsException) {
return parent::REASON_DATABASE_OBJECT_EXISTS;
}
diff --git a/lib/private/DB/MigrationException.php b/lib/private/DB/MigrationException.php
index 5b08ab9cac2..5b50f8ed3a4 100644
--- a/lib/private/DB/MigrationException.php
+++ b/lib/private/DB/MigrationException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php
index 71d7b51d149..4b91b6f0996 100644
--- a/lib/private/DB/MigrationService.php
+++ b/lib/private/DB/MigrationService.php
@@ -1,29 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2017 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
@@ -43,6 +22,7 @@ use OCP\AppFramework\QueryException;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IMigrationStep;
use OCP\Migration\IOutput;
+use OCP\Server;
use Psr\Log\LoggerInterface;
class MigrationService {
@@ -51,6 +31,7 @@ class MigrationService {
private string $migrationsPath;
private string $migrationsNamespace;
private IOutput $output;
+ private LoggerInterface $logger;
private Connection $connection;
private string $appName;
private bool $checkOracle;
@@ -58,11 +39,16 @@ class MigrationService {
/**
* @throws \Exception
*/
- public function __construct($appName, Connection $connection, ?IOutput $output = null, ?AppLocator $appLocator = null) {
+ public function __construct(string $appName, Connection $connection, ?IOutput $output = null, ?AppLocator $appLocator = null, ?LoggerInterface $logger = null) {
$this->appName = $appName;
$this->connection = $connection;
+ if ($logger === null) {
+ $this->logger = Server::get(LoggerInterface::class);
+ } else {
+ $this->logger = $logger;
+ }
if ($output === null) {
- $this->output = new SimpleOutput(\OC::$server->get(LoggerInterface::class), $appName);
+ $this->output = new SimpleOutput($this->logger, $appName);
} else {
$this->output = $output;
}
@@ -72,7 +58,7 @@ class MigrationService {
$this->migrationsNamespace = 'OC\\Core\\Migrations';
$this->checkOracle = true;
} else {
- if (null === $appLocator) {
+ if ($appLocator === null) {
$appLocator = new AppLocator();
}
$appPath = $appLocator->getAppPath($appName);
@@ -100,18 +86,15 @@ class MigrationService {
/**
* Returns the name of the app for which this migration is executed
- *
- * @return string
*/
- public function getApp() {
+ public function getApp(): string {
return $this->appName;
}
/**
- * @return bool
* @codeCoverageIgnore - this will implicitly tested on installation
*/
- private function createMigrationTable() {
+ private function createMigrationTable(): bool {
if ($this->migrationTableCreated) {
return false;
}
@@ -188,7 +171,7 @@ class MigrationService {
->where($qb->expr()->eq('app', $qb->createNamedParameter($this->getApp())))
->orderBy('version');
- $result = $qb->execute();
+ $result = $qb->executeQuery();
$rows = $result->fetchAll(\PDO::FETCH_COLUMN);
$result->closeCursor();
@@ -197,15 +180,17 @@ class MigrationService {
/**
* Returns all versions which are available in the migration folder
- *
- * @return array
+ * @return list<string>
*/
- public function getAvailableVersions() {
+ public function getAvailableVersions(): array {
$this->ensureMigrationsAreLoaded();
return array_map('strval', array_keys($this->migrations));
}
- protected function findMigrations() {
+ /**
+ * @return array<string, string>
+ */
+ protected function findMigrations(): array {
$directory = realpath($this->migrationsPath);
if ($directory === false || !file_exists($directory) || !is_dir($directory)) {
return [];
@@ -322,10 +307,9 @@ class MigrationService {
/**
* Return the explicit version for the aliases; current, next, prev, latest
*
- * @param string $alias
* @return mixed|null|string
*/
- public function getMigration($alias) {
+ public function getMigration(string $alias) {
switch ($alias) {
case 'current':
return $this->getCurrentVersion();
@@ -342,29 +326,22 @@ class MigrationService {
return '0';
}
- /**
- * @param string $version
- * @param int $delta
- * @return null|string
- */
- private function getRelativeVersion($version, $delta) {
+ private function getRelativeVersion(string $version, int $delta): ?string {
$this->ensureMigrationsAreLoaded();
$versions = $this->getAvailableVersions();
- array_unshift($versions, 0);
+ array_unshift($versions, '0');
+ /** @var int $offset */
$offset = array_search($version, $versions, true);
if ($offset === false || !isset($versions[$offset + $delta])) {
// Unknown version or delta out of bounds.
return null;
}
- return (string) $versions[$offset + $delta];
+ return (string)$versions[$offset + $delta];
}
- /**
- * @return string
- */
- private function getCurrentVersion() {
+ private function getCurrentVersion(): string {
$m = $this->getMigratedVersions();
if (count($m) === 0) {
return '0';
@@ -374,11 +351,9 @@ class MigrationService {
}
/**
- * @param string $version
- * @return string
* @throws \InvalidArgumentException
*/
- private function getClass($version) {
+ private function getClass(string $version): string {
$this->ensureMigrationsAreLoaded();
if (isset($this->migrations[$version])) {
@@ -390,22 +365,18 @@ class MigrationService {
/**
* Allows to set an IOutput implementation which is used for logging progress and messages
- *
- * @param IOutput $output
*/
- public function setOutput(IOutput $output) {
+ public function setOutput(IOutput $output): void {
$this->output = $output;
}
/**
* Applies all not yet applied versions up to $to
- *
- * @param string $to
- * @param bool $schemaOnly
* @throws \InvalidArgumentException
*/
- public function migrate($to = 'latest', $schemaOnly = false) {
+ public function migrate(string $to = 'latest', bool $schemaOnly = false): void {
if ($schemaOnly) {
+ $this->output->debug('Migrating schema only');
$this->migrateSchemaOnly($to);
return;
}
@@ -425,11 +396,9 @@ class MigrationService {
/**
* Applies all not yet applied versions up to $to
- *
- * @param string $to
* @throws \InvalidArgumentException
*/
- public function migrateSchemaOnly($to = 'latest') {
+ public function migrateSchemaOnly(string $to = 'latest'): void {
// read known migrations
$toBeExecuted = $this->getMigrationsToExecute($to);
@@ -439,6 +408,7 @@ class MigrationService {
$toSchema = null;
foreach ($toBeExecuted as $version) {
+ $this->output->debug('- Reading ' . $version);
$instance = $this->createInstance($version);
$toSchema = $instance->changeSchema($this->output, function () use ($toSchema): ISchemaWrapper {
@@ -447,16 +417,20 @@ class MigrationService {
}
if ($toSchema instanceof SchemaWrapper) {
+ $this->output->debug('- Checking target database schema');
$targetSchema = $toSchema->getWrappedSchema();
- $this->ensureUniqueNamesConstraints($targetSchema);
+ $this->ensureUniqueNamesConstraints($targetSchema, true);
if ($this->checkOracle) {
$beforeSchema = $this->connection->createSchema();
$this->ensureOracleConstraints($beforeSchema, $targetSchema, strlen($this->connection->getPrefix()));
}
+
+ $this->output->debug('- Migrate database schema');
$this->connection->migrateToSchema($targetSchema);
$toSchema->performDropTableCalls();
}
+ $this->output->debug('- Mark migrations as executed');
foreach ($toBeExecuted as $version) {
$this->markAsExecuted($version);
}
@@ -526,7 +500,7 @@ class MigrationService {
if ($toSchema instanceof SchemaWrapper) {
$targetSchema = $toSchema->getWrappedSchema();
- $this->ensureUniqueNamesConstraints($targetSchema);
+ $this->ensureUniqueNamesConstraints($targetSchema, $schemaOnly);
if ($this->checkOracle) {
$sourceSchema = $this->connection->createSchema();
$this->ensureOracleConstraints($sourceSchema, $targetSchema, strlen($this->connection->getPrefix()));
@@ -662,14 +636,26 @@ class MigrationService {
}
/**
+ * Ensure naming constraints
+ *
* Naming constraints:
* - Index, sequence and primary key names must be unique within a Postgres Schema
*
+ * Only on installation we want to break hard, so that all developers notice
+ * the bugs when installing the app on any database or CI, and can work on
+ * fixing their migrations before releasing a version incompatible with Postgres.
+ *
+ * In case of updates we might be running on production instances and the
+ * administrators being faced with the error would not know how to resolve it
+ * anyway. This can also happen with instances, that had the issue before the
+ * current update, so we don't want to make their life more complicated
+ * than needed.
+ *
* @param Schema $targetSchema
+ * @param bool $isInstalling
*/
- public function ensureUniqueNamesConstraints(Schema $targetSchema): void {
+ public function ensureUniqueNamesConstraints(Schema $targetSchema, bool $isInstalling): void {
$constraintNames = [];
-
$sequences = $targetSchema->getSequences();
foreach ($targetSchema->getTables() as $table) {
@@ -680,14 +666,20 @@ class MigrationService {
}
if (isset($constraintNames[$thing->getName()])) {
- throw new \InvalidArgumentException('Index name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ if ($isInstalling) {
+ throw new \InvalidArgumentException('Index name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ }
+ $this->logErrorOrWarning('Index name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
}
$constraintNames[$thing->getName()] = $table->getName();
}
foreach ($table->getForeignKeys() as $thing) {
if (isset($constraintNames[$thing->getName()])) {
- throw new \InvalidArgumentException('Foreign key name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ if ($isInstalling) {
+ throw new \InvalidArgumentException('Foreign key name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ }
+ $this->logErrorOrWarning('Foreign key name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
}
$constraintNames[$thing->getName()] = $table->getName();
}
@@ -700,7 +692,10 @@ class MigrationService {
}
if (isset($constraintNames[$indexName])) {
- throw new \InvalidArgumentException('Primary index name "' . $indexName . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ if ($isInstalling) {
+ throw new \InvalidArgumentException('Primary index name "' . $indexName . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ }
+ $this->logErrorOrWarning('Primary index name "' . $indexName . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
}
$constraintNames[$indexName] = $table->getName();
}
@@ -708,12 +703,23 @@ class MigrationService {
foreach ($sequences as $sequence) {
if (isset($constraintNames[$sequence->getName()])) {
- throw new \InvalidArgumentException('Sequence name "' . $sequence->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ if ($isInstalling) {
+ throw new \InvalidArgumentException('Sequence name "' . $sequence->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
+ }
+ $this->logErrorOrWarning('Sequence name "' . $sequence->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".');
}
$constraintNames[$sequence->getName()] = 'sequence';
}
}
+ protected function logErrorOrWarning(string $log): void {
+ if ($this->output instanceof SimpleOutput) {
+ $this->output->warning($log);
+ } else {
+ $this->logger->error($log);
+ }
+ }
+
private function ensureMigrationsAreLoaded() {
if (empty($this->migrations)) {
$this->migrations = $this->findMigrations();
diff --git a/lib/private/DB/Migrator.php b/lib/private/DB/Migrator.php
index 74e5a285351..4fd457b4bc6 100644
--- a/lib/private/DB/Migrator.php
+++ b/lib/private/DB/Migrator.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
@@ -31,14 +11,13 @@ use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\AbstractAsset;
-use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaDiff;
use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\Type;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use function preg_match;
-use OCP\EventDispatcher\IEventDispatcher;
class Migrator {
/** @var Connection */
@@ -53,8 +32,8 @@ class Migrator {
private $noEmit = false;
public function __construct(Connection $connection,
- IConfig $config,
- ?IEventDispatcher $dispatcher = null) {
+ IConfig $config,
+ ?IEventDispatcher $dispatcher = null) {
$this->connection = $connection;
$this->config = $config;
$this->dispatcher = $dispatcher;
@@ -75,7 +54,7 @@ class Migrator {
$schemaDiff = $this->getDiff($targetSchema, $this->connection);
$script = '';
- $sqls = $schemaDiff->toSql($this->connection->getDatabasePlatform());
+ $sqls = $this->connection->getDatabasePlatform()->getAlterSchemaSQL($schemaDiff);
foreach ($sqls as $sql) {
$script .= $this->convertStatementToScript($sql);
}
@@ -95,18 +74,20 @@ class Migrator {
}
return preg_match($filterExpression, $asset) === 1;
});
- return $this->connection->getSchemaManager()->createSchema();
+ return $this->connection->createSchemaManager()->introspectSchema();
}
/**
* @return SchemaDiff
*/
protected function getDiff(Schema $targetSchema, Connection $connection) {
- // adjust varchar columns with a length higher then getVarcharMaxLength to clob
+ // Adjust STRING columns with a length higher than 4000 to TEXT (clob)
+ // for consistency between the supported databases and
+ // old vs. new installations.
foreach ($targetSchema->getTables() as $table) {
foreach ($table->getColumns() as $column) {
if ($column->getType() instanceof StringType) {
- if ($column->getLength() > $connection->getDatabasePlatform()->getVarcharMaxLength()) {
+ if ($column->getLength() > 4000) {
$column->setType(Type::getType('text'));
$column->setLength(null);
}
@@ -122,7 +103,7 @@ class Migrator {
}
return preg_match($filterExpression, $asset) === 1;
});
- $sourceSchema = $connection->getSchemaManager()->createSchema();
+ $sourceSchema = $connection->createSchemaManager()->introspectSchema();
// remove tables we don't know about
foreach ($sourceSchema->getTables() as $table) {
@@ -137,15 +118,14 @@ class Migrator {
}
}
- /** @psalm-suppress InternalMethod */
- $comparator = new Comparator();
- return $comparator->compare($sourceSchema, $targetSchema);
+ $comparator = $connection->createSchemaManager()->createComparator();
+ return $comparator->compareSchemas($sourceSchema, $targetSchema);
}
/**
* @throws Exception
*/
- protected function applySchema(Schema $targetSchema, Connection $connection = null) {
+ protected function applySchema(Schema $targetSchema, ?Connection $connection = null) {
if (is_null($connection)) {
$connection = $this->connection;
}
@@ -155,11 +135,11 @@ class Migrator {
if (!$connection->getDatabasePlatform() instanceof MySQLPlatform) {
$connection->beginTransaction();
}
- $sqls = $schemaDiff->toSql($connection->getDatabasePlatform());
+ $sqls = $connection->getDatabasePlatform()->getAlterSchemaSQL($schemaDiff);
$step = 0;
foreach ($sqls as $sql) {
$this->emit($sql, $step++, count($sqls));
- $connection->query($sql);
+ $connection->executeQuery($sql);
}
if (!$connection->getDatabasePlatform() instanceof MySQLPlatform) {
$connection->commit();
@@ -178,7 +158,7 @@ class Migrator {
}
protected function getFilterExpression() {
- return '/^' . preg_quote($this->config->getSystemValueString('dbtableprefix', 'oc_')) . '/';
+ return '/^' . preg_quote($this->config->getSystemValueString('dbtableprefix', 'oc_'), '/') . '/';
}
protected function emit(string $sql, int $step, int $max): void {
diff --git a/lib/private/DB/MigratorExecuteSqlEvent.php b/lib/private/DB/MigratorExecuteSqlEvent.php
index 997a4eee53a..cfcfe7fa512 100644
--- a/lib/private/DB/MigratorExecuteSqlEvent.php
+++ b/lib/private/DB/MigratorExecuteSqlEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/MissingColumnInformation.php b/lib/private/DB/MissingColumnInformation.php
index f651546b4b3..5e8402d394e 100644
--- a/lib/private/DB/MissingColumnInformation.php
+++ b/lib/private/DB/MissingColumnInformation.php
@@ -3,30 +3,13 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
class MissingColumnInformation {
- private $listOfMissingColumns = [];
+ private array $listOfMissingColumns = [];
public function addHintForMissingColumn(string $tableName, string $columnName): void {
$this->listOfMissingColumns[] = [
diff --git a/lib/private/DB/MissingIndexInformation.php b/lib/private/DB/MissingIndexInformation.php
index 74498668349..99a81782858 100644
--- a/lib/private/DB/MissingIndexInformation.php
+++ b/lib/private/DB/MissingIndexInformation.php
@@ -3,40 +3,22 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
class MissingIndexInformation {
- private $listOfMissingIndexes = [];
+ private array $listOfMissingIndices = [];
- public function addHintForMissingSubject(string $tableName, string $indexName) {
- $this->listOfMissingIndexes[] = [
+ public function addHintForMissingIndex(string $tableName, string $indexName): void {
+ $this->listOfMissingIndices[] = [
'tableName' => $tableName,
'indexName' => $indexName
];
}
- public function getListOfMissingIndexes(): array {
- return $this->listOfMissingIndexes;
+ public function getListOfMissingIndices(): array {
+ return $this->listOfMissingIndices;
}
}
diff --git a/lib/private/DB/MissingPrimaryKeyInformation.php b/lib/private/DB/MissingPrimaryKeyInformation.php
index f28c8cfb352..355ce86423a 100644
--- a/lib/private/DB/MissingPrimaryKeyInformation.php
+++ b/lib/private/DB/MissingPrimaryKeyInformation.php
@@ -3,32 +3,15 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
class MissingPrimaryKeyInformation {
- private $listOfMissingPrimaryKeys = [];
+ private array $listOfMissingPrimaryKeys = [];
- public function addHintForMissingSubject(string $tableName) {
+ public function addHintForMissingPrimaryKey(string $tableName): void {
$this->listOfMissingPrimaryKeys[] = [
'tableName' => $tableName,
];
diff --git a/lib/private/DB/MySQLMigrator.php b/lib/private/DB/MySQLMigrator.php
deleted file mode 100644
index 0f8cbb309f3..00000000000
--- a/lib/private/DB/MySQLMigrator.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\DB;
-
-use Doctrine\DBAL\Schema\Schema;
-
-class MySQLMigrator extends Migrator {
- /**
- * @param Schema $targetSchema
- * @param \Doctrine\DBAL\Connection $connection
- * @return \Doctrine\DBAL\Schema\SchemaDiff
- */
- protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
- $platform = $connection->getDatabasePlatform();
- $platform->registerDoctrineTypeMapping('enum', 'string');
- $platform->registerDoctrineTypeMapping('bit', 'string');
-
- $schemaDiff = parent::getDiff($targetSchema, $connection);
-
- // identifiers need to be quoted for mysql
- foreach ($schemaDiff->changedTables as $tableDiff) {
- $tableDiff->name = $this->connection->quoteIdentifier($tableDiff->name);
- foreach ($tableDiff->changedColumns as $column) {
- $column->oldColumnName = $this->connection->quoteIdentifier($column->oldColumnName);
- }
- }
-
- return $schemaDiff;
- }
-}
diff --git a/lib/private/DB/MySqlTools.php b/lib/private/DB/MySqlTools.php
index b129aefec08..cd6b812be61 100644
--- a/lib/private/DB/MySqlTools.php
+++ b/lib/private/DB/MySqlTools.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/OCSqlitePlatform.php b/lib/private/DB/OCSqlitePlatform.php
index 059cb21fdaf..3e2b10e6e40 100644
--- a/lib/private/DB/OCSqlitePlatform.php
+++ b/lib/private/DB/OCSqlitePlatform.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/ObjectParameter.php b/lib/private/DB/ObjectParameter.php
index 61ac16018d8..1b013734c95 100644
--- a/lib/private/DB/ObjectParameter.php
+++ b/lib/private/DB/ObjectParameter.php
@@ -1,37 +1,13 @@
<?php
declare(strict_types = 1);
-
-/*
- * This file is part of the Symfony package.
- *
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @license AGPL-3.0-or-later AND MIT
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * This file is part of the Symfony package.
*
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2022 Fabien Potencier <fabien@symfony.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later AND MIT
*/
-
namespace OC\DB;
final class ObjectParameter {
diff --git a/lib/private/DB/OracleConnection.php b/lib/private/DB/OracleConnection.php
index b7e040965ee..abfb69f129b 100644
--- a/lib/private/DB/OracleConnection.php
+++ b/lib/private/DB/OracleConnection.php
@@ -1,34 +1,17 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
class OracleConnection extends Connection {
/**
* Quote the keys of the array
+ * @param array<string, string> $data
+ * @return array<string, string>
*/
private function quoteKeys(array $data) {
$return = [];
diff --git a/lib/private/DB/OracleMigrator.php b/lib/private/DB/OracleMigrator.php
index 18deb97ec26..c5a7646dbb2 100644
--- a/lib/private/DB/OracleMigrator.php
+++ b/lib/private/DB/OracleMigrator.php
@@ -1,204 +1,122 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Piotr Mrowczynski <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
use Doctrine\DBAL\Exception;
-use Doctrine\DBAL\Schema\Column;
-use Doctrine\DBAL\Schema\ColumnDiff;
-use Doctrine\DBAL\Schema\ForeignKeyConstraint;
-use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
-use Doctrine\DBAL\Schema\Table;
class OracleMigrator extends Migrator {
/**
- * Quote a column's name but changing the name requires recreating
- * the column instance and copying over all properties.
- *
- * @param Column $column old column
- * @return Column new column instance with new name
- */
- protected function quoteColumn(Column $column) {
- $newColumn = new Column(
- $this->connection->quoteIdentifier($column->getName()),
- $column->getType()
- );
- $newColumn->setAutoincrement($column->getAutoincrement());
- $newColumn->setColumnDefinition($column->getColumnDefinition());
- $newColumn->setComment($column->getComment());
- $newColumn->setDefault($column->getDefault());
- $newColumn->setFixed($column->getFixed());
- $newColumn->setLength($column->getLength());
- $newColumn->setNotnull($column->getNotnull());
- $newColumn->setPrecision($column->getPrecision());
- $newColumn->setScale($column->getScale());
- $newColumn->setUnsigned($column->getUnsigned());
- $newColumn->setPlatformOptions($column->getPlatformOptions());
- $newColumn->setCustomSchemaOptions($column->getPlatformOptions());
- return $newColumn;
- }
-
- /**
- * Quote an index's name but changing the name requires recreating
- * the index instance and copying over all properties.
- *
- * @param Index $index old index
- * @return Index new index instance with new name
- */
- protected function quoteIndex($index) {
- return new Index(
- //TODO migrate existing uppercase indexes, then $this->connection->quoteIdentifier($index->getName()),
- $index->getName(),
- array_map(function ($columnName) {
- return $this->connection->quoteIdentifier($columnName);
- }, $index->getColumns()),
- $index->isUnique(),
- $index->isPrimary(),
- $index->getFlags(),
- $index->getOptions()
- );
- }
-
- /**
- * Quote an ForeignKeyConstraint's name but changing the name requires recreating
- * the ForeignKeyConstraint instance and copying over all properties.
- *
- * @param ForeignKeyConstraint $fkc old fkc
- * @return ForeignKeyConstraint new fkc instance with new name
- */
- protected function quoteForeignKeyConstraint($fkc) {
- return new ForeignKeyConstraint(
- array_map(function ($columnName) {
- return $this->connection->quoteIdentifier($columnName);
- }, $fkc->getLocalColumns()),
- $this->connection->quoteIdentifier($fkc->getForeignTableName()),
- array_map(function ($columnName) {
- return $this->connection->quoteIdentifier($columnName);
- }, $fkc->getForeignColumns()),
- $fkc->getName(),
- $fkc->getOptions()
- );
- }
-
- /**
* @param Schema $targetSchema
* @param \Doctrine\DBAL\Connection $connection
* @return \Doctrine\DBAL\Schema\SchemaDiff
* @throws Exception
*/
- protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
- $schemaDiff = parent::getDiff($targetSchema, $connection);
-
+ protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection): \Doctrine\DBAL\Schema\SchemaDiff {
// oracle forces us to quote the identifiers
- $schemaDiff->newTables = array_map(function (Table $table) {
- return new Table(
+ $quotedSchema = new Schema();
+ foreach ($targetSchema->getTables() as $table) {
+ $quotedTable = $quotedSchema->createTable(
$this->connection->quoteIdentifier($table->getName()),
- array_map(function (Column $column) {
- return $this->quoteColumn($column);
- }, $table->getColumns()),
- array_map(function (Index $index) {
- return $this->quoteIndex($index);
- }, $table->getIndexes()),
- [],
- array_map(function (ForeignKeyConstraint $fck) {
- return $this->quoteForeignKeyConstraint($fck);
- }, $table->getForeignKeys()),
- $table->getOptions()
);
- }, $schemaDiff->newTables);
- $schemaDiff->removedTables = array_map(function (Table $table) {
- return new Table(
- $this->connection->quoteIdentifier($table->getName()),
- $table->getColumns(),
- $table->getIndexes(),
- [],
- $table->getForeignKeys(),
- $table->getOptions()
- );
- }, $schemaDiff->removedTables);
-
- foreach ($schemaDiff->changedTables as $tableDiff) {
- $tableDiff->name = $this->connection->quoteIdentifier($tableDiff->name);
-
- $tableDiff->addedColumns = array_map(function (Column $column) {
- return $this->quoteColumn($column);
- }, $tableDiff->addedColumns);
-
- foreach ($tableDiff->changedColumns as $column) {
- $column->oldColumnName = $this->connection->quoteIdentifier($column->oldColumnName);
- // auto increment is not relevant for oracle and can anyhow not be applied on change
- $column->changedProperties = array_diff($column->changedProperties, ['autoincrement', 'unsigned']);
+ foreach ($table->getColumns() as $column) {
+ $newColumn = $quotedTable->addColumn(
+ $this->connection->quoteIdentifier($column->getName()),
+ $column->getType()->getTypeRegistry()->lookupName($column->getType()),
+ );
+ $newColumn->setAutoincrement($column->getAutoincrement());
+ $newColumn->setColumnDefinition($column->getColumnDefinition());
+ $newColumn->setComment($column->getComment());
+ $newColumn->setDefault($column->getDefault());
+ $newColumn->setFixed($column->getFixed());
+ $newColumn->setLength($column->getLength());
+ $newColumn->setNotnull($column->getNotnull());
+ $newColumn->setPrecision($column->getPrecision());
+ $newColumn->setScale($column->getScale());
+ $newColumn->setUnsigned($column->getUnsigned());
+ $newColumn->setPlatformOptions($column->getPlatformOptions());
}
- // remove columns that no longer have changed (because autoincrement and unsigned are not supported)
- $tableDiff->changedColumns = array_filter($tableDiff->changedColumns, function (ColumnDiff $column) {
- return count($column->changedProperties) > 0;
- });
-
- $tableDiff->removedColumns = array_map(function (Column $column) {
- return $this->quoteColumn($column);
- }, $tableDiff->removedColumns);
-
- $tableDiff->renamedColumns = array_map(function (Column $column) {
- return $this->quoteColumn($column);
- }, $tableDiff->renamedColumns);
-
- $tableDiff->addedIndexes = array_map(function (Index $index) {
- return $this->quoteIndex($index);
- }, $tableDiff->addedIndexes);
- $tableDiff->changedIndexes = array_map(function (Index $index) {
- return $this->quoteIndex($index);
- }, $tableDiff->changedIndexes);
-
- $tableDiff->removedIndexes = array_map(function (Index $index) {
- return $this->quoteIndex($index);
- }, $tableDiff->removedIndexes);
+ foreach ($table->getIndexes() as $index) {
+ if ($index->isPrimary()) {
+ $quotedTable->setPrimaryKey(
+ array_map(function ($columnName) {
+ return $this->connection->quoteIdentifier($columnName);
+ }, $index->getColumns()),
+ //TODO migrate existing uppercase indexes, then $this->connection->quoteIdentifier($index->getName()),
+ $index->getName(),
+ );
+ } elseif ($index->isUnique()) {
+ $quotedTable->addUniqueIndex(
+ array_map(function ($columnName) {
+ return $this->connection->quoteIdentifier($columnName);
+ }, $index->getColumns()),
+ //TODO migrate existing uppercase indexes, then $this->connection->quoteIdentifier($index->getName()),
+ $index->getName(),
+ $index->getOptions(),
+ );
+ } else {
+ $quotedTable->addIndex(
+ array_map(function ($columnName) {
+ return $this->connection->quoteIdentifier($columnName);
+ }, $index->getColumns()),
+ //TODO migrate existing uppercase indexes, then $this->connection->quoteIdentifier($index->getName()),
+ $index->getName(),
+ $index->getFlags(),
+ $index->getOptions(),
+ );
+ }
+ }
- $tableDiff->renamedIndexes = array_map(function (Index $index) {
- return $this->quoteIndex($index);
- }, $tableDiff->renamedIndexes);
+ foreach ($table->getUniqueConstraints() as $constraint) {
+ $quotedTable->addUniqueConstraint(
+ array_map(function ($columnName) {
+ return $this->connection->quoteIdentifier($columnName);
+ }, $constraint->getColumns()),
+ $this->connection->quoteIdentifier($constraint->getName()),
+ $constraint->getFlags(),
+ $constraint->getOptions(),
+ );
+ }
- $tableDiff->addedForeignKeys = array_map(function (ForeignKeyConstraint $fkc) {
- return $this->quoteForeignKeyConstraint($fkc);
- }, $tableDiff->addedForeignKeys);
+ foreach ($table->getForeignKeys() as $foreignKey) {
+ $quotedTable->addForeignKeyConstraint(
+ $this->connection->quoteIdentifier($foreignKey->getForeignTableName()),
+ array_map(function ($columnName) {
+ return $this->connection->quoteIdentifier($columnName);
+ }, $foreignKey->getLocalColumns()),
+ array_map(function ($columnName) {
+ return $this->connection->quoteIdentifier($columnName);
+ }, $foreignKey->getForeignColumns()),
+ $foreignKey->getOptions(),
+ $this->connection->quoteIdentifier($foreignKey->getName()),
+ );
+ }
- $tableDiff->changedForeignKeys = array_map(function (ForeignKeyConstraint $fkc) {
- return $this->quoteForeignKeyConstraint($fkc);
- }, $tableDiff->changedForeignKeys);
+ foreach ($table->getOptions() as $option => $value) {
+ $quotedTable->addOption(
+ $option,
+ $value,
+ );
+ }
+ }
- $tableDiff->removedForeignKeys = array_map(function (ForeignKeyConstraint $fkc) {
- return $this->quoteForeignKeyConstraint($fkc);
- }, $tableDiff->removedForeignKeys);
+ foreach ($targetSchema->getSequences() as $sequence) {
+ $quotedSchema->createSequence(
+ $sequence->getName(),
+ $sequence->getAllocationSize(),
+ $sequence->getInitialValue(),
+ );
}
- return $schemaDiff;
+ return parent::getDiff($quotedSchema, $connection);
}
/**
@@ -206,7 +124,7 @@ class OracleMigrator extends Migrator {
* @return string
*/
protected function convertStatementToScript($statement) {
- if (substr($statement, -1) === ';') {
+ if (str_ends_with($statement, ';')) {
return $statement . PHP_EOL . '/' . PHP_EOL;
}
$script = $statement . ';';
diff --git a/lib/private/DB/PgSqlTools.php b/lib/private/DB/PgSqlTools.php
index af385eb5136..35e8016191c 100644
--- a/lib/private/DB/PgSqlTools.php
+++ b/lib/private/DB/PgSqlTools.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author tbelau666 <thomas.belau@gmx.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/PostgreSqlMigrator.php b/lib/private/DB/PostgreSqlMigrator.php
deleted file mode 100644
index 92a0842e1a7..00000000000
--- a/lib/private/DB/PostgreSqlMigrator.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\DB;
-
-use Doctrine\DBAL\Schema\Schema;
-
-class PostgreSqlMigrator extends Migrator {
- /**
- * @param Schema $targetSchema
- * @param \Doctrine\DBAL\Connection $connection
- * @return \Doctrine\DBAL\Schema\SchemaDiff
- */
- protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
- $schemaDiff = parent::getDiff($targetSchema, $connection);
-
- foreach ($schemaDiff->changedTables as $tableDiff) {
- // fix default value in brackets - pg 9.4 is returning a negative default value in ()
- // see https://github.com/doctrine/dbal/issues/2427
- foreach ($tableDiff->changedColumns as $column) {
- $column->changedProperties = array_filter($column->changedProperties, function ($changedProperties) use ($column) {
- if ($changedProperties !== 'default') {
- return true;
- }
- $fromDefault = $column->fromColumn->getDefault();
- $toDefault = $column->column->getDefault();
- $fromDefault = trim((string) $fromDefault, '()');
-
- // by intention usage of !=
- return $fromDefault != $toDefault;
- });
- }
- }
-
- return $schemaDiff;
- }
-}
diff --git a/lib/private/DB/PreparedStatement.php b/lib/private/DB/PreparedStatement.php
index 849aa379832..5fdfa2b03e8 100644
--- a/lib/private/DB/PreparedStatement.php
+++ b/lib/private/DB/PreparedStatement.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
diff --git a/lib/private/DB/QueryBuilder/CompositeExpression.php b/lib/private/DB/QueryBuilder/CompositeExpression.php
index 0c958a96d68..493d804d54d 100644
--- a/lib/private/DB/QueryBuilder/CompositeExpression.php
+++ b/lib/private/DB/QueryBuilder/CompositeExpression.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder;
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
index ae4f19f5d18..a7af00b9f97 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder\ExpressionBuilder;
@@ -117,8 +98,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function comparison($x, string $operator, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->comparison($x, $operator, $y);
}
@@ -140,8 +121,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function eq($x, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->eq($x, $y);
}
@@ -162,8 +143,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function neq($x, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->neq($x, $y);
}
@@ -184,8 +165,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function lt($x, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->lt($x, $y);
}
@@ -206,8 +187,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function lte($x, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->lte($x, $y);
}
@@ -228,8 +209,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function gt($x, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->gt($x, $y);
}
@@ -250,8 +231,8 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return string
*/
public function gte($x, $y, $type = null): string {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
+ $x = $this->prepareColumn($x, $type);
+ $y = $this->prepareColumn($y, $type);
return $this->expressionBuilder->gte($x, $y);
}
@@ -435,4 +416,13 @@ class ExpressionBuilder implements IExpressionBuilder {
$this->helper->quoteColumnName($column)
);
}
+
+ /**
+ * @param mixed $column
+ * @param mixed|null $type
+ * @return array|IQueryFunction|string
+ */
+ protected function prepareColumn($column, $type) {
+ return $this->helper->quoteColumnNames($column);
+ }
}
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
index 618487e0f71..cd2fb5a5cc3 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder\ExpressionBuilder;
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php
index caeb8009885..542e8d62ede 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder\ExpressionBuilder;
@@ -39,80 +22,9 @@ class OCIExpressionBuilder extends ExpressionBuilder {
protected function prepareColumn($column, $type) {
if ($type === IQueryBuilder::PARAM_STR && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) {
$column = $this->castColumn($column, $type);
- } else {
- $column = $this->helper->quoteColumnNames($column);
}
- return $column;
- }
-
- /**
- * @inheritdoc
- */
- public function comparison($x, string $operator, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
-
- return $this->expressionBuilder->comparison($x, $operator, $y);
- }
-
- /**
- * @inheritdoc
- */
- public function eq($x, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
-
- return $this->expressionBuilder->eq($x, $y);
- }
-
- /**
- * @inheritdoc
- */
- public function neq($x, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
-
- return $this->expressionBuilder->neq($x, $y);
- }
-
- /**
- * @inheritdoc
- */
- public function lt($x, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
-
- return $this->expressionBuilder->lt($x, $y);
- }
-
- /**
- * @inheritdoc
- */
- public function lte($x, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
-
- return $this->expressionBuilder->lte($x, $y);
- }
-
- /**
- * @inheritdoc
- */
- public function gt($x, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
-
- return $this->expressionBuilder->gt($x, $y);
- }
-
- /**
- * @inheritdoc
- */
- public function gte($x, $y, $type = null): string {
- $x = $this->prepareColumn($x, $type);
- $y = $this->prepareColumn($y, $type);
- return $this->expressionBuilder->gte($x, $y);
+ return parent::prepareColumn($column, $type);
}
/**
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php
index 03b58e222f3..1a162f04a49 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder\ExpressionBuilder;
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
index 289aa09b003..ac4698cdc76 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
@@ -1,28 +1,16 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\QueryBuilder\ExpressionBuilder;
+use OC\DB\QueryBuilder\QueryFunction;
+use OCP\DB\QueryBuilder\ILiteral;
+use OCP\DB\QueryBuilder\IParameter;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\QueryBuilder\IQueryFunction;
+
class SqliteExpressionBuilder extends ExpressionBuilder {
/**
* @inheritdoc
@@ -34,4 +22,33 @@ class SqliteExpressionBuilder extends ExpressionBuilder {
public function iLike($x, $y, $type = null): string {
return $this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y), $type);
}
+
+ /**
+ * @param mixed $column
+ * @param mixed|null $type
+ * @return array|IQueryFunction|string
+ */
+ protected function prepareColumn($column, $type) {
+ if ($type === IQueryBuilder::PARAM_DATE && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) {
+ return $this->castColumn($column, $type);
+ }
+
+ return parent::prepareColumn($column, $type);
+ }
+
+ /**
+ * Returns a IQueryFunction that casts the column to the given type
+ *
+ * @param string $column
+ * @param mixed $type One of IQueryBuilder::PARAM_*
+ * @return IQueryFunction
+ */
+ public function castColumn($column, $type): IQueryFunction {
+ if ($type === IQueryBuilder::PARAM_DATE) {
+ $column = $this->helper->quoteColumnName($column);
+ return new QueryFunction('DATETIME(' . $column . ')');
+ }
+
+ return parent::castColumn($column, $type);
+ }
}
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
index e0a7549a0ad..b168d2c1a84 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\QueryBuilder\FunctionBuilder;
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php
index a9844ec3373..d0258eafea8 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\QueryBuilder\FunctionBuilder;
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php
index 444f6aa83a4..ee430a6bd71 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\QueryBuilder\FunctionBuilder;
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php
index bb97d2e29f9..956b2123f2c 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\QueryBuilder\FunctionBuilder;
diff --git a/lib/private/DB/QueryBuilder/Literal.php b/lib/private/DB/QueryBuilder/Literal.php
index b4e8a36b86f..f0accce1d93 100644
--- a/lib/private/DB/QueryBuilder/Literal.php
+++ b/lib/private/DB/QueryBuilder/Literal.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder;
@@ -32,10 +17,7 @@ class Literal implements ILiteral {
$this->literal = $literal;
}
- /**
- * @return string
- */
- public function __toString() {
+ public function __toString(): string {
return (string) $this->literal;
}
}
diff --git a/lib/private/DB/QueryBuilder/Parameter.php b/lib/private/DB/QueryBuilder/Parameter.php
index b6cfa844e01..dbd723639fc 100644
--- a/lib/private/DB/QueryBuilder/Parameter.php
+++ b/lib/private/DB/QueryBuilder/Parameter.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder;
@@ -31,10 +17,7 @@ class Parameter implements IParameter {
$this->name = $name;
}
- /**
- * @return string
- */
- public function __toString() {
+ public function __toString(): string {
return (string) $this->name;
}
}
diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php
index 2f97b4a146c..0e7d8d2ff3e 100644
--- a/lib/private/DB/QueryBuilder/QueryBuilder.php
+++ b/lib/private/DB/QueryBuilder/QueryBuilder.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder;
@@ -302,21 +279,6 @@ class QueryBuilder implements IQueryBuilder {
throw new \RuntimeException('Invalid return type for query');
}
- /**
- * Monkey-patched compatibility layer for apps that were adapted for Nextcloud 22 before
- * the first beta, where executeStatement was named executeUpdate.
- *
- * Static analysis should catch those misuses, but until then let's try to keep things
- * running.
- *
- * @internal
- * @deprecated
- * @todo drop ASAP
- */
- public function executeUpdate(): int {
- return $this->executeStatement();
- }
-
public function executeStatement(): int {
if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
throw new \RuntimeException('Invalid query type, expected INSERT, DELETE or UPDATE statement');
@@ -866,7 +828,7 @@ class QueryBuilder implements IQueryBuilder {
public function where(...$predicates) {
if ($this->getQueryPart('where') !== null && $this->systemConfig->getValue('debug', false)) {
// Only logging a warning, not throwing for now.
- $e = new QueryException('Using where() on non-empty WHERE part, please verify it is intentional to not call whereAnd() or whereOr() instead. Otherwise consider creating a new query builder object or call resetQueryPart(\'where\') first.');
+ $e = new QueryException('Using where() on non-empty WHERE part, please verify it is intentional to not call andWhere() or orWhere() instead. Otherwise consider creating a new query builder object or call resetQueryPart(\'where\') first.');
$this->logger->warning($e->getMessage(), ['exception' => $e]);
}
@@ -975,14 +937,10 @@ class QueryBuilder implements IQueryBuilder {
*
* @return $this This QueryBuilder instance.
*/
- public function addGroupBy(...$groupBys) {
- if (count($groupBys) === 1 && is_array($groupBys[0])) {
- $$groupBys = $groupBys[0];
- }
-
+ public function addGroupBy(...$groupBy) {
call_user_func_array(
[$this->queryBuilder, 'addGroupBy'],
- $this->helper->quoteColumnNames($groupBys)
+ $this->helper->quoteColumnNames($groupBy)
);
return $this;
@@ -1202,7 +1160,7 @@ class QueryBuilder implements IQueryBuilder {
* @link http://www.zetacomponents.org
*
* @param mixed $value
- * @param mixed $type
+ * @param IQueryBuilder::PARAM_* $type
* @param string $placeHolder The name to bind with. The string must start with a colon ':'.
*
* @return IParameter the placeholder name used.
@@ -1229,7 +1187,7 @@ class QueryBuilder implements IQueryBuilder {
* </code>
*
* @param mixed $value
- * @param integer $type
+ * @param IQueryBuilder::PARAM_* $type
*
* @return IParameter
*/
diff --git a/lib/private/DB/QueryBuilder/QueryFunction.php b/lib/private/DB/QueryBuilder/QueryFunction.php
index 41798f233cd..9cdd6c31c7b 100644
--- a/lib/private/DB/QueryBuilder/QueryFunction.php
+++ b/lib/private/DB/QueryBuilder/QueryFunction.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder;
@@ -31,10 +17,7 @@ class QueryFunction implements IQueryFunction {
$this->function = $function;
}
- /**
- * @return string
- */
- public function __toString() {
+ public function __toString(): string {
return (string) $this->function;
}
}
diff --git a/lib/private/DB/QueryBuilder/QuoteHelper.php b/lib/private/DB/QueryBuilder/QuoteHelper.php
index 727bb923d9c..a60a9731aa2 100644
--- a/lib/private/DB/QueryBuilder/QuoteHelper.php
+++ b/lib/private/DB/QueryBuilder/QuoteHelper.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB\QueryBuilder;
diff --git a/lib/private/DB/ResultAdapter.php b/lib/private/DB/ResultAdapter.php
index 63881b71e7d..8b004d471ec 100644
--- a/lib/private/DB/ResultAdapter.php
+++ b/lib/private/DB/ResultAdapter.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
diff --git a/lib/private/DB/SQLiteMigrator.php b/lib/private/DB/SQLiteMigrator.php
index cbb39070a48..6be17625476 100644
--- a/lib/private/DB/SQLiteMigrator.php
+++ b/lib/private/DB/SQLiteMigrator.php
@@ -1,31 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
use Doctrine\DBAL\Schema\Schema;
-use Doctrine\DBAL\Types\BigIntType;
-use Doctrine\DBAL\Types\Type;
class SQLiteMigrator extends Migrator {
/**
@@ -34,21 +16,12 @@ class SQLiteMigrator extends Migrator {
* @return \Doctrine\DBAL\Schema\SchemaDiff
*/
protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
- $platform = $connection->getDatabasePlatform();
- $platform->registerDoctrineTypeMapping('tinyint unsigned', 'integer');
- $platform->registerDoctrineTypeMapping('smallint unsigned', 'integer');
- $platform->registerDoctrineTypeMapping('varchar ', 'string');
-
foreach ($targetSchema->getTables() as $table) {
foreach ($table->getColumns() as $column) {
// column comments are not supported on SQLite
if ($column->getComment() !== null) {
$column->setComment(null);
}
- // with sqlite autoincrement columns is of type integer
- if ($column->getType() instanceof BigIntType && $column->getAutoincrement()) {
- $column->setType(Type::getType('integer'));
- }
}
}
diff --git a/lib/private/DB/SQLiteSessionInit.php b/lib/private/DB/SQLiteSessionInit.php
index 89f7e03c5f2..5fe0cb3abf6 100644
--- a/lib/private/DB/SQLiteSessionInit.php
+++ b/lib/private/DB/SQLiteSessionInit.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
diff --git a/lib/private/DB/SchemaWrapper.php b/lib/private/DB/SchemaWrapper.php
index 9dae9ab6248..8ff952b8710 100644
--- a/lib/private/DB/SchemaWrapper.php
+++ b/lib/private/DB/SchemaWrapper.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
diff --git a/lib/private/DB/SetTransactionIsolationLevel.php b/lib/private/DB/SetTransactionIsolationLevel.php
index b067edde441..cd18c4255e3 100644
--- a/lib/private/DB/SetTransactionIsolationLevel.php
+++ b/lib/private/DB/SetTransactionIsolationLevel.php
@@ -3,31 +3,16 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
use Doctrine\Common\EventSubscriber;
+use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
+use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\TransactionIsolationLevel;
class SetTransactionIsolationLevel implements EventSubscriber {
@@ -36,7 +21,13 @@ class SetTransactionIsolationLevel implements EventSubscriber {
* @return void
*/
public function postConnect(ConnectionEventArgs $args) {
- $args->getConnection()->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
+ $connection = $args->getConnection();
+ if ($connection instanceof PrimaryReadReplicaConnection && $connection->isConnectedToPrimary()) {
+ $connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
+ if ($connection->getDatabasePlatform() instanceof MySQLPlatform) {
+ $connection->executeStatement('SET SESSION AUTOCOMMIT=1');
+ }
+ }
}
public function getSubscribedEvents() {
diff --git a/lib/private/Dashboard/Manager.php b/lib/private/Dashboard/Manager.php
index 18a66499167..45038b87f90 100644
--- a/lib/private/Dashboard/Manager.php
+++ b/lib/private/Dashboard/Manager.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Dashboard;
@@ -33,15 +15,15 @@ use OCP\Dashboard\IManager;
use OCP\Dashboard\IWidget;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
-use Throwable;
use Psr\Log\LoggerInterface;
+use Throwable;
class Manager implements IManager {
/** @var array */
private $lazyWidgets = [];
- /** @var IWidget[] */
- private $widgets = [];
+ /** @var array<string, IWidget> */
+ private array $widgets = [];
private ContainerInterface $serverContainer;
private ?IAppManager $appManager = null;
@@ -115,7 +97,7 @@ class Manager implements IManager {
$endTime = microtime(true);
$duration = $endTime - $startTime;
if ($duration > 1) {
- \OC::$server->get(LoggerInterface::class)->error(
+ \OC::$server->get(LoggerInterface::class)->info(
'Dashboard widget {widget} took {duration} seconds to load.',
[
'widget' => $widget->getId(),
@@ -134,6 +116,9 @@ class Manager implements IManager {
$this->lazyWidgets = [];
}
+ /**
+ * @return array<string, IWidget>
+ */
public function getWidgets(): array {
$this->loadLazyPanels();
return $this->widgets;
diff --git a/lib/private/DatabaseException.php b/lib/private/DatabaseException.php
index 88287003af9..c0bb3eb7171 100644
--- a/lib/private/DatabaseException.php
+++ b/lib/private/DatabaseException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/DatabaseSetupException.php b/lib/private/DatabaseSetupException.php
index 44583416dbc..2e99eafa4ad 100644
--- a/lib/private/DatabaseSetupException.php
+++ b/lib/private/DatabaseSetupException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/DateTimeFormatter.php b/lib/private/DateTimeFormatter.php
index 1c8b4f6d3ab..cd765a2a14b 100644
--- a/lib/private/DateTimeFormatter.php
+++ b/lib/private/DateTimeFormatter.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author dartcafe <github@dartcafe.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -77,7 +60,7 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \DateTimeZone $timeZone The timezone to use
* @return \DateTime
*/
- protected function getDateTime($timestamp, \DateTimeZone $timeZone = null) {
+ protected function getDateTime($timestamp, ?\DateTimeZone $timeZone = null) {
if ($timestamp === null) {
return new \DateTime('now', $timeZone);
} elseif (!$timestamp instanceof \DateTime) {
@@ -105,7 +88,7 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \OCP\IL10N $l The locale to use
* @return string Formatted date string
*/
- public function formatDate($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
+ public function formatDate($timestamp, $format = 'long', ?\DateTimeZone $timeZone = null, ?\OCP\IL10N $l = null) {
return $this->format($timestamp, 'date', $format, $timeZone, $l);
}
@@ -124,8 +107,8 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \OCP\IL10N $l The locale to use
* @return string Formatted relative date string
*/
- public function formatDateRelativeDay($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
- if (substr($format, -1) !== '*' && substr($format, -1) !== '*') {
+ public function formatDateRelativeDay($timestamp, $format = 'long', ?\DateTimeZone $timeZone = null, ?\OCP\IL10N $l = null) {
+ if (!str_ends_with($format, '^') && !str_ends_with($format, '*')) {
$format .= '^';
}
@@ -136,16 +119,15 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* Gives the relative date of the timestamp
* Only works for past dates
*
- * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
+ * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
* @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time
- * @return string Dates returned are:
+ * @param \OCP\IL10N $l The locale to use
+ * @return string Formatted date span. Dates returned are:
* < 1 month => Today, Yesterday, n days ago
* < 13 month => last month, n months ago
* >= 13 month => last year, n years ago
- * @param \OCP\IL10N $l The locale to use
- * @return string Formatted date span
*/
- public function formatDateSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) {
+ public function formatDateSpan($timestamp, $baseTimestamp = null, ?\OCP\IL10N $l = null) {
$l = $this->getLocale($l);
$timestamp = $this->getDateTime($timestamp);
$timestamp->setTime(0, 0, 0);
@@ -211,7 +193,7 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \OCP\IL10N $l The locale to use
* @return string Formatted time string
*/
- public function formatTime($timestamp, $format = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
+ public function formatTime($timestamp, $format = 'medium', ?\DateTimeZone $timeZone = null, ?\OCP\IL10N $l = null) {
return $this->format($timestamp, 'time', $format, $timeZone, $l);
}
@@ -220,17 +202,16 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
*
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
* @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time
- * @return string Dates returned are:
+ * @param \OCP\IL10N $l The locale to use
+ * @return string Formatted time span. Dates returned are:
* < 60 sec => seconds ago
* < 1 hour => n minutes ago
* < 1 day => n hours ago
* < 1 month => Yesterday, n days ago
* < 13 month => last month, n months ago
* >= 13 month => last year, n years ago
- * @param \OCP\IL10N $l The locale to use
- * @return string Formatted time span
*/
- public function formatTimeSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) {
+ public function formatTimeSpan($timestamp, $baseTimestamp = null, ?\OCP\IL10N $l = null) {
$l = $this->getLocale($l);
$timestamp = $this->getDateTime($timestamp);
if ($baseTimestamp === null) {
@@ -273,7 +254,7 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \OCP\IL10N $l The locale to use
* @return string Formatted date and time string
*/
- public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
+ public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', ?\DateTimeZone $timeZone = null, ?\OCP\IL10N $l = null) {
return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l);
}
@@ -288,8 +269,8 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \OCP\IL10N $l The locale to use
* @return string Formatted relative date and time string
*/
- public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
- if (substr($formatDate, -1) !== '^' && substr($formatDate, -1) !== '*') {
+ public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', ?\DateTimeZone $timeZone = null, ?\OCP\IL10N $l = null) {
+ if (!str_ends_with($formatDate, '^') && !str_ends_with($formatDate, '*')) {
$formatDate .= '^';
}
@@ -306,7 +287,7 @@ class DateTimeFormatter implements \OCP\IDateTimeFormatter {
* @param \OCP\IL10N $l The locale to use
* @return string Formatted date and time string
*/
- protected function format($timestamp, $type, $format, \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
+ protected function format($timestamp, $type, $format, ?\DateTimeZone $timeZone = null, ?\OCP\IL10N $l = null) {
$l = $this->getLocale($l);
$timeZone = $this->getTimeZone($timeZone);
$timestamp = $this->getDateTime($timestamp, $timeZone);
diff --git a/lib/private/DateTimeZone.php b/lib/private/DateTimeZone.php
index c514f8d7465..ca2e314fabd 100644
--- a/lib/private/DateTimeZone.php
+++ b/lib/private/DateTimeZone.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Diagnostics/Event.php b/lib/private/Diagnostics/Event.php
index 0c3aa6ae29c..cf36bf9f82a 100644
--- a/lib/private/Diagnostics/Event.php
+++ b/lib/private/Diagnostics/Event.php
@@ -1,24 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Diagnostics;
@@ -101,7 +85,7 @@ class Event implements IEvent {
return $this->end - $this->start;
}
- public function __toString() {
+ public function __toString(): string {
return $this->getId() . ' ' . $this->getDescription() . ' ' . $this->getDuration();
}
}
diff --git a/lib/private/Diagnostics/EventLogger.php b/lib/private/Diagnostics/EventLogger.php
index f1dd1addb08..11c59b9227a 100644
--- a/lib/private/Diagnostics/EventLogger.php
+++ b/lib/private/Diagnostics/EventLogger.php
@@ -1,26 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr Mrówczyński <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Diagnostics;
diff --git a/lib/private/Diagnostics/Query.php b/lib/private/Diagnostics/Query.php
index 6a26e57be0e..81610074709 100644
--- a/lib/private/Diagnostics/Query.php
+++ b/lib/private/Diagnostics/Query.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr Mrówczyński <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Diagnostics;
diff --git a/lib/private/Diagnostics/QueryLogger.php b/lib/private/Diagnostics/QueryLogger.php
index 5f401751077..5efe99d1a74 100644
--- a/lib/private/Diagnostics/QueryLogger.php
+++ b/lib/private/Diagnostics/QueryLogger.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr Mrówczyński <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Diagnostics;
@@ -49,7 +32,7 @@ class QueryLogger implements IQueryLogger {
/**
* @inheritdoc
*/
- public function startQuery($sql, array $params = null, array $types = null) {
+ public function startQuery($sql, ?array $params = null, ?array $types = null) {
if ($this->activated) {
$this->activeQuery = new Query($sql, $params, microtime(true), $this->getStack());
}
diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php
index 2dd2abe5408..4b8c6af31e2 100644
--- a/lib/private/DirectEditing/Manager.php
+++ b/lib/private/DirectEditing/Manager.php
@@ -1,32 +1,11 @@
<?php
/**
- * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Tobias Kaminsky <tobias@kaminsky.me>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DirectEditing;
use Doctrine\DBAL\FetchMode;
-use \OCP\Files\Folder;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
@@ -34,10 +13,11 @@ use OCP\Constants;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DirectEditing\ACreateFromTemplate;
use OCP\DirectEditing\IEditor;
-use \OCP\DirectEditing\IManager;
+use OCP\DirectEditing\IManager;
use OCP\DirectEditing\IToken;
use OCP\Encryption\IManager as EncryptionManager;
use OCP\Files\File;
+use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
@@ -153,7 +133,7 @@ class Manager implements IManager {
throw new \RuntimeException('No creator found');
}
- public function open(string $filePath, string $editorId = null, ?int $fileId = null): string {
+ public function open(string $filePath, ?string $editorId = null, ?int $fileId = null): string {
$userFolder = $this->rootFolder->getUserFolder($this->userId);
$file = $userFolder->get($filePath);
if ($fileId !== null && $file instanceof Folder) {
@@ -272,16 +252,14 @@ class Manager implements IManager {
}
public function invokeTokenScope($userId): void {
- \OC_User::setIncognitoMode(true);
\OC_User::setUserId($userId);
}
public function revertTokenScope(): void {
$this->userSession->setUser(null);
- \OC_User::setIncognitoMode(false);
}
- public function createToken($editorId, File $file, string $filePath, IShare $share = null): string {
+ public function createToken($editorId, File $file, string $filePath, ?IShare $share = null): string {
$token = $this->random->generate(64, ISecureRandom::CHAR_HUMAN_READABLE);
$query = $this->connection->getQueryBuilder();
$query->insert(self::TABLE_TOKENS)
@@ -299,10 +277,9 @@ class Manager implements IManager {
}
/**
- * @param $userId
- * @param $fileId
- * @param null $filePath
- * @return Node
+ * @param string $userId
+ * @param int $fileId
+ * @param ?string $filePath
* @throws NotFoundException
*/
public function getFileForToken($userId, $fileId, $filePath = null): Node {
@@ -310,11 +287,11 @@ class Manager implements IManager {
if ($filePath !== null) {
return $userFolder->get($filePath);
}
- $files = $userFolder->getById($fileId);
- if (count($files) === 0) {
+ $file = $userFolder->getFirstNodeById($fileId);
+ if (!$file) {
throw new NotFoundException('File nound found by id ' . $fileId);
}
- return $files[0];
+ return $file;
}
public function isEnabled(): bool {
diff --git a/lib/private/DirectEditing/Token.php b/lib/private/DirectEditing/Token.php
index 0ec911f9624..594cef98086 100644
--- a/lib/private/DirectEditing/Token.php
+++ b/lib/private/DirectEditing/Token.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DirectEditing;
diff --git a/lib/private/EmojiHelper.php b/lib/private/EmojiHelper.php
index d6e44810fab..514973b2959 100644
--- a/lib/private/EmojiHelper.php
+++ b/lib/private/EmojiHelper.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Georg Ehrke
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/Encryption/DecryptAll.php b/lib/private/Encryption/DecryptAll.php
index 7bf4ce62d28..f9a92d07d20 100644
--- a/lib/private/Encryption/DecryptAll.php
+++ b/lib/private/Encryption/DecryptAll.php
@@ -1,36 +1,16 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christian Jürges <christian@eqipe.ch>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author sammo2828 <sammo2828@gmail.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
use OC\Encryption\Exceptions\DecryptionFailedException;
use OC\Files\View;
use OCP\Encryption\IEncryptionModule;
+use OCP\Encryption\IManager;
use OCP\IUserManager;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
@@ -43,31 +23,14 @@ class DecryptAll {
/** @var InputInterface */
protected $input;
- /** @var Manager */
- protected $encryptionManager;
-
- /** @var IUserManager */
- protected $userManager;
-
- /** @var View */
- protected $rootView;
-
/** @var array files which couldn't be decrypted */
protected $failed;
- /**
- * @param Manager $encryptionManager
- * @param IUserManager $userManager
- * @param View $rootView
- */
public function __construct(
- Manager $encryptionManager,
- IUserManager $userManager,
- View $rootView
+ protected IManager $encryptionManager,
+ protected IUserManager $userManager,
+ protected View $rootView
) {
- $this->encryptionManager = $encryptionManager;
- $this->userManager = $userManager;
- $this->rootView = $rootView;
$this->failed = [];
}
diff --git a/lib/private/Encryption/EncryptionWrapper.php b/lib/private/Encryption/EncryptionWrapper.php
index 37264e81823..4ff8a3c0c6d 100644
--- a/lib/private/Encryption/EncryptionWrapper.php
+++ b/lib/private/Encryption/EncryptionWrapper.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
@@ -29,7 +12,8 @@ use OC\Files\Storage\Wrapper\Encryption;
use OC\Files\View;
use OC\Memcache\ArrayCache;
use OCP\Files\Mount\IMountPoint;
-use OCP\Files\Storage;
+use OCP\Files\Storage\IDisableEncryptionStorage;
+use OCP\Files\Storage\IStorage;
use Psr\Log\LoggerInterface;
/**
@@ -52,8 +36,8 @@ class EncryptionWrapper {
* EncryptionWrapper constructor.
*/
public function __construct(ArrayCache $arrayCache,
- Manager $manager,
- LoggerInterface $logger
+ Manager $manager,
+ LoggerInterface $logger
) {
$this->arrayCache = $arrayCache;
$this->manager = $manager;
@@ -64,18 +48,19 @@ class EncryptionWrapper {
* Wraps the given storage when it is not a shared storage
*
* @param string $mountPoint
- * @param Storage $storage
+ * @param IStorage $storage
* @param IMountPoint $mount
- * @return Encryption|Storage
+ * @param bool $force apply the wrapper even if the storage normally has encryption disabled, helpful for repair steps
+ * @return Encryption|IStorage
*/
- public function wrapStorage($mountPoint, Storage $storage, IMountPoint $mount) {
+ public function wrapStorage(string $mountPoint, IStorage $storage, IMountPoint $mount, bool $force = false) {
$parameters = [
'storage' => $storage,
'mountPoint' => $mountPoint,
'mount' => $mount
];
- if (!$storage->instanceOfStorage(Storage\IDisableEncryptionStorage::class) && $mountPoint !== '/') {
+ if ($force || (!$storage->instanceOfStorage(IDisableEncryptionStorage::class) && $mountPoint !== '/')) {
$user = \OC::$server->getUserSession()->getUser();
$mountManager = Filesystem::getMountManager();
$uid = $user ? $user->getUID() : null;
diff --git a/lib/private/Encryption/Exceptions/DecryptionFailedException.php b/lib/private/Encryption/Exceptions/DecryptionFailedException.php
index c67edabd0ce..bdda5b381b6 100644
--- a/lib/private/Encryption/Exceptions/DecryptionFailedException.php
+++ b/lib/private/Encryption/Exceptions/DecryptionFailedException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php b/lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php
index 9a86d876d6a..a2829a8c09c 100644
--- a/lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php
+++ b/lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/EncryptionFailedException.php b/lib/private/Encryption/Exceptions/EncryptionFailedException.php
index 8797df51e8e..04ca6eba79c 100644
--- a/lib/private/Encryption/Exceptions/EncryptionFailedException.php
+++ b/lib/private/Encryption/Exceptions/EncryptionFailedException.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/EncryptionHeaderKeyExistsException.php b/lib/private/Encryption/Exceptions/EncryptionHeaderKeyExistsException.php
index 99cfb1eb8d1..07007dc0ec1 100644
--- a/lib/private/Encryption/Exceptions/EncryptionHeaderKeyExistsException.php
+++ b/lib/private/Encryption/Exceptions/EncryptionHeaderKeyExistsException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/EncryptionHeaderToLargeException.php b/lib/private/Encryption/Exceptions/EncryptionHeaderToLargeException.php
index 45d70dd5f8f..dace9527305 100644
--- a/lib/private/Encryption/Exceptions/EncryptionHeaderToLargeException.php
+++ b/lib/private/Encryption/Exceptions/EncryptionHeaderToLargeException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/ModuleAlreadyExistsException.php b/lib/private/Encryption/Exceptions/ModuleAlreadyExistsException.php
index d0a2756212b..72ff00befc3 100644
--- a/lib/private/Encryption/Exceptions/ModuleAlreadyExistsException.php
+++ b/lib/private/Encryption/Exceptions/ModuleAlreadyExistsException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php b/lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php
index e0ce8616432..8ec382f176d 100644
--- a/lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php
+++ b/lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/Exceptions/UnknownCipherException.php b/lib/private/Encryption/Exceptions/UnknownCipherException.php
index fbb923ce521..a64a413bf8e 100644
--- a/lib/private/Encryption/Exceptions/UnknownCipherException.php
+++ b/lib/private/Encryption/Exceptions/UnknownCipherException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Exceptions;
diff --git a/lib/private/Encryption/File.php b/lib/private/Encryption/File.php
index daab097ce7c..a29d62946c4 100644
--- a/lib/private/Encryption/File.php
+++ b/lib/private/Encryption/File.php
@@ -1,35 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
-use OCP\Cache\CappedMemoryCache;
use OCA\Files_External\Service\GlobalStoragesService;
use OCP\App\IAppManager;
+use OCP\Cache\CappedMemoryCache;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Share\IManager;
@@ -47,8 +27,8 @@ class File implements \OCP\Encryption\IFile {
private ?IAppManager $appManager = null;
public function __construct(Util $util,
- IRootFolder $rootFolder,
- IManager $shareManager) {
+ IRootFolder $rootFolder,
+ IManager $shareManager) {
$this->util = $util;
$this->cache = new CappedMemoryCache();
$this->rootFolder = $rootFolder;
diff --git a/lib/private/Encryption/HookManager.php b/lib/private/Encryption/HookManager.php
index 5081bcccf94..fc6546fb253 100644
--- a/lib/private/Encryption/HookManager.php
+++ b/lib/private/Encryption/HookManager.php
@@ -1,31 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
use OC\Files\Filesystem;
-use OC\Files\View;
use OC\Files\SetupManager;
+use OC\Files\View;
use Psr\Log\LoggerInterface;
class HookManager {
diff --git a/lib/private/Encryption/Keys/Storage.php b/lib/private/Encryption/Keys/Storage.php
index e88c305eeec..532d1a51dd6 100644
--- a/lib/private/Encryption/Keys/Storage.php
+++ b/lib/private/Encryption/Keys/Storage.php
@@ -1,29 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption\Keys;
@@ -98,14 +77,14 @@ class Storage implements IStorage {
*/
public function getFileKey($path, $keyId, $encryptionModuleId) {
$realFile = $this->util->stripPartialFileExtension($path);
- $keyDir = $this->getFileKeyDir($encryptionModuleId, $realFile);
+ $keyDir = $this->util->getFileKeyDir($encryptionModuleId, $realFile);
$key = $this->getKey($keyDir . $keyId)['key'];
if ($key === '' && $realFile !== $path) {
// Check if the part file has keys and use them, if no normal keys
// exist. This is required to fix copyBetweenStorage() when we
// rename a .part file over storage borders.
- $keyDir = $this->getFileKeyDir($encryptionModuleId, $path);
+ $keyDir = $this->util->getFileKeyDir($encryptionModuleId, $path);
$key = $this->getKey($keyDir . $keyId)['key'];
}
@@ -135,7 +114,7 @@ class Storage implements IStorage {
* @inheritdoc
*/
public function setFileKey($path, $keyId, $key, $encryptionModuleId) {
- $keyDir = $this->getFileKeyDir($encryptionModuleId, $path);
+ $keyDir = $this->util->getFileKeyDir($encryptionModuleId, $path);
return $this->setKey($keyDir . $keyId, [
'key' => base64_encode($key),
]);
@@ -177,7 +156,7 @@ class Storage implements IStorage {
* @inheritdoc
*/
public function deleteFileKey($path, $keyId, $encryptionModuleId) {
- $keyDir = $this->getFileKeyDir($encryptionModuleId, $path);
+ $keyDir = $this->util->getFileKeyDir($encryptionModuleId, $path);
return !$this->view->file_exists($keyDir . $keyId) || $this->view->unlink($keyDir . $keyId);
}
@@ -185,7 +164,7 @@ class Storage implements IStorage {
* @inheritdoc
*/
public function deleteAllFileKeys($path) {
- $keyDir = $this->getFileKeyDir('', $path);
+ $keyDir = $this->util->getFileKeyDir('', $path);
return !$this->view->file_exists($keyDir) || $this->view->deleteAll($keyDir);
}
@@ -356,26 +335,6 @@ class Storage implements IStorage {
}
/**
- * get path to key folder for a given file
- *
- * @param string $encryptionModuleId
- * @param string $path path to the file, relative to data/
- * @return string
- */
- private function getFileKeyDir($encryptionModuleId, $path) {
- [$owner, $filename] = $this->util->getUidAndFilename($path);
-
- // in case of system wide mount points the keys are stored directly in the data directory
- if ($this->util->isSystemWideMountPoint($filename, $owner)) {
- $keyPath = $this->root_dir . '/' . $this->keys_base_dir . $filename . '/';
- } else {
- $keyPath = $this->root_dir . '/' . $owner . $this->keys_base_dir . $filename . '/';
- }
-
- return Filesystem::normalizePath($keyPath . $encryptionModuleId . '/', false);
- }
-
- /**
* move keys if a file was renamed
*
* @param string $source
diff --git a/lib/private/Encryption/Manager.php b/lib/private/Encryption/Manager.php
index f751bd94b28..a07c778bfe0 100644
--- a/lib/private/Encryption/Manager.php
+++ b/lib/private/Encryption/Manager.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
@@ -32,39 +14,24 @@ use OC\Memcache\ArrayCache;
use OC\ServiceUnavailableException;
use OCP\Encryption\IEncryptionModule;
use OCP\Encryption\IManager;
+use OCP\Files\Mount\IMountPoint;
+use OCP\Files\Storage\IStorage;
use OCP\IConfig;
use OCP\IL10N;
use Psr\Log\LoggerInterface;
class Manager implements IManager {
- /** @var array */
- protected $encryptionModules;
-
- /** @var IConfig */
- protected $config;
-
- protected LoggerInterface $logger;
-
- /** @var Il10n */
- protected $l;
-
- /** @var View */
- protected $rootView;
-
- /** @var Util */
- protected $util;
-
- /** @var ArrayCache */
- protected $arrayCache;
-
- public function __construct(IConfig $config, LoggerInterface $logger, IL10N $l10n, View $rootView, Util $util, ArrayCache $arrayCache) {
+ protected array $encryptionModules;
+
+ public function __construct(
+ protected IConfig $config,
+ protected LoggerInterface $logger,
+ protected IL10N $l,
+ protected View $rootView,
+ protected Util $util,
+ protected ArrayCache $arrayCache,
+ ) {
$this->encryptionModules = [];
- $this->config = $config;
- $this->logger = $logger;
- $this->l = $l10n;
- $this->rootView = $rootView;
- $this->util = $util;
- $this->arrayCache = $arrayCache;
}
/**
@@ -234,6 +201,11 @@ class Manager implements IManager {
}
}
+ public function forceWrapStorage(IMountPoint $mountPoint, IStorage $storage) {
+ $encryptionWrapper = new EncryptionWrapper($this->arrayCache, $this, $this->logger);
+ return $encryptionWrapper->wrapStorage($mountPoint->getMountPoint(), $storage, $mountPoint, true);
+ }
+
/**
* check if key storage is ready
diff --git a/lib/private/Encryption/Update.php b/lib/private/Encryption/Update.php
index 2e390177baf..87036403b8e 100644
--- a/lib/private/Encryption/Update.php
+++ b/lib/private/Encryption/Update.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
@@ -62,14 +43,14 @@ class Update {
* @param string $uid
*/
public function __construct(
- View $view,
- Util $util,
- Mount\Manager $mountManager,
- Manager $encryptionManager,
- File $file,
- LoggerInterface $logger,
- $uid
- ) {
+ View $view,
+ Util $util,
+ Mount\Manager $mountManager,
+ Manager $encryptionManager,
+ File $file,
+ LoggerInterface $logger,
+ $uid
+ ) {
$this->view = $view;
$this->util = $util;
$this->mountManager = $mountManager;
diff --git a/lib/private/Encryption/Util.php b/lib/private/Encryption/Util.php
index a468908ffc8..1fb08b15696 100644
--- a/lib/private/Encryption/Util.php
+++ b/lib/private/Encryption/Util.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Encryption;
@@ -105,7 +85,7 @@ class Util {
* @return string
* @throws ModuleDoesNotExistsException
*/
- public function getEncryptionModuleId(array $header = null) {
+ public function getEncryptionModuleId(?array $header = null) {
$id = '';
$encryptionModuleKey = self::HEADER_ENCRYPTION_MODULE_KEY;
@@ -357,4 +337,53 @@ class Util {
public function getKeyStorageRoot(): string {
return $this->config->getAppValue('core', 'encryption_key_storage_root', '');
}
+
+ /**
+ * parse raw header to array
+ *
+ * @param string $rawHeader
+ * @return array
+ */
+ public function parseRawHeader(string $rawHeader) {
+ $result = [];
+ if (str_starts_with($rawHeader, Util::HEADER_START)) {
+ $header = $rawHeader;
+ $endAt = strpos($header, Util::HEADER_END);
+ if ($endAt !== false) {
+ $header = substr($header, 0, $endAt + strlen(Util::HEADER_END));
+
+ // +1 to not start with an ':' which would result in empty element at the beginning
+ $exploded = explode(':', substr($header, strlen(Util::HEADER_START) + 1));
+
+ $element = array_shift($exploded);
+ while ($element !== Util::HEADER_END && $element !== null) {
+ $result[$element] = array_shift($exploded);
+ $element = array_shift($exploded);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * get path to key folder for a given file
+ *
+ * @param string $encryptionModuleId
+ * @param string $path path to the file, relative to data/
+ * @return string
+ */
+ public function getFileKeyDir(string $encryptionModuleId, string $path): string {
+ [$owner, $filename] = $this->getUidAndFilename($path);
+ $root = $this->getKeyStorageRoot();
+
+ // in case of system-wide mount points the keys are stored directly in the data directory
+ if ($this->isSystemWideMountPoint($filename, $owner)) {
+ $keyPath = $root . '/' . '/files_encryption/keys' . $filename . '/';
+ } else {
+ $keyPath = $root . '/' . $owner . '/files_encryption/keys' . $filename . '/';
+ }
+
+ return Filesystem::normalizePath($keyPath . $encryptionModuleId . '/', false);
+ }
}
diff --git a/lib/private/EventDispatcher/EventDispatcher.php b/lib/private/EventDispatcher/EventDispatcher.php
index 88c6b2cf32c..b7554c439ea 100644
--- a/lib/private/EventDispatcher/EventDispatcher.php
+++ b/lib/private/EventDispatcher/EventDispatcher.php
@@ -3,59 +3,28 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\EventDispatcher;
-use OC\Log;
-use Psr\Log\LoggerInterface;
-use function get_class;
use OC\Broadcast\Events\BroadcastEvent;
+use OC\Log;
use OCP\Broadcast\Events\IBroadcastEvent;
use OCP\EventDispatcher\ABroadcastedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
-use OCP\IContainer;
use OCP\IServerContainer;
+use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher as SymfonyDispatcher;
+use function get_class;
class EventDispatcher implements IEventDispatcher {
- /** @var SymfonyDispatcher */
- private $dispatcher;
-
- /** @var IContainer */
- private $container;
-
- /** @var LoggerInterface */
- private $logger;
-
- public function __construct(SymfonyDispatcher $dispatcher,
- IServerContainer $container,
- LoggerInterface $logger) {
- $this->dispatcher = $dispatcher;
- $this->container = $container;
- $this->logger = $logger;
-
+ public function __construct(
+ private SymfonyDispatcher $dispatcher,
+ private IServerContainer $container,
+ private LoggerInterface $logger,
+ ) {
// inject the event dispatcher into the logger
// this is done here because there is a cyclic dependency between the event dispatcher and logger
if ($this->logger instanceof Log || $this->logger instanceof Log\PsrLoggerAdapter) {
@@ -64,19 +33,19 @@ class EventDispatcher implements IEventDispatcher {
}
public function addListener(string $eventName,
- callable $listener,
- int $priority = 0): void {
+ callable $listener,
+ int $priority = 0): void {
$this->dispatcher->addListener($eventName, $listener, $priority);
}
public function removeListener(string $eventName,
- callable $listener): void {
+ callable $listener): void {
$this->dispatcher->removeListener($eventName, $listener);
}
public function addServiceListener(string $eventName,
- string $className,
- int $priority = 0): void {
+ string $className,
+ int $priority = 0): void {
$listener = new ServiceEventListener(
$this->container,
$className,
@@ -86,11 +55,15 @@ class EventDispatcher implements IEventDispatcher {
$this->addListener($eventName, $listener, $priority);
}
+ public function hasListeners(string $eventName): bool {
+ return $this->dispatcher->hasListeners($eventName);
+ }
+
/**
* @deprecated
*/
public function dispatch(string $eventName,
- Event $event): void {
+ Event $event): void {
$this->dispatcher->dispatch($event, $eventName);
if ($event instanceof ABroadcastedEvent && !$event->isPropagationStopped()) {
diff --git a/lib/private/EventDispatcher/ServiceEventListener.php b/lib/private/EventDispatcher/ServiceEventListener.php
index 21cdf7f8cc2..03a986ec78c 100644
--- a/lib/private/EventDispatcher/ServiceEventListener.php
+++ b/lib/private/EventDispatcher/ServiceEventListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\EventDispatcher;
@@ -54,8 +36,8 @@ final class ServiceEventListener {
private $service;
public function __construct(IServerContainer $container,
- string $class,
- LoggerInterface $logger) {
+ string $class,
+ LoggerInterface $logger) {
$this->container = $container;
$this->class = $class;
$this->logger = $logger;
diff --git a/lib/private/legacy/OC_EventSource.php b/lib/private/EventSource.php
index cd72ba1f2d5..dbeda25049e 100644
--- a/lib/private/legacy/OC_EventSource.php
+++ b/lib/private/EventSource.php
@@ -1,64 +1,34 @@
<?php
-use OCP\IRequest;
-
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christian Oliff <christianoliff@yahoo.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2020-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-class OC_EventSource implements \OCP\IEventSource {
- /**
- * @var bool
- */
- private $fallback;
-
- /**
- * @var int
- */
- private $fallBackId = 0;
+namespace OC;
- /**
- * @var bool
- */
- private $started = false;
+use OCP\IEventSource;
+use OCP\IRequest;
- private IRequest $request;
+class EventSource implements IEventSource {
+ private bool $fallback = false;
+ private int $fallBackId = 0;
+ private bool $started = false;
- public function __construct(IRequest $request) {
- $this->request = $request;
+ public function __construct(
+ private IRequest $request,
+ ) {
}
- protected function init() {
+ protected function init(): void {
if ($this->started) {
return;
}
$this->started = true;
// prevent php output buffering, caching and nginx buffering
- OC_Util::obEnd();
+ \OC_Util::obEnd();
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no');
$this->fallback = isset($_GET['fallback']) and $_GET['fallback'] == 'true';
@@ -104,7 +74,7 @@ class OC_EventSource implements \OCP\IEventSource {
*/
public function send($type, $data = null) {
if ($data and !preg_match('/^[A-Za-z0-9_]+$/', $type)) {
- throw new BadMethodCallException('Type needs to be alphanumeric ('. $type .')');
+ throw new \BadMethodCallException('Type needs to be alphanumeric ('. $type .')');
}
$this->init();
if (is_null($data)) {
@@ -113,13 +83,13 @@ class OC_EventSource implements \OCP\IEventSource {
}
if ($this->fallback) {
$response = '<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack('
- . $this->fallBackId . ',"' . $type . '",' . OC_JSON::encode($data) . ')</script>' . PHP_EOL;
+ . $this->fallBackId . ',"' . ($type ?? '') . '",' . json_encode($data, JSON_HEX_TAG) . ')</script>' . PHP_EOL;
echo $response;
} else {
if ($type) {
echo 'event: ' . $type . PHP_EOL;
}
- echo 'data: ' . OC_JSON::encode($data) . PHP_EOL;
+ echo 'data: ' . json_encode($data, JSON_HEX_TAG) . PHP_EOL;
}
echo PHP_EOL;
flush();
diff --git a/lib/private/EventSourceFactory.php b/lib/private/EventSourceFactory.php
index 197c8bf9e6c..57888b1be4c 100644
--- a/lib/private/EventSourceFactory.php
+++ b/lib/private/EventSourceFactory.php
@@ -1,23 +1,10 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2023 Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
@@ -27,20 +14,12 @@ use OCP\IEventSourceFactory;
use OCP\IRequest;
class EventSourceFactory implements IEventSourceFactory {
- private IRequest $request;
-
-
- public function __construct(IRequest $request) {
- $this->request = $request;
+ public function __construct(
+ private IRequest $request,
+ ) {
}
- /**
- * Create a new event source
- *
- * @return IEventSource
- * @since 28.0.0
- */
public function create(): IEventSource {
- return new \OC_EventSource($this->request);
+ return new EventSource($this->request);
}
}
diff --git a/lib/private/Federation/CloudFederationFactory.php b/lib/private/Federation/CloudFederationFactory.php
index 391213c21e0..f5f25d14ea1 100644
--- a/lib/private/Federation/CloudFederationFactory.php
+++ b/lib/private/Federation/CloudFederationFactory.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Federation;
diff --git a/lib/private/Federation/CloudFederationNotification.php b/lib/private/Federation/CloudFederationNotification.php
index aa1c3dc9e65..855580843ba 100644
--- a/lib/private/Federation/CloudFederationNotification.php
+++ b/lib/private/Federation/CloudFederationNotification.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Federation;
diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php
index b11c4060ab4..79b37b44c82 100644
--- a/lib/private/Federation/CloudFederationProviderManager.php
+++ b/lib/private/Federation/CloudFederationProviderManager.php
@@ -1,25 +1,10 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Federation;
@@ -32,6 +17,10 @@ use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
use OCP\Http\Client\IClientService;
+use OCP\Http\Client\IResponse;
+use OCP\IConfig;
+use OCP\OCM\Exceptions\OCMProviderException;
+use OCP\OCM\IOCMDiscoveryService;
use Psr\Log\LoggerInterface;
/**
@@ -43,40 +32,16 @@ use Psr\Log\LoggerInterface;
*/
class CloudFederationProviderManager implements ICloudFederationProviderManager {
/** @var array list of available cloud federation providers */
- private $cloudFederationProvider;
-
- /** @var IAppManager */
- private $appManager;
-
- /** @var IClientService */
- private $httpClientService;
-
- /** @var ICloudIdManager */
- private $cloudIdManager;
-
- private LoggerInterface $logger;
-
- /** @var array cache OCM end-points */
- private $ocmEndPoints = [];
-
- private $supportedAPIVersion = '1.0-proposal1';
-
- /**
- * CloudFederationProviderManager constructor.
- *
- * @param IAppManager $appManager
- * @param IClientService $httpClientService
- * @param ICloudIdManager $cloudIdManager
- */
- public function __construct(IAppManager $appManager,
- IClientService $httpClientService,
- ICloudIdManager $cloudIdManager,
- LoggerInterface $logger) {
- $this->cloudFederationProvider = [];
- $this->appManager = $appManager;
- $this->httpClientService = $httpClientService;
- $this->cloudIdManager = $cloudIdManager;
- $this->logger = $logger;
+ private array $cloudFederationProvider = [];
+
+ public function __construct(
+ private IConfig $config,
+ private IAppManager $appManager,
+ private IClientService $httpClientService,
+ private ICloudIdManager $cloudIdManager,
+ private IOCMDiscoveryService $discoveryService,
+ private LoggerInterface $logger
+ ) {
}
@@ -128,18 +93,23 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
}
+ /**
+ * @deprecated 29.0.0 - Use {@see sendCloudShare()} instead and handle errors manually
+ */
public function sendShare(ICloudFederationShare $share) {
$cloudID = $this->cloudIdManager->resolveCloudId($share->getShareWith());
- $ocmEndPoint = $this->getOCMEndPoint($cloudID->getRemote());
- if (empty($ocmEndPoint)) {
+ try {
+ $ocmProvider = $this->discoveryService->discover($cloudID->getRemote());
+ } catch (OCMProviderException $e) {
return false;
}
$client = $this->httpClientService->newClient();
try {
- $response = $client->post($ocmEndPoint . '/shares', [
+ $response = $client->post($ocmProvider->getEndPoint() . '/shares', [
'body' => json_encode($share->getShare()),
'headers' => ['content-type' => 'application/json'],
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates', false),
'timeout' => 10,
'connect_timeout' => 10,
]);
@@ -163,22 +133,52 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
/**
+ * @param ICloudFederationShare $share
+ * @return IResponse
+ * @throws OCMProviderException
+ */
+ public function sendCloudShare(ICloudFederationShare $share): IResponse {
+ $cloudID = $this->cloudIdManager->resolveCloudId($share->getShareWith());
+ $ocmProvider = $this->discoveryService->discover($cloudID->getRemote());
+
+ $client = $this->httpClientService->newClient();
+ try {
+ return $client->post($ocmProvider->getEndPoint() . '/shares', [
+ 'body' => json_encode($share->getShare()),
+ 'headers' => ['content-type' => 'application/json'],
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates', false),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ } catch (\Throwable $e) {
+ $this->logger->error('Error while sending share to federation server: ' . $e->getMessage(), ['exception' => $e]);
+ try {
+ return $client->getResponseFromThrowable($e);
+ } catch (\Throwable $e) {
+ throw new OCMProviderException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+ }
+
+ /**
* @param string $url
* @param ICloudFederationNotification $notification
* @return array|false
+ * @deprecated 29.0.0 - Use {@see sendCloudNotification()} instead and handle errors manually
*/
public function sendNotification($url, ICloudFederationNotification $notification) {
- $ocmEndPoint = $this->getOCMEndPoint($url);
-
- if (empty($ocmEndPoint)) {
+ try {
+ $ocmProvider = $this->discoveryService->discover($url);
+ } catch (OCMProviderException $e) {
return false;
}
$client = $this->httpClientService->newClient();
try {
- $response = $client->post($ocmEndPoint . '/notifications', [
+ $response = $client->post($ocmProvider->getEndPoint() . '/notifications', [
'body' => json_encode($notification->getMessage()),
'headers' => ['content-type' => 'application/json'],
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates', false),
'timeout' => 10,
'connect_timeout' => 10,
]);
@@ -195,43 +195,39 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
/**
- * check if the new cloud federation API is ready to be used
- *
- * @return bool
- */
- public function isReady() {
- return $this->appManager->isEnabledForUser('cloud_federation_api');
- }
- /**
- * check if server supports the new OCM api and ask for the correct end-point
- *
- * @param string $url full base URL of the cloud server
- * @return string
+ * @param string $url
+ * @param ICloudFederationNotification $notification
+ * @return IResponse
+ * @throws OCMProviderException
*/
- protected function getOCMEndPoint($url) {
- if (isset($this->ocmEndPoints[$url])) {
- return $this->ocmEndPoints[$url];
- }
+ public function sendCloudNotification(string $url, ICloudFederationNotification $notification): IResponse {
+ $ocmProvider = $this->discoveryService->discover($url);
$client = $this->httpClientService->newClient();
try {
- $response = $client->get($url . '/ocm-provider/', ['timeout' => 10, 'connect_timeout' => 10]);
- } catch (\Exception $e) {
- $this->ocmEndPoints[$url] = '';
- return '';
- }
-
- $result = $response->getBody();
- $result = json_decode($result, true);
-
- $supportedVersion = isset($result['apiVersion']) && $result['apiVersion'] === $this->supportedAPIVersion;
-
- if (isset($result['endPoint']) && $supportedVersion) {
- $this->ocmEndPoints[$url] = $result['endPoint'];
- return $result['endPoint'];
+ return $client->post($ocmProvider->getEndPoint() . '/notifications', [
+ 'body' => json_encode($notification->getMessage()),
+ 'headers' => ['content-type' => 'application/json'],
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates', false),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ } catch (\Throwable $e) {
+ $this->logger->error('Error while sending notification to federation server: ' . $e->getMessage(), ['exception' => $e]);
+ try {
+ return $client->getResponseFromThrowable($e);
+ } catch (\Throwable $e) {
+ throw new OCMProviderException($e->getMessage(), $e->getCode(), $e);
+ }
}
+ }
- $this->ocmEndPoints[$url] = '';
- return '';
+ /**
+ * check if the new cloud federation API is ready to be used
+ *
+ * @return bool
+ */
+ public function isReady() {
+ return $this->appManager->isEnabledForUser('cloud_federation_api');
}
}
diff --git a/lib/private/Federation/CloudFederationShare.php b/lib/private/Federation/CloudFederationShare.php
index 0f79ba521ea..aa86905f234 100644
--- a/lib/private/Federation/CloudFederationShare.php
+++ b/lib/private/Federation/CloudFederationShare.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Federation;
@@ -57,16 +39,16 @@ class CloudFederationShare implements ICloudFederationShare {
* @param string $sharedSecret
*/
public function __construct($shareWith = '',
- $name = '',
- $description = '',
- $providerId = '',
- $owner = '',
- $ownerDisplayName = '',
- $sharedBy = '',
- $sharedByDisplayName = '',
- $shareType = '',
- $resourceType = '',
- $sharedSecret = ''
+ $name = '',
+ $description = '',
+ $providerId = '',
+ $owner = '',
+ $ownerDisplayName = '',
+ $sharedBy = '',
+ $sharedByDisplayName = '',
+ $shareType = '',
+ $resourceType = '',
+ $sharedSecret = ''
) {
$this->setShareWith($shareWith);
$this->setResourceName($name);
diff --git a/lib/private/Federation/CloudId.php b/lib/private/Federation/CloudId.php
index 50e974831a6..c20dbfc6418 100644
--- a/lib/private/Federation/CloudId.php
+++ b/lib/private/Federation/CloudId.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Federation;
diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php
index 22b06af386f..cd5e4d511c3 100644
--- a/lib/private/Federation/CloudIdManager.php
+++ b/lib/private/Federation/CloudIdManager.php
@@ -3,30 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Guillaume Virlet <github@virlet.org>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Federation;
@@ -168,17 +146,15 @@ class CloudIdManager implements ICloudIdManager {
public function getCloudId(string $user, ?string $remote): ICloudId {
$isLocal = $remote === null;
if ($isLocal) {
- $remote = rtrim($this->removeProtocolFromUrl($this->urlGenerator->getAbsoluteURL('/')), '/');
- $fixedRemote = $this->fixRemoteURL($remote);
- $host = $fixedRemote;
- } else {
- // note that for remote id's we don't strip the protocol for the remote we use to construct the CloudId
- // this way if a user has an explicit non-https cloud id this will be preserved
- // we do still use the version without protocol for looking up the display name
- $fixedRemote = $this->fixRemoteURL($remote);
- $host = $this->removeProtocolFromUrl($fixedRemote);
+ $remote = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
}
+ // note that for remote id's we don't strip the protocol for the remote we use to construct the CloudId
+ // this way if a user has an explicit non-https cloud id this will be preserved
+ // we do still use the version without protocol for looking up the display name
+ $remote = $this->fixRemoteURL($remote);
+ $host = $this->removeProtocolFromUrl($remote);
+
$key = $user . '@' . ($isLocal ? 'local' : $host);
$cached = $this->cache[$key] ?? $this->memCache->get($key);
if ($cached) {
@@ -192,28 +168,30 @@ class CloudIdManager implements ICloudIdManager {
} else {
$displayName = $this->getDisplayNameFromContact($user . '@' . $host);
}
- $id = $user . '@' . $remote;
+
+ // For the visible cloudID we only strip away https
+ $id = $user . '@' . $this->removeProtocolFromUrl($remote, true);
$data = [
'id' => $id,
'user' => $user,
- 'remote' => $fixedRemote,
+ 'remote' => $remote,
'displayName' => $displayName,
];
$this->cache[$key] = $data;
$this->memCache->set($key, $data, 15 * 60);
- return new CloudId($id, $user, $fixedRemote, $displayName);
+ return new CloudId($id, $user, $remote, $displayName);
}
/**
* @param string $url
* @return string
*/
- public function removeProtocolFromUrl(string $url): string {
+ public function removeProtocolFromUrl(string $url, bool $httpsOnly = false): string {
if (str_starts_with($url, 'https://')) {
return substr($url, 8);
}
- if (str_starts_with($url, 'http://')) {
+ if (!$httpsOnly && str_starts_with($url, 'http://')) {
return substr($url, 7);
}
diff --git a/lib/private/Files/AppData/AppData.php b/lib/private/Files/AppData/AppData.php
index 237fcb42e03..c13372ae1d9 100644
--- a/lib/private/Files/AppData/AppData.php
+++ b/lib/private/Files/AppData/AppData.php
@@ -3,32 +3,14 @@
declare(strict_types=1);
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\AppData;
-use OCP\Cache\CappedMemoryCache;
use OC\Files\SimpleFS\SimpleFolder;
use OC\SystemConfig;
+use OCP\Cache\CappedMemoryCache;
use OCP\Files\Folder;
use OCP\Files\IAppData;
use OCP\Files\IRootFolder;
@@ -53,8 +35,8 @@ class AppData implements IAppData {
* @param string $appId
*/
public function __construct(IRootFolder $rootFolder,
- SystemConfig $systemConfig,
- string $appId) {
+ SystemConfig $systemConfig,
+ string $appId) {
$this->rootFolder = $rootFolder;
$this->config = $systemConfig;
$this->appId = $appId;
diff --git a/lib/private/Files/AppData/Factory.php b/lib/private/Files/AppData/Factory.php
index 03f8fdedcbd..38b73f370b8 100644
--- a/lib/private/Files/AppData/Factory.php
+++ b/lib/private/Files/AppData/Factory.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\AppData;
@@ -39,7 +21,7 @@ class Factory implements IAppDataFactory {
private array $folders = [];
public function __construct(IRootFolder $rootFolder,
- SystemConfig $systemConfig) {
+ SystemConfig $systemConfig) {
$this->rootFolder = $rootFolder;
$this->config = $systemConfig;
}
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php
index 67d01bb6999..6c4bd2c9637 100644
--- a/lib/private/Files/Cache/Cache.php
+++ b/lib/private/Files/Cache/Cache.php
@@ -1,55 +1,24 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Ari Selseng <ari@selseng.net>
- * @author Artem Kochnev <MrJeos@gmail.com>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Florin Peter <github@florin-peter.de>
- * @author Frédéric Fortier <frederic.fortier@oronospolytechnique.com>
- * @author Jens-Christian Fischer <jens-christian.fischer@switch.ch>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Cache;
+use Doctrine\DBAL\Exception\RetryableException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
use OC\Files\Storage\Wrapper\Encryption;
+use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Cache\CacheEntryInsertedEvent;
+use OCP\Files\Cache\CacheEntryRemovedEvent;
use OCP\Files\Cache\CacheEntryUpdatedEvent;
use OCP\Files\Cache\CacheInsertEvent;
-use OCP\Files\Cache\CacheEntryRemovedEvent;
use OCP\Files\Cache\CacheUpdateEvent;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
@@ -59,6 +28,7 @@ use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
use OCP\Files\Storage\IStorage;
+use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\IDBConnection;
use OCP\Util;
use Psr\Log\LoggerInterface;
@@ -81,61 +51,53 @@ class Cache implements ICache {
/**
* @var array partial data for the cache
*/
- protected $partial = [];
-
- /**
- * @var string
- */
- protected $storageId;
-
- private $storage;
-
- /**
- * @var Storage $storageCache
- */
- protected $storageCache;
-
- /** @var IMimeTypeLoader */
- protected $mimetypeLoader;
-
- /**
- * @var IDBConnection
- */
- protected $connection;
-
- /**
- * @var IEventDispatcher
- */
- protected $eventDispatcher;
-
- /** @var QuerySearchHelper */
- protected $querySearchHelper;
-
- /**
- * @param IStorage $storage
- */
- public function __construct(IStorage $storage) {
+ protected array $partial = [];
+ protected string $storageId;
+ protected Storage $storageCache;
+ protected IMimeTypeLoader$mimetypeLoader;
+ protected IDBConnection $connection;
+ protected SystemConfig $systemConfig;
+ protected LoggerInterface $logger;
+ protected QuerySearchHelper $querySearchHelper;
+ protected IEventDispatcher $eventDispatcher;
+ protected IFilesMetadataManager $metadataManager;
+
+ public function __construct(
+ private IStorage $storage,
+ // this constructor is used in to many pleases to easily do proper di
+ // so instead we group it all together
+ ?CacheDependencies $dependencies = null,
+ ) {
$this->storageId = $storage->getId();
- $this->storage = $storage;
if (strlen($this->storageId) > 64) {
$this->storageId = md5($this->storageId);
}
-
- $this->storageCache = new Storage($storage);
- $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
- $this->connection = \OC::$server->getDatabaseConnection();
- $this->eventDispatcher = \OC::$server->get(IEventDispatcher::class);
- $this->querySearchHelper = \OCP\Server::get(QuerySearchHelper::class);
+ if (!$dependencies) {
+ $dependencies = \OC::$server->get(CacheDependencies::class);
+ }
+ $this->storageCache = new Storage($this->storage, true, $dependencies->getConnection());
+ $this->mimetypeLoader = $dependencies->getMimeTypeLoader();
+ $this->connection = $dependencies->getConnection();
+ $this->systemConfig = $dependencies->getSystemConfig();
+ $this->logger = $dependencies->getLogger();
+ $this->querySearchHelper = $dependencies->getQuerySearchHelper();
+ $this->eventDispatcher = $dependencies->getEventDispatcher();
+ $this->metadataManager = $dependencies->getMetadataManager();
}
protected function getQueryBuilder() {
return new CacheQueryBuilder(
$this->connection,
- \OC::$server->getSystemConfig(),
- \OC::$server->get(LoggerInterface::class)
+ $this->systemConfig,
+ $this->logger,
+ $this->metadataManager,
);
}
+ public function getStorageCache(): Storage {
+ return $this->storageCache;
+ }
+
/**
* Get the numeric storage id for this cache's storage
*
@@ -154,6 +116,7 @@ class Cache implements ICache {
public function get($file) {
$query = $this->getQueryBuilder();
$query->selectFileCache();
+ $metadataQuery = $query->selectMetadata();
if (is_string($file) || $file == '') {
// normalize file
@@ -175,6 +138,7 @@ class Cache implements ICache {
} elseif (!$data) {
return $data;
} else {
+ $data['metadata'] = $metadataQuery->extractMetadata($data)->asArray();
return self::cacheEntryFromData($data, $this->mimetypeLoader);
}
}
@@ -239,11 +203,14 @@ class Cache implements ICache {
->whereParent($fileId)
->orderBy('name', 'ASC');
+ $metadataQuery = $query->selectMetadata();
+
$result = $query->execute();
$files = $result->fetchAll();
$result->closeCursor();
- return array_map(function (array $data) {
+ return array_map(function (array $data) use ($metadataQuery) {
+ $data['metadata'] = $metadataQuery->extractMetadata($data)->asArray();
return self::cacheEntryFromData($data, $this->mimetypeLoader);
}, $files);
}
@@ -447,7 +414,7 @@ class Cache implements ICache {
$params = [];
$extensionParams = [];
foreach ($data as $name => $value) {
- if (array_search($name, $fields) !== false) {
+ if (in_array($name, $fields)) {
if ($name === 'path') {
$params['path_hash'] = md5($value);
} elseif ($name === 'mimetype') {
@@ -467,7 +434,7 @@ class Cache implements ICache {
}
$params[$name] = $value;
}
- if (array_search($name, $extensionFields) !== false) {
+ if (in_array($name, $extensionFields)) {
$extensionParams[$name] = $value;
}
}
@@ -586,8 +553,13 @@ class Cache implements ICache {
return $cacheEntry->getPath();
}, $children);
- $deletedIds = array_merge($deletedIds, $childIds);
- $deletedPaths = array_merge($deletedPaths, $childPaths);
+ foreach ($childIds as $childId) {
+ $deletedIds[] = $childId;
+ }
+
+ foreach ($childPaths as $childPath) {
+ $deletedPaths[] = $childPath;
+ }
$query = $this->getQueryBuilder();
$query->delete('filecache_extended')
@@ -599,9 +571,12 @@ class Cache implements ICache {
}
/** @var ICacheEntry[] $childFolders */
- $childFolders = array_filter($children, function ($child) {
- return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
- });
+ $childFolders = [];
+ foreach ($children as $child) {
+ if ($child->getMimeType() == FileInfo::MIMETYPE_FOLDER) {
+ $childFolders[] = $child;
+ }
+ }
foreach ($childFolders as $folder) {
$parentIds[] = $folder->getId();
$queue[] = $folder->getId();
@@ -612,6 +587,9 @@ class Cache implements ICache {
$query->delete('filecache')
->whereParentInParameter('parentIds');
+ // Sorting before chunking allows the db to find the entries close to each
+ // other in the index
+ sort($parentIds, SORT_NUMERIC);
foreach (array_chunk($parentIds, 1000) as $parentIdChunk) {
$query->setParameter('parentIds', $parentIdChunk, IQueryBuilder::PARAM_INT_ARRAY);
$query->execute();
@@ -685,7 +663,6 @@ class Cache implements ICache {
throw new \Exception('Invalid target storage id: ' . $targetStorageId);
}
- $this->connection->beginTransaction();
if ($sourceData['mimetype'] === 'httpd/unix-directory') {
//update all child entries
$sourceLength = mb_strlen($sourcePath);
@@ -708,12 +685,31 @@ class Cache implements ICache {
$query->set('encrypted', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT));
}
- try {
- $query->execute();
- } catch (\OC\DatabaseException $e) {
- $this->connection->rollBack();
- throw $e;
+ // Retry transaction in case of RetryableException like deadlocks.
+ // Retry up to 4 times because we should receive up to 4 concurrent requests from the frontend
+ $retryLimit = 4;
+ for ($i = 1; $i <= $retryLimit; $i++) {
+ try {
+ $this->connection->beginTransaction();
+ $query->executeStatement();
+ break;
+ } catch (\OC\DatabaseException $e) {
+ $this->connection->rollBack();
+ throw $e;
+ } catch (RetryableException $e) {
+ // Simply throw if we already retried 4 times.
+ if ($i === $retryLimit) {
+ throw $e;
+ }
+
+ $this->connection->rollBack();
+
+ // Sleep a bit to give some time to the other transaction to finish.
+ usleep(100 * 1000 * $i);
+ }
}
+ } else {
+ $this->connection->beginTransaction();
}
$query = $this->getQueryBuilder();
diff --git a/lib/private/Files/Cache/CacheDependencies.php b/lib/private/Files/Cache/CacheDependencies.php
new file mode 100644
index 00000000000..61d2a2f9646
--- /dev/null
+++ b/lib/private/Files/Cache/CacheDependencies.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Cache;
+
+use OC\SystemConfig;
+use OC\User\DisplayNameCache;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\IMimeTypeLoader;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use OCP\IDBConnection;
+use Psr\Log\LoggerInterface;
+
+class CacheDependencies {
+ public function __construct(
+ private IMimeTypeLoader $mimeTypeLoader,
+ private IDBConnection $connection,
+ private IEventDispatcher $eventDispatcher,
+ private QuerySearchHelper $querySearchHelper,
+ private SystemConfig $systemConfig,
+ private LoggerInterface $logger,
+ private IFilesMetadataManager $metadataManager,
+ private DisplayNameCache $displayNameCache,
+ ) {
+ }
+
+ public function getMimeTypeLoader(): IMimeTypeLoader {
+ return $this->mimeTypeLoader;
+ }
+
+ public function getConnection(): IDBConnection {
+ return $this->connection;
+ }
+
+ public function getEventDispatcher(): IEventDispatcher {
+ return $this->eventDispatcher;
+ }
+
+ public function getQuerySearchHelper(): QuerySearchHelper {
+ return $this->querySearchHelper;
+ }
+
+ public function getSystemConfig(): SystemConfig {
+ return $this->systemConfig;
+ }
+
+ public function getLogger(): LoggerInterface {
+ return $this->logger;
+ }
+
+ public function getDisplayNameCache(): DisplayNameCache {
+ return $this->displayNameCache;
+ }
+
+ public function getMetadataManager(): IFilesMetadataManager {
+ return $this->metadataManager;
+ }
+}
diff --git a/lib/private/Files/Cache/CacheEntry.php b/lib/private/Files/Cache/CacheEntry.php
index ce9df2823c8..e9417c8012a 100644
--- a/lib/private/Files/Cache/CacheEntry.php
+++ b/lib/private/Files/Cache/CacheEntry.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
@@ -134,7 +119,7 @@ class CacheEntry implements ICacheEntry {
}
public function getUnencryptedSize(): int {
- if (isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
+ if ($this->data['encrypted'] && isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
return $this->data['unencrypted_size'];
} else {
return $this->data['size'] ?? 0;
diff --git a/lib/private/Files/Cache/CacheQueryBuilder.php b/lib/private/Files/Cache/CacheQueryBuilder.php
index 34d2177b84e..9bf5f970458 100644
--- a/lib/private/Files/Cache/CacheQueryBuilder.php
+++ b/lib/private/Files/Cache/CacheQueryBuilder.php
@@ -3,31 +3,16 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache;
use OC\DB\QueryBuilder\QueryBuilder;
use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use OCP\FilesMetadata\IMetadataQuery;
use OCP\IDBConnection;
use Psr\Log\LoggerInterface;
@@ -35,9 +20,14 @@ use Psr\Log\LoggerInterface;
* Query builder with commonly used helpers for filecache queries
*/
class CacheQueryBuilder extends QueryBuilder {
- private $alias = null;
-
- public function __construct(IDBConnection $connection, SystemConfig $systemConfig, LoggerInterface $logger) {
+ private ?string $alias = null;
+
+ public function __construct(
+ IDBConnection $connection,
+ SystemConfig $systemConfig,
+ LoggerInterface $logger,
+ private IFilesMetadataManager $filesMetadataManager,
+ ) {
parent::__construct($connection, $systemConfig, $logger);
}
@@ -60,10 +50,10 @@ class CacheQueryBuilder extends QueryBuilder {
return $this;
}
- public function selectFileCache(string $alias = null, bool $joinExtendedCache = true) {
+ public function selectFileCache(?string $alias = null, bool $joinExtendedCache = true) {
$name = $alias ?: 'filecache';
$this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", "$name.name", 'mimetype', 'mimepart', 'size', 'mtime',
- 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'unencrypted_size')
+ 'storage_mtime', 'encrypted', 'etag', "$name.permissions", 'checksum', 'unencrypted_size')
->from('filecache', $name);
if ($joinExtendedCache) {
@@ -126,4 +116,15 @@ class CacheQueryBuilder extends QueryBuilder {
return $this;
}
+
+ /**
+ * join metadata to current query builder and returns an helper
+ *
+ * @return IMetadataQuery
+ */
+ public function selectMetadata(): IMetadataQuery {
+ $metadataQuery = $this->filesMetadataManager->getMetadataQuery($this, $this->alias, 'fileid');
+ $metadataQuery->retrieveMetadata();
+ return $metadataQuery;
+ }
}
diff --git a/lib/private/Files/Cache/FailedCache.php b/lib/private/Files/Cache/FailedCache.php
index d60e09ea329..8ba2ac491bf 100644
--- a/lib/private/Files/Cache/FailedCache.php
+++ b/lib/private/Files/Cache/FailedCache.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/FileAccess.php b/lib/private/Files/Cache/FileAccess.php
new file mode 100644
index 00000000000..5818017bd66
--- /dev/null
+++ b/lib/private/Files/Cache/FileAccess.php
@@ -0,0 +1,99 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Cache;
+
+use OC\FilesMetadata\FilesMetadataManager;
+use OC\SystemConfig;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Files\Cache\IFileAccess;
+use OCP\Files\IMimeTypeLoader;
+use OCP\IDBConnection;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Low level access to the file cache
+ */
+class FileAccess implements IFileAccess {
+ public function __construct(
+ private IDBConnection $connection,
+ private SystemConfig $systemConfig,
+ private LoggerInterface $logger,
+ private FilesMetadataManager $metadataManager,
+ private IMimeTypeLoader $mimeTypeLoader,
+ ) {
+ }
+
+ private function getQuery(): CacheQueryBuilder {
+ return new CacheQueryBuilder(
+ $this->connection,
+ $this->systemConfig,
+ $this->logger,
+ $this->metadataManager,
+ );
+ }
+
+ public function getByFileIdInStorage(int $fileId, int $storageId): ?CacheEntry {
+ $items = array_values($this->getByFileIdsInStorage([$fileId], $storageId));
+ return $items[0] ?? null;
+ }
+
+ public function getByPathInStorage(string $path, int $storageId): ?CacheEntry {
+ $query = $this->getQuery()->selectFileCache();
+ $query->andWhere($query->expr()->eq('filecache.path_hash', $query->createNamedParameter(md5($path))));
+ $query->andWhere($query->expr()->eq('filecache.storage', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
+
+ $row = $query->executeQuery()->fetch();
+ return $row ? Cache::cacheEntryFromData($row, $this->mimeTypeLoader) : null;
+ }
+
+ public function getByFileId(int $fileId): ?CacheEntry {
+ $items = array_values($this->getByFileIds([$fileId]));
+ return $items[0] ?? null;
+ }
+
+ /**
+ * @param array[] $rows
+ * @return array<int, CacheEntry>
+ */
+ private function rowsToEntries(array $rows): array {
+ $result = [];
+ foreach ($rows as $row) {
+ $entry = Cache::cacheEntryFromData($row, $this->mimeTypeLoader);
+ $result[$entry->getId()] = $entry;
+ }
+ return $result;
+ }
+
+ /**
+ * @param int[] $fileIds
+ * @return array<int, CacheEntry>
+ */
+ public function getByFileIds(array $fileIds): array {
+ $query = $this->getQuery()->selectFileCache();
+ $query->andWhere($query->expr()->in('filecache.fileid', $query->createNamedParameter($fileIds, IQueryBuilder::PARAM_INT_ARRAY)));
+
+ $rows = $query->executeQuery()->fetchAll();
+ return $this->rowsToEntries($rows);
+ }
+
+ /**
+ * @param int[] $fileIds
+ * @param int $storageId
+ * @return array<int, CacheEntry>
+ */
+ public function getByFileIdsInStorage(array $fileIds, int $storageId): array {
+ $fileIds = array_values($fileIds);
+ $query = $this->getQuery()->selectFileCache();
+ $query->andWhere($query->expr()->in('filecache.fileid', $query->createNamedParameter($fileIds, IQueryBuilder::PARAM_INT_ARRAY)));
+ $query->andWhere($query->expr()->eq('filecache.storage', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
+
+ $rows = $query->executeQuery()->fetchAll();
+ return $this->rowsToEntries($rows);
+ }
+}
diff --git a/lib/private/Files/Cache/HomeCache.php b/lib/private/Files/Cache/HomeCache.php
index 83e5cb89b8a..248cdc818f0 100644
--- a/lib/private/Files/Cache/HomeCache.php
+++ b/lib/private/Files/Cache/HomeCache.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/HomePropagator.php b/lib/private/Files/Cache/HomePropagator.php
index 6dba09d756b..d4ac8a7c8e3 100644
--- a/lib/private/Files/Cache/HomePropagator.php
+++ b/lib/private/Files/Cache/HomePropagator.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/LocalRootScanner.php b/lib/private/Files/Cache/LocalRootScanner.php
index df5ddd0075b..3f4f70b865b 100644
--- a/lib/private/Files/Cache/LocalRootScanner.php
+++ b/lib/private/Files/Cache/LocalRootScanner.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/MoveFromCacheTrait.php b/lib/private/Files/Cache/MoveFromCacheTrait.php
index 77cd7ea6d8c..db35c6bb7f8 100644
--- a/lib/private/Files/Cache/MoveFromCacheTrait.php
+++ b/lib/private/Files/Cache/MoveFromCacheTrait.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/NullWatcher.php b/lib/private/Files/Cache/NullWatcher.php
index 2e83c1006bb..e3659214849 100644
--- a/lib/private/Files/Cache/NullWatcher.php
+++ b/lib/private/Files/Cache/NullWatcher.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/Propagator.php b/lib/private/Files/Cache/Propagator.php
index 327d0d80bf2..5580dcf22a8 100644
--- a/lib/private/Files/Cache/Propagator.php
+++ b/lib/private/Files/Cache/Propagator.php
@@ -1,27 +1,10 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Cache;
use OC\DB\Exceptions\DbalException;
diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php
index 15c089a0f11..c31d62e1a86 100644
--- a/lib/private/Files/Cache/QuerySearchHelper.php
+++ b/lib/private/Files/Cache/QuerySearchHelper.php
@@ -1,27 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tobias Kaminsky <tobias@kaminsky.me>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache;
@@ -37,52 +17,47 @@ use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchQuery;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use OCP\FilesMetadata\IMetadataQuery;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IUser;
use Psr\Log\LoggerInterface;
class QuerySearchHelper {
- /** @var IMimeTypeLoader */
- private $mimetypeLoader;
- /** @var IDBConnection */
- private $connection;
- /** @var SystemConfig */
- private $systemConfig;
- private LoggerInterface $logger;
- /** @var SearchBuilder */
- private $searchBuilder;
- /** @var QueryOptimizer */
- private $queryOptimizer;
- private IGroupManager $groupManager;
-
public function __construct(
- IMimeTypeLoader $mimetypeLoader,
- IDBConnection $connection,
- SystemConfig $systemConfig,
- LoggerInterface $logger,
- SearchBuilder $searchBuilder,
- QueryOptimizer $queryOptimizer,
- IGroupManager $groupManager,
+ private IMimeTypeLoader $mimetypeLoader,
+ private IDBConnection $connection,
+ private SystemConfig $systemConfig,
+ private LoggerInterface $logger,
+ private SearchBuilder $searchBuilder,
+ private QueryOptimizer $queryOptimizer,
+ private IGroupManager $groupManager,
+ private IFilesMetadataManager $filesMetadataManager,
) {
- $this->mimetypeLoader = $mimetypeLoader;
- $this->connection = $connection;
- $this->systemConfig = $systemConfig;
- $this->logger = $logger;
- $this->searchBuilder = $searchBuilder;
- $this->queryOptimizer = $queryOptimizer;
- $this->groupManager = $groupManager;
}
protected function getQueryBuilder() {
return new CacheQueryBuilder(
$this->connection,
$this->systemConfig,
- $this->logger
+ $this->logger,
+ $this->filesMetadataManager,
);
}
- protected function applySearchConstraints(CacheQueryBuilder $query, ISearchQuery $searchQuery, array $caches): void {
+ /**
+ * @param CacheQueryBuilder $query
+ * @param ISearchQuery $searchQuery
+ * @param array $caches
+ * @param IMetadataQuery|null $metadataQuery
+ */
+ protected function applySearchConstraints(
+ CacheQueryBuilder $query,
+ ISearchQuery $searchQuery,
+ array $caches,
+ ?IMetadataQuery $metadataQuery = null
+ ): void {
$storageFilters = array_values(array_map(function (ICache $cache) {
return $cache->getQueryFilterForStorage();
}, $caches));
@@ -90,12 +65,12 @@ class QuerySearchHelper {
$filter = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [$searchQuery->getSearchOperation(), $storageFilter]);
$this->queryOptimizer->processOperator($filter);
- $searchExpr = $this->searchBuilder->searchOperatorToDBExpr($query, $filter);
+ $searchExpr = $this->searchBuilder->searchOperatorToDBExpr($query, $filter, $metadataQuery);
if ($searchExpr) {
$query->andWhere($searchExpr);
}
- $this->searchBuilder->addSearchOrdersToQuery($query, $searchQuery->getOrder());
+ $this->searchBuilder->addSearchOrdersToQuery($query, $searchQuery->getOrder(), $metadataQuery);
if ($searchQuery->getLimit()) {
$query->setMaxResults($searchQuery->getLimit());
@@ -144,6 +119,11 @@ class QuerySearchHelper {
));
}
+
+ protected function equipQueryForShares(CacheQueryBuilder $query): void {
+ $query->join('file', 'share', 's', $query->expr()->eq('file.fileid', 's.file_source'));
+ }
+
/**
* Perform a file system search in multiple caches
*
@@ -175,19 +155,26 @@ class QuerySearchHelper {
$query = $builder->selectFileCache('file', false);
$requestedFields = $this->searchBuilder->extractRequestedFields($searchQuery->getSearchOperation());
+
if (in_array('systemtag', $requestedFields)) {
$this->equipQueryForSystemTags($query, $this->requireUser($searchQuery));
}
if (in_array('tagname', $requestedFields) || in_array('favorite', $requestedFields)) {
$this->equipQueryForDavTags($query, $this->requireUser($searchQuery));
}
+ if (in_array('owner', $requestedFields) || in_array('share_with', $requestedFields) || in_array('share_type', $requestedFields)) {
+ $this->equipQueryForShares($query);
+ }
- $this->applySearchConstraints($query, $searchQuery, $caches);
+ $metadataQuery = $query->selectMetadata();
+
+ $this->applySearchConstraints($query, $searchQuery, $caches, $metadataQuery);
$result = $query->execute();
$files = $result->fetchAll();
- $rawEntries = array_map(function (array $data) {
+ $rawEntries = array_map(function (array $data) use ($metadataQuery) {
+ $data['metadata'] = $metadataQuery->extractMetadata($data)->asArray();
return Cache::cacheEntryFromData($data, $this->mimetypeLoader);
}, $files);
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php
index 52268032409..c44fc6fbd3d 100644
--- a/lib/private/Files/Cache/Scanner.php
+++ b/lib/private/Files/Cache/Scanner.php
@@ -1,50 +1,22 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Ari Selseng <ari@selseng.net>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Jagszent <daniel@jagszent.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Martin Mattel <martin.mattel@diemattels.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Owen Winkler <a_github@midnightcircus.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
use Doctrine\DBAL\Exception;
use OC\Files\Storage\Wrapper\Encryption;
+use OC\Files\Storage\Wrapper\Jail;
+use OC\Hooks\BasicEmitter;
use OCP\Files\Cache\IScanner;
use OCP\Files\ForbiddenException;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IReliableEtagStorage;
use OCP\IDBConnection;
use OCP\Lock\ILockingProvider;
-use OC\Files\Storage\Wrapper\Jail;
-use OC\Hooks\BasicEmitter;
use Psr\Log\LoggerInterface;
/**
@@ -96,7 +68,7 @@ class Scanner extends BasicEmitter implements IScanner {
$this->storageId = $this->storage->getId();
$this->cache = $storage->getCache();
$this->cacheActive = !\OC::$server->getConfig()->getSystemValueBool('filesystem_cache_readonly', false);
- $this->lockingProvider = \OC::$server->getLockingProvider();
+ $this->lockingProvider = \OC::$server->get(ILockingProvider::class);
$this->connection = \OC::$server->get(IDBConnection::class);
}
@@ -203,7 +175,9 @@ class Scanner extends BasicEmitter implements IScanner {
$fileId = $cacheData['fileid'];
$data['fileid'] = $fileId;
// only reuse data if the file hasn't explicitly changed
- if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) {
+ $mtimeUnchanged = isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime'];
+ // if the folder is marked as unscanned, never reuse etags
+ if ($mtimeUnchanged && $cacheData['size'] !== -1) {
$data['mtime'] = $cacheData['mtime'];
if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
$data['size'] = $cacheData['size'];
@@ -219,7 +193,13 @@ class Scanner extends BasicEmitter implements IScanner {
}
// Only update metadata that has changed
- $newData = array_diff_assoc($data, $cacheData->getData());
+ // i.e. get all the values in $data that are not present in the cache already
+ $newData = $this->array_diff_assoc_multi($data, $cacheData->getData());
+
+ // make it known to the caller that etag has been changed and needs propagation
+ if (isset($newData['etag'])) {
+ $data['etag_changed'] = true;
+ }
} else {
// we only updated unencrypted_size if it's already set
unset($data['unencrypted_size']);
@@ -363,6 +343,50 @@ class Scanner extends BasicEmitter implements IScanner {
}
/**
+ * Compares $array1 against $array2 and returns all the values in $array1 that are not in $array2
+ * Note this is a one-way check - i.e. we don't care about things that are in $array2 that aren't in $array1
+ *
+ * Supports multi-dimensional arrays
+ * Also checks keys/indexes
+ * Comparisons are strict just like array_diff_assoc
+ * Order of keys/values does not matter
+ *
+ * @param array $array1
+ * @param array $array2
+ * @return array with the differences between $array1 and $array1
+ * @throws \InvalidArgumentException if $array1 isn't an actual array
+ *
+ */
+ protected function array_diff_assoc_multi(array $array1, array $array2) {
+
+ $result = [];
+
+ foreach ($array1 as $key => $value) {
+
+ // if $array2 doesn't have the same key, that's a result
+ if (!array_key_exists($key, $array2)) {
+ $result[$key] = $value;
+ continue;
+ }
+
+ // if $array2's value for the same key is different, that's a result
+ if ($array2[$key] !== $value && !is_array($value)) {
+ $result[$key] = $value;
+ continue;
+ }
+
+ if (is_array($value)) {
+ $nestedDiff = $this->array_diff_assoc_multi($value, $array2[$key]);
+ if (!empty($nestedDiff)) {
+ $result[$key] = $nestedDiff;
+ continue;
+ }
+ }
+ }
+ return $result;
+ }
+
+ /**
* Get the children currently in the cache
*
* @param int $folderId
@@ -385,19 +409,23 @@ class Scanner extends BasicEmitter implements IScanner {
* @param int $reuse a combination of self::REUSE_*
* @param int $folderId id for the folder to be scanned
* @param bool $lock set to false to disable getting an additional read lock during scanning
- * @param int $oldSize the size of the folder before (re)scanning the children
+ * @param int|float $oldSize the size of the folder before (re)scanning the children
* @return int|float the size of the scanned folder or -1 if the size is unknown at this stage
*/
- protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int $oldSize) {
+ protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize, &$etagChanged = false) {
if ($reuse === -1) {
$reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG;
}
$this->emit('\OC\Files\Cache\Scanner', 'scanFolder', [$path, $this->storageId]);
$size = 0;
- $childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size);
+ $childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size, $etagChanged);
foreach ($childQueue as $child => [$childId, $childSize]) {
- $childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock, $childSize);
+ // "etag changed" propagates up, but not down, so we pass `false` to the children even if we already know that the etag of the current folder changed
+ $childEtagChanged = false;
+ $childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock, $childSize, $childEtagChanged);
+ $etagChanged |= $childEtagChanged;
+
if ($childSize === -1) {
$size = -1;
} elseif ($size !== -1) {
@@ -410,15 +438,27 @@ class Scanner extends BasicEmitter implements IScanner {
if ($this->storage->instanceOfStorage(Encryption::class)) {
$this->cache->calculateFolderSize($path);
} else {
- if ($this->cacheActive && $oldSize !== $size) {
- $this->cache->update($folderId, ['size' => $size]);
+ if ($this->cacheActive) {
+ $updatedData = [];
+ if ($oldSize !== $size) {
+ $updatedData['size'] = $size;
+ }
+ if ($etagChanged) {
+ $updatedData['etag'] = uniqid();
+ }
+ if ($updatedData) {
+ $this->cache->update($folderId, $updatedData);
+ }
}
}
$this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', [$path, $this->storageId]);
return $size;
}
- private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$size) {
+ /**
+ * @param bool|IScanner::SCAN_RECURSIVE_INCOMPLETE $recursive
+ */
+ private function handleChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float &$size, bool &$etagChanged): array {
// we put this in it's own function so it cleans up the memory before we start recursing
$existingChildren = $this->getExistingChildren($folderId);
$newChildren = iterator_to_array($this->storage->getDirectoryContent($path));
@@ -436,7 +476,7 @@ class Scanner extends BasicEmitter implements IScanner {
$childQueue = [];
$newChildNames = [];
foreach ($newChildren as $fileMeta) {
- $permissions = isset($fileMeta['scan_permissions']) ? $fileMeta['scan_permissions'] : $fileMeta['permissions'];
+ $permissions = $fileMeta['scan_permissions'] ?? $fileMeta['permissions'];
if ($permissions === 0) {
continue;
}
@@ -453,7 +493,7 @@ class Scanner extends BasicEmitter implements IScanner {
$newChildNames[] = $file;
$child = $path ? $path . '/' . $file : $file;
try {
- $existingData = isset($existingChildren[$file]) ? $existingChildren[$file] : false;
+ $existingData = $existingChildren[$file] ?? false;
$data = $this->scanFile($child, $reuse, $folderId, $existingData, $lock, $fileMeta);
if ($data) {
if ($data['mimetype'] === 'httpd/unix-directory' && $recursive === self::SCAN_RECURSIVE) {
@@ -466,6 +506,10 @@ class Scanner extends BasicEmitter implements IScanner {
} elseif ($size !== -1) {
$size += $data['size'];
}
+
+ if (isset($data['etag_changed']) && $data['etag_changed']) {
+ $etagChanged = true;
+ }
}
} catch (Exception $ex) {
// might happen if inserting duplicate while a scanning
diff --git a/lib/private/Files/Cache/SearchBuilder.php b/lib/private/Files/Cache/SearchBuilder.php
index b9a70bbd39b..32502cb8258 100644
--- a/lib/private/Files/Cache/SearchBuilder.php
+++ b/lib/private/Files/Cache/SearchBuilder.php
@@ -1,27 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tobias Kaminsky <tobias@kaminsky.me>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache;
@@ -32,11 +12,16 @@ use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchOrder;
+use OCP\FilesMetadata\IMetadataQuery;
/**
* Tools for transforming search queries into database queries
+ *
+ * @psalm-import-type ParamSingleValue from ISearchComparison
+ * @psalm-import-type ParamValue from ISearchComparison
*/
class SearchBuilder {
+ /** @var array<string, string> */
protected static $searchOperatorMap = [
ISearchComparison::COMPARE_LIKE => 'iLike',
ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE => 'like',
@@ -45,8 +30,11 @@ class SearchBuilder {
ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte',
ISearchComparison::COMPARE_LESS_THAN => 'lt',
ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte',
+ ISearchComparison::COMPARE_DEFINED => 'isNotNull',
+ ISearchComparison::COMPARE_IN => 'in',
];
+ /** @var array<string, string> */
protected static $searchOperatorNegativeMap = [
ISearchComparison::COMPARE_LIKE => 'notLike',
ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE => 'notLike',
@@ -55,6 +43,39 @@ class SearchBuilder {
ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt',
ISearchComparison::COMPARE_LESS_THAN => 'gte',
ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'gt',
+ ISearchComparison::COMPARE_DEFINED => 'isNull',
+ ISearchComparison::COMPARE_IN => 'notIn',
+ ];
+
+ /** @var array<string, string> */
+ protected static $fieldTypes = [
+ 'mimetype' => 'string',
+ 'mtime' => 'integer',
+ 'name' => 'string',
+ 'path' => 'string',
+ 'size' => 'integer',
+ 'tagname' => 'string',
+ 'systemtag' => 'string',
+ 'favorite' => 'boolean',
+ 'fileid' => 'integer',
+ 'storage' => 'integer',
+ 'share_with' => 'string',
+ 'share_type' => 'integer',
+ 'owner' => 'string',
+ ];
+
+ /** @var array<string, int> */
+ protected static $paramTypeMap = [
+ 'string' => IQueryBuilder::PARAM_STR,
+ 'integer' => IQueryBuilder::PARAM_INT,
+ 'boolean' => IQueryBuilder::PARAM_BOOL,
+ ];
+
+ /** @var array<string, int> */
+ protected static $paramArrayTypeMap = [
+ 'string' => IQueryBuilder::PARAM_STR_ARRAY,
+ 'integer' => IQueryBuilder::PARAM_INT_ARRAY,
+ 'boolean' => IQueryBuilder::PARAM_INT_ARRAY,
];
public const TAG_FAVORITE = '_$!<Favorite>!$_';
@@ -76,7 +97,7 @@ class SearchBuilder {
return array_reduce($operator->getArguments(), function (array $fields, ISearchOperator $operator) {
return array_unique(array_merge($fields, $this->extractRequestedFields($operator)));
}, []);
- } elseif ($operator instanceof ISearchComparison) {
+ } elseif ($operator instanceof ISearchComparison && !$operator->getExtra()) {
return [$operator->getField()];
}
return [];
@@ -86,13 +107,21 @@ class SearchBuilder {
* @param IQueryBuilder $builder
* @param ISearchOperator[] $operators
*/
- public function searchOperatorArrayToDBExprArray(IQueryBuilder $builder, array $operators) {
- return array_filter(array_map(function ($operator) use ($builder) {
- return $this->searchOperatorToDBExpr($builder, $operator);
+ public function searchOperatorArrayToDBExprArray(
+ IQueryBuilder $builder,
+ array $operators,
+ ?IMetadataQuery $metadataQuery = null
+ ) {
+ return array_filter(array_map(function ($operator) use ($builder, $metadataQuery) {
+ return $this->searchOperatorToDBExpr($builder, $operator, $metadataQuery);
}, $operators));
}
- public function searchOperatorToDBExpr(IQueryBuilder $builder, ISearchOperator $operator) {
+ public function searchOperatorToDBExpr(
+ IQueryBuilder $builder,
+ ISearchOperator $operator,
+ ?IMetadataQuery $metadataQuery = null
+ ) {
$expr = $builder->expr();
if ($operator instanceof ISearchBinaryOperator) {
@@ -104,62 +133,99 @@ class SearchBuilder {
case ISearchBinaryOperator::OPERATOR_NOT:
$negativeOperator = $operator->getArguments()[0];
if ($negativeOperator instanceof ISearchComparison) {
- return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap);
+ return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap, $metadataQuery);
} else {
throw new \InvalidArgumentException('Binary operators inside "not" is not supported');
}
// no break
case ISearchBinaryOperator::OPERATOR_AND:
- return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
+ return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments(), $metadataQuery));
case ISearchBinaryOperator::OPERATOR_OR:
- return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
+ return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments(), $metadataQuery));
default:
throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType());
}
} elseif ($operator instanceof ISearchComparison) {
- return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap);
+ return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap, $metadataQuery);
} else {
throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator));
}
}
- private function searchComparisonToDBExpr(IQueryBuilder $builder, ISearchComparison $comparison, array $operatorMap) {
- $this->validateComparison($comparison);
+ private function searchComparisonToDBExpr(
+ IQueryBuilder $builder,
+ ISearchComparison $comparison,
+ array $operatorMap,
+ ?IMetadataQuery $metadataQuery = null
+ ) {
+ if ($comparison->getExtra()) {
+ [$field, $value, $type, $paramType] = $this->getExtraOperatorField($comparison, $metadataQuery);
+ } else {
+ [$field, $value, $type, $paramType] = $this->getOperatorFieldAndValue($comparison);
+ }
- [$field, $value, $type] = $this->getOperatorFieldAndValue($comparison);
if (isset($operatorMap[$type])) {
$queryOperator = $operatorMap[$type];
- return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value));
+ return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value, $paramType));
} else {
throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType());
}
}
- private function getOperatorFieldAndValue(ISearchComparison $operator) {
+ /**
+ * @param ISearchComparison $operator
+ * @return list{string, ParamValue, string, string}
+ */
+ private function getOperatorFieldAndValue(ISearchComparison $operator): array {
+ $this->validateComparison($operator);
$field = $operator->getField();
$value = $operator->getValue();
$type = $operator->getType();
+ $pathEqHash = $operator->getQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, true);
+ return $this->getOperatorFieldAndValueInner($field, $value, $type, $pathEqHash);
+ }
+
+ /**
+ * @param string $field
+ * @param ParamValue $value
+ * @param string $type
+ * @return list{string, ParamValue, string, string}
+ */
+ private function getOperatorFieldAndValueInner(string $field, mixed $value, string $type, bool $pathEqHash): array {
+ $paramType = self::$fieldTypes[$field];
+ if ($type === ISearchComparison::COMPARE_IN) {
+ $resultField = $field;
+ $values = [];
+ foreach ($value as $arrayValue) {
+ /** @var ParamSingleValue $arrayValue */
+ [$arrayField, $arrayValue] = $this->getOperatorFieldAndValueInner($field, $arrayValue, ISearchComparison::COMPARE_EQUAL, $pathEqHash);
+ $resultField = $arrayField;
+ $values[] = $arrayValue;
+ }
+ return [$resultField, $values, ISearchComparison::COMPARE_IN, $paramType];
+ }
if ($field === 'mimetype') {
$value = (string)$value;
- if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) {
- $value = (int)$this->mimetypeLoader->getId($value);
- } elseif ($operator->getType() === ISearchComparison::COMPARE_LIKE) {
+ if ($type === ISearchComparison::COMPARE_EQUAL) {
+ $value = $this->mimetypeLoader->getId($value);
+ } elseif ($type === ISearchComparison::COMPARE_LIKE) {
// transform "mimetype='foo/%'" to "mimepart='foo'"
if (preg_match('|(.+)/%|', $value, $matches)) {
$field = 'mimepart';
- $value = (int)$this->mimetypeLoader->getId($matches[1]);
+ $value = $this->mimetypeLoader->getId($matches[1]);
$type = ISearchComparison::COMPARE_EQUAL;
} elseif (str_contains($value, '%')) {
throw new \InvalidArgumentException('Unsupported query value for mimetype: ' . $value . ', only values in the format "mime/type" or "mime/%" are supported');
} else {
$field = 'mimetype';
- $value = (int)$this->mimetypeLoader->getId($value);
+ $value = $this->mimetypeLoader->getId($value);
$type = ISearchComparison::COMPARE_EQUAL;
}
}
} elseif ($field === 'favorite') {
$field = 'tag.category';
$value = self::TAG_FAVORITE;
+ $paramType = 'string';
} elseif ($field === 'name') {
$field = 'file.name';
} elseif ($field === 'tagname') {
@@ -168,59 +234,82 @@ class SearchBuilder {
$field = 'systemtag.name';
} elseif ($field === 'fileid') {
$field = 'file.fileid';
- } elseif ($field === 'path' && $type === ISearchComparison::COMPARE_EQUAL && $operator->getQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, true)) {
+ } elseif ($field === 'path' && $type === ISearchComparison::COMPARE_EQUAL && $pathEqHash) {
$field = 'path_hash';
$value = md5((string)$value);
+ } elseif ($field === 'owner') {
+ $field = 'uid_owner';
}
- return [$field, $value, $type];
+ return [$field, $value, $type, $paramType];
}
private function validateComparison(ISearchComparison $operator) {
- $types = [
- 'mimetype' => 'string',
- 'mtime' => 'integer',
- 'name' => 'string',
- 'path' => 'string',
- 'size' => 'integer',
- 'tagname' => 'string',
- 'systemtag' => 'string',
- 'favorite' => 'boolean',
- 'fileid' => 'integer',
- 'storage' => 'integer',
- ];
$comparisons = [
- 'mimetype' => ['eq', 'like'],
+ 'mimetype' => ['eq', 'like', 'in'],
'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'],
- 'name' => ['eq', 'like', 'clike'],
- 'path' => ['eq', 'like', 'clike'],
+ 'name' => ['eq', 'like', 'clike', 'in'],
+ 'path' => ['eq', 'like', 'clike', 'in'],
'size' => ['eq', 'gt', 'lt', 'gte', 'lte'],
'tagname' => ['eq', 'like'],
'systemtag' => ['eq', 'like'],
'favorite' => ['eq'],
- 'fileid' => ['eq'],
- 'storage' => ['eq'],
+ 'fileid' => ['eq', 'in'],
+ 'storage' => ['eq', 'in'],
+ 'share_with' => ['eq'],
+ 'share_type' => ['eq'],
+ 'owner' => ['eq'],
];
- if (!isset($types[$operator->getField()])) {
+ if (!isset(self::$fieldTypes[$operator->getField()])) {
throw new \InvalidArgumentException('Unsupported comparison field ' . $operator->getField());
}
- $type = $types[$operator->getField()];
- if (gettype($operator->getValue()) !== $type) {
- throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField());
+ $type = self::$fieldTypes[$operator->getField()];
+ if ($operator->getType() === ISearchComparison::COMPARE_IN) {
+ if (!is_array($operator->getValue())) {
+ throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField());
+ }
+ foreach ($operator->getValue() as $arrayValue) {
+ if (gettype($arrayValue) !== $type) {
+ throw new \InvalidArgumentException('Invalid type in array for field ' . $operator->getField());
+ }
+ }
+ } else {
+ if (gettype($operator->getValue()) !== $type) {
+ throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField());
+ }
}
if (!in_array($operator->getType(), $comparisons[$operator->getField()])) {
throw new \InvalidArgumentException('Unsupported comparison for field ' . $operator->getField() . ': ' . $operator->getType());
}
}
- private function getParameterForValue(IQueryBuilder $builder, $value) {
+
+ private function getExtraOperatorField(ISearchComparison $operator, IMetadataQuery $metadataQuery): array {
+ $paramType = self::$fieldTypes[$operator->getField()];
+ $field = $operator->getField();
+ $value = $operator->getValue();
+ $type = $operator->getType();
+
+ switch($operator->getExtra()) {
+ case IMetadataQuery::EXTRA:
+ $metadataQuery->joinIndex($field); // join index table if not joined yet
+ $field = $metadataQuery->getMetadataValueField($field);
+ break;
+ default:
+ throw new \InvalidArgumentException('Invalid extra type: ' . $operator->getExtra());
+ }
+
+ return [$field, $value, $type, $paramType];
+ }
+
+ private function getParameterForValue(IQueryBuilder $builder, $value, string $paramType) {
if ($value instanceof \DateTime) {
$value = $value->getTimestamp();
}
- if (is_numeric($value)) {
- $type = IQueryBuilder::PARAM_INT;
+ if (is_array($value)) {
+ $type = self::$paramArrayTypeMap[$paramType];
} else {
- $type = IQueryBuilder::PARAM_STR;
+ $type = self::$paramTypeMap[$paramType];
}
return $builder->createNamedParameter($value, $type);
}
@@ -228,24 +317,32 @@ class SearchBuilder {
/**
* @param IQueryBuilder $query
* @param ISearchOrder[] $orders
+ * @param IMetadataQuery|null $metadataQuery
*/
- public function addSearchOrdersToQuery(IQueryBuilder $query, array $orders) {
+ public function addSearchOrdersToQuery(IQueryBuilder $query, array $orders, ?IMetadataQuery $metadataQuery = null): void {
foreach ($orders as $order) {
$field = $order->getField();
- if ($field === 'fileid') {
- $field = 'file.fileid';
- }
+ switch ($order->getExtra()) {
+ case IMetadataQuery::EXTRA:
+ $metadataQuery->joinIndex($field); // join index table if not joined yet
+ $field = $metadataQuery->getMetadataValueField($order->getField());
+ break;
- // Mysql really likes to pick an index for sorting if it can't fully satisfy the where
- // filter with an index, since search queries pretty much never are fully filtered by index
- // mysql often picks an index for sorting instead of the much more useful index for filtering.
- //
- // By changing the order by to an expression, mysql isn't smart enough to see that it could still
- // use the index, so it instead picks an index for the filtering
- if ($field === 'mtime') {
- $field = $query->func()->add($field, $query->createNamedParameter(0));
- }
+ default:
+ if ($field === 'fileid') {
+ $field = 'file.fileid';
+ }
+ // Mysql really likes to pick an index for sorting if it can't fully satisfy the where
+ // filter with an index, since search queries pretty much never are fully filtered by index
+ // mysql often picks an index for sorting instead of the much more useful index for filtering.
+ //
+ // By changing the order by to an expression, mysql isn't smart enough to see that it could still
+ // use the index, so it instead picks an index for the filtering
+ if ($field === 'mtime') {
+ $field = $query->func()->add($field, $query->createNamedParameter(0));
+ }
+ }
$query->addOrderBy($field, $order->getDirection());
}
}
diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php
index 01fc638cef8..0929907fcff 100644
--- a/lib/private/Files/Cache/Storage.php
+++ b/lib/private/Files/Cache/Storage.php
@@ -1,36 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Storage\IStorage;
+use OCP\IDBConnection;
use Psr\Log\LoggerInterface;
/**
@@ -65,7 +44,7 @@ class Storage {
* @param bool $isAvailable
* @throws \RuntimeException
*/
- public function __construct($storage, $isAvailable = true) {
+ public function __construct($storage, $isAvailable, IDBConnection $connection) {
if ($storage instanceof IStorage) {
$this->storageId = $storage->getId();
} else {
@@ -76,7 +55,6 @@ class Storage {
if ($row = self::getStorageById($this->storageId)) {
$this->numericId = (int)$row['numeric_id'];
} else {
- $connection = \OC::$server->getDatabaseConnection();
$available = $isAvailable ? 1 : 0;
if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId, 'available' => $available])) {
$this->numericId = $connection->lastInsertId('*PREFIX*storages');
diff --git a/lib/private/Files/Cache/StorageGlobal.php b/lib/private/Files/Cache/StorageGlobal.php
index 74cbd5abdb2..b55c0fcdb91 100644
--- a/lib/private/Files/Cache/StorageGlobal.php
+++ b/lib/private/Files/Cache/StorageGlobal.php
@@ -1,25 +1,8 @@
<?php
+
/**
- * @copyright Robin Appelman <robin@icewind.nl>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache;
diff --git a/lib/private/Files/Cache/Updater.php b/lib/private/Files/Cache/Updater.php
index 457dd207e9d..e8c6d32599e 100644
--- a/lib/private/Files/Cache/Updater.php
+++ b/lib/private/Files/Cache/Updater.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Jagszent <daniel@jagszent.de>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
@@ -119,7 +99,7 @@ class Updater implements IUpdater {
* @param string $path
* @param int $time
*/
- public function update($path, $time = null) {
+ public function update($path, $time = null, ?int $sizeDifference = null) {
if (!$this->enabled or Scanner::isPartialFile($path)) {
return;
}
@@ -128,20 +108,22 @@ class Updater implements IUpdater {
}
$data = $this->scanner->scan($path, Scanner::SCAN_SHALLOW, -1, false);
- if (
- isset($data['oldSize']) && isset($data['size']) &&
- !$data['encrypted'] // encryption is a pita and touches the cache itself
- ) {
+
+ if (isset($data['oldSize']) && isset($data['size'])) {
$sizeDifference = $data['size'] - $data['oldSize'];
- } else {
- // scanner didn't provide size info, fallback to full size calculation
- $sizeDifference = 0;
- if ($this->cache instanceof Cache) {
- $this->cache->correctFolderSize($path, $data);
- }
+ }
+
+ // encryption is a pita and touches the cache itself
+ if (isset($data['encrypted']) && !!$data['encrypted']) {
+ $sizeDifference = null;
+ }
+
+ // scanner didn't provide size info, fallback to full size calculation
+ if ($this->cache instanceof Cache && $sizeDifference === null) {
+ $this->cache->correctFolderSize($path, $data);
}
$this->correctParentStorageMtime($path);
- $this->propagator->propagateChange($path, $time, $sizeDifference);
+ $this->propagator->propagateChange($path, $time, $sizeDifference ?? 0);
}
/**
diff --git a/lib/private/Files/Cache/Watcher.php b/lib/private/Files/Cache/Watcher.php
index acc76f263dc..2e42b716695 100644
--- a/lib/private/Files/Cache/Watcher.php
+++ b/lib/private/Files/Cache/Watcher.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Jagszent <daniel@jagszent.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache;
@@ -129,7 +110,7 @@ class Watcher implements IWatcher {
* @return bool
*/
public function needsUpdate($path, $cachedData) {
- if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and array_search($path, $this->checkedPaths) === false)) {
+ if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and !in_array($path, $this->checkedPaths))) {
$this->checkedPaths[] = $path;
return $this->storage->hasUpdated($path, $cachedData['storage_mtime']);
}
diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php
index d8cf3eb61d7..ea0f992114a 100644
--- a/lib/private/Files/Cache/Wrapper/CacheJail.php
+++ b/lib/private/Files/Cache/Wrapper/CacheJail.php
@@ -1,35 +1,17 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Jagszent <daniel@jagszent.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache\Wrapper;
use OC\Files\Cache\Cache;
+use OC\Files\Cache\CacheDependencies;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
+use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
@@ -45,15 +27,13 @@ class CacheJail extends CacheWrapper {
protected $root;
protected $unjailedRoot;
- /**
- * @param ?\OCP\Files\Cache\ICache $cache
- * @param string $root
- */
- public function __construct($cache, $root) {
- parent::__construct($cache);
+ public function __construct(
+ ?ICache $cache,
+ string $root,
+ ?CacheDependencies $dependencies = null,
+ ) {
+ parent::__construct($cache, $dependencies);
$this->root = $root;
- $this->connection = \OC::$server->getDatabaseConnection();
- $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
if ($cache instanceof CacheJail) {
$this->unjailedRoot = $cache->getSourcePath($root);
@@ -88,7 +68,7 @@ class CacheJail extends CacheWrapper {
* @param null|string $root
* @return null|string the jailed path or null if the path is outside the jail
*/
- protected function getJailedPath(string $path, string $root = null) {
+ protected function getJailedPath(string $path, ?string $root = null) {
if ($root === null) {
$root = $this->getRoot();
}
diff --git a/lib/private/Files/Cache/Wrapper/CachePermissionsMask.php b/lib/private/Files/Cache/Wrapper/CachePermissionsMask.php
index cbf16a909ff..ff17cb79ac7 100644
--- a/lib/private/Files/Cache/Wrapper/CachePermissionsMask.php
+++ b/lib/private/Files/Cache/Wrapper/CachePermissionsMask.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache\Wrapper;
diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php
index 39a78f31343..17f1031d1cc 100644
--- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php
+++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php
@@ -1,62 +1,39 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Ari Selseng <ari@selseng.net>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Jagszent <daniel@jagszent.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Cache\Wrapper;
use OC\Files\Cache\Cache;
-use OC\Files\Cache\QuerySearchHelper;
+use OC\Files\Cache\CacheDependencies;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
-use OCP\Files\IMimeTypeLoader;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
-use OCP\IDBConnection;
+use OCP\Server;
class CacheWrapper extends Cache {
/**
- * @var \OCP\Files\Cache\ICache
+ * @var ?ICache
*/
protected $cache;
- /**
- * @param \OCP\Files\Cache\ICache $cache
- */
- public function __construct($cache) {
+ public function __construct(?ICache $cache, ?CacheDependencies $dependencies = null) {
$this->cache = $cache;
- if ($cache instanceof Cache) {
+ if (!$dependencies && $cache instanceof Cache) {
$this->mimetypeLoader = $cache->mimetypeLoader;
$this->connection = $cache->connection;
$this->querySearchHelper = $cache->querySearchHelper;
} else {
- $this->mimetypeLoader = \OC::$server->get(IMimeTypeLoader::class);
- $this->connection = \OC::$server->get(IDBConnection::class);
- $this->querySearchHelper = \OC::$server->get(QuerySearchHelper::class);
+ if (!$dependencies) {
+ $dependencies = Server::get(CacheDependencies::class);
+ }
+ $this->mimetypeLoader = $dependencies->getMimeTypeLoader();
+ $this->connection = $dependencies->getConnection();
+ $this->querySearchHelper = $dependencies->getQuerySearchHelper();
}
}
@@ -91,7 +68,7 @@ class CacheWrapper extends Cache {
*/
public function get($file) {
$result = $this->getCache()->get($file);
- if ($result) {
+ if ($result instanceof ICacheEntry) {
$result = $this->formatCacheEntry($result);
}
return $result;
diff --git a/lib/private/Files/Cache/Wrapper/JailPropagator.php b/lib/private/Files/Cache/Wrapper/JailPropagator.php
index 25e53ded39d..19ca4a13ece 100644
--- a/lib/private/Files/Cache/Wrapper/JailPropagator.php
+++ b/lib/private/Files/Cache/Wrapper/JailPropagator.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Cache\Wrapper;
diff --git a/lib/private/Files/Cache/Wrapper/JailWatcher.php b/lib/private/Files/Cache/Wrapper/JailWatcher.php
new file mode 100644
index 00000000000..9bd7da57233
--- /dev/null
+++ b/lib/private/Files/Cache/Wrapper/JailWatcher.php
@@ -0,0 +1,58 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Cache\Wrapper;
+
+use OC\Files\Cache\Watcher;
+
+class JailWatcher extends Watcher {
+ private string $root;
+ private Watcher $watcher;
+
+ public function __construct(Watcher $watcher, string $root) {
+ $this->watcher = $watcher;
+ $this->root = $root;
+ }
+
+ protected function getRoot(): string {
+ return $this->root;
+ }
+
+ protected function getSourcePath($path): string {
+ if ($path === '') {
+ return $this->getRoot();
+ } else {
+ return $this->getRoot() . '/' . ltrim($path, '/');
+ }
+ }
+
+ public function setPolicy($policy) {
+ $this->watcher->setPolicy($policy);
+ }
+
+ public function getPolicy() {
+ return $this->watcher->getPolicy();
+ }
+
+
+ public function checkUpdate($path, $cachedEntry = null) {
+ return $this->watcher->checkUpdate($this->getSourcePath($path), $cachedEntry);
+ }
+
+ public function update($path, $cachedData) {
+ $this->watcher->update($this->getSourcePath($path), $cachedData);
+ }
+
+ public function needsUpdate($path, $cachedData) {
+ return $this->watcher->needsUpdate($this->getSourcePath($path), $cachedData);
+ }
+
+ public function cleanFolder($path) {
+ $this->watcher->cleanFolder($this->getSourcePath($path));
+ }
+
+}
diff --git a/lib/private/Files/Config/CachedMountFileInfo.php b/lib/private/Files/Config/CachedMountFileInfo.php
index 11a9a505808..41dbec87ef5 100644
--- a/lib/private/Files/Config/CachedMountFileInfo.php
+++ b/lib/private/Files/Config/CachedMountFileInfo.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Config;
diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php
index 43c9fae63ec..80423dcae40 100644
--- a/lib/private/Files/Config/CachedMountInfo.php
+++ b/lib/private/Files/Config/CachedMountInfo.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Semih Serhat Karakaya <karakayasemi@itu.edu.tr>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Config;
@@ -35,6 +20,7 @@ class CachedMountInfo implements ICachedMountInfo {
protected ?int $mountId;
protected string $rootInternalPath;
protected string $mountProvider;
+ protected string $key;
/**
* CachedMountInfo constructor.
@@ -52,7 +38,7 @@ class CachedMountInfo implements ICachedMountInfo {
int $rootId,
string $mountPoint,
string $mountProvider,
- int $mountId = null,
+ ?int $mountId = null,
string $rootInternalPath = ''
) {
$this->user = $user;
@@ -65,6 +51,7 @@ class CachedMountInfo implements ICachedMountInfo {
throw new \Exception("Mount provider $mountProvider name exceeds the limit of 128 characters");
}
$this->mountProvider = $mountProvider;
+ $this->key = $rootId . '::' . $mountPoint;
}
/**
@@ -95,12 +82,7 @@ class CachedMountInfo implements ICachedMountInfo {
// TODO injection etc
Filesystem::initMountPoints($this->getUser()->getUID());
$userNode = \OC::$server->getUserFolder($this->getUser()->getUID());
- $nodes = $userNode->getParent()->getById($this->getRootId());
- if (count($nodes) > 0) {
- return $nodes[0];
- } else {
- return null;
- }
+ return $userNode->getParent()->getFirstNodeById($this->getRootId());
}
/**
@@ -132,4 +114,8 @@ class CachedMountInfo implements ICachedMountInfo {
public function getMountProvider(): string {
return $this->mountProvider;
}
+
+ public function getKey(): string {
+ return $this->key;
+ }
}
diff --git a/lib/private/Files/Config/LazyPathCachedMountInfo.php b/lib/private/Files/Config/LazyPathCachedMountInfo.php
new file mode 100644
index 00000000000..d2396109b1a
--- /dev/null
+++ b/lib/private/Files/Config/LazyPathCachedMountInfo.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Config;
+
+use OCP\IUser;
+
+class LazyPathCachedMountInfo extends CachedMountInfo {
+ // we don't allow \ in paths so it makes a great placeholder
+ private const PATH_PLACEHOLDER = '\\PLACEHOLDER\\';
+
+ /** @var callable(CachedMountInfo): string */
+ protected $rootInternalPathCallback;
+
+ /**
+ * @param IUser $user
+ * @param int $storageId
+ * @param int $rootId
+ * @param string $mountPoint
+ * @param string $mountProvider
+ * @param int|null $mountId
+ * @param callable(CachedMountInfo): string $rootInternalPathCallback
+ * @throws \Exception
+ */
+ public function __construct(
+ IUser $user,
+ int $storageId,
+ int $rootId,
+ string $mountPoint,
+ string $mountProvider,
+ ?int $mountId,
+ callable $rootInternalPathCallback,
+ ) {
+ parent::__construct($user, $storageId, $rootId, $mountPoint, $mountProvider, $mountId, self::PATH_PLACEHOLDER);
+ $this->rootInternalPathCallback = $rootInternalPathCallback;
+ }
+
+ public function getRootInternalPath(): string {
+ if ($this->rootInternalPath === self::PATH_PLACEHOLDER) {
+ $this->rootInternalPath = ($this->rootInternalPathCallback)($this);
+ }
+ return $this->rootInternalPath;
+ }
+}
diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php
index 78055a2cdb8..eb2c60dfa46 100644
--- a/lib/private/Files/Config/LazyStorageMountInfo.php
+++ b/lib/private/Files/Config/LazyStorageMountInfo.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Config;
@@ -39,6 +25,7 @@ class LazyStorageMountInfo extends CachedMountInfo {
$this->rootId = 0;
$this->storageId = 0;
$this->mountPoint = '';
+ $this->key = '';
}
/**
@@ -87,4 +74,11 @@ class LazyStorageMountInfo extends CachedMountInfo {
public function getMountProvider(): string {
return $this->mount->getMountProvider();
}
+
+ public function getKey(): string {
+ if (!$this->key) {
+ $this->key = $this->getRootId() . '::' . $this->getMountPoint();
+ }
+ return $this->key;
+ }
}
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index ae6481e45bb..0e103690b6b 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Config;
@@ -119,7 +102,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
return $this->getUserMountsForProviders($user, $providers);
}
- public function addMountForUser(IUser $user, IMountManager $mountManager, callable $providerFilter = null) {
+ public function addMountForUser(IUser $user, IMountManager $mountManager, ?callable $providerFilter = null) {
// shared mount provider gets to go last since it needs to know existing files
// to check for name collisions
$firstMounts = [];
@@ -238,6 +221,11 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
return array_merge($mounts, $providerMounts);
}, []);
+
+ if (count($mounts) === 0) {
+ throw new \Exception("No root mounts provided by any provider");
+ }
+
return $mounts;
}
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index 90f94b6598e..0afdf9cdcc2 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -1,41 +1,19 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Dariusz Olszewski <starypatyk@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Config;
+use OC\User\LazyUser;
use OCP\Cache\CappedMemoryCache;
-use OCA\Files_Sharing\SharedMount;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Diagnostics\IEventLogger;
use OCP\Files\Config\ICachedMountFileInfo;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IUserMountCache;
-use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
use OCP\IUser;
@@ -54,6 +32,11 @@ class UserMountCache implements IUserMountCache {
* @var CappedMemoryCache<ICachedMountInfo[]>
**/
private CappedMemoryCache $mountsForUsers;
+ /**
+ * fileid => internal path mapping for cached mount info.
+ * @var CappedMemoryCache<string>
+ **/
+ private CappedMemoryCache $internalPathCache;
private LoggerInterface $logger;
/** @var CappedMemoryCache<array> */
private CappedMemoryCache $cacheInfoCache;
@@ -73,46 +56,33 @@ class UserMountCache implements IUserMountCache {
$this->logger = $logger;
$this->eventLogger = $eventLogger;
$this->cacheInfoCache = new CappedMemoryCache();
+ $this->internalPathCache = new CappedMemoryCache();
$this->mountsForUsers = new CappedMemoryCache();
}
- public function registerMounts(IUser $user, array $mounts, array $mountProviderClasses = null) {
+ public function registerMounts(IUser $user, array $mounts, ?array $mountProviderClasses = null) {
$this->eventLogger->start('fs:setup:user:register', 'Registering mounts for user');
- // filter out non-proper storages coming from unit tests
- $mounts = array_filter($mounts, function (IMountPoint $mount) {
- return $mount instanceof SharedMount || ($mount->getStorage() && $mount->getStorage()->getCache());
- });
- /** @var ICachedMountInfo[] $newMounts */
- $newMounts = array_map(function (IMountPoint $mount) use ($user) {
+ /** @var array<string, ICachedMountInfo> $newMounts */
+ $newMounts = [];
+ foreach ($mounts as $mount) {
// filter out any storages which aren't scanned yet since we aren't interested in files from those storages (yet)
- if ($mount->getStorageRootId() === -1) {
- return null;
- } else {
- return new LazyStorageMountInfo($user, $mount);
+ if ($mount->getStorageRootId() !== -1) {
+ $mountInfo = new LazyStorageMountInfo($user, $mount);
+ $newMounts[$mountInfo->getKey()] = $mountInfo;
}
- }, $mounts);
- $newMounts = array_values(array_filter($newMounts));
- $newMountKeys = array_map(function (ICachedMountInfo $mount) {
- return $mount->getRootId() . '::' . $mount->getMountPoint();
- }, $newMounts);
- $newMounts = array_combine($newMountKeys, $newMounts);
+ }
$cachedMounts = $this->getMountsForUser($user);
if (is_array($mountProviderClasses)) {
$cachedMounts = array_filter($cachedMounts, function (ICachedMountInfo $mountInfo) use ($mountProviderClasses, $newMounts) {
// for existing mounts that didn't have a mount provider set
// we still want the ones that map to new mounts
- $mountKey = $mountInfo->getRootId() . '::' . $mountInfo->getMountPoint();
- if ($mountInfo->getMountProvider() === '' && isset($newMounts[$mountKey])) {
+ if ($mountInfo->getMountProvider() === '' && isset($newMounts[$mountInfo->getKey()])) {
return true;
}
return in_array($mountInfo->getMountProvider(), $mountProviderClasses);
});
}
- $cachedRootKeys = array_map(function (ICachedMountInfo $mount) {
- return $mount->getRootId() . '::' . $mount->getMountPoint();
- }, $cachedMounts);
- $cachedMounts = array_combine($cachedRootKeys, $cachedMounts);
$addedMounts = [];
$removedMounts = [];
@@ -131,46 +101,44 @@ class UserMountCache implements IUserMountCache {
$changedMounts = $this->findChangedMounts($newMounts, $cachedMounts);
- $this->connection->beginTransaction();
- try {
- foreach ($addedMounts as $mount) {
- $this->addToCache($mount);
- /** @psalm-suppress InvalidArgument */
- $this->mountsForUsers[$user->getUID()][] = $mount;
- }
- foreach ($removedMounts as $mount) {
- $this->removeFromCache($mount);
- $index = array_search($mount, $this->mountsForUsers[$user->getUID()]);
- unset($this->mountsForUsers[$user->getUID()][$index]);
- }
- foreach ($changedMounts as $mount) {
- $this->updateCachedMount($mount);
+ if ($addedMounts || $removedMounts || $changedMounts) {
+ $this->connection->beginTransaction();
+ $userUID = $user->getUID();
+ try {
+ foreach ($addedMounts as $mount) {
+ $this->addToCache($mount);
+ /** @psalm-suppress InvalidArgument */
+ $this->mountsForUsers[$userUID][$mount->getKey()] = $mount;
+ }
+ foreach ($removedMounts as $mount) {
+ $this->removeFromCache($mount);
+ unset($this->mountsForUsers[$userUID][$mount->getKey()]);
+ }
+ foreach ($changedMounts as $mount) {
+ $this->updateCachedMount($mount);
+ /** @psalm-suppress InvalidArgument */
+ $this->mountsForUsers[$userUID][$mount->getKey()] = $mount;
+ }
+ $this->connection->commit();
+ } catch (\Throwable $e) {
+ $this->connection->rollBack();
+ throw $e;
}
- $this->connection->commit();
- } catch (\Throwable $e) {
- $this->connection->rollBack();
- throw $e;
}
$this->eventLogger->end('fs:setup:user:register');
}
/**
- * @param ICachedMountInfo[] $newMounts
- * @param ICachedMountInfo[] $cachedMounts
+ * @param array<string, ICachedMountInfo> $newMounts
+ * @param array<string, ICachedMountInfo> $cachedMounts
* @return ICachedMountInfo[]
*/
private function findChangedMounts(array $newMounts, array $cachedMounts) {
- $new = [];
- foreach ($newMounts as $mount) {
- $new[$mount->getRootId() . '::' . $mount->getMountPoint()] = $mount;
- }
$changed = [];
- foreach ($cachedMounts as $cachedMount) {
- $key = $cachedMount->getRootId() . '::' . $cachedMount->getMountPoint();
- if (isset($new[$key])) {
- $newMount = $new[$key];
+ foreach ($cachedMounts as $key => $cachedMount) {
+ if (isset($newMounts[$key])) {
+ $newMount = $newMounts[$key];
if (
- $newMount->getMountPoint() !== $cachedMount->getMountPoint() ||
$newMount->getStorageId() !== $cachedMount->getStorageId() ||
$newMount->getMountId() !== $cachedMount->getMountId() ||
$newMount->getMountProvider() !== $cachedMount->getMountProvider()
@@ -222,24 +190,38 @@ class UserMountCache implements IUserMountCache {
$query->execute();
}
- private function dbRowToMountInfo(array $row) {
- $user = $this->userManager->get($row['user_id']);
- if (is_null($user)) {
- return null;
- }
+ /**
+ * @param array $row
+ * @param (callable(CachedMountInfo): string)|null $pathCallback
+ * @return CachedMountInfo
+ */
+ private function dbRowToMountInfo(array $row, ?callable $pathCallback = null): ICachedMountInfo {
+ $user = new LazyUser($row['user_id'], $this->userManager);
$mount_id = $row['mount_id'];
if (!is_null($mount_id)) {
$mount_id = (int)$mount_id;
}
- return new CachedMountInfo(
- $user,
- (int)$row['storage_id'],
- (int)$row['root_id'],
- $row['mount_point'],
- $row['mount_provider_class'] ?? '',
- $mount_id,
- isset($row['path']) ? $row['path'] : '',
- );
+ if ($pathCallback) {
+ return new LazyPathCachedMountInfo(
+ $user,
+ (int)$row['storage_id'],
+ (int)$row['root_id'],
+ $row['mount_point'],
+ $row['mount_provider_class'] ?? '',
+ $mount_id,
+ $pathCallback,
+ );
+ } else {
+ return new CachedMountInfo(
+ $user,
+ (int)$row['storage_id'],
+ (int)$row['root_id'],
+ $row['mount_point'],
+ $row['mount_provider_class'] ?? '',
+ $mount_id,
+ $row['path'] ?? '',
+ );
+ }
}
/**
@@ -247,20 +229,43 @@ class UserMountCache implements IUserMountCache {
* @return ICachedMountInfo[]
*/
public function getMountsForUser(IUser $user) {
- if (!isset($this->mountsForUsers[$user->getUID()])) {
+ $userUID = $user->getUID();
+ if (!$this->userManager->userExists($userUID)) {
+ return [];
+ }
+ if (!isset($this->mountsForUsers[$userUID])) {
$builder = $this->connection->getQueryBuilder();
- $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'mount_provider_class')
->from('mounts', 'm')
- ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
- ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID())));
+ ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($userUID)));
$result = $query->execute();
$rows = $result->fetchAll();
$result->closeCursor();
- $this->mountsForUsers[$user->getUID()] = array_filter(array_map([$this, 'dbRowToMountInfo'], $rows));
+ /** @var array<string, ICachedMountInfo> $mounts */
+ $mounts = [];
+ foreach ($rows as $row) {
+ $mount = $this->dbRowToMountInfo($row, [$this, 'getInternalPathForMountInfo']);
+ if ($mount !== null) {
+ $mounts[$mount->getKey()] = $mount;
+ }
+ }
+ $this->mountsForUsers[$userUID] = $mounts;
}
- return $this->mountsForUsers[$user->getUID()];
+ return $this->mountsForUsers[$userUID];
+ }
+
+ public function getInternalPathForMountInfo(CachedMountInfo $info): string {
+ $cached = $this->internalPathCache->get($info->getRootId());
+ if ($cached !== null) {
+ return $cached;
+ }
+ $builder = $this->connection->getQueryBuilder();
+ $query = $builder->select('path')
+ ->from('filecache')
+ ->where($builder->expr()->eq('fileid', $builder->createPositionalParameter($info->getRootId())));
+ return $query->executeQuery()->fetchOne() ?: '';
}
/**
@@ -345,30 +350,22 @@ class UserMountCache implements IUserMountCache {
} catch (NotFoundException $e) {
return [];
}
- $builder = $this->connection->getQueryBuilder();
- $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
- ->from('mounts', 'm')
- ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
- ->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($storageId, IQueryBuilder::PARAM_INT)));
-
- if ($user) {
- $query->andWhere($builder->expr()->eq('user_id', $builder->createPositionalParameter($user)));
- }
+ $mountsForStorage = $this->getMountsForStorageId($storageId, $user);
- $result = $query->execute();
- $rows = $result->fetchAll();
- $result->closeCursor();
- // filter mounts that are from the same storage but a different directory
- $filteredMounts = array_filter($rows, function (array $row) use ($internalPath, $fileId) {
- if ($fileId === (int)$row['root_id']) {
+ // filter mounts that are from the same storage but not a parent of the file we care about
+ $filteredMounts = array_filter($mountsForStorage, function (ICachedMountInfo $mount) use ($internalPath, $fileId) {
+ if ($fileId === $mount->getRootId()) {
return true;
}
- $internalMountPath = $row['path'] ?? '';
+ $internalMountPath = $mount->getRootInternalPath();
+
+ return $internalMountPath === '' || str_starts_with($internalPath, $internalMountPath . '/');
+ });
- return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/';
+ $filteredMounts = array_filter($filteredMounts, function (ICachedMountInfo $mount) {
+ return $this->userManager->userExists($mount->getUser()->getUID());
});
- $filteredMounts = array_filter(array_map([$this, 'dbRowToMountInfo'], $filteredMounts));
return array_map(function (ICachedMountInfo $mount) use ($internalPath) {
return new CachedMountFileInfo(
$mount->getUser(),
@@ -463,7 +460,7 @@ class UserMountCache implements IUserMountCache {
}, $mounts);
$mounts = array_combine($mountPoints, $mounts);
- $current = $path;
+ $current = rtrim($path, '/');
// walk up the directory tree until we find a path that has a mountpoint set
// the loop will return if a mountpoint is found or break if none are found
while (true) {
diff --git a/lib/private/Files/Config/UserMountCacheListener.php b/lib/private/Files/Config/UserMountCacheListener.php
index eef91a03853..40995de8986 100644
--- a/lib/private/Files/Config/UserMountCacheListener.php
+++ b/lib/private/Files/Config/UserMountCacheListener.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Config;
diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php
index 3937ee16a7c..c3dcb531342 100644
--- a/lib/private/Files/FileInfo.php
+++ b/lib/private/Files/FileInfo.php
@@ -1,43 +1,22 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr M <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author tbartenstein <tbartenstein@users.noreply.github.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files;
-use OCA\Files_Sharing\ISharedStorage;
+use OC\Files\Mount\HomeMountPoint;
+use OCA\Files_Sharing\External\Mount;
+use OCA\Files_Sharing\ISharedMountPoint;
use OCP\Files\Cache\ICacheEntry;
-use OCP\Files\IHomeStorage;
use OCP\Files\Mount\IMountPoint;
use OCP\IUser;
+/**
+ * @template-implements \ArrayAccess<string,mixed>
+ */
class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
private array|ICacheEntry $data;
/**
@@ -121,21 +100,14 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset) {
- if ($offset === 'type') {
- return $this->getType();
- } elseif ($offset === 'etag') {
- return $this->getEtag();
- } elseif ($offset === 'size') {
- return $this->getSize();
- } elseif ($offset === 'mtime') {
- return $this->getMTime();
- } elseif ($offset === 'permissions') {
- return $this->getPermissions();
- } elseif (isset($this->data[$offset])) {
- return $this->data[$offset];
- } else {
- return null;
- }
+ return match ($offset) {
+ 'type' => $this->getType(),
+ 'etag' => $this->getEtag(),
+ 'size' => $this->getSize(),
+ 'mtime' => $this->getMTime(),
+ 'permissions' => $this->getPermissions(),
+ default => $this->data[$offset] ?? null,
+ };
}
/**
@@ -183,7 +155,9 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @return string
*/
public function getName() {
- return isset($this->data['name']) ? $this->data['name'] : basename($this->getPath());
+ return empty($this->data['name'])
+ ? basename($this->getPath())
+ : $this->data['name'];
}
/**
@@ -207,7 +181,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
if ($includeMounts) {
$this->updateEntryfromSubMounts();
- if (isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
+ if ($this->isEncrypted() && isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
return $this->data['unencrypted_size'];
} else {
return isset($this->data['size']) ? 0 + $this->data['size'] : 0;
@@ -229,11 +203,11 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @return bool
*/
public function isEncrypted() {
- return $this->data['encrypted'];
+ return $this->data['encrypted'] ?? false;
}
/**
- * Return the currently version used for the HMAC in the encryption app
+ * Return the current version used for the HMAC in the encryption app
*/
public function getEncryptedVersion(): int {
return isset($this->data['encryptedVersion']) ? (int) $this->data['encryptedVersion'] : 1;
@@ -243,11 +217,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @return int
*/
public function getPermissions() {
- $perms = (int) $this->data['permissions'];
- if (\OCP\Util::isSharingDisabledForUser() || ($this->isShared() && !\OC\Share\Share::isResharingAllowed())) {
- $perms = $perms & ~\OCP\Constants::PERMISSION_SHARE;
- }
- return $perms;
+ return (int) $this->data['permissions'];
}
/**
@@ -315,13 +285,12 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @return bool
*/
public function isShared() {
- $storage = $this->getStorage();
- return $storage->instanceOfStorage(ISharedStorage::class);
+ return $this->mount instanceof ISharedMountPoint;
}
public function isMounted() {
- $storage = $this->getStorage();
- return !($storage->instanceOfStorage(IHomeStorage::class) || $storage->instanceOfStorage(ISharedStorage::class));
+ $isHome = $this->mount instanceof HomeMountPoint;
+ return !$isHome && !$this->isShared();
}
/**
@@ -416,4 +385,16 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
public function getUploadTime(): int {
return (int) $this->data['upload_time'];
}
+
+ public function getParentId(): int {
+ return $this->data['parent'] ?? -1;
+ }
+
+ /**
+ * @inheritDoc
+ * @return array<string, int|string|bool|float|string[]|int[]>
+ */
+ public function getMetadata(): array {
+ return $this->data['metadata'] ?? [];
+ }
}
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index 5f7c0c403db..db7420c3c4c 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -1,45 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Florin Peter <github@florin-peter.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author korelstar <korelstar@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sam Tuke <mail@samtuke.com>
- * @author Stephan Peijnik <speijnik@anexia-it.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files;
-use OCP\Cache\CappedMemoryCache;
use OC\Files\Mount\MountPoint;
use OC\User\NoUserException;
+use OCP\Cache\CappedMemoryCache;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\Mount\IMountManager;
@@ -48,6 +18,7 @@ use OCP\Files\Storage\IStorageFactory;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
class Filesystem {
private static ?Mount\Manager $mounts = null;
@@ -200,7 +171,7 @@ class Filesystem {
*/
public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
if (self::$logWarningWhenAddingStorageWrapper) {
- \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
+ \OCP\Server::get(LoggerInterface::class)->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
'wrapper' => $wrapperName,
'app' => 'filesystem',
]);
diff --git a/lib/private/Files/Lock/LockManager.php b/lib/private/Files/Lock/LockManager.php
index e2af532a01c..978c378e506 100644
--- a/lib/private/Files/Lock/LockManager.php
+++ b/lib/private/Files/Lock/LockManager.php
@@ -1,5 +1,9 @@
<?php
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
namespace OC\Files\Lock;
use OCP\Files\Lock\ILock;
@@ -7,8 +11,11 @@ use OCP\Files\Lock\ILockManager;
use OCP\Files\Lock\ILockProvider;
use OCP\Files\Lock\LockContext;
use OCP\PreConditionNotMetException;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
class LockManager implements ILockManager {
+ private ?string $lockProviderClass = null;
private ?ILockProvider $lockProvider = null;
private ?LockContext $lockInScope = null;
@@ -20,12 +27,34 @@ class LockManager implements ILockManager {
$this->lockProvider = $lockProvider;
}
+ public function registerLazyLockProvider(string $lockProviderClass): void {
+ if ($this->lockProviderClass || $this->lockProvider) {
+ throw new PreConditionNotMetException('There is already a registered lock provider');
+ }
+
+ $this->lockProviderClass = $lockProviderClass;
+ }
+
+ private function getLockProvider(): ?ILockProvider {
+ if ($this->lockProvider) {
+ return $this->lockProvider;
+ }
+ if ($this->lockProviderClass) {
+ try {
+ $this->lockProvider = \OCP\Server::get($this->lockProviderClass);
+ } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
+ }
+ }
+
+ return $this->lockProvider;
+ }
+
public function isLockProviderAvailable(): bool {
- return $this->lockProvider !== null;
+ return $this->getLockProvider() !== null;
}
public function runInScope(LockContext $lock, callable $callback): void {
- if (!$this->lockProvider) {
+ if (!$this->getLockProvider()) {
$callback();
return;
}
@@ -47,26 +76,26 @@ class LockManager implements ILockManager {
}
public function getLocks(int $fileId): array {
- if (!$this->lockProvider) {
+ if (!$this->getLockProvider()) {
throw new PreConditionNotMetException('No lock provider available');
}
- return $this->lockProvider->getLocks($fileId);
+ return $this->getLockProvider()->getLocks($fileId);
}
public function lock(LockContext $lockInfo): ILock {
- if (!$this->lockProvider) {
+ if (!$this->getLockProvider()) {
throw new PreConditionNotMetException('No lock provider available');
}
- return $this->lockProvider->lock($lockInfo);
+ return $this->getLockProvider()->lock($lockInfo);
}
public function unlock(LockContext $lockInfo): void {
- if (!$this->lockProvider) {
+ if (!$this->getLockProvider()) {
throw new PreConditionNotMetException('No lock provider available');
}
- $this->lockProvider->unlock($lockInfo);
+ $this->getLockProvider()->unlock($lockInfo);
}
}
diff --git a/lib/private/Files/Mount/CacheMountProvider.php b/lib/private/Files/Mount/CacheMountProvider.php
index 903b93276c0..27c7eec9da3 100644
--- a/lib/private/Files/Mount/CacheMountProvider.php
+++ b/lib/private/Files/Mount/CacheMountProvider.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Mount;
diff --git a/lib/private/Files/Mount/HomeMountPoint.php b/lib/private/Files/Mount/HomeMountPoint.php
new file mode 100644
index 00000000000..0aa4b54ddf0
--- /dev/null
+++ b/lib/private/Files/Mount/HomeMountPoint.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Files\Mount;
+
+use OCP\Files\Storage\IStorageFactory;
+use OCP\IUser;
+
+class HomeMountPoint extends MountPoint {
+ private IUser $user;
+
+ public function __construct(
+ IUser $user,
+ $storage,
+ string $mountpoint,
+ ?array $arguments = null,
+ ?IStorageFactory $loader = null,
+ ?array $mountOptions = null,
+ ?int $mountId = null,
+ ?string $mountProvider = null
+ ) {
+ parent::__construct($storage, $mountpoint, $arguments, $loader, $mountOptions, $mountId, $mountProvider);
+ $this->user = $user;
+ }
+
+ public function getUser(): IUser {
+ return $this->user;
+ }
+}
diff --git a/lib/private/Files/Mount/LocalHomeMountProvider.php b/lib/private/Files/Mount/LocalHomeMountProvider.php
index 25a67fc1574..a2b3d3b2a99 100644
--- a/lib/private/Files/Mount/LocalHomeMountProvider.php
+++ b/lib/private/Files/Mount/LocalHomeMountProvider.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Mount;
@@ -38,6 +24,6 @@ class LocalHomeMountProvider implements IHomeMountProvider {
*/
public function getHomeMountForUser(IUser $user, IStorageFactory $loader) {
$arguments = ['user' => $user];
- return new MountPoint('\OC\Files\Storage\Home', '/' . $user->getUID(), $arguments, $loader, null, null, self::class);
+ return new HomeMountPoint($user, '\OC\Files\Storage\Home', '/' . $user->getUID(), $arguments, $loader, null, null, self::class);
}
}
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 805cce658a6..c2267af3c96 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -1,38 +1,18 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Mount;
-use OCP\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
use OC\Files\SetupManager;
use OC\Files\SetupManagerFactory;
+use OCP\Cache\CappedMemoryCache;
+use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
@@ -99,6 +79,15 @@ class Manager implements IMountManager {
return $this->pathCache[$path];
}
+
+
+ if (count($this->mounts) === 0) {
+ $this->setupManager->setupRoot();
+ if (count($this->mounts) === 0) {
+ throw new \Exception("No mounts even after explicitly setting up the root mounts");
+ }
+ }
+
$current = $path;
while (true) {
$mountPoint = $current . '/';
@@ -115,7 +104,7 @@ class Manager implements IMountManager {
}
}
- throw new NotFoundException("No mount for path " . $path . " existing mounts: " . implode(",", array_keys($this->mounts)));
+ throw new NotFoundException("No mount for path " . $path . " existing mounts (" . count($this->mounts) ."): " . implode(",", array_keys($this->mounts)));
}
/**
@@ -226,4 +215,21 @@ class Manager implements IMountManager {
});
}
}
+
+ /**
+ * Return the mount matching a cached mount info (or mount file info)
+ *
+ * @param ICachedMountInfo $info
+ *
+ * @return IMountPoint|null
+ */
+ public function getMountFromMountInfo(ICachedMountInfo $info): ?IMountPoint {
+ $this->setupManager->setupForPath($info->getMountPoint());
+ foreach ($this->mounts as $mount) {
+ if ($mount->getMountPoint() === $info->getMountPoint()) {
+ return $mount;
+ }
+ }
+ return null;
+ }
}
diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php
index f526928cc15..cb3a3e8a22d 100644
--- a/lib/private/Files/Mount/MountPoint.php
+++ b/lib/private/Files/Mount/MountPoint.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Mount;
@@ -94,11 +71,11 @@ class MountPoint implements IMountPoint {
public function __construct(
$storage,
string $mountpoint,
- array $arguments = null,
- IStorageFactory $loader = null,
- array $mountOptions = null,
- int $mountId = null,
- string $mountProvider = null
+ ?array $arguments = null,
+ ?IStorageFactory $loader = null,
+ ?array $mountOptions = null,
+ ?int $mountId = null,
+ ?string $mountProvider = null
) {
if (is_null($arguments)) {
$arguments = [];
@@ -272,7 +249,7 @@ class MountPoint implements IMountPoint {
* @return mixed
*/
public function getOption($name, $default) {
- return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
+ return $this->mountOptions[$name] ?? $default;
}
/**
diff --git a/lib/private/Files/Mount/MoveableMount.php b/lib/private/Files/Mount/MoveableMount.php
index 7dbed24504e..755733bf651 100644
--- a/lib/private/Files/Mount/MoveableMount.php
+++ b/lib/private/Files/Mount/MoveableMount.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Mount;
diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php
index 77912adfd34..99c52108fa8 100644
--- a/lib/private/Files/Mount/ObjectHomeMountProvider.php
+++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vlastimil Pecinka <pecinka@email.cz>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Mount;
@@ -65,7 +48,7 @@ class ObjectHomeMountProvider implements IHomeMountProvider {
return null;
}
- return new MountPoint('\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader, null, null, self::class);
+ return new HomeMountPoint($user, '\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader, null, null, self::class);
}
/**
@@ -122,7 +105,7 @@ class ObjectHomeMountProvider implements IHomeMountProvider {
$config['arguments']['bucket'] = '';
}
$mapper = new \OC\Files\ObjectStore\Mapper($user, $this->config);
- $numBuckets = isset($config['arguments']['num_buckets']) ? $config['arguments']['num_buckets'] : 64;
+ $numBuckets = $config['arguments']['num_buckets'] ?? 64;
$config['arguments']['bucket'] .= $mapper->getBucket($numBuckets);
$this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $config['arguments']['bucket']);
diff --git a/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php b/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
index 3a20afba5a5..1546ef98f50 100644
--- a/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
+++ b/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Mount;
diff --git a/lib/private/Files/Mount/RootMountProvider.php b/lib/private/Files/Mount/RootMountProvider.php
index 794421181c7..7ad7a7f059c 100644
--- a/lib/private/Files/Mount/RootMountProvider.php
+++ b/lib/private/Files/Mount/RootMountProvider.php
@@ -2,23 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Mount;
diff --git a/lib/private/Files/Node/File.php b/lib/private/Files/Node/File.php
index b6cd6571651..eb6411d7d13 100644
--- a/lib/private/Files/Node/File.php
+++ b/lib/private/Files/Node/File.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index ccd10da9d0c..148dc28318f 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -1,33 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2022 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
@@ -177,7 +152,7 @@ class Folder extends Node implements \OCP\Files\Folder {
* @throws \OCP\Files\NotPermittedException
*/
public function newFile($path, $content = null) {
- if (empty($path)) {
+ if ($path === '') {
throw new NotPermittedException('Could not create as provided path is empty');
}
if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
@@ -199,7 +174,7 @@ class Folder extends Node implements \OCP\Files\Folder {
throw new NotPermittedException('No create permission for path "' . $path . '"');
}
- private function queryFromOperator(ISearchOperator $operator, string $uid = null, int $limit = 0, int $offset = 0): ISearchQuery {
+ private function queryFromOperator(ISearchOperator $operator, ?string $uid = null, int $limit = 0, int $offset = 0): ISearchQuery {
if ($uid === null) {
$user = null;
} else {
@@ -307,13 +282,17 @@ class Folder extends Node implements \OCP\Files\Folder {
/**
* @param int $id
- * @return \OC\Files\Node\Node[]
+ * @return \OCP\Files\Node[]
*/
public function getById($id) {
return $this->root->getByIdInPath((int)$id, $this->getPath());
}
- protected function getAppDataDirectoryName(): string {
+ public function getFirstNodeById(int $id): ?\OCP\Files\Node {
+ return current($this->getById($id)) ?: null;
+ }
+
+ public function getAppDataDirectoryName(): string {
$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
return 'appdata_' . $instanceId;
}
diff --git a/lib/private/Files/Node/HookConnector.php b/lib/private/Files/Node/HookConnector.php
index a8e76d95c22..8fd2ffa3369 100644
--- a/lib/private/Files/Node/HookConnector.php
+++ b/lib/private/Files/Node/HookConnector.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
@@ -30,6 +12,7 @@ use OC\Files\Filesystem;
use OC\Files\View;
use OCP\EventDispatcher\GenericEvent;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Exceptions\AbortedEventException;
use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
use OCP\Files\Events\Node\BeforeNodeCreatedEvent;
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
@@ -46,27 +29,18 @@ use OCP\Files\Events\Node\NodeWrittenEvent;
use OCP\Files\FileInfo;
use OCP\Files\IRootFolder;
use OCP\Util;
+use Psr\Log\LoggerInterface;
class HookConnector {
- /** @var IRootFolder */
- private $root;
-
- /** @var View */
- private $view;
-
/** @var FileInfo[] */
- private $deleteMetaCache = [];
-
- /** @var IEventDispatcher */
- private $dispatcher;
+ private array $deleteMetaCache = [];
public function __construct(
- IRootFolder $root,
- View $view,
- IEventDispatcher $dispatcher) {
- $this->root = $root;
- $this->view = $view;
- $this->dispatcher = $dispatcher;
+ private IRootFolder $root,
+ private View $view,
+ private IEventDispatcher $dispatcher,
+ private LoggerInterface $logger
+ ) {
}
public function viewToNode() {
@@ -134,7 +108,12 @@ class HookConnector {
$this->dispatcher->dispatch('\OCP\Files::preDelete', new GenericEvent($node));
$event = new BeforeNodeDeletedEvent($node);
- $this->dispatcher->dispatchTyped($event);
+ try {
+ $this->dispatcher->dispatchTyped($event);
+ } catch (AbortedEventException $e) {
+ $arguments['run'] = false;
+ $this->logger->warning('delete process aborted', ['exception' => $e]);
+ }
}
public function postDelete($arguments) {
@@ -172,7 +151,12 @@ class HookConnector {
$this->dispatcher->dispatch('\OCP\Files::preRename', new GenericEvent([$source, $target]));
$event = new BeforeNodeRenamedEvent($source, $target);
- $this->dispatcher->dispatchTyped($event);
+ try {
+ $this->dispatcher->dispatchTyped($event);
+ } catch (AbortedEventException $e) {
+ $arguments['run'] = false;
+ $this->logger->warning('rename process aborted', ['exception' => $e]);
+ }
}
public function postRename($arguments) {
@@ -192,7 +176,12 @@ class HookConnector {
$this->dispatcher->dispatch('\OCP\Files::preCopy', new GenericEvent([$source, $target]));
$event = new BeforeNodeCopiedEvent($source, $target);
- $this->dispatcher->dispatchTyped($event);
+ try {
+ $this->dispatcher->dispatchTyped($event);
+ } catch (AbortedEventException $e) {
+ $arguments['run'] = false;
+ $this->logger->warning('copy process aborted', ['exception' => $e]);
+ }
}
public function postCopy($arguments) {
diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php
index d495d6f4c57..83ed7e534a7 100644
--- a/lib/private/Files/Node/LazyFolder.php
+++ b/lib/private/Files/Node/LazyFolder.php
@@ -1,35 +1,19 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Files\Node;
+use OC\Files\Filesystem;
use OC\Files\Utils\PathHelper;
-use OCP\Files\Folder;
use OCP\Constants;
+use OCP\Files\Folder;
+use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\NotPermittedException;
/**
* Class LazyFolder
@@ -41,23 +25,33 @@ use OCP\Files\Mount\IMountPoint;
*/
class LazyFolder implements Folder {
/** @var \Closure(): Folder */
- private $folderClosure;
-
- /** @var LazyFolder | null */
- protected $folder = null;
-
+ private \Closure $folderClosure;
+ protected ?Folder $folder = null;
+ protected IRootFolder $rootFolder;
protected array $data;
/**
- * LazyFolder constructor.
- *
+ * @param IRootFolder $rootFolder
* @param \Closure(): Folder $folderClosure
+ * @param array $data
*/
- public function __construct(\Closure $folderClosure, array $data = []) {
+ public function __construct(IRootFolder $rootFolder, \Closure $folderClosure, array $data = []) {
+ $this->rootFolder = $rootFolder;
$this->folderClosure = $folderClosure;
$this->data = $data;
}
+ protected function getRootFolder(): IRootFolder {
+ return $this->rootFolder;
+ }
+
+ protected function getRealFolder(): Folder {
+ if ($this->folder === null) {
+ $this->folder = call_user_func($this->folderClosure);
+ }
+ return $this->folder;
+ }
+
/**
* Magic method to first get the real rootFolder and then
* call $method with $args on it
@@ -67,11 +61,7 @@ class LazyFolder implements Folder {
* @return mixed
*/
public function __call($method, $args) {
- if ($this->folder === null) {
- $this->folder = call_user_func($this->folderClosure);
- }
-
- return call_user_func_array([$this->folder, $method], $args);
+ return call_user_func_array([$this->getRealFolder(), $method], $args);
}
/**
@@ -91,7 +81,7 @@ class LazyFolder implements Folder {
/**
* @inheritDoc
*/
- public function removeListener($scope = null, $method = null, callable $callback = null) {
+ public function removeListener($scope = null, $method = null, ?callable $callback = null) {
$this->__call(__FUNCTION__, func_get_args());
}
@@ -148,7 +138,7 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function get($path) {
- return $this->__call(__FUNCTION__, func_get_args());
+ return $this->getRootFolder()->get($this->getFullPath($path));
}
/**
@@ -207,6 +197,9 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getId() {
+ if (isset($this->data['fileid'])) {
+ return $this->data['fileid'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -221,6 +214,9 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getMTime() {
+ if (isset($this->data['mtime'])) {
+ return $this->data['mtime'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -228,6 +224,9 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getSize($includeMounts = true): int|float {
+ if (isset($this->data['size'])) {
+ return $this->data['size'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -235,6 +234,9 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getEtag() {
+ if (isset($this->data['etag'])) {
+ return $this->data['etag'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -299,6 +301,12 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getName() {
+ if (isset($this->data['path'])) {
+ return basename($this->data['path']);
+ }
+ if (isset($this->data['name'])) {
+ return $this->data['name'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -390,6 +398,13 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getFullPath($path) {
+ if (isset($this->data['path'])) {
+ $path = PathHelper::normalizePath($path);
+ if (!Filesystem::isValidPath($path)) {
+ throw new NotPermittedException('Invalid path "' . $path . '"');
+ }
+ return $this->data['path'] . $path;
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -457,7 +472,11 @@ class LazyFolder implements Folder {
* @inheritDoc
*/
public function getById($id) {
- return $this->__call(__FUNCTION__, func_get_args());
+ return $this->getRootFolder()->getByIdInPath((int)$id, $this->getPath());
+ }
+
+ public function getFirstNodeById(int $id): ?\OCP\Files\Node {
+ return $this->getRootFolder()->getFirstNodeByIdInPath($id, $this->getPath());
}
/**
@@ -533,4 +552,19 @@ class LazyFolder implements Folder {
public function getRelativePath($path) {
return PathHelper::getRelativePath($this->getPath(), $path);
}
+
+ public function getParentId(): int {
+ if (isset($this->data['parent'])) {
+ return $this->data['parent'];
+ }
+ return $this->__call(__FUNCTION__, func_get_args());
+ }
+
+ /**
+ * @inheritDoc
+ * @return array<string, int|string|bool|float|string[]|int[]>
+ */
+ public function getMetadata(): array {
+ return $this->data['metadata'] ?? $this->__call(__FUNCTION__, func_get_args());
+ }
}
diff --git a/lib/private/Files/Node/LazyRoot.php b/lib/private/Files/Node/LazyRoot.php
index c01b9fdbb83..bc3f3a2e80f 100644
--- a/lib/private/Files/Node/LazyRoot.php
+++ b/lib/private/Files/Node/LazyRoot.php
@@ -1,28 +1,17 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
+use OCP\Files\Cache\ICacheEntry;
use OCP\Files\IRootFolder;
+use OCP\Files\Mount\IMountPoint;
+use OCP\Files\Node;
+use OCP\Files\Node as INode;
/**
* Class LazyRoot
@@ -33,9 +22,18 @@ use OCP\Files\IRootFolder;
* @package OC\Files\Node
*/
class LazyRoot extends LazyFolder implements IRootFolder {
- /**
- * @inheritDoc
- */
+ public function __construct(\Closure $folderClosure, array $data = []) {
+ parent::__construct($this, $folderClosure, $data);
+ }
+
+ protected function getRootFolder(): IRootFolder {
+ $folder = $this->getRealFolder();
+ if (!$folder instanceof IRootFolder) {
+ throw new \Exception('Lazy root folder closure didn\'t return a root folder');
+ }
+ return $folder;
+ }
+
public function getUserFolder($userId) {
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -43,4 +41,16 @@ class LazyRoot extends LazyFolder implements IRootFolder {
public function getByIdInPath(int $id, string $path) {
return $this->__call(__FUNCTION__, func_get_args());
}
+
+ public function getFirstNodeByIdInPath(int $id, string $path): ?Node {
+ return $this->__call(__FUNCTION__, func_get_args());
+ }
+
+ public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode {
+ return $this->getRootFolder()->getNodeFromCacheEntryAndMount($cacheEntry, $mountPoint);
+ }
+
+ public function getAppDataDirectoryName(): string {
+ return $this->__call(__FUNCTION__, func_get_args());
+ }
}
diff --git a/lib/private/Files/Node/LazyUserFolder.php b/lib/private/Files/Node/LazyUserFolder.php
index 8fbdec4b49d..f9908b9b7b6 100644
--- a/lib/private/Files/Node/LazyUserFolder.php
+++ b/lib/private/Files/Node/LazyUserFolder.php
@@ -2,51 +2,34 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Files\Node;
-use OCP\Files\FileInfo;
use OCP\Constants;
+use OCP\Files\File;
+use OCP\Files\FileInfo;
+use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountManager;
use OCP\Files\NotFoundException;
-use OCP\Files\Folder;
-use OCP\Files\File;
use OCP\IUser;
use Psr\Log\LoggerInterface;
class LazyUserFolder extends LazyFolder {
- private IRootFolder $root;
private IUser $user;
private string $path;
private IMountManager $mountManager;
public function __construct(IRootFolder $rootFolder, IUser $user, IMountManager $mountManager) {
- $this->root = $rootFolder;
$this->user = $user;
$this->mountManager = $mountManager;
$this->path = '/' . $user->getUID() . '/files';
- parent::__construct(function () use ($user): Folder {
+ parent::__construct($rootFolder, function () use ($user): Folder {
try {
- $node = $this->root->get($this->path);
+ $node = $this->getRootFolder()->get($this->path);
if ($node instanceof File) {
$e = new \RuntimeException();
\OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: ' . $this->path, [
@@ -56,31 +39,20 @@ class LazyUserFolder extends LazyFolder {
}
return $node;
} catch (NotFoundException $e) {
- if (!$this->root->nodeExists('/' . $user->getUID())) {
- $this->root->newFolder('/' . $user->getUID());
+ if (!$this->getRootFolder()->nodeExists('/' . $user->getUID())) {
+ $this->getRootFolder()->newFolder('/' . $user->getUID());
}
- return $this->root->newFolder($this->path);
+ return $this->getRootFolder()->newFolder($this->path);
}
}, [
'path' => $this->path,
- 'permissions' => Constants::PERMISSION_ALL,
+ // Sharing user root folder is not allowed
+ 'permissions' => Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE,
'type' => FileInfo::TYPE_FOLDER,
'mimetype' => FileInfo::MIMETYPE_FOLDER,
]);
}
- public function get($path) {
- return $this->root->get('/' . $this->user->getUID() . '/files/' . ltrim($path, '/'));
- }
-
- /**
- * @param int $id
- * @return \OCP\Files\Node[]
- */
- public function getById($id) {
- return $this->root->getByIdInPath((int)$id, $this->getPath());
- }
-
public function getMountPoint() {
if ($this->folder !== null) {
return $this->folder->getMountPoint();
diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php
index 61ae762638f..e7f533e73a9 100644
--- a/lib/private/Files/Node/Node.php
+++ b/lib/private/Files/Node/Node.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
@@ -43,7 +21,7 @@ use OCP\Files\NotPermittedException;
use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
-// FIXME: this class really should be abstract
+// FIXME: this class really should be abstract (+1)
class Node implements INode {
/**
* @var \OC\Files\View $view
@@ -59,10 +37,7 @@ class Node implements INode {
protected ?FileInfo $fileInfo;
- /**
- * @var Node|null
- */
- protected $parent;
+ protected ?INode $parent;
private bool $infoHasSubMountsIncluded;
@@ -72,7 +47,7 @@ class Node implements INode {
* @param string $path
* @param FileInfo $fileInfo
*/
- public function __construct(IRootFolder $root, $view, $path, $fileInfo = null, ?Node $parent = null, bool $infoHasSubMountsIncluded = true) {
+ public function __construct(IRootFolder $root, $view, $path, $fileInfo = null, ?INode $parent = null, bool $infoHasSubMountsIncluded = true) {
if (Filesystem::normalizePath($view->getRoot()) !== '/') {
throw new PreConditionNotMetException('The view passed to the node should not have any fake root set');
}
@@ -126,7 +101,7 @@ class Node implements INode {
/**
* @param string[] $hooks
*/
- protected function sendHooks($hooks, array $args = null) {
+ protected function sendHooks($hooks, ?array $args = null) {
$args = !empty($args) ? $args : [$this];
/** @var IEventDispatcher $dispatcher */
$dispatcher = \OC::$server->get(IEventDispatcher::class);
@@ -134,7 +109,14 @@ class Node implements INode {
if (method_exists($this->root, 'emit')) {
$this->root->emit('\OC\Files', $hook, $args);
}
- $dispatcher->dispatch('\OCP\Files::' . $hook, new GenericEvent($args));
+
+ if (in_array($hook, ['preWrite', 'postWrite', 'preCreate', 'postCreate', 'preTouch', 'postTouch', 'preDelete', 'postDelete'], true)) {
+ $event = new GenericEvent($args[0]);
+ } else {
+ $event = new GenericEvent($args);
+ }
+
+ $dispatcher->dispatch('\OCP\Files::' . $hook, $event);
}
}
@@ -300,7 +282,25 @@ class Node implements INode {
return $this->root;
}
- $this->parent = $this->root->get($newPath);
+ // Manually fetch the parent if the current node doesn't have a file info yet
+ try {
+ $fileInfo = $this->getFileInfo();
+ } catch (NotFoundException) {
+ $this->parent = $this->root->get($newPath);
+ /** @var \OCP\Files\Folder $this->parent */
+ return $this->parent;
+ }
+
+ // gather the metadata we already know about our parent
+ $parentData = [
+ 'path' => $newPath,
+ 'fileid' => $fileInfo->getParentId(),
+ ];
+
+ // and create lazy folder with it instead of always querying
+ $this->parent = new LazyFolder($this->root, function () use ($newPath) {
+ return $this->root->get($newPath);
+ }, $parentData);
}
return $this->parent;
@@ -328,13 +328,7 @@ class Node implements INode {
* @return bool
*/
public function isValidPath($path) {
- if (!$path || $path[0] !== '/') {
- $path = '/' . $path;
- }
- if (strstr($path, '/../') || strrchr($path, '/') === '/..') {
- return false;
- }
- return true;
+ return Filesystem::isValidPath($path);
}
public function isMounted() {
@@ -477,4 +471,16 @@ class Node implements INode {
public function getUploadTime(): int {
return $this->getFileInfo()->getUploadTime();
}
+
+ public function getParentId(): int {
+ return $this->fileInfo->getParentId();
+ }
+
+ /**
+ * @inheritDoc
+ * @return array<string, int|string|bool|float|string[]|int[]>
+ */
+ public function getMetadata(): array {
+ return $this->fileInfo->getMetadata();
+ }
}
diff --git a/lib/private/Files/Node/NonExistingFile.php b/lib/private/Files/Node/NonExistingFile.php
index f42f2e33b72..d154876432e 100644
--- a/lib/private/Files/Node/NonExistingFile.php
+++ b/lib/private/Files/Node/NonExistingFile.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
diff --git a/lib/private/Files/Node/NonExistingFolder.php b/lib/private/Files/Node/NonExistingFolder.php
index 34621b18f19..5650c99fe73 100644
--- a/lib/private/Files/Node/NonExistingFolder.php
+++ b/lib/private/Files/Node/NonExistingFolder.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Node;
@@ -162,6 +146,10 @@ class NonExistingFolder extends Folder {
throw new NotFoundException();
}
+ public function getFirstNodeById(int $id): ?\OCP\Files\Node {
+ throw new NotFoundException();
+ }
+
public function getFreeSpace() {
throw new NotFoundException();
}
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index 7bd88981ff2..5fb4013cfc9 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -1,38 +1,12 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Node;
-use OCP\Cache\CappedMemoryCache;
use OC\Files\FileInfo;
use OC\Files\Mount\Manager;
use OC\Files\Mount\MountPoint;
@@ -40,7 +14,9 @@ use OC\Files\Utils\PathHelper;
use OC\Files\View;
use OC\Hooks\PublicEmitter;
use OC\User\NoUserException;
+use OCP\Cache\CappedMemoryCache;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\IRootFolder;
@@ -48,6 +24,8 @@ use OCP\Files\Mount\IMountPoint;
use OCP\Files\Node as INode;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IUser;
use OCP\IUserManager;
use Psr\Log\LoggerInterface;
@@ -80,6 +58,7 @@ class Root extends Folder implements IRootFolder {
private LoggerInterface $logger;
private IUserManager $userManager;
private IEventDispatcher $eventDispatcher;
+ private ICache $pathByIdCache;
/**
* @param Manager $manager
@@ -93,7 +72,8 @@ class Root extends Folder implements IRootFolder {
IUserMountCache $userMountCache,
LoggerInterface $logger,
IUserManager $userManager,
- IEventDispatcher $eventDispatcher
+ IEventDispatcher $eventDispatcher,
+ ICacheFactory $cacheFactory,
) {
parent::__construct($this, $view, '');
$this->mountManager = $manager;
@@ -106,6 +86,7 @@ class Root extends Folder implements IRootFolder {
$eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
$this->userFolderCache = new CappedMemoryCache();
});
+ $this->pathByIdCache = $cacheFactory->createLocal('path-by-id');
}
/**
@@ -131,7 +112,7 @@ class Root extends Folder implements IRootFolder {
* @param string $method optional
* @param callable $callback optional
*/
- public function removeListener($scope = null, $method = null, callable $callback = null) {
+ public function removeListener($scope = null, $method = null, ?callable $callback = null) {
$this->emitter->removeListener($scope, $method, $callback);
}
@@ -382,7 +363,7 @@ class Root extends Folder implements IRootFolder {
try {
$folder = $this->get('/' . $userId . '/files');
if (!$folder instanceof \OCP\Files\Folder) {
- throw new \Exception("User folder for $userId exists as a file");
+ throw new \Exception("Account folder for \"$userId\" exists as a file");
}
} catch (NotFoundException $e) {
if (!$this->nodeExists('/' . $userId)) {
@@ -404,6 +385,31 @@ class Root extends Folder implements IRootFolder {
return $this->userMountCache;
}
+ public function getFirstNodeByIdInPath(int $id, string $path): ?INode {
+ // scope the cache by user, so we don't return nodes for different users
+ if ($this->user) {
+ $cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id);
+ if ($cachedPath && str_starts_with($path, $cachedPath)) {
+ // getting the node by path is significantly cheaper than finding it by id
+ $node = $this->get($cachedPath);
+ // by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path
+ // if the cached path is invalid or a different file now we fall back to the uncached logic
+ if ($node && $node->getId() === $id) {
+ return $node;
+ }
+ }
+ }
+ $node = current($this->getByIdInPath($id, $path));
+ if (!$node) {
+ return null;
+ }
+
+ if ($this->user) {
+ $this->pathByIdCache->set($this->user->getUID() . '::' . $id, $node->getPath());
+ }
+ return $node;
+ }
+
/**
* @param int $id
* @return Node[]
@@ -487,4 +493,29 @@ class Root extends Folder implements IRootFolder {
});
return $folders;
}
+
+ public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode {
+ $path = $cacheEntry->getPath();
+ $fullPath = $mountPoint->getMountPoint() . $path;
+ // todo: LazyNode?
+ $info = new FileInfo($fullPath, $mountPoint->getStorage(), $path, $cacheEntry, $mountPoint);
+ $parentPath = dirname($fullPath);
+ $parent = new LazyFolder($this, function () use ($parentPath) {
+ $parent = $this->get($parentPath);
+ if ($parent instanceof \OCP\Files\Folder) {
+ return $parent;
+ } else {
+ throw new \Exception("parent $parentPath is not a folder");
+ }
+ }, [
+ 'path' => $parentPath,
+ ]);
+ $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
+ $view = new View('');
+ if ($isDir) {
+ return new Folder($this, $view, $path, $info, $parent);
+ } else {
+ return new File($this, $view, $path, $info, $parent);
+ }
+ }
}
diff --git a/lib/private/Files/Notify/Change.php b/lib/private/Files/Notify/Change.php
index decb0db96b1..d2448e5deec 100644
--- a/lib/private/Files/Notify/Change.php
+++ b/lib/private/Files/Notify/Change.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Notify;
diff --git a/lib/private/Files/Notify/RenameChange.php b/lib/private/Files/Notify/RenameChange.php
index e581278c504..98fd7099a58 100644
--- a/lib/private/Files/Notify/RenameChange.php
+++ b/lib/private/Files/Notify/RenameChange.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Notify;
diff --git a/lib/private/Files/ObjectStore/AppdataPreviewObjectStoreStorage.php b/lib/private/Files/ObjectStore/AppdataPreviewObjectStoreStorage.php
index 2f6db935236..66fa74172d3 100644
--- a/lib/private/Files/ObjectStore/AppdataPreviewObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/AppdataPreviewObjectStoreStorage.php
@@ -3,32 +3,18 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
class AppdataPreviewObjectStoreStorage extends ObjectStoreStorage {
- /** @var string */
- private $internalId;
+ private string $internalId;
+ /**
+ * @param array $params
+ * @throws \Exception
+ */
public function __construct($params) {
if (!isset($params['internal-id'])) {
throw new \Exception('missing id in parameters');
@@ -37,7 +23,7 @@ class AppdataPreviewObjectStoreStorage extends ObjectStoreStorage {
parent::__construct($params);
}
- public function getId() {
+ public function getId(): string {
return 'object::appdata::preview:' . $this->internalId;
}
}
diff --git a/lib/private/Files/ObjectStore/Azure.php b/lib/private/Files/ObjectStore/Azure.php
index 553f593b299..55400d4131c 100644
--- a/lib/private/Files/ObjectStore/Azure.php
+++ b/lib/private/Files/ObjectStore/Azure.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
@@ -100,7 +83,7 @@ class Azure implements IObjectStore {
return $blob->getContentStream();
}
- public function writeObject($urn, $stream, string $mimetype = null) {
+ public function writeObject($urn, $stream, ?string $mimetype = null) {
$options = new CreateBlockBlobOptions();
if ($mimetype) {
$options->setContentType($mimetype);
diff --git a/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php b/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php
index 824adcc1d0e..b543d223f4c 100644
--- a/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php
@@ -1,46 +1,34 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\ObjectStore;
-use OC\User\User;
+use Exception;
+use OCP\Files\IHomeStorage;
+use OCP\IUser;
+
+class HomeObjectStoreStorage extends ObjectStoreStorage implements IHomeStorage {
+ protected IUser $user;
-class HomeObjectStoreStorage extends ObjectStoreStorage implements \OCP\Files\IHomeStorage {
/**
* The home user storage requires a user object to create a unique storage id
+ *
* @param array $params
+ * @throws Exception
*/
public function __construct($params) {
- if (! isset($params['user']) || ! $params['user'] instanceof User) {
- throw new \Exception('missing user object in parameters');
+ if (! isset($params['user']) || ! $params['user'] instanceof IUser) {
+ throw new Exception('missing user object in parameters');
}
$this->user = $params['user'];
parent::__construct($params);
}
- public function getId() {
+ public function getId(): string {
return 'object::user:' . $this->user->getUID();
}
@@ -48,20 +36,13 @@ class HomeObjectStoreStorage extends ObjectStoreStorage implements \OCP\Files\IH
* get the owner of a path
*
* @param string $path The path to get the owner
- * @return false|string uid
+ * @return string uid
*/
- public function getOwner($path) {
- if (is_object($this->user)) {
- return $this->user->getUID();
- }
- return false;
+ public function getOwner($path): string {
+ return $this->user->getUID();
}
- /**
- * @param string $path, optional
- * @return \OC\User\User
- */
- public function getUser($path = null) {
+ public function getUser(): IUser {
return $this->user;
}
}
diff --git a/lib/private/Files/ObjectStore/Mapper.php b/lib/private/Files/ObjectStore/Mapper.php
index ef3c6878d81..e1174a285a6 100644
--- a/lib/private/Files/ObjectStore/Mapper.php
+++ b/lib/private/Files/ObjectStore/Mapper.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\ObjectStore;
diff --git a/lib/private/Files/ObjectStore/ObjectStoreScanner.php b/lib/private/Files/ObjectStore/ObjectStoreScanner.php
index f001f90fdaa..d8a77d36dee 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreScanner.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreScanner.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\ObjectStore;
@@ -39,7 +20,7 @@ class ObjectStoreScanner extends Scanner {
return [];
}
- protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int $oldSize) {
+ protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize, &$etagChanged = false) {
return 0;
}
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
index d918bd98729..389f744eab4 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
@@ -1,33 +1,10 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Marcel Klehr <mklehr@gmx.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\ObjectStore;
use Aws\S3\Exception\S3Exception;
@@ -47,30 +24,24 @@ use OCP\Files\ObjectStore\IObjectStore;
use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload;
use OCP\Files\Storage\IChunkedFileWrite;
use OCP\Files\Storage\IStorage;
+use Psr\Log\LoggerInterface;
class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFileWrite {
use CopyDirectory;
- /**
- * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
- */
- protected $objectStore;
- /**
- * @var string $id
- */
- protected $id;
- /**
- * @var \OC\User\User $user
- */
- protected $user;
-
- private $objectPrefix = 'urn:oid:';
+ protected IObjectStore $objectStore;
+ protected string $id;
+ private string $objectPrefix = 'urn:oid:';
- private $logger;
+ private LoggerInterface $logger;
- /** @var bool */
- protected $validateWrites = true;
+ private bool $handleCopiesAsOwned;
+ protected bool $validateWrites = true;
+ /**
+ * @param array $params
+ * @throws \Exception
+ */
public function __construct($params) {
if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
$this->objectStore = $params['objectstore'];
@@ -88,8 +59,9 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
if (isset($params['validateWrites'])) {
$this->validateWrites = (bool)$params['validateWrites'];
}
+ $this->handleCopiesAsOwned = (bool)($params['handleCopiesAsOwned'] ?? false);
- $this->logger = \OC::$server->getLogger();
+ $this->logger = \OCP\Server::get(LoggerInterface::class);
}
public function mkdir($path, bool $force = false) {
@@ -225,10 +197,13 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
$this->objectStore->deleteObject($this->getURN($entry->getId()));
} catch (\Exception $ex) {
if ($ex->getCode() !== 404) {
- $this->logger->logException($ex, [
- 'app' => 'objectstore',
- 'message' => 'Could not delete object ' . $this->getURN($entry->getId()) . ' for ' . $entry->getPath(),
- ]);
+ $this->logger->error(
+ 'Could not delete object ' . $this->getURN($entry->getId()) . ' for ' . $entry->getPath(),
+ [
+ 'app' => 'objectstore',
+ 'exception' => $ex,
+ ]
+ );
return false;
}
//removing from cache is ok as it does not exist in the objectstore anyway
@@ -291,7 +266,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
return IteratorDirectory::wrap($files);
} catch (\Exception $e) {
- $this->logger->logException($e);
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
return false;
}
}
@@ -341,16 +316,22 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
}
return $handle;
} catch (NotFoundException $e) {
- $this->logger->logException($e, [
- 'app' => 'objectstore',
- 'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
- ]);
+ $this->logger->error(
+ 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
+ [
+ 'app' => 'objectstore',
+ 'exception' => $e,
+ ]
+ );
throw $e;
- } catch (\Exception $ex) {
- $this->logger->logException($ex, [
- 'app' => 'objectstore',
- 'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
- ]);
+ } catch (\Exception $e) {
+ $this->logger->error(
+ 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
+ [
+ 'app' => 'objectstore',
+ 'exception' => $e,
+ ]
+ );
return false;
}
} else {
@@ -447,10 +428,13 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
];
$this->getCache()->put($path, $stat);
} catch (\Exception $ex) {
- $this->logger->logException($ex, [
- 'app' => 'objectstore',
- 'message' => 'Could not create object for ' . $path,
- ]);
+ $this->logger->error(
+ 'Could not create object for ' . $path,
+ [
+ 'app' => 'objectstore',
+ 'exception' => $ex,
+ ]
+ );
throw $ex;
}
}
@@ -487,7 +471,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
return $result;
}
- public function writeStream(string $path, $stream, int $size = null): int {
+ public function writeStream(string $path, $stream, ?int $size = null): int {
$stat = $this->stat($path);
if (empty($stat)) {
// create new file
@@ -545,20 +529,28 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
* Else people lose access to existing files
*/
$this->getCache()->remove($uploadPath);
- $this->logger->logException($ex, [
- 'app' => 'objectstore',
- 'message' => 'Could not create object ' . $urn . ' for ' . $path,
- ]);
+ $this->logger->error(
+ 'Could not create object ' . $urn . ' for ' . $path,
+ [
+ 'app' => 'objectstore',
+ 'exception' => $ex,
+ ]
+ );
} else {
- $this->logger->logException($ex, [
- 'app' => 'objectstore',
- 'message' => 'Could not update object ' . $urn . ' for ' . $path,
- ]);
+ $this->logger->error(
+ 'Could not update object ' . $urn . ' for ' . $path,
+ [
+ 'app' => 'objectstore',
+ 'exception' => $ex,
+ ]
+ );
}
throw $ex; // make this bubble up
}
if ($exists) {
+ // Always update the unencrypted size, for encryption the Encryption wrapper will update this afterwards anyways
+ $stat['unencrypted_size'] = $stat['size'];
$this->getCache()->update($fileId, $stat);
} else {
if (!$this->validateWrites || $this->objectStore->objectExists($urn)) {
@@ -649,6 +641,10 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
try {
$this->objectStore->copyObject($sourceUrn, $targetUrn);
+ if ($this->handleCopiesAsOwned) {
+ // Copied the file thus we gain all permissions as we are the owner now ! warning while this aligns with local storage it should not be used and instead fix local storage !
+ $cache->update($targetId, ['permissions' => \OCP\Constants::PERMISSION_ALL]);
+ }
} catch (\Exception $e) {
$cache->remove($to);
@@ -712,10 +708,13 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
}
} catch (S3MultipartUploadException|S3Exception $e) {
$this->objectStore->abortMultipartUpload($urn, $writeToken);
- $this->logger->logException($e, [
- 'app' => 'objectstore',
- 'message' => 'Could not compete multipart upload ' . $urn . ' with uploadId ' . $writeToken,
- ]);
+ $this->logger->error(
+ 'Could not compete multipart upload ' . $urn . ' with uploadId ' . $writeToken,
+ [
+ 'app' => 'objectstore',
+ 'exception' => $e,
+ ]
+ );
throw new GenericFileException('Could not write chunked file');
}
return $size;
diff --git a/lib/private/Files/ObjectStore/S3.php b/lib/private/Files/ObjectStore/S3.php
index b1cd89388ae..72c19d951e4 100644
--- a/lib/private/Files/ObjectStore/S3.php
+++ b/lib/private/Files/ObjectStore/S3.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
diff --git a/lib/private/Files/ObjectStore/S3ConfigTrait.php b/lib/private/Files/ObjectStore/S3ConfigTrait.php
new file mode 100644
index 00000000000..3a399e6413d
--- /dev/null
+++ b/lib/private/Files/ObjectStore/S3ConfigTrait.php
@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\ObjectStore;
+
+/**
+ * Shared configuration between ConnectionTrait and ObjectTrait to ensure both to be in sync
+ */
+trait S3ConfigTrait {
+ protected array $params;
+
+ protected string $bucket;
+
+ /** Maximum number of concurrent multipart uploads */
+ protected int $concurrency;
+
+ protected int $timeout;
+
+ protected string $proxy;
+
+ protected string $storageClass;
+
+ /** @var int Part size in bytes (float is added for 32bit support) */
+ protected int|float $uploadPartSize;
+
+ /** @var int Limit on PUT in bytes (float is added for 32bit support) */
+ private int|float $putSizeLimit;
+
+ /** @var int Limit on COPY in bytes (float is added for 32bit support) */
+ private int|float $copySizeLimit;
+
+ private bool $useMultipartCopy = true;
+}
diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
index deb03571c76..02f5e5ded04 100644
--- a/lib/private/Files/ObjectStore/S3ConnectionTrait.php
+++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
@@ -1,35 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Florent <florent@coppint.com>
- * @author James Letendre <James.Letendre@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author S. Cat <33800996+sparrowjack63@users.noreply.github.com>
- * @author Stephen Cuppett <steve@cuppett.com>
- * @author Jasper Weyne <jasperweyne@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Files\ObjectStore;
use Aws\ClientResolver;
@@ -44,34 +17,13 @@ use OCP\ICertificateManager;
use Psr\Log\LoggerInterface;
trait S3ConnectionTrait {
- /** @var array */
- protected $params;
-
- /** @var S3Client */
- protected $connection;
-
- /** @var string */
- protected $id;
-
- /** @var string */
- protected $bucket;
+ use S3ConfigTrait;
- /** @var int */
- protected $timeout;
+ protected string $id;
- /** @var string */
- protected $proxy;
+ protected bool $test;
- /** @var string */
- protected $storageClass;
-
- /** @var int */
- protected $uploadPartSize;
-
- /** @var int */
- private $putSizeLimit;
-
- protected $test;
+ protected ?S3Client $connection = null;
protected function parseParams($params) {
if (empty($params['bucket'])) {
@@ -82,17 +34,27 @@ trait S3ConnectionTrait {
$this->test = isset($params['test']);
$this->bucket = $params['bucket'];
+ // Default to 5 like the S3 SDK does
+ $this->concurrency = $params['concurrency'] ?? 5;
$this->proxy = $params['proxy'] ?? false;
$this->timeout = $params['timeout'] ?? 15;
$this->storageClass = !empty($params['storageClass']) ? $params['storageClass'] : 'STANDARD';
$this->uploadPartSize = $params['uploadPartSize'] ?? 524288000;
$this->putSizeLimit = $params['putSizeLimit'] ?? 104857600;
+ $this->copySizeLimit = $params['copySizeLimit'] ?? 5242880000;
+ $this->useMultipartCopy = (bool)($params['useMultipartCopy'] ?? true);
$params['region'] = empty($params['region']) ? 'eu-west-1' : $params['region'];
+ $params['s3-accelerate'] = $params['hostname'] == 's3-accelerate.amazonaws.com' || $params['hostname'] == 's3-accelerate.dualstack.amazonaws.com';
$params['hostname'] = empty($params['hostname']) ? 's3.' . $params['region'] . '.amazonaws.com' : $params['hostname'];
if (!isset($params['port']) || $params['port'] === '') {
$params['port'] = (isset($params['use_ssl']) && $params['use_ssl'] === false) ? 80 : 443;
}
- $params['verify_bucket_exists'] = empty($params['verify_bucket_exists']) ? true : $params['verify_bucket_exists'];
+ $params['verify_bucket_exists'] = $params['verify_bucket_exists'] ?? true;
+
+ if ($params['s3-accelerate']) {
+ $params['verify_bucket_exists'] = false;
+ }
+
$this->params = $params;
}
@@ -111,7 +73,7 @@ trait S3ConnectionTrait {
* @throws \Exception if connection could not be made
*/
public function getConnection() {
- if (!is_null($this->connection)) {
+ if ($this->connection !== null) {
return $this->connection;
}
@@ -128,7 +90,7 @@ trait S3ConnectionTrait {
);
$options = [
- 'version' => isset($this->params['version']) ? $this->params['version'] : 'latest',
+ 'version' => $this->params['version'] ?? 'latest',
'credentials' => $provider,
'endpoint' => $base_url,
'region' => $this->params['region'],
@@ -139,6 +101,13 @@ trait S3ConnectionTrait {
'http' => ['verify' => $this->getCertificateBundlePath()],
'use_aws_shared_config_files' => false,
];
+
+ if ($this->params['s3-accelerate']) {
+ $options['use_accelerate_endpoint'] = true;
+ } else {
+ $options['endpoint'] = $base_url;
+ }
+
if ($this->getProxy()) {
$options['http']['proxy'] = $this->getProxy();
}
@@ -167,7 +136,9 @@ trait S3ConnectionTrait {
'exception' => $e,
'app' => 'objectstore',
]);
- throw new \Exception('Creation of bucket "' . $this->bucket . '" failed. ' . $e->getMessage());
+ if ($e->getAwsErrorCode() !== "BucketAlreadyOwnedByYou") {
+ throw new \Exception('Creation of bucket "' . $this->bucket . '" failed. ' . $e->getMessage());
+ }
}
}
diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php
index e0d0f2ce9c7..5d00c184ca7 100644
--- a/lib/private/Files/ObjectStore/S3ObjectTrait.php
+++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php
@@ -1,32 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Florent <florent@coppint.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
use Aws\S3\Exception\S3MultipartUploadException;
+use Aws\S3\MultipartCopy;
use Aws\S3\MultipartUploader;
use Aws\S3\S3Client;
use GuzzleHttp\Psr7;
@@ -35,6 +16,8 @@ use OC\Files\Stream\SeekableHttpStream;
use Psr\Http\Message\StreamInterface;
trait S3ObjectTrait {
+ use S3ConfigTrait;
+
/**
* Returns the connection
*
@@ -103,7 +86,7 @@ trait S3ObjectTrait {
* @param string|null $mimetype the mimetype to set for the remove object @since 22.0.0
* @throws \Exception when something goes wrong, message will be logged
*/
- protected function writeSingle(string $urn, StreamInterface $stream, string $mimetype = null): void {
+ protected function writeSingle(string $urn, StreamInterface $stream, ?string $mimetype = null): void {
$this->getConnection()->putObject([
'Bucket' => $this->bucket,
'Key' => $urn,
@@ -123,9 +106,10 @@ trait S3ObjectTrait {
* @param string|null $mimetype the mimetype to set for the remove object
* @throws \Exception when something goes wrong, message will be logged
*/
- protected function writeMultiPart(string $urn, StreamInterface $stream, string $mimetype = null): void {
+ protected function writeMultiPart(string $urn, StreamInterface $stream, ?string $mimetype = null): void {
$uploader = new MultipartUploader($this->getConnection(), $stream, [
'bucket' => $this->bucket,
+ 'concurrency' => $this->concurrency,
'key' => $urn,
'part_size' => $this->uploadPartSize,
'params' => [
@@ -155,7 +139,7 @@ trait S3ObjectTrait {
* @throws \Exception when something goes wrong, message will be logged
* @since 7.0.0
*/
- public function writeObject($urn, $stream, string $mimetype = null) {
+ public function writeObject($urn, $stream, ?string $mimetype = null) {
$psrStream = Utils::streamFor($stream);
// ($psrStream->isSeekable() && $psrStream->getSize() !== null) evaluates to true for a On-Seekable stream
@@ -189,9 +173,31 @@ trait S3ObjectTrait {
return $this->getConnection()->doesObjectExist($this->bucket, $urn, $this->getSSECParameters());
}
- public function copyObject($from, $to) {
- $this->getConnection()->copy($this->getBucket(), $from, $this->getBucket(), $to, 'private', [
- 'params' => $this->getSSECParameters() + $this->getSSECParameters(true)
- ]);
+ public function copyObject($from, $to, array $options = []) {
+ $sourceMetadata = $this->getConnection()->headObject([
+ 'Bucket' => $this->getBucket(),
+ 'Key' => $from,
+ ] + $this->getSSECParameters());
+
+ $size = (int)($sourceMetadata->get('Size') ?? $sourceMetadata->get('ContentLength'));
+
+ if ($this->useMultipartCopy && $size > $this->copySizeLimit) {
+ $copy = new MultipartCopy($this->getConnection(), [
+ "source_bucket" => $this->getBucket(),
+ "source_key" => $from
+ ], array_merge([
+ "bucket" => $this->getBucket(),
+ "key" => $to,
+ "acl" => "private",
+ "params" => $this->getSSECParameters() + $this->getSSECParameters(true),
+ "source_metadata" => $sourceMetadata
+ ], $options));
+ $copy->copy();
+ } else {
+ $this->getConnection()->copy($this->getBucket(), $from, $this->getBucket(), $to, 'private', array_merge([
+ 'params' => $this->getSSECParameters() + $this->getSSECParameters(true),
+ 'mup_threshold' => PHP_INT_MAX,
+ ], $options));
+ }
}
}
diff --git a/lib/private/Files/ObjectStore/S3Signature.php b/lib/private/Files/ObjectStore/S3Signature.php
index cf3d29c4185..fd24a34b090 100644
--- a/lib/private/Files/ObjectStore/S3Signature.php
+++ b/lib/private/Files/ObjectStore/S3Signature.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
diff --git a/lib/private/Files/ObjectStore/StorageObjectStore.php b/lib/private/Files/ObjectStore/StorageObjectStore.php
index 85926be897e..5e7125e18a6 100644
--- a/lib/private/Files/ObjectStore/StorageObjectStore.php
+++ b/lib/private/Files/ObjectStore/StorageObjectStore.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
@@ -64,7 +46,7 @@ class StorageObjectStore implements IObjectStore {
throw new \Exception();
}
- public function writeObject($urn, $stream, string $mimetype = null) {
+ public function writeObject($urn, $stream, ?string $mimetype = null) {
$handle = $this->storage->fopen($urn, 'w');
if ($handle) {
stream_copy_to_stream($stream, $handle);
diff --git a/lib/private/Files/ObjectStore/Swift.php b/lib/private/Files/ObjectStore/Swift.php
index b463cb9d44d..aa8b3bb34ec 100644
--- a/lib/private/Files/ObjectStore/Swift.php
+++ b/lib/private/Files/ObjectStore/Swift.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Adrian Brzezinski <adrian.brzezinski@eo.pl>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\ObjectStore;
@@ -45,7 +27,7 @@ class Swift implements IObjectStore {
/** @var SwiftFactory */
private $swiftFactory;
- public function __construct($params, SwiftFactory $connectionFactory = null) {
+ public function __construct($params, ?SwiftFactory $connectionFactory = null) {
$this->swiftFactory = $connectionFactory ?: new SwiftFactory(
\OC::$server->getMemCacheFactory()->createDistributed('swift::'),
$params,
@@ -74,7 +56,7 @@ class Swift implements IObjectStore {
return $this->params['container'];
}
- public function writeObject($urn, $stream, string $mimetype = null) {
+ public function writeObject($urn, $stream, ?string $mimetype = null) {
$tmpFile = \OC::$server->getTempManager()->getTemporaryFile('swiftwrite');
file_put_contents($tmpFile, $stream);
$handle = fopen($tmpFile, 'rb');
diff --git a/lib/private/Files/ObjectStore/SwiftFactory.php b/lib/private/Files/ObjectStore/SwiftFactory.php
index bd75ccada2e..0db5c9762d2 100644
--- a/lib/private/Files/ObjectStore/SwiftFactory.php
+++ b/lib/private/Files/ObjectStore/SwiftFactory.php
@@ -3,32 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Adrian Brzezinski <adrian.brzezinski@eo.pl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julien Lutran <julien.lutran@corp.ovh.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Volker <skydiablo@gmx.net>
- * @author William Pain <pain.william@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
diff --git a/lib/private/Files/ObjectStore/SwiftV2CachingAuthService.php b/lib/private/Files/ObjectStore/SwiftV2CachingAuthService.php
index b1478762550..266781af142 100644
--- a/lib/private/Files/ObjectStore/SwiftV2CachingAuthService.php
+++ b/lib/private/Files/ObjectStore/SwiftV2CachingAuthService.php
@@ -3,33 +3,19 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\ObjectStore;
+use OpenStack\Common\Auth\Token;
use OpenStack\Identity\v2\Service;
class SwiftV2CachingAuthService extends Service {
public function authenticate(array $options = []): array {
- if (!empty($options['v2cachedToken'])) {
+ if (isset($options['v2cachedToken'], $options['v2serviceUrl'])
+ && $options['v2cachedToken'] instanceof Token
+ && is_string($options['v2serviceUrl'])) {
return [$options['v2cachedToken'], $options['v2serviceUrl']];
} else {
return parent::authenticate($options);
diff --git a/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php b/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php
new file mode 100644
index 00000000000..2bde6f0bbdb
--- /dev/null
+++ b/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\SearchBinaryOperator;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchOperator;
+
+class FlattenNestedBool extends QueryOptimizerStep {
+ public function processOperator(ISearchOperator &$operator) {
+ if (
+ $operator instanceof SearchBinaryOperator && (
+ $operator->getType() === ISearchBinaryOperator::OPERATOR_OR ||
+ $operator->getType() === ISearchBinaryOperator::OPERATOR_AND
+ )
+ ) {
+ $newArguments = [];
+ foreach ($operator->getArguments() as $oldArgument) {
+ if ($oldArgument instanceof SearchBinaryOperator && $oldArgument->getType() === $operator->getType()) {
+ $newArguments = array_merge($newArguments, $oldArgument->getArguments());
+ } else {
+ $newArguments[] = $oldArgument;
+ }
+ }
+ $operator->setArguments($newArguments);
+ }
+ parent::processOperator($operator);
+ }
+}
diff --git a/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php b/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php
new file mode 100644
index 00000000000..cb04351534a
--- /dev/null
+++ b/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Search\QueryOptimizer;
+
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchOperator;
+
+/**
+ * replace single argument AND and OR operations with their single argument
+ */
+class FlattenSingleArgumentBinaryOperation extends ReplacingOptimizerStep {
+ public function processOperator(ISearchOperator &$operator): bool {
+ parent::processOperator($operator);
+ if (
+ $operator instanceof ISearchBinaryOperator &&
+ count($operator->getArguments()) === 1 &&
+ (
+ $operator->getType() === ISearchBinaryOperator::OPERATOR_OR ||
+ $operator->getType() === ISearchBinaryOperator::OPERATOR_AND
+ )
+ ) {
+ $operator = $operator->getArguments()[0];
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/lib/private/Files/Search/QueryOptimizer/MergeDistributiveOperations.php b/lib/private/Files/Search/QueryOptimizer/MergeDistributiveOperations.php
new file mode 100644
index 00000000000..4949ca7396b
--- /dev/null
+++ b/lib/private/Files/Search/QueryOptimizer/MergeDistributiveOperations.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchOperator;
+
+/**
+ * Attempt to transform
+ *
+ * (A AND B) OR (A AND C) OR (A AND D AND E) into A AND (B OR C OR (D AND E))
+ *
+ * This is always valid because logical 'AND' and 'OR' are distributive[1].
+ *
+ * [1]: https://en.wikipedia.org/wiki/Distributive_property
+ */
+class MergeDistributiveOperations extends ReplacingOptimizerStep {
+ public function processOperator(ISearchOperator &$operator): bool {
+ if ($operator instanceof SearchBinaryOperator) {
+ // either 'AND' or 'OR'
+ $topLevelType = $operator->getType();
+
+ // split the arguments into groups that share a first argument
+ $groups = $this->groupBinaryOperatorsByChild($operator->getArguments(), 0);
+ $outerOperations = array_map(function (array $operators) use ($topLevelType) {
+ // no common operations, no need to change anything
+ if (count($operators) === 1) {
+ return $operators[0];
+ }
+
+ // for groups with size >1 we know they are binary operators with at least 1 child
+ /** @var ISearchBinaryOperator $firstArgument */
+ $firstArgument = $operators[0];
+
+ // we already checked that all arguments have the same type, so this type applies for all, either 'AND' or 'OR'
+ $innerType = $firstArgument->getType();
+
+ // the common operation we move out ('A' from the example)
+ $extractedLeftHand = $firstArgument->getArguments()[0];
+
+ // for each argument we remove the extracted operation to get the leftovers ('B', 'C' and '(D AND E)' in the example)
+ // note that we leave them inside the "inner" binary operation for when the "inner" operation contained more than two parts
+ // in the (common) case where the "inner" operation only has 1 item left it will be cleaned up in a follow up step
+ $rightHandArguments = array_map(function (ISearchOperator $inner) {
+ /** @var ISearchBinaryOperator $inner */
+ $arguments = $inner->getArguments();
+ array_shift($arguments);
+ if (count($arguments) === 1) {
+ return $arguments[0];
+ }
+ return new SearchBinaryOperator($inner->getType(), $arguments);
+ }, $operators);
+
+ // combine the extracted operation ('A') with the remaining bit ('(B OR C OR (D AND E))')
+ // note that because of how distribution work, we use the "outer" type "inside" and the "inside" type "outside".
+ $extractedRightHand = new SearchBinaryOperator($topLevelType, $rightHandArguments);
+ return new SearchBinaryOperator(
+ $innerType,
+ [$extractedLeftHand, $extractedRightHand]
+ );
+ }, $groups);
+
+ // combine all groups again
+ $operator = new SearchBinaryOperator($topLevelType, $outerOperations);
+ parent::processOperator($operator);
+ return true;
+ }
+ return parent::processOperator($operator);
+ }
+
+ /**
+ * Group a list of binary search operators that have a common argument
+ *
+ * Non-binary operators, or empty binary operators will each get their own 1-sized group
+ *
+ * @param ISearchOperator[] $operators
+ * @return ISearchOperator[][]
+ */
+ private function groupBinaryOperatorsByChild(array $operators, int $index = 0): array {
+ $result = [];
+ foreach ($operators as $operator) {
+ if ($operator instanceof ISearchBinaryOperator && count($operator->getArguments()) > 0) {
+ /** @var SearchBinaryOperator|SearchComparison $child */
+ $child = $operator->getArguments()[$index];
+ $childKey = (string)$child;
+ $result[$childKey][] = $operator;
+ } else {
+ $result[] = [$operator];
+ }
+ }
+ return array_values($result);
+ }
+}
diff --git a/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php b/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php
new file mode 100644
index 00000000000..3f2b36823ab
--- /dev/null
+++ b/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use OCP\Files\Search\ISearchOperator;
+
+/**
+ * transform (field == A OR field == B ...) into field IN (A, B, ...)
+ */
+class OrEqualsToIn extends ReplacingOptimizerStep {
+ public function processOperator(ISearchOperator &$operator): bool {
+ if (
+ $operator instanceof ISearchBinaryOperator &&
+ $operator->getType() === ISearchBinaryOperator::OPERATOR_OR
+ ) {
+ $groups = $this->groupEqualsComparisonsByField($operator->getArguments());
+ $newParts = array_map(function (array $group) {
+ if (count($group) > 1) {
+ // because of the logic from `groupEqualsComparisonsByField` we now that group is all comparisons on the same field
+ /** @var ISearchComparison[] $group */
+ $field = $group[0]->getField();
+ $values = array_map(function (ISearchComparison $comparison) {
+ /** @var string|integer|bool|\DateTime $value */
+ $value = $comparison->getValue();
+ return $value;
+ }, $group);
+ $in = new SearchComparison(ISearchComparison::COMPARE_IN, $field, $values);
+ $pathEqHash = array_reduce($group, function ($pathEqHash, ISearchComparison $comparison) {
+ return $comparison->getQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, true) && $pathEqHash;
+ }, true);
+ $in->setQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, $pathEqHash);
+ return $in;
+ } else {
+ return $group[0];
+ }
+ }, $groups);
+ if (count($newParts) === 1) {
+ $operator = $newParts[0];
+ } else {
+ $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $newParts);
+ }
+ parent::processOperator($operator);
+ return true;
+ }
+ parent::processOperator($operator);
+ return false;
+ }
+
+ /**
+ * Non-equals operators are put in a separate group for each
+ *
+ * @param ISearchOperator[] $operators
+ * @return ISearchOperator[][]
+ */
+ private function groupEqualsComparisonsByField(array $operators): array {
+ $result = [];
+ foreach ($operators as $operator) {
+ if ($operator instanceof ISearchComparison && $operator->getType() === ISearchComparison::COMPARE_EQUAL) {
+ $result[$operator->getField()][] = $operator;
+ } else {
+ $result[] = [$operator];
+ }
+ }
+ return array_values($result);
+ }
+}
diff --git a/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php b/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php
index 0caa9b12a02..9d50746d5d1 100644
--- a/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php
+++ b/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Files\Search\QueryOptimizer;
use OC\Files\Search\SearchComparison;
@@ -48,7 +32,7 @@ class PathPrefixOptimizer extends QueryOptimizerStep {
}
public function processOperator(ISearchOperator &$operator) {
- if (!$this->useHashEq && $operator instanceof ISearchComparison && $operator->getField() === 'path' && $operator->getType() === ISearchComparison::COMPARE_EQUAL) {
+ if (!$this->useHashEq && $operator instanceof ISearchComparison && !$operator->getExtra() && $operator->getField() === 'path' && $operator->getType() === ISearchComparison::COMPARE_EQUAL) {
$operator->setQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, false);
}
@@ -69,7 +53,7 @@ class PathPrefixOptimizer extends QueryOptimizerStep {
private function operatorPairIsPathPrefix(ISearchOperator $like, ISearchOperator $equal): bool {
return (
$like instanceof ISearchComparison && $equal instanceof ISearchComparison &&
- $like->getField() === 'path' && $equal->getField() === 'path' &&
+ !$like->getExtra() && !$equal->getExtra() && $like->getField() === 'path' && $equal->getField() === 'path' &&
$like->getType() === ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE && $equal->getType() === ISearchComparison::COMPARE_EQUAL
&& $like->getValue() === SearchComparison::escapeLikeParameter($equal->getValue()) . '/%'
);
diff --git a/lib/private/Files/Search/QueryOptimizer/QueryOptimizer.php b/lib/private/Files/Search/QueryOptimizer/QueryOptimizer.php
index 160b27b7f11..5259ca25ad3 100644
--- a/lib/private/Files/Search/QueryOptimizer/QueryOptimizer.php
+++ b/lib/private/Files/Search/QueryOptimizer/QueryOptimizer.php
@@ -2,23 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Search\QueryOptimizer;
@@ -29,15 +14,20 @@ class QueryOptimizer {
/** @var QueryOptimizerStep[] */
private $steps = [];
- public function __construct(
- PathPrefixOptimizer $pathPrefixOptimizer
- ) {
+ public function __construct() {
+ // note that the order here is relevant
$this->steps = [
- $pathPrefixOptimizer
+ new PathPrefixOptimizer(),
+ new MergeDistributiveOperations(),
+ new FlattenSingleArgumentBinaryOperation(),
+ new FlattenNestedBool(),
+ new OrEqualsToIn(),
+ new FlattenNestedBool(),
+ new SplitLargeIn(),
];
}
- public function processOperator(ISearchOperator $operator) {
+ public function processOperator(ISearchOperator &$operator) {
foreach ($this->steps as $step) {
$step->inspectOperator($operator);
}
diff --git a/lib/private/Files/Search/QueryOptimizer/QueryOptimizerStep.php b/lib/private/Files/Search/QueryOptimizer/QueryOptimizerStep.php
index b16898e9087..15b5b580ec1 100644
--- a/lib/private/Files/Search/QueryOptimizer/QueryOptimizerStep.php
+++ b/lib/private/Files/Search/QueryOptimizer/QueryOptimizerStep.php
@@ -2,23 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Search\QueryOptimizer;
diff --git a/lib/private/Files/Search/QueryOptimizer/ReplacingOptimizerStep.php b/lib/private/Files/Search/QueryOptimizer/ReplacingOptimizerStep.php
new file mode 100644
index 00000000000..a9c9ba876bc
--- /dev/null
+++ b/lib/private/Files/Search/QueryOptimizer/ReplacingOptimizerStep.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\SearchBinaryOperator;
+use OCP\Files\Search\ISearchOperator;
+
+/**
+ * Optimizer step that can replace the $operator altogether instead of just modifying it
+ * These steps need some extra logic to properly replace the arguments of binary operators
+ */
+class ReplacingOptimizerStep extends QueryOptimizerStep {
+ /**
+ * Allow optimizer steps to modify query operators
+ *
+ * Returns true if the reference $operator points to a new value
+ */
+ public function processOperator(ISearchOperator &$operator): bool {
+ if ($operator instanceof SearchBinaryOperator) {
+ $modified = false;
+ $arguments = $operator->getArguments();
+ foreach ($arguments as &$argument) {
+ if ($this->processOperator($argument)) {
+ $modified = true;
+ }
+ }
+ if ($modified) {
+ $operator->setArguments($arguments);
+ }
+ }
+ return false;
+ }
+}
diff --git a/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php b/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php
new file mode 100644
index 00000000000..5c7655b49c1
--- /dev/null
+++ b/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use OCP\Files\Search\ISearchOperator;
+
+/**
+ * transform IN (1000+ element) into (IN (1000 elements) OR IN(...))
+ */
+class SplitLargeIn extends ReplacingOptimizerStep {
+ public function processOperator(ISearchOperator &$operator): bool {
+ if (
+ $operator instanceof ISearchComparison &&
+ $operator->getType() === ISearchComparison::COMPARE_IN &&
+ count($operator->getValue()) > 1000
+ ) {
+ $chunks = array_chunk($operator->getValue(), 1000);
+ $chunkComparisons = array_map(function (array $values) use ($operator) {
+ return new SearchComparison(ISearchComparison::COMPARE_IN, $operator->getField(), $values);
+ }, $chunks);
+
+ $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $chunkComparisons);
+ return true;
+ }
+ parent::processOperator($operator);
+ return false;
+ }
+}
diff --git a/lib/private/Files/Search/SearchBinaryOperator.php b/lib/private/Files/Search/SearchBinaryOperator.php
index d7bba8f1b4e..59a1ba2dfaf 100644
--- a/lib/private/Files/Search/SearchBinaryOperator.php
+++ b/lib/private/Files/Search/SearchBinaryOperator.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Search;
@@ -28,7 +11,7 @@ use OCP\Files\Search\ISearchOperator;
class SearchBinaryOperator implements ISearchBinaryOperator {
/** @var string */
private $type;
- /** @var ISearchOperator[] */
+ /** @var (SearchBinaryOperator|SearchComparison)[] */
private $arguments;
private $hints = [];
@@ -36,7 +19,7 @@ class SearchBinaryOperator implements ISearchBinaryOperator {
* SearchBinaryOperator constructor.
*
* @param string $type
- * @param ISearchOperator[] $arguments
+ * @param (SearchBinaryOperator|SearchComparison)[] $arguments
*/
public function __construct($type, array $arguments) {
$this->type = $type;
@@ -57,6 +40,14 @@ class SearchBinaryOperator implements ISearchBinaryOperator {
return $this->arguments;
}
+ /**
+ * @param ISearchOperator[] $arguments
+ * @return void
+ */
+ public function setArguments(array $arguments): void {
+ $this->arguments = $arguments;
+ }
+
public function getQueryHint(string $name, $default) {
return $this->hints[$name] ?? $default;
}
@@ -64,4 +55,11 @@ class SearchBinaryOperator implements ISearchBinaryOperator {
public function setQueryHint(string $name, $value): void {
$this->hints[$name] = $value;
}
+
+ public function __toString(): string {
+ if ($this->type === ISearchBinaryOperator::OPERATOR_NOT) {
+ return '(not ' . $this->arguments[0] . ')';
+ }
+ return '(' . implode(' ' . $this->type . ' ', $this->arguments) . ')';
+ }
}
diff --git a/lib/private/Files/Search/SearchComparison.php b/lib/private/Files/Search/SearchComparison.php
index 122a1f730b4..e3a8f800506 100644
--- a/lib/private/Files/Search/SearchComparison.php
+++ b/lib/private/Files/Search/SearchComparison.php
@@ -1,70 +1,53 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Search;
use OCP\Files\Search\ISearchComparison;
+/**
+ * @psalm-import-type ParamValue from ISearchComparison
+ */
class SearchComparison implements ISearchComparison {
- /** @var string */
- private $type;
- /** @var string */
- private $field;
- /** @var string|integer|\DateTime */
- private $value;
- private $hints = [];
+ private array $hints = [];
- /**
- * SearchComparison constructor.
- *
- * @param string $type
- * @param string $field
- * @param \DateTime|int|string $value
- */
- public function __construct($type, $field, $value) {
- $this->type = $type;
- $this->field = $field;
- $this->value = $value;
+ public function __construct(
+ private string $type,
+ private string $field,
+ /** @var ParamValue $value */
+ private \DateTime|int|string|bool|array $value,
+ private string $extra = ''
+ ) {
}
/**
* @return string
*/
- public function getType() {
+ public function getType(): string {
return $this->type;
}
/**
* @return string
*/
- public function getField() {
+ public function getField(): string {
return $this->field;
}
+ public function getValue(): string|int|bool|\DateTime|array {
+ return $this->value;
+ }
+
/**
- * @return \DateTime|int|string
+ * @return string
+ * @since 28.0.0
*/
- public function getValue() {
- return $this->value;
+ public function getExtra(): string {
+ return $this->extra;
}
public function getQueryHint(string $name, $default) {
@@ -78,4 +61,8 @@ class SearchComparison implements ISearchComparison {
public static function escapeLikeParameter(string $param): string {
return addcslashes($param, '\\_%');
}
+
+ public function __toString(): string {
+ return $this->field . ' ' . $this->type . ' ' . json_encode($this->value);
+ }
}
diff --git a/lib/private/Files/Search/SearchOrder.php b/lib/private/Files/Search/SearchOrder.php
index 1395a87ac72..f3f62b933a1 100644
--- a/lib/private/Files/Search/SearchOrder.php
+++ b/lib/private/Files/Search/SearchOrder.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Search;
@@ -26,34 +9,33 @@ use OCP\Files\FileInfo;
use OCP\Files\Search\ISearchOrder;
class SearchOrder implements ISearchOrder {
- /** @var string */
- private $direction;
- /** @var string */
- private $field;
+ public function __construct(
+ private string $direction,
+ private string $field,
+ private string $extra = ''
+ ) {
+ }
/**
- * SearchOrder constructor.
- *
- * @param string $direction
- * @param string $field
+ * @return string
*/
- public function __construct($direction, $field) {
- $this->direction = $direction;
- $this->field = $field;
+ public function getDirection(): string {
+ return $this->direction;
}
/**
* @return string
*/
- public function getDirection() {
- return $this->direction;
+ public function getField(): string {
+ return $this->field;
}
/**
* @return string
+ * @since 28.0.0
*/
- public function getField() {
- return $this->field;
+ public function getExtra(): string {
+ return $this->extra;
}
public function sortFileInfo(FileInfo $a, FileInfo $b): int {
diff --git a/lib/private/Files/Search/SearchQuery.php b/lib/private/Files/Search/SearchQuery.php
index 7c76bdff978..e7cb031da3e 100644
--- a/lib/private/Files/Search/SearchQuery.php
+++ b/lib/private/Files/Search/SearchQuery.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Search;
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index b44ead003a8..53befe57e36 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -2,30 +2,15 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files;
use OC\Files\Config\MountProviderCollection;
+use OC\Files\Mount\HomeMountPoint;
use OC\Files\Mount\MountPoint;
-use OC\Files\ObjectStore\HomeObjectStoreStorage;
use OC\Files\Storage\Common;
use OC\Files\Storage\Home;
use OC\Files\Storage\Storage;
@@ -34,9 +19,15 @@ use OC\Files\Storage\Wrapper\Encoding;
use OC\Files\Storage\Wrapper\PermissionsMask;
use OC\Files\Storage\Wrapper\Quota;
use OC\Lockdown\Filesystem\NullStorage;
+use OC\Share\Share;
+use OC\Share20\ShareDisableChecker;
use OC_App;
use OC_Hook;
use OC_Util;
+use OCA\Files_External\Config\ConfigAdapter;
+use OCA\Files_Sharing\External\Mount;
+use OCA\Files_Sharing\ISharedMountPoint;
+use OCA\Files_Sharing\SharedMount;
use OCP\Constants;
use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
@@ -64,52 +55,35 @@ use Psr\Log\LoggerInterface;
class SetupManager {
private bool $rootSetup = false;
- private IEventLogger $eventLogger;
- private MountProviderCollection $mountProviderCollection;
- private IMountManager $mountManager;
- private IUserManager $userManager;
// List of users for which at least one mount is setup
private array $setupUsers = [];
// List of users for which all mounts are setup
private array $setupUsersComplete = [];
/** @var array<string, string[]> */
private array $setupUserMountProviders = [];
- private IEventDispatcher $eventDispatcher;
- private IUserMountCache $userMountCache;
- private ILockdownManager $lockdownManager;
- private IUserSession $userSession;
private ICache $cache;
- private LoggerInterface $logger;
- private IConfig $config;
private bool $listeningForProviders;
private array $fullSetupRequired = [];
private bool $setupBuiltinWrappersDone = false;
+ private bool $forceFullSetup = false;
public function __construct(
- IEventLogger $eventLogger,
- MountProviderCollection $mountProviderCollection,
- IMountManager $mountManager,
- IUserManager $userManager,
- IEventDispatcher $eventDispatcher,
- IUserMountCache $userMountCache,
- ILockdownManager $lockdownManager,
- IUserSession $userSession,
+ private IEventLogger $eventLogger,
+ private MountProviderCollection $mountProviderCollection,
+ private IMountManager $mountManager,
+ private IUserManager $userManager,
+ private IEventDispatcher $eventDispatcher,
+ private IUserMountCache $userMountCache,
+ private ILockdownManager $lockdownManager,
+ private IUserSession $userSession,
ICacheFactory $cacheFactory,
- LoggerInterface $logger,
- IConfig $config
+ private LoggerInterface $logger,
+ private IConfig $config,
+ private ShareDisableChecker $shareDisableChecker,
) {
- $this->eventLogger = $eventLogger;
- $this->mountProviderCollection = $mountProviderCollection;
- $this->mountManager = $mountManager;
- $this->userManager = $userManager;
- $this->eventDispatcher = $eventDispatcher;
- $this->userMountCache = $userMountCache;
- $this->lockdownManager = $lockdownManager;
- $this->logger = $logger;
- $this->userSession = $userSession;
$this->cache = $cacheFactory->createDistributed('setupmanager::');
$this->listeningForProviders = false;
- $this->config = $config;
+ $this->forceFullSetup = $this->config->getSystemValueBool('debug.force-full-fs-setup');
$this->setupListeners();
}
@@ -133,52 +107,55 @@ class SetupManager {
$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
- if ($storage->instanceOfStorage(Common::class)) {
+ if ($mount->getOptions() && $storage->instanceOfStorage(Common::class)) {
$storage->setMountOptions($mount->getOptions());
}
return $storage;
});
- Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
- if (!$mount->getOption('enable_sharing', true)) {
- return new PermissionsMask([
- 'storage' => $storage,
- 'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE,
- ]);
+ $reSharingEnabled = Share::isResharingAllowed();
+ $user = $this->userSession->getUser();
+ $sharingEnabledForUser = $user ? !$this->shareDisableChecker->sharingDisabledForUser($user->getUID()) : true;
+ Filesystem::addStorageWrapper(
+ 'sharing_mask',
+ function ($mountPoint, IStorage $storage, IMountPoint $mount) use ($reSharingEnabled, $sharingEnabledForUser) {
+ $sharingEnabledForMount = $mount->getOption('enable_sharing', true);
+ $isShared = $mount instanceof ISharedMountPoint;
+ if (!$sharingEnabledForMount || !$sharingEnabledForUser || (!$reSharingEnabled && $isShared)) {
+ return new PermissionsMask([
+ 'storage' => $storage,
+ 'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE,
+ ]);
+ }
+ return $storage;
}
- return $storage;
- });
+ );
// install storage availability wrapper, before most other wrappers
- Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) {
- if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
+ Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ $externalMount = $mount instanceof ConfigAdapter || $mount instanceof Mount;
+ if ($externalMount && !$storage->isLocal()) {
return new Availability(['storage' => $storage]);
}
return $storage;
});
Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
- if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
+ if ($mount->getOption('encoding_compatibility', false) && !$mount instanceof SharedMount) {
return new Encoding(['storage' => $storage]);
}
return $storage;
});
$quotaIncludeExternal = $this->config->getSystemValue('quota_include_external_storage', false);
- Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) use ($quotaIncludeExternal) {
+ Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage, IMountPoint $mount) use ($quotaIncludeExternal) {
// set up quota for home storages, even for other users
// which can happen when using sharing
-
- /**
- * @var Storage $storage
- */
- if ($storage->instanceOfStorage(HomeObjectStoreStorage::class) || $storage->instanceOfStorage(Home::class)) {
- if (is_object($storage->getUser())) {
- $user = $storage->getUser();
- return new Quota(['storage' => $storage, 'quotaCallback' => function () use ($user) {
- return OC_Util::getUserQuota($user);
- }, 'root' => 'files', 'include_external_storage' => $quotaIncludeExternal]);
- }
+ if ($mount instanceof HomeMountPoint) {
+ $user = $mount->getUser();
+ return new Quota(['storage' => $storage, 'quotaCallback' => function () use ($user) {
+ return OC_Util::getUserQuota($user);
+ }, 'root' => 'files', 'include_external_storage' => $quotaIncludeExternal]);
}
return $storage;
@@ -345,12 +322,13 @@ class SetupManager {
if ($this->rootSetup) {
return;
}
+
+ $this->setupBuiltinWrappers();
+
$this->rootSetup = true;
$this->eventLogger->start('fs:setup:root', 'Setup root filesystem');
- $this->setupBuiltinWrappers();
-
$rootMounts = $this->mountProviderCollection->getRootMounts();
foreach ($rootMounts as $rootMountProvider) {
$this->mountManager->addMount($rootMountProvider);
@@ -479,6 +457,10 @@ class SetupManager {
}
private function fullSetupRequired(IUser $user): bool {
+ if ($this->forceFullSetup) {
+ return true;
+ }
+
// we perform a "cached" setup only after having done the full setup recently
// this is also used to trigger a full setup after handling events that are likely
// to change the available mounts
diff --git a/lib/private/Files/SetupManagerFactory.php b/lib/private/Files/SetupManagerFactory.php
index 1d9efbd411f..6ae38c6fdbc 100644
--- a/lib/private/Files/SetupManagerFactory.php
+++ b/lib/private/Files/SetupManagerFactory.php
@@ -2,27 +2,13 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files;
+use OC\Share20\ShareDisableChecker;
use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IMountProviderCollection;
@@ -36,40 +22,21 @@ use OCP\Lockdown\ILockdownManager;
use Psr\Log\LoggerInterface;
class SetupManagerFactory {
- private IEventLogger $eventLogger;
- private IMountProviderCollection $mountProviderCollection;
- private IUserManager $userManager;
- private IEventDispatcher $eventDispatcher;
- private IUserMountCache $userMountCache;
- private ILockdownManager $lockdownManager;
- private IUserSession $userSession;
private ?SetupManager $setupManager;
- private ICacheFactory $cacheFactory;
- private LoggerInterface $logger;
- private IConfig $config;
public function __construct(
- IEventLogger $eventLogger,
- IMountProviderCollection $mountProviderCollection,
- IUserManager $userManager,
- IEventDispatcher $eventDispatcher,
- IUserMountCache $userMountCache,
- ILockdownManager $lockdownManager,
- IUserSession $userSession,
- ICacheFactory $cacheFactory,
- LoggerInterface $logger,
- IConfig $config
+ private IEventLogger $eventLogger,
+ private IMountProviderCollection $mountProviderCollection,
+ private IUserManager $userManager,
+ private IEventDispatcher $eventDispatcher,
+ private IUserMountCache $userMountCache,
+ private ILockdownManager $lockdownManager,
+ private IUserSession $userSession,
+ private ICacheFactory $cacheFactory,
+ private LoggerInterface $logger,
+ private IConfig $config,
+ private ShareDisableChecker $shareDisableChecker,
) {
- $this->eventLogger = $eventLogger;
- $this->mountProviderCollection = $mountProviderCollection;
- $this->userManager = $userManager;
- $this->eventDispatcher = $eventDispatcher;
- $this->userMountCache = $userMountCache;
- $this->lockdownManager = $lockdownManager;
- $this->userSession = $userSession;
- $this->cacheFactory = $cacheFactory;
- $this->logger = $logger;
- $this->config = $config;
$this->setupManager = null;
}
@@ -86,7 +53,8 @@ class SetupManagerFactory {
$this->userSession,
$this->cacheFactory,
$this->logger,
- $this->config
+ $this->config,
+ $this->shareDisableChecker,
);
}
return $this->setupManager;
diff --git a/lib/private/Files/SimpleFS/NewSimpleFile.php b/lib/private/Files/SimpleFS/NewSimpleFile.php
index 50511b5a5f9..d0986592c03 100644
--- a/lib/private/Files/SimpleFS/NewSimpleFile.php
+++ b/lib/private/Files/SimpleFS/NewSimpleFile.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\SimpleFS;
diff --git a/lib/private/Files/SimpleFS/SimpleFile.php b/lib/private/Files/SimpleFS/SimpleFile.php
index 76ab06feaab..cbb3af4db29 100644
--- a/lib/private/Files/SimpleFS/SimpleFile.php
+++ b/lib/private/Files/SimpleFS/SimpleFile.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\SimpleFS;
diff --git a/lib/private/Files/SimpleFS/SimpleFolder.php b/lib/private/Files/SimpleFS/SimpleFolder.php
index 4d24aa138c1..0da552e402b 100644
--- a/lib/private/Files/SimpleFS/SimpleFolder.php
+++ b/lib/private/Files/SimpleFS/SimpleFolder.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\SimpleFS;
@@ -28,8 +9,8 @@ use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
-use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
class SimpleFolder implements ISimpleFolder {
/** @var Folder */
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index 5ab411434d0..e613e435f03 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -1,48 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Greta Doci <gretadoci@gmail.com>
- * @author hkjolhede <hkjolhede@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Martin Mattel <martin.mattel@diemattels.at>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Roland Tapken <roland@bitarbeiter.net>
- * @author Sam Tuke <mail@samtuke.com>
- * @author scambra <sergio@entrecables.com>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Vinicius Cubas Brand <vinicius@eita.org.br>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
use OC\Files\Cache\Cache;
+use OC\Files\Cache\CacheDependencies;
use OC\Files\Cache\Propagator;
use OC\Files\Cache\Scanner;
use OC\Files\Cache\Updater;
@@ -61,8 +27,10 @@ use OCP\Files\ReservedWordException;
use OCP\Files\Storage\ILockingStorage;
use OCP\Files\Storage\IStorage;
use OCP\Files\Storage\IWriteStreamStorage;
+use OCP\Files\StorageNotAvailableException;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
+use OCP\Server;
use Psr\Log\LoggerInterface;
/**
@@ -338,12 +306,20 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
return $this->filemtime($path) > $time;
}
+ protected function getCacheDependencies(): CacheDependencies {
+ static $dependencies = null;
+ if (!$dependencies) {
+ $dependencies = Server::get(CacheDependencies::class);
+ }
+ return $dependencies;
+ }
+
public function getCache($path = '', $storage = null) {
if (!$storage) {
$storage = $this;
}
if (!isset($storage->cache)) {
- $storage->cache = new Cache($storage);
+ $storage->cache = new Cache($storage, $this->getCacheDependencies());
}
return $storage->cache;
}
@@ -398,13 +374,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
}
public function getStorageCache($storage = null) {
- if (!$storage) {
- $storage = $this;
- }
- if (!isset($this->storageCache)) {
- $this->storageCache = new \OC\Files\Cache\Storage($storage);
- }
- return $this->storageCache;
+ return $this->getCache($storage)->getStorageCache();
}
/**
@@ -562,7 +532,9 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
* @throws InvalidPathException
*/
protected function verifyPosixPath($fileName) {
- $this->scanForInvalidCharacters($fileName, "\\/");
+ $invalidChars = \OCP\Util::getForbiddenFileNameChars();
+ $this->scanForInvalidCharacters($fileName, $invalidChars);
+
$fileName = trim($fileName);
$reservedNames = ['*'];
if (in_array($fileName, $reservedNames)) {
@@ -572,11 +544,11 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
/**
* @param string $fileName
- * @param string $invalidChars
+ * @param string[] $invalidChars
* @throws InvalidPathException
*/
- private function scanForInvalidCharacters($fileName, $invalidChars) {
- foreach (str_split($invalidChars) as $char) {
+ private function scanForInvalidCharacters(string $fileName, array $invalidChars) {
+ foreach ($invalidChars as $char) {
if (str_contains($fileName, $char)) {
throw new InvalidCharacterInPathException();
}
@@ -601,7 +573,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
* @return mixed
*/
public function getMountOption($name, $default = null) {
- return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
+ return $this->mountOptions[$name] ?? $default;
}
/**
@@ -663,7 +635,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
private function isSameStorage(IStorage $storage): bool {
while ($storage->instanceOfStorage(Wrapper::class)) {
/**
- * @var Wrapper $sourceStorage
+ * @var Wrapper $storage
*/
$storage = $storage->getWrapperStorage();
}
@@ -861,6 +833,19 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
}
/**
+ * Allow setting the storage owner
+ *
+ * This can be used for storages that do not have a dedicated owner, where we want to
+ * pass the user that we setup the mountpoint for along to the storage layer
+ *
+ * @param string|null $user
+ * @return void
+ */
+ public function setOwner(?string $user): void {
+ $this->owner = $user;
+ }
+
+ /**
* @return bool
*/
public function needsPartFile() {
@@ -875,7 +860,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
* @param int $size
* @return int
*/
- public function writeStream(string $path, $stream, int $size = null): int {
+ public function writeStream(string $path, $stream, ?int $size = null): int {
$target = $this->fopen($path, 'w');
if (!$target) {
throw new GenericFileException("Failed to open $path for writing");
@@ -894,6 +879,11 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
public function getDirectoryContent($directory): \Traversable {
$dh = $this->opendir($directory);
+
+ if ($dh === false) {
+ throw new StorageNotAvailableException('Directory listing failed');
+ }
+
if (is_resource($dh)) {
$basePath = rtrim($directory, '/');
while (($file = readdir($dh)) !== false) {
diff --git a/lib/private/Files/Storage/CommonTest.php b/lib/private/Files/Storage/CommonTest.php
index 3800bba2b52..b92e493bc2c 100644
--- a/lib/private/Files/Storage/CommonTest.php
+++ b/lib/private/Files/Storage/CommonTest.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php
index 70f22a17034..50e0dd5271a 100644
--- a/lib/private/Files/Storage/DAV.php
+++ b/lib/private/Files/Storage/DAV.php
@@ -1,39 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Carlos Cerrillo <ccerrillo@gmail.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Philipp Kapfer <philipp.kapfer@gmx.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
@@ -55,11 +25,11 @@ use OCP\ICertificateManager;
use OCP\IConfig;
use OCP\Util;
use Psr\Http\Message\ResponseInterface;
+use Psr\Log\LoggerInterface;
use Sabre\DAV\Client;
use Sabre\DAV\Xml\Property\ResourceType;
use Sabre\HTTP\ClientException;
use Sabre\HTTP\ClientHttpException;
-use Psr\Log\LoggerInterface;
use Sabre\HTTP\RequestInterface;
/**
@@ -120,9 +90,9 @@ class DAV extends Common {
if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
$host = $params['host'];
//remove leading http[s], will be generated in createBaseUri()
- if (substr($host, 0, 8) == "https://") {
+ if (str_starts_with($host, "https://")) {
$host = substr($host, 8);
- } elseif (substr($host, 0, 7) == "http://") {
+ } elseif (str_starts_with($host, "http://")) {
$host = substr($host, 7);
}
$this->host = $host;
@@ -470,9 +440,6 @@ class DAV extends Common {
$this->client->proppatch($this->encodePath($path), ['{DAV:}lastmodified' => $mtime]);
// non-owncloud clients might not have accepted the property, need to recheck it
$response = $this->client->propfind($this->encodePath($path), ['{DAV:}getlastmodified'], 0);
- if ($response === false) {
- return false;
- }
if (isset($response['{DAV:}getlastmodified'])) {
$remoteMtime = strtotime($response['{DAV:}getlastmodified']);
if ($remoteMtime !== $mtime) {
@@ -911,9 +878,6 @@ class DAV extends Common {
self::PROPFIND_PROPS,
1
);
- if ($responses === false) {
- return;
- }
array_shift($responses); //the first entry is the current directory
if (!$this->statCache->hasKey($directory)) {
@@ -921,7 +885,7 @@ class DAV extends Common {
}
foreach ($responses as $file => $response) {
- $file = urldecode($file);
+ $file = rawurldecode($file);
$file = substr($file, strlen($this->root));
$file = $this->cleanPath($file);
$this->statCache->set($file, $response);
diff --git a/lib/private/Files/Storage/FailedStorage.php b/lib/private/Files/Storage/FailedStorage.php
index 07b3b21d965..87a6e7f5041 100644
--- a/lib/private/Files/Storage/FailedStorage.php
+++ b/lib/private/Files/Storage/FailedStorage.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/Home.php b/lib/private/Files/Storage/Home.php
index 5427bc425c2..9a336d2efcc 100644
--- a/lib/private/Files/Storage/Home.php
+++ b/lib/private/Files/Storage/Home.php
@@ -1,31 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
use OC\Files\Cache\HomePropagator;
+use OCP\IUser;
/**
* Specialized version of Local storage for home directory usage
@@ -67,7 +50,7 @@ class Home extends Local implements \OCP\Files\IHomeStorage {
$storage = $this;
}
if (!isset($this->cache)) {
- $this->cache = new \OC\Files\Cache\HomeCache($storage);
+ $this->cache = new \OC\Files\Cache\HomeCache($storage, $this->getCacheDependencies());
}
return $this->cache;
}
@@ -94,7 +77,7 @@ class Home extends Local implements \OCP\Files\IHomeStorage {
*
* @return \OC\User\User owner of this home storage
*/
- public function getUser() {
+ public function getUser(): IUser {
return $this->user;
}
diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php
index 02708ed4f7d..ac3696118f7 100644
--- a/lib/private/Files/Storage/Local.php
+++ b/lib/private/Files/Storage/Local.php
@@ -1,45 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author aler9 <46489434+aler9@users.noreply.github.com>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Boris Rybalkin <ribalkin@gmail.com>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Leuker <j.leuker@hosting.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Klaas Freitag <freitag@owncloud.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Martin Brugnara <martin@0x6d62.eu>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sjors van der Pluijm <sjors@desjors.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
@@ -51,6 +15,7 @@ use OCP\Files\ForbiddenException;
use OCP\Files\GenericFileException;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\Storage\IStorage;
+use OCP\Files\StorageNotAvailableException;
use OCP\IConfig;
use OCP\Util;
use Psr\Log\LoggerInterface;
@@ -73,6 +38,8 @@ class Local extends \OC\Files\Storage\Common {
protected bool $unlinkOnTruncate;
+ protected bool $caseInsensitive = false;
+
public function __construct($arguments) {
if (!isset($arguments['datadir']) || !is_string($arguments['datadir'])) {
throw new \InvalidArgumentException('No data directory set for local storage');
@@ -85,16 +52,23 @@ class Local extends \OC\Files\Storage\Common {
$realPath = realpath($this->datadir) ?: $this->datadir;
$this->realDataDir = rtrim($realPath, '/') . '/';
}
- if (substr($this->datadir, -1) !== '/') {
+ if (!str_ends_with($this->datadir, '/')) {
$this->datadir .= '/';
}
$this->dataDirLength = strlen($this->realDataDir);
$this->config = \OC::$server->get(IConfig::class);
$this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class);
$this->defUMask = $this->config->getSystemValue('localstorage.umask', 0022);
+ $this->caseInsensitive = $this->config->getSystemValueBool('localstorage.case_insensitive', false);
// support Write-Once-Read-Many file systems
$this->unlinkOnTruncate = $this->config->getSystemValueBool('localstorage.unlink_on_truncate', false);
+
+ if (isset($arguments['isExternal']) && $arguments['isExternal'] && !$this->stat('')) {
+ // data dir not accessible or available, can happen when using an external storage of type Local
+ // on an unmounted system mount point
+ throw new StorageNotAvailableException('Local storage path does not exist "' . $this->getSourcePath('') . '"');
+ }
}
public function __destruct() {
@@ -155,13 +129,19 @@ class Local extends \OC\Files\Storage\Common {
}
public function is_dir($path) {
- if (substr($path, -1) == '/') {
+ if ($this->caseInsensitive && !$this->file_exists($path)) {
+ return false;
+ }
+ if (str_ends_with($path, '/')) {
$path = substr($path, 0, -1);
}
return is_dir($this->getSourcePath($path));
}
public function is_file($path) {
+ if ($this->caseInsensitive && !$this->file_exists($path)) {
+ return false;
+ }
return is_file($this->getSourcePath($path));
}
@@ -264,7 +244,17 @@ class Local extends \OC\Files\Storage\Common {
}
public function file_exists($path) {
- return file_exists($this->getSourcePath($path));
+ if ($this->caseInsensitive) {
+ $fullPath = $this->getSourcePath($path);
+ $parentPath = dirname($fullPath);
+ if (!is_dir($parentPath)) {
+ return false;
+ }
+ $content = scandir($parentPath, SCANDIR_SORT_NONE);
+ return is_array($content) && array_search(basename($fullPath), $content) !== false;
+ } else {
+ return file_exists($this->getSourcePath($path));
+ }
}
public function filemtime($path) {
@@ -365,6 +355,11 @@ class Local extends \OC\Files\Storage\Common {
}
if (@rename($this->getSourcePath($source), $this->getSourcePath($target))) {
+ if ($this->caseInsensitive) {
+ if (mb_strtolower($target) === mb_strtolower($source) && !$this->file_exists($target)) {
+ return false;
+ }
+ }
return true;
}
@@ -381,6 +376,11 @@ class Local extends \OC\Files\Storage\Common {
}
$result = copy($this->getSourcePath($source), $this->getSourcePath($target));
umask($oldMask);
+ if ($this->caseInsensitive) {
+ if (mb_strtolower($target) === mb_strtolower($source) && !$this->file_exists($target)) {
+ return false;
+ }
+ }
return $result;
}
}
@@ -488,6 +488,7 @@ class Local extends \OC\Files\Storage\Common {
$realPath = realpath($pathToResolve);
while ($realPath === false) { // for non existing files check the parent directory
$currentPath = dirname($currentPath);
+ /** @psalm-suppress TypeDoesNotContainType Let's be extra cautious and still check for empty string */
if ($currentPath === '' || $currentPath === '.') {
return $fullPath;
}
@@ -548,11 +549,14 @@ class Local extends \OC\Files\Storage\Common {
}
private function canDoCrossStorageMove(IStorage $sourceStorage) {
+ /** @psalm-suppress UndefinedClass */
return $sourceStorage->instanceOfStorage(Local::class)
// Don't treat ACLStorageWrapper like local storage where copy can be done directly.
// Instead, use the slower recursive copying in php from Common::copyFromStorage with
// more permissions checks.
&& !$sourceStorage->instanceOfStorage('OCA\GroupFolders\ACL\ACLStorageWrapper')
+ // Same for access control
+ && !$sourceStorage->instanceOfStorage(\OCA\FilesAccessControl\StorageWrapper::class)
// when moving encrypted files we have to handle keys and the target might not be encrypted
&& !$sourceStorage->instanceOfStorage(Encryption::class);
}
@@ -606,7 +610,7 @@ class Local extends \OC\Files\Storage\Common {
}
}
- public function writeStream(string $path, $stream, int $size = null): int {
+ public function writeStream(string $path, $stream, ?int $size = null): int {
/** @var int|false $result We consider here that returned size will never be a float because we write less than 4GB */
$result = $this->file_put_contents($path, $stream);
if (is_resource($stream)) {
diff --git a/lib/private/Files/Storage/LocalRootStorage.php b/lib/private/Files/Storage/LocalRootStorage.php
index 71584afef08..ae0575fe043 100644
--- a/lib/private/Files/Storage/LocalRootStorage.php
+++ b/lib/private/Files/Storage/LocalRootStorage.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/LocalTempFileTrait.php b/lib/private/Files/Storage/LocalTempFileTrait.php
index 314e38cb277..26fbcc238fd 100644
--- a/lib/private/Files/Storage/LocalTempFileTrait.php
+++ b/lib/private/Files/Storage/LocalTempFileTrait.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/PolyFill/CopyDirectory.php b/lib/private/Files/Storage/PolyFill/CopyDirectory.php
index ff05eecb134..4b3e367da78 100644
--- a/lib/private/Files/Storage/PolyFill/CopyDirectory.php
+++ b/lib/private/Files/Storage/PolyFill/CopyDirectory.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Martin Mattel <martin.mattel@diemattels.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\PolyFill;
diff --git a/lib/private/Files/Storage/Storage.php b/lib/private/Files/Storage/Storage.php
index 0a2511de164..44b1a52cfc0 100644
--- a/lib/private/Files/Storage/Storage.php
+++ b/lib/private/Files/Storage/Storage.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/StorageFactory.php b/lib/private/Files/Storage/StorageFactory.php
index cab739c4a81..18fca1d28e3 100644
--- a/lib/private/Files/Storage/StorageFactory.php
+++ b/lib/private/Files/Storage/StorageFactory.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/Temporary.php b/lib/private/Files/Storage/Temporary.php
index 393a37f834a..95ae84cb7d9 100644
--- a/lib/private/Files/Storage/Temporary.php
+++ b/lib/private/Files/Storage/Temporary.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage;
diff --git a/lib/private/Files/Storage/Wrapper/Availability.php b/lib/private/Files/Storage/Wrapper/Availability.php
index 693d943f0dc..149cbbaa33b 100644
--- a/lib/private/Files/Storage/Wrapper/Availability.php
+++ b/lib/private/Files/Storage/Wrapper/Availability.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\Wrapper;
diff --git a/lib/private/Files/Storage/Wrapper/Encoding.php b/lib/private/Files/Storage/Wrapper/Encoding.php
index 6633cbf41e3..11f21eb828e 100644
--- a/lib/private/Files/Storage/Wrapper/Encoding.php
+++ b/lib/private/Files/Storage/Wrapper/Encoding.php
@@ -1,35 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\Wrapper;
-use OCP\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
+use OCP\Cache\CappedMemoryCache;
use OCP\Files\Storage\IStorage;
use OCP\ICache;
diff --git a/lib/private/Files/Storage/Wrapper/EncodingDirectoryWrapper.php b/lib/private/Files/Storage/Wrapper/EncodingDirectoryWrapper.php
index 3cda399f22d..26b32d9aa62 100644
--- a/lib/private/Files/Storage/Wrapper/EncodingDirectoryWrapper.php
+++ b/lib/private/Files/Storage/Wrapper/EncodingDirectoryWrapper.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2021, Nextcloud GmbH.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Storage\Wrapper;
use Icewind\Streams\DirectoryWrapper;
diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php
index a27f499a210..5c7862e8226 100644
--- a/lib/private/Files/Storage/Wrapper/Encryption.php
+++ b/lib/private/Files/Storage/Wrapper/Encryption.php
@@ -1,40 +1,10 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author jknockaert <jasper@knockaert.nl>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr M <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Richard Steinmetz <richard@steinmetz.cloud>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Storage\Wrapper;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
@@ -100,20 +70,22 @@ class Encryption extends Wrapper {
/** @var CappedMemoryCache<bool> */
private CappedMemoryCache $encryptedPaths;
+ private $enabled = true;
+
/**
* @param array $parameters
*/
public function __construct(
$parameters,
- IManager $encryptionManager = null,
- Util $util = null,
- LoggerInterface $logger = null,
- IFile $fileHelper = null,
+ ?IManager $encryptionManager = null,
+ ?Util $util = null,
+ ?LoggerInterface $logger = null,
+ ?IFile $fileHelper = null,
$uid = null,
- IStorage $keyStorage = null,
- Update $update = null,
- Manager $mountManager = null,
- ArrayCache $arrayCache = null
+ ?IStorage $keyStorage = null,
+ ?Update $update = null,
+ ?Manager $mountManager = null,
+ ?ArrayCache $arrayCache = null
) {
$this->mountPoint = $parameters['mountPoint'];
$this->mount = $parameters['mount'];
@@ -392,6 +364,10 @@ class Encryption extends Wrapper {
return $this->storage->fopen($path, $mode);
}
+ if (!$this->enabled) {
+ return $this->storage->fopen($path, $mode);
+ }
+
$encryptionEnabled = $this->encryptionManager->isEnabled();
$shouldEncrypt = false;
$encryptionModule = null;
@@ -938,34 +914,6 @@ class Encryption extends Wrapper {
}
/**
- * parse raw header to array
- *
- * @param string $rawHeader
- * @return array
- */
- protected function parseRawHeader($rawHeader) {
- $result = [];
- if (str_starts_with($rawHeader, Util::HEADER_START)) {
- $header = $rawHeader;
- $endAt = strpos($header, Util::HEADER_END);
- if ($endAt !== false) {
- $header = substr($header, 0, $endAt + strlen(Util::HEADER_END));
-
- // +1 to not start with an ':' which would result in empty element at the beginning
- $exploded = explode(':', substr($header, strlen(Util::HEADER_START) + 1));
-
- $element = array_shift($exploded);
- while ($element !== Util::HEADER_END) {
- $result[$element] = array_shift($exploded);
- $element = array_shift($exploded);
- }
- }
- }
-
- return $result;
- }
-
- /**
* read header from file
*
* @param string $path
@@ -988,7 +936,7 @@ class Encryption extends Wrapper {
if ($isEncrypted) {
$firstBlock = $this->readFirstBlock($path);
- $result = $this->parseRawHeader($firstBlock);
+ $result = $this->util->parseRawHeader($firstBlock);
// if the header doesn't contain a encryption module we check if it is a
// legacy file. If true, we add the default encryption module
@@ -1084,7 +1032,7 @@ class Encryption extends Wrapper {
return $encryptionModule->shouldEncrypt($fullPath);
}
- public function writeStream(string $path, $stream, int $size = null): int {
+ public function writeStream(string $path, $stream, ?int $size = null): int {
// always fall back to fopen
$target = $this->fopen($path, 'w');
[$count, $result] = \OC_Helper::streamCopy($stream, $target);
@@ -1093,7 +1041,7 @@ class Encryption extends Wrapper {
// object store, stores the size after write and doesn't update this during scan
// manually store the unencrypted size
- if ($result && $this->getWrapperStorage()->instanceOfStorage(ObjectStoreStorage::class)) {
+ if ($result && $this->getWrapperStorage()->instanceOfStorage(ObjectStoreStorage::class) && $this->shouldEncrypt($path)) {
$this->getCache()->put($path, ['unencrypted_size' => $count]);
}
@@ -1103,4 +1051,14 @@ class Encryption extends Wrapper {
public function clearIsEncryptedCache(): void {
$this->encryptedPaths->clear();
}
+
+ /**
+ * Allow temporarily disabling the wrapper
+ *
+ * @param bool $enabled
+ * @return void
+ */
+ public function setEnabled(bool $enabled): void {
+ $this->enabled = $enabled;
+ }
}
diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php
index 1921ac27848..2e8306dc705 100644
--- a/lib/private/Files/Storage/Wrapper/Jail.php
+++ b/lib/private/Files/Storage/Wrapper/Jail.php
@@ -1,35 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\Wrapper;
use OC\Files\Cache\Wrapper\CacheJail;
use OC\Files\Cache\Wrapper\JailPropagator;
+use OC\Files\Cache\Wrapper\JailWatcher;
use OC\Files\Filesystem;
use OCP\Files\Storage\IStorage;
use OCP\Files\Storage\IWriteStreamStorage;
@@ -396,10 +376,7 @@ class Jail extends Wrapper {
* @return \OC\Files\Cache\Cache
*/
public function getCache($path = '', $storage = null) {
- if (!$storage) {
- $storage = $this->getWrapperStorage();
- }
- $sourceCache = $this->getWrapperStorage()->getCache($this->getUnjailedPath($path), $storage);
+ $sourceCache = $this->getWrapperStorage()->getCache($this->getUnjailedPath($path));
return new CacheJail($sourceCache, $this->rootPath);
}
@@ -421,10 +398,8 @@ class Jail extends Wrapper {
* @return \OC\Files\Cache\Watcher
*/
public function getWatcher($path = '', $storage = null) {
- if (!$storage) {
- $storage = $this;
- }
- return $this->getWrapperStorage()->getWatcher($this->getUnjailedPath($path), $storage);
+ $sourceWatcher = $this->getWrapperStorage()->getWatcher($this->getUnjailedPath($path), $this->getWrapperStorage());
+ return new JailWatcher($sourceWatcher, $this->rootPath);
}
/**
@@ -517,7 +492,7 @@ class Jail extends Wrapper {
return $this->propagator;
}
- public function writeStream(string $path, $stream, int $size = null): int {
+ public function writeStream(string $path, $stream, ?int $size = null): int {
$storage = $this->getWrapperStorage();
if ($storage->instanceOfStorage(IWriteStreamStorage::class)) {
/** @var IWriteStreamStorage $storage */
diff --git a/lib/private/Files/Storage/Wrapper/KnownMtime.php b/lib/private/Files/Storage/Wrapper/KnownMtime.php
new file mode 100644
index 00000000000..a7360ae1346
--- /dev/null
+++ b/lib/private/Files/Storage/Wrapper/KnownMtime.php
@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Files\Storage\Wrapper;
+
+use OCP\Cache\CappedMemoryCache;
+use OCP\Files\Storage\IStorage;
+use Psr\Clock\ClockInterface;
+
+/**
+ * Wrapper that overwrites the mtime return by stat/getMetaData if the returned value
+ * is lower than when we last modified the file.
+ *
+ * This is useful because some storage servers can return an outdated mtime right after writes
+ */
+class KnownMtime extends Wrapper {
+ private CappedMemoryCache $knowMtimes;
+ private ClockInterface $clock;
+
+ public function __construct($arguments) {
+ parent::__construct($arguments);
+ $this->knowMtimes = new CappedMemoryCache();
+ $this->clock = $arguments['clock'];
+ }
+
+ public function file_put_contents($path, $data) {
+ $result = parent::file_put_contents($path, $data);
+ if ($result) {
+ $now = $this->clock->now()->getTimestamp();
+ $this->knowMtimes->set($path, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function stat($path) {
+ $stat = parent::stat($path);
+ if ($stat) {
+ $this->applyKnownMtime($path, $stat);
+ }
+ return $stat;
+ }
+
+ public function getMetaData($path) {
+ $stat = parent::getMetaData($path);
+ if ($stat) {
+ $this->applyKnownMtime($path, $stat);
+ }
+ return $stat;
+ }
+
+ private function applyKnownMtime(string $path, array &$stat) {
+ if (isset($stat['mtime'])) {
+ $knownMtime = $this->knowMtimes->get($path) ?? 0;
+ $stat['mtime'] = max($stat['mtime'], $knownMtime);
+ }
+ }
+
+ public function filemtime($path) {
+ $knownMtime = $this->knowMtimes->get($path) ?? 0;
+ return max(parent::filemtime($path), $knownMtime);
+ }
+
+ public function mkdir($path) {
+ $result = parent::mkdir($path);
+ if ($result) {
+ $this->knowMtimes->set($path, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function rmdir($path) {
+ $result = parent::rmdir($path);
+ if ($result) {
+ $this->knowMtimes->set($path, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function unlink($path) {
+ $result = parent::unlink($path);
+ if ($result) {
+ $this->knowMtimes->set($path, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function rename($source, $target) {
+ $result = parent::rename($source, $target);
+ if ($result) {
+ $this->knowMtimes->set($target, $this->clock->now()->getTimestamp());
+ $this->knowMtimes->set($source, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function copy($source, $target) {
+ $result = parent::copy($source, $target);
+ if ($result) {
+ $this->knowMtimes->set($target, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function fopen($path, $mode) {
+ $result = parent::fopen($path, $mode);
+ if ($result && $mode === 'w') {
+ $this->knowMtimes->set($path, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function touch($path, $mtime = null) {
+ $result = parent::touch($path, $mtime);
+ if ($result) {
+ $this->knowMtimes->set($path, $mtime ?? $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ $result = parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ if ($result) {
+ $this->knowMtimes->set($targetInternalPath, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ $result = parent::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ if ($result) {
+ $this->knowMtimes->set($targetInternalPath, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+
+ public function writeStream(string $path, $stream, ?int $size = null): int {
+ $result = parent::writeStream($path, $stream, $size);
+ if ($result) {
+ $this->knowMtimes->set($path, $this->clock->now()->getTimestamp());
+ }
+ return $result;
+ }
+}
diff --git a/lib/private/Files/Storage/Wrapper/PermissionsMask.php b/lib/private/Files/Storage/Wrapper/PermissionsMask.php
index 0d140e0a39d..c502de41a86 100644
--- a/lib/private/Files/Storage/Wrapper/PermissionsMask.php
+++ b/lib/private/Files/Storage/Wrapper/PermissionsMask.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\Wrapper;
@@ -140,7 +120,7 @@ class PermissionsMask extends Wrapper {
$data = parent::getMetaData($path);
if ($data && isset($data['permissions'])) {
- $data['scan_permissions'] = isset($data['scan_permissions']) ? $data['scan_permissions'] : $data['permissions'];
+ $data['scan_permissions'] = $data['scan_permissions'] ?? $data['permissions'];
$data['permissions'] &= $this->mask;
}
return $data;
@@ -155,7 +135,7 @@ class PermissionsMask extends Wrapper {
public function getDirectoryContent($directory): \Traversable {
foreach ($this->getWrapperStorage()->getDirectoryContent($directory) as $data) {
- $data['scan_permissions'] = isset($data['scan_permissions']) ? $data['scan_permissions'] : $data['permissions'];
+ $data['scan_permissions'] = $data['scan_permissions'] ?? $data['permissions'];
$data['permissions'] &= $this->mask;
yield $data;
diff --git a/lib/private/Files/Storage/Wrapper/Quota.php b/lib/private/Files/Storage/Wrapper/Quota.php
index 35dbc9fcd26..8c6799fdd2d 100644
--- a/lib/private/Files/Storage/Wrapper/Quota.php
+++ b/lib/private/Files/Storage/Wrapper/Quota.php
@@ -1,34 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\Wrapper;
diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php
index 9f5564b4490..29acc9ad1c2 100644
--- a/lib/private/Files/Storage/Wrapper/Wrapper.php
+++ b/lib/private/Files/Storage/Wrapper/Wrapper.php
@@ -1,41 +1,20 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Vinicius Cubas Brand <vinicius@eita.org.br>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Storage\Wrapper;
+use OC\Files\Storage\FailedStorage;
use OCP\Files\InvalidPathException;
use OCP\Files\Storage\ILockingStorage;
use OCP\Files\Storage\IStorage;
use OCP\Files\Storage\IWriteStreamStorage;
use OCP\Lock\ILockingProvider;
+use OCP\Server;
+use Psr\Log\LoggerInterface;
class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStreamStorage {
/**
@@ -60,6 +39,12 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea
* @return \OC\Files\Storage\Storage
*/
public function getWrapperStorage() {
+ if (!$this->storage) {
+ $message = "storage wrapper " . get_class($this) . " doesn't have a wrapped storage set";
+ $logger = Server::get(LoggerInterface::class);
+ $logger->error($message);
+ $this->storage = new FailedStorage(['exception' => new \Exception($message)]);
+ }
return $this->storage;
}
@@ -637,7 +622,7 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea
return $this->getWrapperStorage()->needsPartFile();
}
- public function writeStream(string $path, $stream, int $size = null): int {
+ public function writeStream(string $path, $stream, ?int $size = null): int {
$storage = $this->getWrapperStorage();
if ($storage->instanceOfStorage(IWriteStreamStorage::class)) {
/** @var IWriteStreamStorage $storage */
@@ -654,4 +639,19 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea
public function getDirectoryContent($directory): \Traversable {
return $this->getWrapperStorage()->getDirectoryContent($directory);
}
+
+ public function isWrapperOf(IStorage $storage) {
+ $wrapped = $this->getWrapperStorage();
+ if ($wrapped === $storage) {
+ return true;
+ }
+ if ($wrapped instanceof Wrapper) {
+ return $wrapped->isWrapperOf($storage);
+ }
+ return false;
+ }
+
+ public function setOwner(?string $user): void {
+ $this->getWrapperStorage()->setOwner($user);
+ }
}
diff --git a/lib/private/Files/Stream/Encryption.php b/lib/private/Files/Stream/Encryption.php
index bcf0a10740b..32c0021cd23 100644
--- a/lib/private/Files/Stream/Encryption.php
+++ b/lib/private/Files/Stream/Encryption.php
@@ -1,33 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author jknockaert <jasper@knockaert.nl>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author martink-p <47943787+martink-p@users.noreply.github.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Stream;
@@ -153,18 +129,18 @@ class Encryption extends Wrapper {
* @throws \BadMethodCallException
*/
public static function wrap($source, $internalPath, $fullPath, array $header,
- $uid,
- \OCP\Encryption\IEncryptionModule $encryptionModule,
- \OC\Files\Storage\Storage $storage,
- \OC\Files\Storage\Wrapper\Encryption $encStorage,
- \OC\Encryption\Util $util,
- \OC\Encryption\File $file,
- $mode,
- $size,
- $unencryptedSize,
- $headerSize,
- $signed,
- $wrapper = Encryption::class) {
+ $uid,
+ \OCP\Encryption\IEncryptionModule $encryptionModule,
+ \OC\Files\Storage\Storage $storage,
+ \OC\Files\Storage\Wrapper\Encryption $encStorage,
+ \OC\Encryption\Util $util,
+ \OC\Encryption\File $file,
+ $mode,
+ $size,
+ $unencryptedSize,
+ $headerSize,
+ $signed,
+ $wrapper = Encryption::class) {
$context = stream_context_create([
'ocencryption' => [
'source' => $source,
@@ -321,7 +297,7 @@ class Encryption extends Wrapper {
$result .= substr($this->cache, $blockPosition, $remainingLength);
$this->position += $remainingLength;
$count = 0;
- // otherwise remainder of current block is fetched, the block is flushed and the position updated
+ // otherwise remainder of current block is fetched, the block is flushed and the position updated
} else {
$result .= substr($this->cache, $blockPosition);
$this->flush();
@@ -389,8 +365,8 @@ class Encryption extends Wrapper {
$this->position += $remainingLength;
$length += $remainingLength;
$data = '';
- // if $data doesn't fit the current block, the fill the current block and reiterate
- // after the block is filled, it is flushed and $data is updatedxxx
+ // if $data doesn't fit the current block, the fill the current block and reiterate
+ // after the block is filled, it is flushed and $data is updatedxxx
} else {
$this->cache = substr($this->cache, 0, $blockPosition) .
substr($data, 0, $this->unencryptedBlockSize - $blockPosition);
diff --git a/lib/private/Files/Stream/HashWrapper.php b/lib/private/Files/Stream/HashWrapper.php
index 4060d74de7d..5956ad92549 100644
--- a/lib/private/Files/Stream/HashWrapper.php
+++ b/lib/private/Files/Stream/HashWrapper.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Stream;
diff --git a/lib/private/Files/Stream/Quota.php b/lib/private/Files/Stream/Quota.php
index 1549d95eba8..d8e7ae6dff0 100644
--- a/lib/private/Files/Stream/Quota.php
+++ b/lib/private/Files/Stream/Quota.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Stream;
diff --git a/lib/private/Files/Stream/SeekableHttpStream.php b/lib/private/Files/Stream/SeekableHttpStream.php
index 66f94768e62..02ed1470fbd 100644
--- a/lib/private/Files/Stream/SeekableHttpStream.php
+++ b/lib/private/Files/Stream/SeekableHttpStream.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2020, Lukas Stabe (lukas@stabe.de)
- *
- * @author Lukas Stabe <lukas@stabe.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Stream;
diff --git a/lib/private/Files/Template/TemplateManager.php b/lib/private/Files/Template/TemplateManager.php
index bf72e9e23e8..8362298b831 100644
--- a/lib/private/Files/Template/TemplateManager.php
+++ b/lib/private/Files/Template/TemplateManager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Julius Härtl <jus@bitgrid.net>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Files\Template;
@@ -31,8 +12,8 @@ use OC\AppFramework\Bootstrap\Coordinator;
use OC\Files\Cache\Scanner;
use OC\Files\Filesystem;
use OCP\EventDispatcher\IEventDispatcher;
-use OCP\Files\Folder;
use OCP\Files\File;
+use OCP\Files\Folder;
use OCP\Files\GenericFileException;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
@@ -40,6 +21,7 @@ use OCP\Files\NotFoundException;
use OCP\Files\Template\FileCreatedFromTemplateEvent;
use OCP\Files\Template\ICustomTemplateProvider;
use OCP\Files\Template\ITemplateManager;
+use OCP\Files\Template\RegisterTemplateCreatorEvent;
use OCP\Files\Template\Template;
use OCP\Files\Template\TemplateFileCreator;
use OCP\IConfig;
@@ -119,6 +101,7 @@ class TemplateManager implements ITemplateManager {
if (!empty($this->types)) {
return $this->types;
}
+ $this->eventDispatcher->dispatchTyped(new RegisterTemplateCreatorEvent($this));
foreach ($this->registeredTypes as $registeredType) {
$this->types[] = $registeredType();
}
@@ -240,7 +223,8 @@ class TemplateManager implements ITemplateManager {
'mime' => $file->getMimetype(),
'size' => $file->getSize(),
'type' => $file->getType(),
- 'hasPreview' => $this->previewManager->isAvailable($file)
+ 'hasPreview' => $this->previewManager->isAvailable($file),
+ 'permissions' => $file->getPermissions(),
];
}
@@ -261,7 +245,7 @@ class TemplateManager implements ITemplateManager {
return $this->config->getUserValue($this->userId, 'core', 'templateDirectory', '');
}
- public function initializeTemplateDirectory(string $path = null, string $userId = null, $copyTemplates = true): string {
+ public function initializeTemplateDirectory(?string $path = null, ?string $userId = null, $copyTemplates = true): string {
if ($userId !== null) {
$this->userId = $userId;
}
@@ -274,6 +258,11 @@ class TemplateManager implements ITemplateManager {
$isDefaultTemplates = $skeletonTemplatePath === $defaultTemplateDirectory;
$userLang = $this->l10nFactory->getUserLanguage($this->userManager->get($this->userId));
+ if ($skeletonTemplatePath === '') {
+ $this->setTemplatePath('');
+ return '';
+ }
+
try {
$l10n = $this->l10nFactory->get('lib', $userLang);
$userFolder = $this->rootFolder->getUserFolder($this->userId);
diff --git a/lib/private/Files/Type/Detection.php b/lib/private/Files/Type/Detection.php
index 9a61aa93b95..b1e4c098e54 100644
--- a/lib/private/Files/Type/Detection.php
+++ b/lib/private/Files/Type/Detection.php
@@ -1,43 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author bladewing <lukas@ifflaender-family.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Hendrik Leppelsack <hendrik@leppelsack.de>
- * @author Jens-Christian Fischer <jens-christian.fischer@switch.ch>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author lui87kw <lukas.ifflaender@uni-wuerzburg.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Magnus Walbeck <mw@mwalbeck.org>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Xheni Myrtaj <myrtajxheni@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Type;
@@ -56,32 +23,19 @@ class Detection implements IMimeTypeDetector {
private const CUSTOM_MIMETYPEMAPPING = 'mimetypemapping.json';
private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json';
- protected $mimetypes = [];
- protected $secureMimeTypes = [];
-
- protected $mimetypeIcons = [];
- /** @var string[] */
- protected $mimeTypeAlias = [];
-
- /** @var IURLGenerator */
- private $urlGenerator;
-
- private LoggerInterface $logger;
-
- /** @var string */
- private $customConfigDir;
+ protected array $mimetypes = [];
+ protected array $secureMimeTypes = [];
- /** @var string */
- private $defaultConfigDir;
+ protected array $mimetypeIcons = [];
+ /** @var array<string,string> */
+ protected array $mimeTypeAlias = [];
- public function __construct(IURLGenerator $urlGenerator,
- LoggerInterface $logger,
- string $customConfigDir,
- string $defaultConfigDir) {
- $this->urlGenerator = $urlGenerator;
- $this->logger = $logger;
- $this->customConfigDir = $customConfigDir;
- $this->defaultConfigDir = $defaultConfigDir;
+ public function __construct(
+ private IURLGenerator $urlGenerator,
+ private LoggerInterface $logger,
+ private string $customConfigDir,
+ private string $defaultConfigDir,
+ ) {
}
/**
@@ -96,8 +50,8 @@ class Detection implements IMimeTypeDetector {
* @param string|null $secureMimeType
*/
public function registerType(string $extension,
- string $mimetype,
- ?string $secureMimeType = null): void {
+ string $mimetype,
+ ?string $secureMimeType = null): void {
$this->mimetypes[$extension] = [$mimetype, $secureMimeType];
$this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype;
}
@@ -151,7 +105,7 @@ class Detection implements IMimeTypeDetector {
}
/**
- * @return string[]
+ * @return array<string,string>
*/
public function getAllAliases(): array {
$this->loadAliases();
diff --git a/lib/private/Files/Type/Loader.php b/lib/private/Files/Type/Loader.php
index 20c298f21b3..247acf0141a 100644
--- a/lib/private/Files/Type/Loader.php
+++ b/lib/private/Files/Type/Loader.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Rello <Rello@users.noreply.github.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Type;
@@ -38,14 +21,13 @@ use OCP\IDBConnection;
class Loader implements IMimeTypeLoader {
use TTransactional;
- /** @var IDBConnection */
- private $dbConnection;
+ private IDBConnection $dbConnection;
- /** @var array [id => mimetype] */
- protected $mimetypes;
+ /** @psalm-var array<int, string> */
+ protected array $mimetypes;
- /** @var array [mimetype => id] */
- protected $mimetypeIds;
+ /** @psalm-var array<string, int> */
+ protected array $mimetypeIds;
/**
* @param IDBConnection $dbConnection
@@ -58,11 +40,8 @@ class Loader implements IMimeTypeLoader {
/**
* Get a mimetype from its ID
- *
- * @param int $id
- * @return string|null
*/
- public function getMimetypeById($id) {
+ public function getMimetypeById(int $id): ?string {
if (!$this->mimetypes) {
$this->loadMimetypes();
}
@@ -74,11 +53,8 @@ class Loader implements IMimeTypeLoader {
/**
* Get a mimetype ID, adding the mimetype to the DB if it does not exist
- *
- * @param string $mimetype
- * @return int
*/
- public function getId($mimetype) {
+ public function getId(string $mimetype): int {
if (!$this->mimetypeIds) {
$this->loadMimetypes();
}
@@ -90,11 +66,8 @@ class Loader implements IMimeTypeLoader {
/**
* Test if a mimetype exists in the database
- *
- * @param string $mimetype
- * @return bool
*/
- public function exists($mimetype) {
+ public function exists(string $mimetype): bool {
if (!$this->mimetypeIds) {
$this->loadMimetypes();
}
@@ -104,7 +77,7 @@ class Loader implements IMimeTypeLoader {
/**
* Clear all loaded mimetypes, allow for re-loading
*/
- public function reset() {
+ public function reset(): void {
$this->mimetypes = [];
$this->mimetypeIds = [];
}
@@ -115,9 +88,9 @@ class Loader implements IMimeTypeLoader {
* @param string $mimetype
* @return int inserted ID
*/
- protected function store($mimetype) {
- $mimetypeId = $this->atomic(function () use ($mimetype) {
- try {
+ protected function store(string $mimetype): int {
+ try {
+ $mimetypeId = $this->atomic(function () use ($mimetype) {
$insert = $this->dbConnection->getQueryBuilder();
$insert->insert('mimetypes')
->values([
@@ -125,26 +98,24 @@ class Loader implements IMimeTypeLoader {
])
->executeStatement();
return $insert->getLastInsertId();
- } catch (DbalException $e) {
- if ($e->getReason() !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
- throw $e;
- }
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('id')
- ->from('mimetypes')
- ->where($qb->expr()->eq('mimetype', $qb->createNamedParameter($mimetype)));
- $result = $qb->executeQuery();
- $id = $result->fetchOne();
- $result->closeCursor();
- if ($id !== false) {
- return (int) $id;
- }
+ }, $this->dbConnection);
+ } catch (DbalException $e) {
+ if ($e->getReason() !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
+ throw $e;
+ }
+
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->select('id')
+ ->from('mimetypes')
+ ->where($qb->expr()->eq('mimetype', $qb->createNamedParameter($mimetype)));
+ $result = $qb->executeQuery();
+ $id = $result->fetchOne();
+ $result->closeCursor();
+ if ($id === false) {
throw new \Exception("Database threw an unique constraint on inserting a new mimetype, but couldn't return the ID for this very mimetype");
}
- }, $this->dbConnection);
- if (!$mimetypeId) {
- throw new \Exception("Failed to get mimetype id for $mimetype after trying to store it");
+ $mimetypeId = (int) $id;
}
$this->mimetypes[$mimetypeId] = $mimetype;
@@ -155,29 +126,27 @@ class Loader implements IMimeTypeLoader {
/**
* Load all mimetypes from DB
*/
- private function loadMimetypes() {
+ private function loadMimetypes(): void {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('id', 'mimetype')
->from('mimetypes');
- $result = $qb->execute();
+ $result = $qb->executeQuery();
$results = $result->fetchAll();
$result->closeCursor();
foreach ($results as $row) {
- $this->mimetypes[$row['id']] = $row['mimetype'];
- $this->mimetypeIds[$row['mimetype']] = $row['id'];
+ $this->mimetypes[(int) $row['id']] = $row['mimetype'];
+ $this->mimetypeIds[$row['mimetype']] = (int) $row['id'];
}
}
/**
* Update filecache mimetype based on file extension
*
- * @param string $ext file extension
- * @param int $mimeTypeId
* @return int number of changed rows
*/
- public function updateFilecache($ext, $mimeTypeId) {
+ public function updateFilecache(string $ext, int $mimeTypeId): int {
$folderMimeTypeId = $this->getId('httpd/unix-directory');
$update = $this->dbConnection->getQueryBuilder();
$update->update('filecache')
diff --git a/lib/private/Files/Type/TemplateManager.php b/lib/private/Files/Type/TemplateManager.php
index 6210edaaf05..a0c0e9fac9f 100644
--- a/lib/private/Files/Type/TemplateManager.php
+++ b/lib/private/Files/Type/TemplateManager.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files\Type;
diff --git a/lib/private/Files/Utils/PathHelper.php b/lib/private/Files/Utils/PathHelper.php
index 0fb7ba663cc..a6ae029b957 100644
--- a/lib/private/Files/Utils/PathHelper.php
+++ b/lib/private/Files/Utils/PathHelper.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Files\Utils;
class PathHelper {
diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php
index b7f6972ee10..bcc54dea0dc 100644
--- a/lib/private/Files/Utils/Scanner.php
+++ b/lib/private/Files/Utils/Scanner.php
@@ -1,33 +1,10 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Blaok <i@blaok.me>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Utils;
use OC\Files\Cache\Cache;
@@ -41,15 +18,16 @@ use OCA\Files_Sharing\SharedStorage;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Events\BeforeFileScannedEvent;
use OCP\Files\Events\BeforeFolderScannedEvent;
-use OCP\Files\Events\NodeAddedToCache;
use OCP\Files\Events\FileCacheUpdated;
-use OCP\Files\Events\NodeRemovedFromCache;
use OCP\Files\Events\FileScannedEvent;
use OCP\Files\Events\FolderScannedEvent;
+use OCP\Files\Events\NodeAddedToCache;
+use OCP\Files\Events\NodeRemovedFromCache;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\Files\StorageNotAvailableException;
use OCP\IDBConnection;
+use OCP\Lock\ILockingProvider;
use Psr\Log\LoggerInterface;
/**
@@ -100,7 +78,7 @@ class Scanner extends PublicEmitter {
$this->dispatcher = $dispatcher;
$this->logger = $logger;
// when DB locking is used, no DB transactions will be used
- $this->useTransaction = !(\OC::$server->getLockingProvider() instanceof DBLockingProvider);
+ $this->useTransaction = !(\OC::$server->get(ILockingProvider::class) instanceof DBLockingProvider);
}
/**
@@ -156,33 +134,37 @@ class Scanner extends PublicEmitter {
public function backgroundScan($dir) {
$mounts = $this->getMounts($dir);
foreach ($mounts as $mount) {
- $storage = $mount->getStorage();
- if (is_null($storage)) {
- continue;
- }
+ try {
+ $storage = $mount->getStorage();
+ if (is_null($storage)) {
+ continue;
+ }
- // don't bother scanning failed storages (shortcut for same result)
- if ($storage->instanceOfStorage(FailedStorage::class)) {
- continue;
- }
+ // don't bother scanning failed storages (shortcut for same result)
+ if ($storage->instanceOfStorage(FailedStorage::class)) {
+ continue;
+ }
- $scanner = $storage->getScanner();
- $this->attachListener($mount);
+ $scanner = $storage->getScanner();
+ $this->attachListener($mount);
- $scanner->listen('\OC\Files\Cache\Scanner', 'removeFromCache', function ($path) use ($storage) {
- $this->triggerPropagator($storage, $path);
- });
- $scanner->listen('\OC\Files\Cache\Scanner', 'updateCache', function ($path) use ($storage) {
- $this->triggerPropagator($storage, $path);
- });
- $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function ($path) use ($storage) {
- $this->triggerPropagator($storage, $path);
- });
+ $scanner->listen('\OC\Files\Cache\Scanner', 'removeFromCache', function ($path) use ($storage) {
+ $this->triggerPropagator($storage, $path);
+ });
+ $scanner->listen('\OC\Files\Cache\Scanner', 'updateCache', function ($path) use ($storage) {
+ $this->triggerPropagator($storage, $path);
+ });
+ $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function ($path) use ($storage) {
+ $this->triggerPropagator($storage, $path);
+ });
- $propagator = $storage->getPropagator();
- $propagator->beginBatch();
- $scanner->backgroundScan();
- $propagator->commitBatch();
+ $propagator = $storage->getPropagator();
+ $propagator->beginBatch();
+ $scanner->backgroundScan();
+ $propagator->commitBatch();
+ } catch (\Exception $e) {
+ $this->logger->error("Error while trying to scan mount as {$mount->getMountPoint()}:" . $e->getMessage(), ['exception' => $e, 'app' => 'files']);
+ }
}
}
@@ -193,7 +175,7 @@ class Scanner extends PublicEmitter {
* @throws ForbiddenException
* @throws NotFoundException
*/
- public function scan($dir = '', $recursive = \OC\Files\Cache\Scanner::SCAN_RECURSIVE, callable $mountFilter = null) {
+ public function scan($dir = '', $recursive = \OC\Files\Cache\Scanner::SCAN_RECURSIVE, ?callable $mountFilter = null) {
if (!Filesystem::isValidPath($dir)) {
throw new \InvalidArgumentException('Invalid path to scan');
}
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index 71815939310..0150a3e117a 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -1,73 +1,38 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Ashod Nakashian <ashod.nakashian@collabora.co.uk>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Florin Peter <github@florin-peter.de>
- * @author Jesús Macias <jmacias@solidgear.es>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author karakayasemi <karakayasemi@itu.edu.tr>
- * @author Klaas Freitag <freitag@owncloud.com>
- * @author korelstar <korelstar@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Luke Policinski <lpolicinski@gmail.com>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr Filiciak <piotr@filiciak.pl>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sam Tuke <mail@samtuke.com>
- * @author Scott Dutton <exussum12@users.noreply.github.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Files;
use Icewind\Streams\CallbackWrapper;
use OC\Files\Mount\MoveableMount;
use OC\Files\Storage\Storage;
-use OC\User\LazyUser;
use OC\Share\Share;
-use OC\User\User;
+use OC\User\LazyUser;
use OC\User\Manager as UserManager;
+use OC\User\User;
use OCA\Files_Sharing\SharedMount;
use OCP\Constants;
use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\ConnectionLostException;
use OCP\Files\EmptyFileNameException;
use OCP\Files\FileNameTooLongException;
+use OCP\Files\ForbiddenException;
use OCP\Files\InvalidCharacterInPathException;
use OCP\Files\InvalidDirectoryException;
use OCP\Files\InvalidPathException;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
use OCP\Files\ReservedWordException;
-use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
+use OCP\Server;
+use OCP\Share\IManager;
+use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
/**
@@ -103,7 +68,7 @@ class View {
}
$this->fakeRoot = $root;
- $this->lockingProvider = \OC::$server->getLockingProvider();
+ $this->lockingProvider = \OC::$server->get(ILockingProvider::class);
$this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider);
$this->userManager = \OC::$server->getUserManager();
$this->logger = \OC::$server->get(LoggerInterface::class);
@@ -286,12 +251,12 @@ class View {
$this->updaterEnabled = true;
}
- protected function writeUpdate(Storage $storage, string $internalPath, ?int $time = null): void {
+ protected function writeUpdate(Storage $storage, string $internalPath, ?int $time = null, ?int $sizeDifference = null): void {
if ($this->updaterEnabled) {
if (is_null($time)) {
$time = time();
}
- $storage->getUpdater()->update($internalPath, $time);
+ $storage->getUpdater()->update($internalPath, $time, $sizeDifference);
}
}
@@ -397,10 +362,11 @@ class View {
}
$handle = $this->fopen($path, 'rb');
if ($handle) {
- $chunkSize = 524288; // 512 kB chunks
+ $chunkSize = 524288; // 512 kiB chunks
while (!feof($handle)) {
echo fread($handle, $chunkSize);
flush();
+ $this->checkConnectionStatus();
}
fclose($handle);
return $this->filesize($path);
@@ -423,7 +389,7 @@ class View {
}
$handle = $this->fopen($path, 'rb');
if ($handle) {
- $chunkSize = 524288; // 512 kB chunks
+ $chunkSize = 524288; // 512 kiB chunks
$startReading = true;
if ($from !== 0 && $from !== '0' && fseek($handle, $from) !== 0) {
@@ -453,6 +419,7 @@ class View {
}
echo fread($handle, $len);
flush();
+ $this->checkConnectionStatus();
}
return ftell($handle) - $from;
}
@@ -462,6 +429,13 @@ class View {
return false;
}
+ private function checkConnectionStatus(): void {
+ $connectionStatus = \connection_status();
+ if ($connectionStatus !== CONNECTION_NORMAL) {
+ throw new ConnectionLostException("Connection lost. Status: $connectionStatus");
+ }
+ }
+
/**
* @param string $path
* @return mixed
@@ -721,6 +695,13 @@ class View {
public function rename($source, $target) {
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($source));
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($target));
+
+ if (str_starts_with($absolutePath2, $absolutePath1 . '/')) {
+ throw new ForbiddenException("Moving a folder into a child folder is forbidden", false);
+ }
+
+ $targetParts = explode('/', $absolutePath2);
+ $targetUser = $targetParts[1] ?? null;
$result = false;
if (
Filesystem::isValidPath($target)
@@ -775,7 +756,7 @@ class View {
if ($internalPath1 === '') {
if ($mount1 instanceof MoveableMount) {
$sourceParentMount = $this->getMount(dirname($source));
- if ($sourceParentMount === $mount2 && $this->targetIsNotShared($storage2, $internalPath2)) {
+ if ($sourceParentMount === $mount2 && $this->targetIsNotShared($targetUser, $absolutePath2)) {
/**
* @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1
*/
@@ -788,14 +769,14 @@ class View {
} else {
$result = false;
}
- // moving a file/folder within the same mount point
+ // moving a file/folder within the same mount point
} elseif ($storage1 === $storage2) {
if ($storage1) {
$result = $storage1->rename($internalPath1, $internalPath2);
} else {
$result = false;
}
- // moving a file/folder between storages (from $storage1 to $storage2)
+ // moving a file/folder between storages (from $storage1 to $storage2)
} else {
$result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
}
@@ -1163,10 +1144,12 @@ class View {
$this->removeUpdate($storage, $internalPath);
}
if ($result !== false && in_array('write', $hooks, true) && $operation !== 'fopen' && $operation !== 'touch') {
- $this->writeUpdate($storage, $internalPath);
+ $isCreateOperation = $operation === 'mkdir' || ($operation === 'file_put_contents' && in_array('create', $hooks, true));
+ $sizeDifference = $operation === 'mkdir' ? 0 : $result;
+ $this->writeUpdate($storage, $internalPath, null, $isCreateOperation ? $sizeDifference : null);
}
if ($result !== false && in_array('touch', $hooks)) {
- $this->writeUpdate($storage, $internalPath, $extraParam);
+ $this->writeUpdate($storage, $internalPath, $extraParam, 0);
}
if ((in_array('write', $hooks) || in_array('delete', $hooks)) && ($operation !== 'fopen' || $result === false)) {
@@ -1412,7 +1395,7 @@ class View {
* @param string $mimetype_filter limit returned content to this mimetype or mimepart
* @return FileInfo[]
*/
- public function getDirectoryContent($directory, $mimetype_filter = '', \OCP\Files\FileInfo $directoryInfo = null) {
+ public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Files\FileInfo $directoryInfo = null) {
$this->assertPathLength($directory);
if (!Filesystem::isValidPath($directory)) {
return [];
@@ -1465,6 +1448,13 @@ class View {
//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
$mounts = Filesystem::getMountManager()->findIn($path);
+
+ // make sure nested mounts are sorted after their parent mounts
+ // otherwise doesn't propagate the etag across storage boundaries correctly
+ usort($mounts, function (IMountPoint $a, IMountPoint $b) {
+ return $a->getMountPoint() <=> $b->getMountPoint();
+ });
+
$dirLength = strlen($path);
foreach ($mounts as $mount) {
$mountPoint = $mount->getMountPoint();
@@ -1515,7 +1505,7 @@ class View {
$rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/
// if sharing was disabled for the user we remove the share permissions
- if (\OCP\Util::isSharingDisabledForUser()) {
+ if ($sharingDisabled) {
$rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
@@ -1710,7 +1700,7 @@ class View {
* @return string
* @throws NotFoundException
*/
- public function getPath($id, int $storageId = null) {
+ public function getPath($id, ?int $storageId = null) {
$id = (int)$id;
$manager = Filesystem::getMountManager();
$mounts = $manager->findIn($this->fakeRoot);
@@ -1769,28 +1759,29 @@ class View {
* It is not allowed to move a mount point into a different mount point or
* into an already shared folder
*/
- private function targetIsNotShared(IStorage $targetStorage, string $targetInternalPath): bool {
- // note: cannot use the view because the target is already locked
- $fileId = $targetStorage->getCache()->getId($targetInternalPath);
- if ($fileId === -1) {
- // target might not exist, need to check parent instead
- $fileId = $targetStorage->getCache()->getId(dirname($targetInternalPath));
- }
-
- // check if any of the parents were shared by the current owner (include collections)
- $shares = Share::getItemShared(
- 'folder',
- (string)$fileId,
- \OC\Share\Constants::FORMAT_NONE,
- null,
- true
- );
-
- if (count($shares) > 0) {
- $this->logger->debug(
- 'It is not allowed to move one mount point into a shared folder',
- ['app' => 'files']);
- return false;
+ private function targetIsNotShared(string $user, string $targetPath): bool {
+ $providers = [
+ IShare::TYPE_USER,
+ IShare::TYPE_GROUP,
+ IShare::TYPE_EMAIL,
+ IShare::TYPE_CIRCLE,
+ IShare::TYPE_ROOM,
+ IShare::TYPE_DECK,
+ IShare::TYPE_SCIENCEMESH
+ ];
+ $shareManager = Server::get(IManager::class);
+ /** @var IShare[] $shares */
+ $shares = array_merge(...array_map(function (int $type) use ($shareManager, $user) {
+ return $shareManager->getSharesBy($user, $type);
+ }, $providers));
+
+ foreach ($shares as $share) {
+ if (str_starts_with($targetPath, $share->getNode()->getPath())) {
+ $this->logger->debug(
+ 'It is not allowed to move one mount point into a shared folder',
+ ['app' => 'files']);
+ return false;
+ }
}
return true;
@@ -1834,19 +1825,19 @@ class View {
[$storage, $internalPath] = $this->resolvePath($path);
$storage->verifyPath($internalPath, $fileName);
} catch (ReservedWordException $ex) {
- $l = \OC::$server->getL10N('lib');
+ $l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('File name is a reserved word'));
} catch (InvalidCharacterInPathException $ex) {
- $l = \OC::$server->getL10N('lib');
+ $l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('File name contains at least one invalid character'));
} catch (FileNameTooLongException $ex) {
- $l = \OC::$server->getL10N('lib');
+ $l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('File name is too long'));
} catch (InvalidDirectoryException $ex) {
- $l = \OC::$server->getL10N('lib');
+ $l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('Dot files are not allowed'));
} catch (EmptyFileNameException $ex) {
- $l = \OC::$server->getL10N('lib');
+ $l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('Empty filename is not allowed'));
}
}
diff --git a/lib/private/FilesMetadata/FilesMetadataManager.php b/lib/private/FilesMetadata/FilesMetadataManager.php
new file mode 100644
index 00000000000..231fb2ec98f
--- /dev/null
+++ b/lib/private/FilesMetadata/FilesMetadataManager.php
@@ -0,0 +1,303 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata;
+
+use JsonException;
+use OC\FilesMetadata\Job\UpdateSingleMetadata;
+use OC\FilesMetadata\Listener\MetadataDelete;
+use OC\FilesMetadata\Listener\MetadataUpdate;
+use OC\FilesMetadata\Model\FilesMetadata;
+use OC\FilesMetadata\Service\IndexRequestService;
+use OC\FilesMetadata\Service\MetadataRequestService;
+use OCP\BackgroundJob\IJobList;
+use OCP\DB\Exception;
+use OCP\DB\Exception as DBException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Cache\CacheEntryRemovedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\Files\InvalidPathException;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\FilesMetadata\Event\MetadataBackgroundEvent;
+use OCP\FilesMetadata\Event\MetadataLiveEvent;
+use OCP\FilesMetadata\Event\MetadataNamedEvent;
+use OCP\FilesMetadata\Exceptions\FilesMetadataException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use OCP\FilesMetadata\IMetadataQuery;
+use OCP\FilesMetadata\Model\IFilesMetadata;
+use OCP\FilesMetadata\Model\IMetadataValueWrapper;
+use OCP\IAppConfig;
+use Psr\Log\LoggerInterface;
+
+/**
+ * @inheritDoc
+ * @since 28.0.0
+ */
+class FilesMetadataManager implements IFilesMetadataManager {
+ public const CONFIG_KEY = 'files_metadata';
+ public const MIGRATION_DONE = 'files_metadata_installed';
+ private const JSON_MAXSIZE = 100000;
+
+ private ?IFilesMetadata $all = null;
+
+ public function __construct(
+ private IEventDispatcher $eventDispatcher,
+ private IJobList $jobList,
+ private IAppConfig $appConfig,
+ private LoggerInterface $logger,
+ private MetadataRequestService $metadataRequestService,
+ private IndexRequestService $indexRequestService,
+ ) {
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param Node $node related node
+ * @param int $process type of process
+ *
+ * @return IFilesMetadata
+ * @throws FilesMetadataException if metadata are invalid
+ * @throws InvalidPathException if path to file is not valid
+ * @throws NotFoundException if file cannot be found
+ * @see self::PROCESS_BACKGROUND
+ * @see self::PROCESS_LIVE
+ * @since 28.0.0
+ */
+ public function refreshMetadata(
+ Node $node,
+ int $process = self::PROCESS_LIVE,
+ string $namedEvent = ''
+ ): IFilesMetadata {
+ try {
+ $metadata = $this->metadataRequestService->getMetadataFromFileId($node->getId());
+ } catch (FilesMetadataNotFoundException) {
+ $metadata = new FilesMetadata($node->getId());
+ }
+
+ // if $process is LIVE, we enforce LIVE
+ // if $process is NAMED, we go NAMED
+ // else BACKGROUND
+ if ((self::PROCESS_LIVE & $process) !== 0) {
+ $event = new MetadataLiveEvent($node, $metadata);
+ } elseif ((self::PROCESS_NAMED & $process) !== 0) {
+ $event = new MetadataNamedEvent($node, $metadata, $namedEvent);
+ } else {
+ $event = new MetadataBackgroundEvent($node, $metadata);
+ }
+
+ $this->eventDispatcher->dispatchTyped($event);
+ $this->saveMetadata($event->getMetadata());
+
+ // if requested, we add a new job for next cron to refresh metadata out of main thread
+ // if $process was set to LIVE+BACKGROUND, we run background process directly
+ if ($event instanceof MetadataLiveEvent && $event->isRunAsBackgroundJobRequested()) {
+ if ((self::PROCESS_BACKGROUND & $process) !== 0) {
+ return $this->refreshMetadata($node, self::PROCESS_BACKGROUND);
+ }
+
+ $this->jobList->add(UpdateSingleMetadata::class, [$node->getOwner()->getUID(), $node->getId()]);
+ }
+
+ return $metadata;
+ }
+
+ /**
+ * @param int $fileId file id
+ * @param boolean $generate Generate if metadata does not exists
+ *
+ * @inheritDoc
+ * @return IFilesMetadata
+ * @throws FilesMetadataNotFoundException if not found
+ * @since 28.0.0
+ */
+ public function getMetadata(int $fileId, bool $generate = false): IFilesMetadata {
+ try {
+ return $this->metadataRequestService->getMetadataFromFileId($fileId);
+ } catch (FilesMetadataNotFoundException $ex) {
+ if ($generate) {
+ return new FilesMetadata($fileId);
+ }
+
+ throw $ex;
+ }
+ }
+
+ /**
+ * returns metadata of multiple file ids
+ *
+ * @param int[] $fileIds file ids
+ *
+ * @return array File ID is the array key, files without metadata are not returned in the array
+ * @psalm-return array<int, IFilesMetadata>
+ * @since 28.0.0
+ */
+ public function getMetadataForFiles(array $fileIds): array {
+ return $this->metadataRequestService->getMetadataFromFileIds($fileIds);
+ }
+
+ /**
+ * @param IFilesMetadata $filesMetadata metadata
+ *
+ * @inheritDoc
+ * @throws FilesMetadataException if metadata seems malformed
+ * @since 28.0.0
+ */
+ public function saveMetadata(IFilesMetadata $filesMetadata): void {
+ if ($filesMetadata->getFileId() === 0 || !$filesMetadata->updated()) {
+ return;
+ }
+
+ $json = json_encode($filesMetadata->jsonSerialize());
+ if (strlen($json) > self::JSON_MAXSIZE) {
+ $this->logger->debug('huge metadata content detected: ' . $json);
+ throw new FilesMetadataException('json cannot exceed ' . self::JSON_MAXSIZE . ' characters long; fileId: ' . $filesMetadata->getFileId() . '; size: ' . strlen($json));
+ }
+
+ try {
+ if ($filesMetadata->getSyncToken() === '') {
+ $this->metadataRequestService->store($filesMetadata);
+ } else {
+ $this->metadataRequestService->updateMetadata($filesMetadata);
+ }
+ } catch (DBException $e) {
+ // most of the logged exception are the result of race condition
+ // between 2 simultaneous process trying to create/update metadata
+ $this->logger->warning('issue while saveMetadata', ['exception' => $e, 'metadata' => $filesMetadata]);
+
+ return;
+ }
+
+ // update indexes
+ foreach ($filesMetadata->getIndexes() as $index) {
+ try {
+ $this->indexRequestService->updateIndex($filesMetadata, $index);
+ } catch (DBException $e) {
+ $this->logger->warning('issue while updateIndex', ['exception' => $e]);
+ }
+ }
+
+ // update metadata types list
+ $current = $this->getKnownMetadata();
+ $current->import($filesMetadata->jsonSerialize(true));
+ $this->appConfig->setValueArray('core', self::CONFIG_KEY, $current->jsonSerialize(), lazy: true);
+ }
+
+ /**
+ * @param int $fileId file id
+ *
+ * @inheritDoc
+ * @since 28.0.0
+ */
+ public function deleteMetadata(int $fileId): void {
+ try {
+ $this->metadataRequestService->dropMetadata($fileId);
+ } catch (Exception $e) {
+ $this->logger->warning('issue while deleteMetadata', ['exception' => $e, 'fileId' => $fileId]);
+ }
+
+ try {
+ $this->indexRequestService->dropIndex($fileId);
+ } catch (Exception $e) {
+ $this->logger->warning('issue while deleteMetadata', ['exception' => $e, 'fileId' => $fileId]);
+ }
+ }
+
+ /**
+ * @param IQueryBuilder $qb
+ * @param string $fileTableAlias alias of the table that contains data about files
+ * @param string $fileIdField alias of the field that contains file ids
+ *
+ * @inheritDoc
+ * @return IMetadataQuery
+ * @see IMetadataQuery
+ * @since 28.0.0
+ */
+ public function getMetadataQuery(
+ IQueryBuilder $qb,
+ string $fileTableAlias,
+ string $fileIdField
+ ): IMetadataQuery {
+ return new MetadataQuery($qb, $this, $fileTableAlias, $fileIdField);
+ }
+
+ /**
+ * @inheritDoc
+ * @return IFilesMetadata
+ * @since 28.0.0
+ */
+ public function getKnownMetadata(): IFilesMetadata {
+ if ($this->all !== null) {
+ return $this->all;
+ }
+ $this->all = new FilesMetadata();
+
+ try {
+ $this->all->import($this->appConfig->getValueArray('core', self::CONFIG_KEY, lazy: true));
+ } catch (JsonException) {
+ $this->logger->warning('issue while reading stored list of metadata. Advised to run ./occ files:scan --all --generate-metadata');
+ }
+
+ return $this->all;
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param string $type metadata type
+ * @param bool $indexed TRUE if metadata can be search
+ * @param int $editPermission remote edit permission via Webdav PROPPATCH
+ *
+ * @inheritDoc
+ * @since 28.0.0
+ * @see IMetadataValueWrapper::TYPE_INT
+ * @see IMetadataValueWrapper::TYPE_FLOAT
+ * @see IMetadataValueWrapper::TYPE_BOOL
+ * @see IMetadataValueWrapper::TYPE_ARRAY
+ * @see IMetadataValueWrapper::TYPE_STRING_LIST
+ * @see IMetadataValueWrapper::TYPE_INT_LIST
+ * @see IMetadataValueWrapper::TYPE_STRING
+ * @see IMetadataValueWrapper::EDIT_FORBIDDEN
+ * @see IMetadataValueWrapper::EDIT_REQ_OWNERSHIP
+ * @see IMetadataValueWrapper::EDIT_REQ_WRITE_PERMISSION
+ * @see IMetadataValueWrapper::EDIT_REQ_READ_PERMISSION
+ */
+ public function initMetadata(
+ string $key,
+ string $type,
+ bool $indexed = false,
+ int $editPermission = IMetadataValueWrapper::EDIT_FORBIDDEN
+ ): void {
+ $current = $this->getKnownMetadata();
+ try {
+ if ($current->getType($key) === $type
+ && $indexed === $current->isIndex($key)
+ && $editPermission === $current->getEditPermission($key)) {
+ return; // if key exists, with same type and indexed, we do nothing.
+ }
+ } catch (FilesMetadataNotFoundException) {
+ // if value does not exist, we keep on the writing of course
+ }
+
+ $current->import([$key => ['type' => $type, 'indexed' => $indexed, 'editPermission' => $editPermission]]);
+ $this->appConfig->setValueArray('core', self::CONFIG_KEY, $current->jsonSerialize(), lazy: true);
+ $this->all = $current;
+ }
+
+ /**
+ * load listeners
+ *
+ * @param IEventDispatcher $eventDispatcher
+ */
+ public static function loadListeners(IEventDispatcher $eventDispatcher): void {
+ $eventDispatcher->addServiceListener(NodeWrittenEvent::class, MetadataUpdate::class);
+ $eventDispatcher->addServiceListener(CacheEntryRemovedEvent::class, MetadataDelete::class);
+ }
+}
diff --git a/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php b/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php
new file mode 100644
index 00000000000..c4b0117db13
--- /dev/null
+++ b/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Job;
+
+use OC\FilesMetadata\FilesMetadataManager;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\QueuedJob;
+use OCP\Files\IRootFolder;
+use OCP\FilesMetadata\Event\MetadataLiveEvent;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Simple background job, created when requested by an app during the
+ * dispatch of MetadataLiveEvent.
+ * This background job will re-run the event to refresh metadata on a non-live thread.
+ *
+ * @see MetadataLiveEvent::requestBackgroundJob()
+ * @since 28.0.0
+ */
+class UpdateSingleMetadata extends QueuedJob {
+ public function __construct(
+ ITimeFactory $time,
+ private IRootFolder $rootFolder,
+ private FilesMetadataManager $filesMetadataManager,
+ private LoggerInterface $logger
+ ) {
+ parent::__construct($time);
+ }
+
+ protected function run($argument) {
+ [$userId, $fileId] = $argument;
+
+ try {
+ $node = $this->rootFolder->getUserFolder($userId)->getFirstNodeById($fileId);
+ if ($node) {
+ $this->filesMetadataManager->refreshMetadata($node, IFilesMetadataManager::PROCESS_BACKGROUND);
+ }
+ } catch (\Exception $e) {
+ $this->logger->warning('issue while running UpdateSingleMetadata', ['exception' => $e, 'userId' => $userId, 'fileId' => $fileId]);
+ }
+ }
+}
diff --git a/lib/private/FilesMetadata/Listener/MetadataDelete.php b/lib/private/FilesMetadata/Listener/MetadataDelete.php
new file mode 100644
index 00000000000..c0a6fc758c1
--- /dev/null
+++ b/lib/private/FilesMetadata/Listener/MetadataDelete.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Listener;
+
+use Exception;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Cache\CacheEntryRemovedEvent;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Handle file deletion event and remove stored metadata related to the deleted file
+ *
+ * @template-implements IEventListener<CacheEntryRemovedEvent>
+ */
+class MetadataDelete implements IEventListener {
+ public function __construct(
+ private IFilesMetadataManager $filesMetadataManager,
+ private LoggerInterface $logger
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof CacheEntryRemovedEvent)) {
+ return;
+ }
+
+ try {
+ $nodeId = $event->getFileId();
+ if ($nodeId > 0) {
+ $this->filesMetadataManager->deleteMetadata($nodeId);
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('issue while running MetadataDelete', ['exception' => $e]);
+ }
+ }
+}
diff --git a/lib/private/FilesMetadata/Listener/MetadataUpdate.php b/lib/private/FilesMetadata/Listener/MetadataUpdate.php
new file mode 100644
index 00000000000..05422ba5aba
--- /dev/null
+++ b/lib/private/FilesMetadata/Listener/MetadataUpdate.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Listener;
+
+use Exception;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Events\Node\NodeCreatedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Handle file creation/modification events and initiate a new event related to the created/edited file.
+ * The generated new event is broadcast in order to obtain file related metadata from other apps.
+ * metadata will be stored in database.
+ *
+ * @template-implements IEventListener<NodeCreatedEvent|NodeWrittenEvent>
+ */
+class MetadataUpdate implements IEventListener {
+ public function __construct(
+ private IFilesMetadataManager $filesMetadataManager,
+ private LoggerInterface $logger
+ ) {
+ }
+
+ /**
+ * @param Event $event
+ */
+ public function handle(Event $event): void {
+ if (!($event instanceof NodeWrittenEvent)) {
+ return;
+ }
+
+ try {
+ $this->filesMetadataManager->refreshMetadata($event->getNode());
+ } catch (Exception $e) {
+ $this->logger->warning('issue while running MetadataUpdate', ['exception' => $e]);
+ }
+ }
+}
diff --git a/lib/private/FilesMetadata/MetadataQuery.php b/lib/private/FilesMetadata/MetadataQuery.php
new file mode 100644
index 00000000000..aac93a23446
--- /dev/null
+++ b/lib/private/FilesMetadata/MetadataQuery.php
@@ -0,0 +1,176 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata;
+
+use OC\FilesMetadata\Model\FilesMetadata;
+use OC\FilesMetadata\Service\IndexRequestService;
+use OC\FilesMetadata\Service\MetadataRequestService;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataTypeException;
+use OCP\FilesMetadata\IFilesMetadataManager;
+use OCP\FilesMetadata\IMetadataQuery;
+use OCP\FilesMetadata\Model\IFilesMetadata;
+use OCP\FilesMetadata\Model\IMetadataValueWrapper;
+use Psr\Log\LoggerInterface;
+
+/**
+ * @inheritDoc
+ * @since 28.0.0
+ */
+class MetadataQuery implements IMetadataQuery {
+ private array $knownJoinedIndex = [];
+ public function __construct(
+ private IQueryBuilder $queryBuilder,
+ private IFilesMetadata|IFilesMetadataManager $manager,
+ private string $fileTableAlias = 'fc',
+ private string $fileIdField = 'fileid',
+ private string $alias = 'meta',
+ private string $aliasIndexPrefix = 'meta_index'
+ ) {
+ if ($manager instanceof IFilesMetadata) {
+ /**
+ * Since 29, because knownMetadata is stored in lazy appconfig, it seems smarter
+ * to not call getKnownMetadata() at the load of this class as it is only needed
+ * in {@see getMetadataValueField}.
+ *
+ * FIXME: remove support for IFilesMetadata
+ */
+ $logger = \OCP\Server::get(LoggerInterface::class);
+ $logger->debug('It is deprecated to use IFilesMetadata as second parameter when calling MetadataQuery::__construct()');
+ }
+ }
+
+ /**
+ * @inheritDoc
+ * @see self::extractMetadata()
+ * @since 28.0.0
+ */
+ public function retrieveMetadata(): void {
+ $this->queryBuilder->selectAlias($this->alias . '.json', 'meta_json');
+ $this->queryBuilder->selectAlias($this->alias . '.sync_token', 'meta_sync_token');
+ $this->queryBuilder->leftJoin(
+ $this->fileTableAlias, MetadataRequestService::TABLE_METADATA, $this->alias,
+ $this->queryBuilder->expr()->eq($this->fileTableAlias . '.' . $this->fileIdField, $this->alias . '.file_id')
+ );
+ }
+
+ /**
+ * @param array $row result row
+ *
+ * @inheritDoc
+ * @return IFilesMetadata metadata
+ * @see self::retrieveMetadata()
+ * @since 28.0.0
+ */
+ public function extractMetadata(array $row): IFilesMetadata {
+ $fileId = (array_key_exists($this->fileIdField, $row)) ? $row[$this->fileIdField] : 0;
+ $metadata = new FilesMetadata((int)$fileId);
+ try {
+ $metadata->importFromDatabase($row, $this->alias . '_');
+ } catch (FilesMetadataNotFoundException) {
+ // can be ignored as files' metadata are optional and might not exist in database
+ }
+
+ return $metadata;
+ }
+
+ /**
+ * @param string $metadataKey metadata key
+ * @param bool $enforce limit the request only to existing metadata
+ *
+ * @inheritDoc
+ * @since 28.0.0
+ */
+ public function joinIndex(string $metadataKey, bool $enforce = false): string {
+ if (array_key_exists($metadataKey, $this->knownJoinedIndex)) {
+ return $this->knownJoinedIndex[$metadataKey];
+ }
+
+ $aliasIndex = $this->aliasIndexPrefix . '_' . count($this->knownJoinedIndex);
+ $this->knownJoinedIndex[$metadataKey] = $aliasIndex;
+
+ $expr = $this->queryBuilder->expr();
+ $andX = $expr->andX($expr->eq($aliasIndex . '.file_id', $this->fileTableAlias . '.' . $this->fileIdField));
+ $andX->add($expr->eq($this->getMetadataKeyField($metadataKey), $this->queryBuilder->createNamedParameter($metadataKey)));
+
+ if ($enforce) {
+ $this->queryBuilder->innerJoin(
+ $this->fileTableAlias,
+ IndexRequestService::TABLE_METADATA_INDEX,
+ $aliasIndex,
+ $andX
+ );
+ } else {
+ $this->queryBuilder->leftJoin(
+ $this->fileTableAlias,
+ IndexRequestService::TABLE_METADATA_INDEX,
+ $aliasIndex,
+ $andX
+ );
+ }
+
+ return $aliasIndex;
+ }
+
+ /**
+ * @throws FilesMetadataNotFoundException
+ */
+ private function joinedTableAlias(string $metadataKey): string {
+ if (!array_key_exists($metadataKey, $this->knownJoinedIndex)) {
+ throw new FilesMetadataNotFoundException('table related to ' . $metadataKey . ' not initiated, you need to use leftJoin() first.');
+ }
+
+ return $this->knownJoinedIndex[$metadataKey];
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $metadataKey metadata key
+ *
+ * @return string table field
+ * @throws FilesMetadataNotFoundException
+ * @since 28.0.0
+ */
+ public function getMetadataKeyField(string $metadataKey): string {
+ return $this->joinedTableAlias($metadataKey) . '.meta_key';
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $metadataKey metadata key
+ *
+ * @return string table field
+ * @throws FilesMetadataNotFoundException if metadataKey is not known
+ * @throws FilesMetadataTypeException is metadataKey is not set as indexed
+ * @since 28.0.0
+ */
+ public function getMetadataValueField(string $metadataKey): string {
+ if ($this->manager instanceof IFilesMetadataManager) {
+ /**
+ * Since 29, because knownMetadata is stored in lazy appconfig, it seems smarter
+ * to not call getKnownMetadata() at the load of this class as it is only needed
+ * in this method.
+ *
+ * FIXME: keep only this line and remove support for previous IFilesMetadata in constructor
+ */
+ $knownMetadata = $this->manager->getKnownMetadata();
+ } else {
+ $knownMetadata = $this->manager;
+ }
+
+ return match ($knownMetadata->getType($metadataKey)) {
+ IMetadataValueWrapper::TYPE_STRING => $this->joinedTableAlias($metadataKey) . '.meta_value_string',
+ IMetadataValueWrapper::TYPE_INT, IMetadataValueWrapper::TYPE_BOOL => $this->joinedTableAlias($metadataKey) . '.meta_value_int',
+ default => throw new FilesMetadataTypeException('metadata is not set as indexed'),
+ };
+ }
+}
diff --git a/lib/private/FilesMetadata/Model/FilesMetadata.php b/lib/private/FilesMetadata/Model/FilesMetadata.php
new file mode 100644
index 00000000000..dfeb429507a
--- /dev/null
+++ b/lib/private/FilesMetadata/Model/FilesMetadata.php
@@ -0,0 +1,621 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Model;
+
+use JsonException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataKeyFormatException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataTypeException;
+use OCP\FilesMetadata\Model\IFilesMetadata;
+use OCP\FilesMetadata\Model\IMetadataValueWrapper;
+
+/**
+ * Model that represent metadata linked to a specific file.
+ *
+ * @inheritDoc
+ * @since 28.0.0
+ */
+class FilesMetadata implements IFilesMetadata {
+ /** @var array<string, MetadataValueWrapper> */
+ private array $metadata = [];
+ private bool $updated = false;
+ private int $lastUpdate = 0;
+ private string $syncToken = '';
+
+ public function __construct(
+ private int $fileId = 0
+ ) {
+ }
+
+ /**
+ * @inheritDoc
+ * @return int related file id
+ * @since 28.0.0
+ */
+ public function getFileId(): int {
+ return $this->fileId;
+ }
+
+ /**
+ * @inheritDoc
+ * @return int timestamp
+ * @since 28.0.0
+ */
+ public function lastUpdateTimestamp(): int {
+ return $this->lastUpdate;
+ }
+
+ /**
+ * @inheritDoc
+ * @return string token
+ * @since 28.0.0
+ */
+ public function getSyncToken(): string {
+ return $this->syncToken;
+ }
+
+ /**
+ * @inheritDoc
+ * @return string[] list of keys
+ * @since 28.0.0
+ */
+ public function getKeys(): array {
+ return array_keys($this->metadata);
+ }
+
+ /**
+ * @param string $needle metadata key to search
+ *
+ * @inheritDoc
+ * @return bool TRUE if key exist
+ * @since 28.0.0
+ */
+ public function hasKey(string $needle): bool {
+ return (in_array($needle, $this->getKeys()));
+ }
+
+ /**
+ * @inheritDoc
+ * @return string[] list of indexes
+ * @since 28.0.0
+ */
+ public function getIndexes(): array {
+ $indexes = [];
+ foreach ($this->getKeys() as $key) {
+ if ($this->metadata[$key]->isIndexed()) {
+ $indexes[] = $key;
+ }
+ }
+
+ return $indexes;
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return bool TRUE if key exists and is set as indexed
+ * @since 28.0.0
+ */
+ public function isIndex(string $key): bool {
+ return $this->metadata[$key]?->isIndexed() ?? false;
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return int edit permission
+ * @throws FilesMetadataNotFoundException
+ * @since 28.0.0
+ */
+ public function getEditPermission(string $key): int {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getEditPermission();
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param int $permission edit permission
+ *
+ * @inheritDoc
+ * @throws FilesMetadataNotFoundException
+ * @since 28.0.0
+ */
+ public function setEditPermission(string $key, int $permission): void {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ $this->metadata[$key]->setEditPermission($permission);
+ }
+
+
+ public function getEtag(string $key): string {
+ if (!array_key_exists($key, $this->metadata)) {
+ return '';
+ }
+
+ return $this->metadata[$key]->getEtag();
+ }
+
+ public function setEtag(string $key, string $etag): void {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ $this->metadata[$key]->setEtag($etag);
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return string metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getString(string $key): string {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueString();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return int metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getInt(string $key): int {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueInt();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return float metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getFloat(string $key): float {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueFloat();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return bool metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getBool(string $key): bool {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueBool();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return array metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getArray(string $key): array {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueArray();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return string[] metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getStringList(string $key): array {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueStringList();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return int[] metadata value
+ * @throws FilesMetadataNotFoundException
+ * @throws FilesMetadataTypeException
+ * @since 28.0.0
+ */
+ public function getIntList(string $key): array {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getValueIntList();
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return string value type
+ * @throws FilesMetadataNotFoundException
+ * @see IMetadataValueWrapper::TYPE_STRING
+ * @see IMetadataValueWrapper::TYPE_INT
+ * @see IMetadataValueWrapper::TYPE_FLOAT
+ * @see IMetadataValueWrapper::TYPE_BOOL
+ * @see IMetadataValueWrapper::TYPE_ARRAY
+ * @see IMetadataValueWrapper::TYPE_STRING_LIST
+ * @see IMetadataValueWrapper::TYPE_INT_LIST
+ * @since 28.0.0
+ */
+ public function getType(string $key): string {
+ if (!array_key_exists($key, $this->metadata)) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ return $this->metadata[$key]->getType();
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param string $value metadata value
+ * @param bool $index set TRUE if value must be indexed
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setString(string $key, string $value, bool $index = false): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getString($key) === $value && $index === $this->isIndex($key)) {
+ return $this; // we ignore if value and index have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $meta = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_STRING);
+ $this->updated = true;
+ $this->metadata[$key] = $meta->setValueString($value)->setIndexed($index);
+
+ return $this;
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param int $value metadata value
+ * @param bool $index set TRUE if value must be indexed
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setInt(string $key, int $value, bool $index = false): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getInt($key) === $value && $index === $this->isIndex($key)) {
+ return $this; // we ignore if value have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $meta = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_INT);
+ $this->metadata[$key] = $meta->setValueInt($value)->setIndexed($index);
+ $this->updated = true;
+
+ return $this;
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param float $value metadata value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setFloat(string $key, float $value, bool $index = false): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getFloat($key) === $value && $index === $this->isIndex($key)) {
+ return $this; // we ignore if value have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $meta = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_FLOAT);
+ $this->metadata[$key] = $meta->setValueFloat($value)->setIndexed($index);
+ $this->updated = true;
+
+ return $this;
+ }
+
+
+ /**
+ * @param string $key metadata key
+ * @param bool $value metadata value
+ * @param bool $index set TRUE if value must be indexed
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setBool(string $key, bool $value, bool $index = false): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getBool($key) === $value && $index === $this->isIndex($key)) {
+ return $this; // we ignore if value have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $meta = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_BOOL);
+ $this->metadata[$key] = $meta->setValueBool($value)->setIndexed($index);
+ $this->updated = true;
+
+ return $this;
+ }
+
+
+ /**
+ * @param string $key metadata key
+ * @param array $value metadata value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setArray(string $key, array $value): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getArray($key) === $value) {
+ return $this; // we ignore if value have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $meta = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_ARRAY);
+ $this->metadata[$key] = $meta->setValueArray($value);
+ $this->updated = true;
+
+ return $this;
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param string[] $value metadata value
+ * @param bool $index set TRUE if each values from the list must be indexed
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setStringList(string $key, array $value, bool $index = false): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getStringList($key) === $value) {
+ return $this; // we ignore if value have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $meta = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_STRING_LIST);
+ $this->metadata[$key] = $meta->setValueStringList($value)->setIndexed($index);
+ $this->updated = true;
+
+ return $this;
+ }
+
+ /**
+ * @param string $key metadata key
+ * @param int[] $value metadata value
+ * @param bool $index set TRUE if each values from the list must be indexed
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataKeyFormatException
+ * @since 28.0.0
+ */
+ public function setIntList(string $key, array $value, bool $index = false): IFilesMetadata {
+ $this->confirmKeyFormat($key);
+ try {
+ if ($this->getIntList($key) === $value) {
+ return $this; // we ignore if value have not changed
+ }
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException $e) {
+ // if value does not exist, or type has changed, we keep on the writing
+ }
+
+ $valueWrapper = new MetadataValueWrapper(IMetadataValueWrapper::TYPE_INT_LIST);
+ $this->metadata[$key] = $valueWrapper->setValueIntList($value)->setIndexed($index);
+ $this->updated = true;
+
+ return $this;
+ }
+
+ /**
+ * @param string $key metadata key
+ *
+ * @inheritDoc
+ * @return self
+ * @since 28.0.0
+ */
+ public function unset(string $key): IFilesMetadata {
+ if (!array_key_exists($key, $this->metadata)) {
+ return $this;
+ }
+
+ unset($this->metadata[$key]);
+ $this->updated = true;
+
+ return $this;
+ }
+
+ /**
+ * @param string $keyPrefix metadata key prefix
+ *
+ * @inheritDoc
+ * @return self
+ * @since 28.0.0
+ */
+ public function removeStartsWith(string $keyPrefix): IFilesMetadata {
+ if ($keyPrefix === '') {
+ return $this;
+ }
+
+ foreach ($this->getKeys() as $key) {
+ if (str_starts_with($key, $keyPrefix)) {
+ $this->unset($key);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string $key
+ *
+ * @return void
+ * @throws FilesMetadataKeyFormatException
+ */
+ private function confirmKeyFormat(string $key): void {
+ $acceptedChars = ['-', '_'];
+ if (ctype_alnum(str_replace($acceptedChars, '', $key))) {
+ return;
+ }
+
+ throw new FilesMetadataKeyFormatException('key can only contains alphanumerical characters, and dash (-, _)');
+ }
+
+ /**
+ * @inheritDoc
+ * @return bool TRUE if metadata have been modified
+ * @since 28.0.0
+ */
+ public function updated(): bool {
+ return $this->updated;
+ }
+
+ public function jsonSerialize(bool $emptyValues = false): array {
+ $data = [];
+ foreach ($this->metadata as $metaKey => $metaValueWrapper) {
+ $data[$metaKey] = $metaValueWrapper->jsonSerialize($emptyValues);
+ }
+
+ return $data;
+ }
+
+ /**
+ * @return array<string, string|int|bool|float|string[]|int[]>
+ */
+ public function asArray(): array {
+ $data = [];
+ foreach ($this->metadata as $metaKey => $metaValueWrapper) {
+ try {
+ $data[$metaKey] = $metaValueWrapper->getValueAny();
+ } catch (FilesMetadataNotFoundException $e) {
+ // ignore exception
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @inheritDoc
+ * @return IFilesMetadata
+ * @since 28.0.0
+ */
+ public function import(array $data): IFilesMetadata {
+ foreach ($data as $k => $v) {
+ $valueWrapper = new MetadataValueWrapper();
+ $this->metadata[$k] = $valueWrapper->import($v);
+ }
+ $this->updated = false;
+
+ return $this;
+ }
+
+ /**
+ * import data from database to configure this model
+ *
+ * @param array $data
+ * @param string $prefix
+ *
+ * @return IFilesMetadata
+ * @throws FilesMetadataNotFoundException
+ * @since 28.0.0
+ */
+ public function importFromDatabase(array $data, string $prefix = ''): IFilesMetadata {
+ try {
+ $this->syncToken = $data[$prefix . 'sync_token'] ?? '';
+
+ return $this->import(
+ json_decode(
+ $data[$prefix . 'json'] ?? '[]',
+ true,
+ 512,
+ JSON_THROW_ON_ERROR
+ )
+ );
+ } catch (JsonException) {
+ throw new FilesMetadataNotFoundException();
+ }
+ }
+}
diff --git a/lib/private/FilesMetadata/Model/MetadataValueWrapper.php b/lib/private/FilesMetadata/Model/MetadataValueWrapper.php
new file mode 100644
index 00000000000..710a8129340
--- /dev/null
+++ b/lib/private/FilesMetadata/Model/MetadataValueWrapper.php
@@ -0,0 +1,428 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Model;
+
+use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataTypeException;
+use OCP\FilesMetadata\Model\IMetadataValueWrapper;
+
+/**
+ * @inheritDoc
+ * @see IFilesMetadata
+ * @since 28.0.0
+ */
+class MetadataValueWrapper implements IMetadataValueWrapper {
+ private string $type;
+ /** @var string|int|float|bool|array|string[]|int[] */
+ private mixed $value = null;
+ private string $etag = '';
+ private bool $indexed = false;
+ private int $editPermission = self::EDIT_FORBIDDEN;
+
+ /**
+ * @param string $type value type
+ *
+ * @inheritDoc
+ * @see self::TYPE_INT
+ * @see self::TYPE_FLOAT
+ * @see self::TYPE_BOOL
+ * @see self::TYPE_ARRAY
+ * @see self::TYPE_STRING_LIST
+ * @see self::TYPE_INT_LIST
+ * @see self::TYPE_STRING
+ * @since 28.0.0
+ */
+ public function __construct(string $type = '') {
+ $this->type = $type;
+ }
+
+ /**
+ * @inheritDoc
+ * @return string value type
+ * @see self::TYPE_INT
+ * @see self::TYPE_FLOAT
+ * @see self::TYPE_BOOL
+ * @see self::TYPE_ARRAY
+ * @see self::TYPE_STRING_LIST
+ * @see self::TYPE_INT_LIST
+ * @see self::TYPE_STRING
+ * @since 28.0.0
+ */
+ public function getType(): string {
+ return $this->type;
+ }
+
+ /**
+ * @param string $type value type
+ *
+ * @inheritDoc
+ * @return bool
+ * @see self::TYPE_INT
+ * @see self::TYPE_FLOAT
+ * @see self::TYPE_BOOL
+ * @see self::TYPE_ARRAY
+ * @see self::TYPE_STRING_LIST
+ * @see self::TYPE_INT_LIST
+ * @see self::TYPE_STRING
+ * @since 28.0.0
+ */
+ public function isType(string $type): bool {
+ return (strtolower($type) === strtolower($this->type));
+ }
+
+ /**
+ * @param string $type value type
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if type cannot be confirmed
+ * @see self::TYPE_INT
+ * @see self::TYPE_BOOL
+ * @see self::TYPE_ARRAY
+ * @see self::TYPE_STRING_LIST
+ * @see self::TYPE_INT_LIST
+ * @see self::TYPE_STRING
+ * @see self::TYPE_FLOAT
+ * @since 28.0.0
+ */
+ public function assertType(string $type): self {
+ if (!$this->isType($type)) {
+ throw new FilesMetadataTypeException('type is \'' . $this->getType() . '\', expecting \'' . $type . '\'');
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string $value string to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store a string
+ * @since 28.0.0
+ */
+ public function setValueString(string $value): self {
+ $this->assertType(self::TYPE_STRING);
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @param int $value int to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store an int
+ * @since 28.0.0
+ */
+ public function setValueInt(int $value): self {
+ $this->assertType(self::TYPE_INT);
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @param float $value float to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store a float
+ * @since 28.0.0
+ */
+ public function setValueFloat(float $value): self {
+ $this->assertType(self::TYPE_FLOAT);
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @param bool $value bool to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store a bool
+ * @since 28.0.0
+ */
+ public function setValueBool(bool $value): self {
+ $this->assertType(self::TYPE_BOOL);
+ $this->value = $value;
+
+
+ return $this;
+ }
+
+ /**
+ * @param array $value array to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store an array
+ * @since 28.0.0
+ */
+ public function setValueArray(array $value): self {
+ $this->assertType(self::TYPE_ARRAY);
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @param string[] $value string list to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store a string list
+ * @since 28.0.0
+ */
+ public function setValueStringList(array $value): self {
+ $this->assertType(self::TYPE_STRING_LIST);
+ // TODO confirm value is an array or string ?
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @param int[] $value int list to be set as value
+ *
+ * @inheritDoc
+ * @return self
+ * @throws FilesMetadataTypeException if wrapper was not set to store an int list
+ * @since 28.0.0
+ */
+ public function setValueIntList(array $value): self {
+ $this->assertType(self::TYPE_INT_LIST);
+ // TODO confirm value is an array of int ?
+ $this->value = $value;
+
+ return $this;
+ }
+
+
+ /**
+ * @inheritDoc
+ * @return string set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store a string
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueString(): string {
+ $this->assertType(self::TYPE_STRING);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (string)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return int set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store an int
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueInt(): int {
+ $this->assertType(self::TYPE_INT);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (int)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return float set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store a float
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueFloat(): float {
+ $this->assertType(self::TYPE_FLOAT);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (float)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return bool set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store a bool
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueBool(): bool {
+ $this->assertType(self::TYPE_BOOL);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (bool)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return array set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store an array
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueArray(): array {
+ $this->assertType(self::TYPE_ARRAY);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (array)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return string[] set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store a string list
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueStringList(): array {
+ $this->assertType(self::TYPE_STRING_LIST);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (array)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return int[] set value
+ * @throws FilesMetadataTypeException if wrapper was not set to store an int list
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueIntList(): array {
+ $this->assertType(self::TYPE_INT_LIST);
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return (array)$this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return string|int|float|bool|array|string[]|int[] set value
+ * @throws FilesMetadataNotFoundException if value is not set
+ * @since 28.0.0
+ */
+ public function getValueAny(): mixed {
+ if ($this->value === null) {
+ throw new FilesMetadataNotFoundException('value is not set');
+ }
+
+ return $this->value;
+ }
+
+ /**
+ * @inheritDoc
+ * @return string stored etag
+ * @since 29.0.0
+ */
+ public function getEtag(): string {
+ return $this->etag;
+ }
+
+ /**
+ * @param string $etag etag value
+ *
+ * @inheritDoc
+ * @return self
+ * @since 29.0.0
+ */
+ public function setEtag(string $etag): self {
+ $this->etag = $etag;
+ return $this;
+ }
+
+ /**
+ * @param bool $indexed TRUE to set the stored value as an indexed value
+ *
+ * @inheritDoc
+ * @return self
+ * @since 28.0.0
+ */
+ public function setIndexed(bool $indexed): self {
+ $this->indexed = $indexed;
+
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
+ * @return bool TRUE if value is an indexed value
+ * @since 28.0.0
+ */
+ public function isIndexed(): bool {
+ return $this->indexed;
+ }
+
+ /**
+ * @param int $permission edit permission
+ *
+ * @inheritDoc
+ * @return self
+ * @since 28.0.0
+ */
+ public function setEditPermission(int $permission): self {
+ $this->editPermission = $permission;
+
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
+ * @return int edit permission
+ * @since 28.0.0
+ */
+ public function getEditPermission(): int {
+ return $this->editPermission;
+ }
+
+ /**
+ * @param array $data serialized version of the object
+ *
+ * @inheritDoc
+ * @return self
+ * @see jsonSerialize
+ * @since 28.0.0
+ */
+ public function import(array $data): self {
+ $this->value = $data['value'] ?? null;
+ $this->type = $data['type'] ?? '';
+ $this->setEtag($data['etag'] ?? '');
+ $this->setIndexed($data['indexed'] ?? false);
+ $this->setEditPermission($data['editPermission'] ?? self::EDIT_FORBIDDEN);
+ return $this;
+ }
+
+ public function jsonSerialize(bool $emptyValues = false): array {
+ return [
+ 'value' => ($emptyValues) ? null : $this->value,
+ 'type' => $this->getType(),
+ 'etag' => $this->getEtag(),
+ 'indexed' => $this->isIndexed(),
+ 'editPermission' => $this->getEditPermission()
+ ];
+ }
+}
diff --git a/lib/private/FilesMetadata/Service/IndexRequestService.php b/lib/private/FilesMetadata/Service/IndexRequestService.php
new file mode 100644
index 00000000000..32248ff5c24
--- /dev/null
+++ b/lib/private/FilesMetadata/Service/IndexRequestService.php
@@ -0,0 +1,178 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Service;
+
+use OCP\DB\Exception as DbException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
+use OCP\FilesMetadata\Exceptions\FilesMetadataTypeException;
+use OCP\FilesMetadata\Model\IFilesMetadata;
+use OCP\FilesMetadata\Model\IMetadataValueWrapper;
+use OCP\IDBConnection;
+use Psr\Log\LoggerInterface;
+
+/**
+ * manage sql request to the metadata_index table
+ */
+class IndexRequestService {
+ public const TABLE_METADATA_INDEX = 'files_metadata_index';
+
+ public function __construct(
+ private IDBConnection $dbConnection,
+ private LoggerInterface $logger
+ ) {
+ }
+
+ /**
+ * update the index for a specific metadata key
+ *
+ * @param IFilesMetadata $filesMetadata metadata
+ * @param string $key metadata key to update
+ *
+ * @throws DbException
+ */
+ public function updateIndex(IFilesMetadata $filesMetadata, string $key): void {
+ $fileId = $filesMetadata->getFileId();
+ try {
+ $metadataType = $filesMetadata->getType($key);
+ } catch (FilesMetadataNotFoundException $e) {
+ return;
+ }
+
+ /**
+ * might look harsh, but a lot simpler than comparing current indexed data, as we can expect
+ * conflict with a change of types.
+ * We assume that each time one random metadata were modified we can drop all index for this
+ * key and recreate them.
+ * To make it slightly cleaner, we'll use transaction
+ */
+ $this->dbConnection->beginTransaction();
+ try {
+ $this->dropIndex($fileId, $key);
+ match ($metadataType) {
+ IMetadataValueWrapper::TYPE_STRING => $this->insertIndexString($fileId, $key, $filesMetadata->getString($key)),
+ IMetadataValueWrapper::TYPE_INT => $this->insertIndexInt($fileId, $key, $filesMetadata->getInt($key)),
+ IMetadataValueWrapper::TYPE_BOOL => $this->insertIndexBool($fileId, $key, $filesMetadata->getBool($key)),
+ IMetadataValueWrapper::TYPE_STRING_LIST => $this->insertIndexStringList($fileId, $key, $filesMetadata->getStringList($key)),
+ IMetadataValueWrapper::TYPE_INT_LIST => $this->insertIndexIntList($fileId, $key, $filesMetadata->getIntList($key))
+ };
+ } catch (FilesMetadataNotFoundException|FilesMetadataTypeException|DbException $e) {
+ $this->dbConnection->rollBack();
+ $this->logger->warning('issue while updateIndex', ['exception' => $e, 'fileId' => $fileId, 'key' => $key]);
+ }
+
+ $this->dbConnection->commit();
+ }
+
+ /**
+ * insert a new entry in the metadata_index table for a string value
+ *
+ * @param int $fileId file id
+ * @param string $key metadata key
+ * @param string $value metadata value
+ *
+ * @throws DbException
+ */
+ private function insertIndexString(int $fileId, string $key, string $value): void {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->insert(self::TABLE_METADATA_INDEX)
+ ->setValue('meta_key', $qb->createNamedParameter($key))
+ ->setValue('meta_value_string', $qb->createNamedParameter($value))
+ ->setValue('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT));
+ $qb->executeStatement();
+ }
+
+ /**
+ * insert a new entry in the metadata_index table for an int value
+ *
+ * @param int $fileId file id
+ * @param string $key metadata key
+ * @param int $value metadata value
+ *
+ * @throws DbException
+ */
+ public function insertIndexInt(int $fileId, string $key, int $value): void {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->insert(self::TABLE_METADATA_INDEX)
+ ->setValue('meta_key', $qb->createNamedParameter($key))
+ ->setValue('meta_value_int', $qb->createNamedParameter($value, IQueryBuilder::PARAM_INT))
+ ->setValue('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT));
+ $qb->executeStatement();
+ }
+
+ /**
+ * insert a new entry in the metadata_index table for a bool value
+ *
+ * @param int $fileId file id
+ * @param string $key metadata key
+ * @param bool $value metadata value
+ *
+ * @throws DbException
+ */
+ public function insertIndexBool(int $fileId, string $key, bool $value): void {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->insert(self::TABLE_METADATA_INDEX)
+ ->setValue('meta_key', $qb->createNamedParameter($key))
+ ->setValue('meta_value_int', $qb->createNamedParameter(($value) ? '1' : '0', IQueryBuilder::PARAM_INT))
+ ->setValue('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT));
+ $qb->executeStatement();
+ }
+
+ /**
+ * insert entries in the metadata_index table for list of string
+ *
+ * @param int $fileId file id
+ * @param string $key metadata key
+ * @param string[] $values metadata values
+ *
+ * @throws DbException
+ */
+ public function insertIndexStringList(int $fileId, string $key, array $values): void {
+ foreach ($values as $value) {
+ $this->insertIndexString($fileId, $key, $value);
+ }
+ }
+
+ /**
+ * insert entries in the metadata_index table for list of int
+ *
+ * @param int $fileId file id
+ * @param string $key metadata key
+ * @param int[] $values metadata values
+ *
+ * @throws DbException
+ */
+ public function insertIndexIntList(int $fileId, string $key, array $values): void {
+ foreach ($values as $value) {
+ $this->insertIndexInt($fileId, $key, $value);
+ }
+ }
+
+ /**
+ * drop indexes related to a file id
+ * if a key is specified, only drop entries related to it
+ *
+ * @param int $fileId file id
+ * @param string $key metadata key
+ *
+ * @throws DbException
+ */
+ public function dropIndex(int $fileId, string $key = ''): void {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $expr = $qb->expr();
+ $qb->delete(self::TABLE_METADATA_INDEX)
+ ->where($expr->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+
+ if ($key !== '') {
+ $qb->andWhere($expr->eq('meta_key', $qb->createNamedParameter($key)));
+ }
+
+ $qb->executeStatement();
+ }
+}
diff --git a/lib/private/FilesMetadata/Service/MetadataRequestService.php b/lib/private/FilesMetadata/Service/MetadataRequestService.php
new file mode 100644
index 00000000000..08982a2a659
--- /dev/null
+++ b/lib/private/FilesMetadata/Service/MetadataRequestService.php
@@ -0,0 +1,169 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\FilesMetadata\Service;
+
+use OC\FilesMetadata\Model\FilesMetadata;
+use OCP\DB\Exception;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
+use OCP\FilesMetadata\Model\IFilesMetadata;
+use OCP\IDBConnection;
+use Psr\Log\LoggerInterface;
+
+/**
+ * manage sql request to the metadata table
+ */
+class MetadataRequestService {
+ public const TABLE_METADATA = 'files_metadata';
+
+ public function __construct(
+ private IDBConnection $dbConnection,
+ private LoggerInterface $logger
+ ) {
+ }
+
+ /**
+ * store metadata into database
+ *
+ * @param IFilesMetadata $filesMetadata
+ *
+ * @throws Exception
+ */
+ public function store(IFilesMetadata $filesMetadata): void {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->insert(self::TABLE_METADATA)
+ ->setValue('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT))
+ ->setValue('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize())))
+ ->setValue('sync_token', $qb->createNamedParameter($this->generateSyncToken()))
+ ->setValue('last_update', (string) $qb->createFunction('NOW()'));
+ $qb->executeStatement();
+ }
+
+ /**
+ * returns metadata for a file id
+ *
+ * @param int $fileId file id
+ *
+ * @return IFilesMetadata
+ * @throws FilesMetadataNotFoundException if no metadata are found in database
+ */
+ public function getMetadataFromFileId(int $fileId): IFilesMetadata {
+ try {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->select('json', 'sync_token')->from(self::TABLE_METADATA);
+ $qb->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+ $result = $qb->executeQuery();
+ $data = $result->fetch();
+ $result->closeCursor();
+ } catch (Exception $e) {
+ $this->logger->warning('exception while getMetadataFromDatabase()', ['exception' => $e, 'fileId' => $fileId]);
+ throw new FilesMetadataNotFoundException();
+ }
+
+ if ($data === false) {
+ throw new FilesMetadataNotFoundException();
+ }
+
+ $metadata = new FilesMetadata($fileId);
+ $metadata->importFromDatabase($data);
+
+ return $metadata;
+ }
+
+ /**
+ * returns metadata for multiple file ids
+ *
+ * @param array $fileIds file ids
+ *
+ * @return array File ID is the array key, files without metadata are not returned in the array
+ * @psalm-return array<int, IFilesMetadata>
+ */
+ public function getMetadataFromFileIds(array $fileIds): array {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->select('file_id', 'json', 'sync_token')->from(self::TABLE_METADATA);
+ $qb->where($qb->expr()->in('file_id', $qb->createNamedParameter($fileIds, IQueryBuilder::PARAM_INT_ARRAY)));
+
+ $list = [];
+ $result = $qb->executeQuery();
+ while ($data = $result->fetch()) {
+ $fileId = (int) $data['file_id'];
+ $metadata = new FilesMetadata($fileId);
+ try {
+ $metadata->importFromDatabase($data);
+ } catch (FilesMetadataNotFoundException) {
+ continue;
+ }
+ $list[$fileId] = $metadata;
+ }
+ $result->closeCursor();
+
+ return $list;
+ }
+
+ /**
+ * drop metadata related to a file id
+ *
+ * @param int $fileId file id
+ *
+ * @return void
+ * @throws Exception
+ */
+ public function dropMetadata(int $fileId): void {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->delete(self::TABLE_METADATA)
+ ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+ $qb->executeStatement();
+ }
+
+ /**
+ * update metadata in the database
+ *
+ * @param IFilesMetadata $filesMetadata metadata
+ *
+ * @return int number of affected rows
+ * @throws Exception
+ */
+ public function updateMetadata(IFilesMetadata $filesMetadata): int {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $expr = $qb->expr();
+
+ $qb->update(self::TABLE_METADATA)
+ ->set('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize())))
+ ->set('sync_token', $qb->createNamedParameter($this->generateSyncToken()))
+ ->set('last_update', $qb->createFunction('NOW()'))
+ ->where(
+ $expr->andX(
+ $expr->eq('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT)),
+ $expr->eq('sync_token', $qb->createNamedParameter($filesMetadata->getSyncToken()))
+ )
+ );
+
+ return $qb->executeStatement();
+ }
+
+ /**
+ * generate a random token
+ * @return string
+ */
+ private function generateSyncToken(): string {
+ $chars = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
+
+ $str = '';
+ $max = strlen($chars);
+ for ($i = 0; $i < 7; $i++) {
+ try {
+ $str .= $chars[random_int(0, $max - 2)];
+ } catch (\Exception $e) {
+ $this->logger->warning('exception during generateSyncToken', ['exception' => $e]);
+ }
+ }
+
+ return $str;
+ }
+}
diff --git a/lib/private/ForbiddenException.php b/lib/private/ForbiddenException.php
index 8cc9a698253..e65576d27ad 100644
--- a/lib/private/ForbiddenException.php
+++ b/lib/private/ForbiddenException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/FullTextSearch/FullTextSearchManager.php b/lib/private/FullTextSearch/FullTextSearchManager.php
index 8d850513949..3ef8547ad3f 100644
--- a/lib/private/FullTextSearch/FullTextSearchManager.php
+++ b/lib/private/FullTextSearch/FullTextSearchManager.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
- *
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\FullTextSearch;
@@ -39,47 +22,35 @@ use OCP\FullTextSearch\Service\ISearchService;
* @package OC\FullTextSearch
*/
class FullTextSearchManager implements IFullTextSearchManager {
- /** @var IProviderService */
- private $providerService;
+ private ?IProviderService $providerService = null;
- /** @var IIndexService */
- private $indexService;
-
- /** @var ISearchService */
- private $searchService;
+ private ?IIndexService $indexService = null;
+ private ?ISearchService $searchService = null;
/**
* @since 15.0.0
- *
- * @param IProviderService $providerService
*/
- public function registerProviderService(IProviderService $providerService) {
+ public function registerProviderService(IProviderService $providerService): void {
$this->providerService = $providerService;
}
/**
* @since 15.0.0
- *
- * @param IIndexService $indexService
*/
- public function registerIndexService(IIndexService $indexService) {
+ public function registerIndexService(IIndexService $indexService): void {
$this->indexService = $indexService;
}
/**
* @since 15.0.0
- *
- * @param ISearchService $searchService
*/
- public function registerSearchService(ISearchService $searchService) {
+ public function registerSearchService(ISearchService $searchService): void {
$this->searchService = $searchService;
}
/**
* @since 16.0.0
- *
- * @return bool
*/
public function isAvailable(): bool {
if ($this->indexService === null ||
@@ -93,7 +64,6 @@ class FullTextSearchManager implements IFullTextSearchManager {
/**
- * @return IProviderService
* @throws FullTextSearchAppNotAvailableException
*/
private function getProviderService(): IProviderService {
@@ -106,7 +76,6 @@ class FullTextSearchManager implements IFullTextSearchManager {
/**
- * @return IIndexService
* @throws FullTextSearchAppNotAvailableException
*/
private function getIndexService(): IIndexService {
@@ -119,7 +88,6 @@ class FullTextSearchManager implements IFullTextSearchManager {
/**
- * @return ISearchService
* @throws FullTextSearchAppNotAvailableException
*/
private function getSearchService(): ISearchService {
@@ -134,15 +102,12 @@ class FullTextSearchManager implements IFullTextSearchManager {
/**
* @throws FullTextSearchAppNotAvailableException
*/
- public function addJavascriptAPI() {
+ public function addJavascriptAPI(): void {
$this->getProviderService()->addJavascriptAPI();
}
/**
- * @param string $providerId
- *
- * @return bool
* @throws FullTextSearchAppNotAvailableException
*/
public function isProviderIndexed(string $providerId): bool {
@@ -151,9 +116,6 @@ class FullTextSearchManager implements IFullTextSearchManager {
/**
- * @param string $providerId
- * @param string $documentId
- * @return IIndex
* @throws FullTextSearchAppNotAvailableException
*/
public function getIndex(string $providerId, string $documentId): IIndex {
@@ -161,46 +123,45 @@ class FullTextSearchManager implements IFullTextSearchManager {
}
/**
- * @param string $providerId
- * @param string $documentId
- * @param string $userId
- * @param int $status
- *
* @see IIndex for available value for $status.
*
- * @return IIndex
* @throws FullTextSearchAppNotAvailableException
*/
- public function createIndex(string $providerId, string $documentId, string $userId, int $status = 0): IIndex {
+ public function createIndex(
+ string $providerId,
+ string $documentId,
+ string $userId,
+ int $status = 0,
+ ): IIndex {
return $this->getIndexService()->createIndex($providerId, $documentId, $userId, $status);
}
/**
- * @param string $providerId
- * @param string $documentId
- * @param int $status
- * @param bool $reset
- *
* @see IIndex for available value for $status.
*
* @throws FullTextSearchAppNotAvailableException
*/
- public function updateIndexStatus(string $providerId, string $documentId, int $status, bool $reset = false) {
+ public function updateIndexStatus(
+ string $providerId,
+ string $documentId,
+ int $status,
+ bool $reset = false,
+ ): void {
$this->getIndexService()->updateIndexStatus($providerId, $documentId, $status, $reset);
}
/**
- * @param string $providerId
- * @param array $documentIds
- * @param int $status
- * @param bool $reset
- *
* @see IIndex for available value for $status.
*
* @throws FullTextSearchAppNotAvailableException
*/
- public function updateIndexesStatus(string $providerId, array $documentIds, int $status, bool $reset = false) {
+ public function updateIndexesStatus(
+ string $providerId,
+ array $documentIds,
+ int $status,
+ bool $reset = false,
+ ): void {
$this->getIndexService()->updateIndexesStatus($providerId, $documentIds, $status, $reset);
}
@@ -210,15 +171,12 @@ class FullTextSearchManager implements IFullTextSearchManager {
*
* @throws FullTextSearchAppNotAvailableException
*/
- public function updateIndexes(array $indexes) {
+ public function updateIndexes(array $indexes): void {
$this->getIndexService()->updateIndexes($indexes);
}
/**
- * @param array $request
- * @param string $userId
- *
* @return ISearchResult[]
* @throws FullTextSearchAppNotAvailableException
*/
diff --git a/lib/private/FullTextSearch/Model/DocumentAccess.php b/lib/private/FullTextSearch/Model/DocumentAccess.php
index cb2b95284f1..9efffeaee88 100644
--- a/lib/private/FullTextSearch/Model/DocumentAccess.php
+++ b/lib/private/FullTextSearch/Model/DocumentAccess.php
@@ -1,27 +1,9 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright 2018
- *
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\FullTextSearch\Model;
@@ -49,23 +31,17 @@ use OCP\FullTextSearch\Model\IDocumentAccess;
* @package OC\FullTextSearch\Model
*/
final class DocumentAccess implements IDocumentAccess, JsonSerializable {
- /** @var string */
- private $ownerId;
+ private string $ownerId;
- /** @var string */
- private $viewerId = '';
+ private string $viewerId = '';
- /** @var array */
- private $users = [];
+ private array $users = [];
- /** @var array */
- private $groups = [];
+ private array $groups = [];
- /** @var array */
- private $circles = [];
+ private array $circles = [];
- /** @var array */
- private $links = [];
+ private array $links = [];
/**
@@ -74,8 +50,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* @since 16.0.0
*
* IDocumentAccess constructor.
- *
- * @param string $ownerId
*/
public function __construct(string $ownerId = '') {
$this->setOwnerId($ownerId);
@@ -86,10 +60,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Set the Owner of the document.
*
* @since 16.0.0
- *
- * @param string $ownerId
- *
- * @return IDocumentAccess
*/
public function setOwnerId(string $ownerId): IDocumentAccess {
$this->ownerId = $ownerId;
@@ -101,8 +71,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Get the Owner of the document.
*
* @since 16.0.0
- *
- * @return string
*/
public function getOwnerId(): string {
return $this->ownerId;
@@ -113,10 +81,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Set the viewer of the document.
*
* @since 16.0.0
- *
- * @param string $viewerId
- *
- * @return IDocumentAccess
*/
public function setViewerId(string $viewerId): IDocumentAccess {
$this->viewerId = $viewerId;
@@ -128,8 +92,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Get the viewer of the document.
*
* @since 16.0.0
- *
- * @return string
*/
public function getViewerId(): string {
return $this->viewerId;
@@ -140,10 +102,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Set the list of users that have read access to the document.
*
* @since 16.0.0
- *
- * @param array $users
- *
- * @return IDocumentAccess
*/
public function setUsers(array $users): IDocumentAccess {
$this->users = $users;
@@ -155,10 +113,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Add an entry to the list of users that have read access to the document.
*
* @since 16.0.0
- *
- * @param string $user
- *
- * @return IDocumentAccess
*/
public function addUser(string $user): IDocumentAccess {
$this->users[] = $user;
@@ -171,10 +125,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* document.
*
* @since 16.0.0
- *
- * @param array $users
- *
- * @return IDocumentAccess
*/
public function addUsers($users): IDocumentAccess {
$this->users = array_merge($this->users, $users);
@@ -186,8 +136,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Get the complete list of users that have read access to the document.
*
* @since 16.0.0
- *
- * @return array
*/
public function getUsers(): array {
return $this->users;
@@ -198,10 +146,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Set the list of groups that have read access to the document.
*
* @since 16.0.0
- *
- * @param array $groups
- *
- * @return IDocumentAccess
*/
public function setGroups(array $groups): IDocumentAccess {
$this->groups = $groups;
@@ -213,10 +157,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Add an entry to the list of groups that have read access to the document.
*
* @since 16.0.0
- *
- * @param string $group
- *
- * @return IDocumentAccess
*/
public function addGroup(string $group): IDocumentAccess {
$this->groups[] = $group;
@@ -229,12 +169,8 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* document.
*
* @since 16.0.0
- *
- * @param array $groups
- *
- * @return IDocumentAccess
*/
- public function addGroups(array $groups) {
+ public function addGroups(array $groups): IDocumentAccess {
$this->groups = array_merge($this->groups, $groups);
return $this;
@@ -244,8 +180,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Get the complete list of groups that have read access to the document.
*
* @since 16.0.0
- *
- * @return array
*/
public function getGroups(): array {
return $this->groups;
@@ -256,10 +190,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Set the list of circles that have read access to the document.
*
* @since 16.0.0
- *
- * @param array $circles
- *
- * @return IDocumentAccess
*/
public function setCircles(array $circles): IDocumentAccess {
$this->circles = $circles;
@@ -271,10 +201,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Add an entry to the list of circles that have read access to the document.
*
* @since 16.0.0
- *
- * @param string $circle
- *
- * @return IDocumentAccess
*/
public function addCircle(string $circle): IDocumentAccess {
$this->circles[] = $circle;
@@ -287,10 +213,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* document.
*
* @since 16.0.0
- *
- * @param array $circles
- *
- * @return IDocumentAccess
*/
public function addCircles(array $circles): IDocumentAccess {
$this->circles = array_merge($this->circles, $circles);
@@ -302,8 +224,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Get the complete list of circles that have read access to the document.
*
* @since 16.0.0
- *
- * @return array
*/
public function getCircles(): array {
return $this->circles;
@@ -314,10 +234,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Set the list of links that have read access to the document.
*
* @since 16.0.0
- *
- * @param array $links
- *
- * @return IDocumentAccess
*/
public function setLinks(array $links): IDocumentAccess {
$this->links = $links;
@@ -329,8 +245,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
* Get the list of links that have read access to the document.
*
* @since 16.0.0
- *
- * @return array
*/
public function getLinks(): array {
return $this->links;
@@ -339,8 +253,6 @@ final class DocumentAccess implements IDocumentAccess, JsonSerializable {
/**
* @since 16.0.0
- *
- * @return array
*/
public function jsonSerialize(): array {
return [
diff --git a/lib/private/FullTextSearch/Model/IndexDocument.php b/lib/private/FullTextSearch/Model/IndexDocument.php
index 74788463693..6f9da9416fa 100644
--- a/lib/private/FullTextSearch/Model/IndexDocument.php
+++ b/lib/private/FullTextSearch/Model/IndexDocument.php
@@ -1,31 +1,14 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright 2018
- *
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\FullTextSearch\Model;
use JsonSerializable;
+use OCP\FullTextSearch\Exceptions\FullTextSearchIndexNotAvailableException;
use OCP\FullTextSearch\Model\IDocumentAccess;
use OCP\FullTextSearch\Model\IIndex;
use OCP\FullTextSearch\Model\IIndexDocument;
@@ -47,62 +30,41 @@ use OCP\FullTextSearch\Model\IIndexDocument;
* @package OC\FullTextSearch\Model
*/
class IndexDocument implements IIndexDocument, JsonSerializable {
- /** @var string */
- protected $id = '';
-
- /** @var string */
- protected $providerId = '';
+ protected string $id = '';
- /** @var DocumentAccess */
- protected $access;
+ protected DocumentAccess $access;
- /** @var IIndex */
- protected $index;
+ protected ?IIndex $index = null;
- /** @var int */
- protected $modifiedTime = 0;
+ protected int $modifiedTime = 0;
- /** @var string */
- protected $source = '';
+ protected string $source = '';
- /** @var array */
- protected $tags = [];
+ protected array $tags = [];
- /** @var array */
- protected $metaTags = [];
+ protected array $metaTags = [];
- /** @var array */
- protected $subTags = [];
+ protected array $subTags = [];
- /** @var string */
- protected $title = '';
+ protected string $title = '';
- /** @var string */
- protected $content = '';
+ protected string $content = '';
- /** @var string */
- protected $hash = '';
+ protected string $hash = '';
- /** @var array */
- protected $parts = [];
+ protected array $parts = [];
- /** @var string */
- protected $link = '';
+ protected string $link = '';
- /** @var array */
- protected $more = [];
+ protected array $more = [];
- /** @var array */
- protected $excerpts = [];
+ protected array $excerpts = [];
- /** @var string */
- protected $score = '';
+ protected string $score = '';
- /** @var array */
- protected $info = [];
+ protected array $info = [];
- /** @var int */
- protected $contentEncoded = 0;
+ protected int $contentEncoded = 0;
/**
@@ -112,12 +74,11 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* and the Id of the original document.
*
* @since 15.0.0
- *
- * @param string $providerId
- * @param string $documentId
*/
- public function __construct(string $providerId, string $documentId) {
- $this->providerId = $providerId;
+ public function __construct(
+ protected string $providerId,
+ string $documentId,
+ ) {
$this->id = $documentId;
}
@@ -126,8 +87,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Returns the Id of the original document.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getId(): string {
return $this->id;
@@ -138,8 +97,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Returns the Id of the provider.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getProviderId(): string {
return $this->providerId;
@@ -152,10 +109,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* @see IIndex
*
* @since 15.0.0
- *
- * @param IIndex $index
- *
- * @return IIndexDocument
*/
final public function setIndex(IIndex $index): IIndexDocument {
$this->index = $index;
@@ -166,11 +119,14 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
/**
* Get the Index.
*
+ * @throws FullTextSearchIndexNotAvailableException
* @since 15.0.0
- *
- * @return IIndex
*/
final public function getIndex(): IIndex {
+ if ($this->index === null) {
+ throw new FullTextSearchIndexNotAvailableException('No IIndex generated');
+ }
+
return $this->index;
}
@@ -178,22 +134,15 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* return if Index is defined.
*
* @since 16.0.0
- *
- * @return bool
*/
final public function hasIndex(): bool {
- return ($this->index !== null);
+ return $this->index !== null;
}
-
/**
* Set the modified time of the original document.
*
* @since 15.0.0
- *
- * @param int $modifiedTime
- *
- * @return IIndexDocument
*/
final public function setModifiedTime(int $modifiedTime): IIndexDocument {
$this->modifiedTime = $modifiedTime;
@@ -205,8 +154,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the modified time of the original document.
*
* @since 15.0.0
- *
- * @return int
*/
final public function getModifiedTime(): int {
return $this->modifiedTime;
@@ -216,10 +163,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Check if the original document of the IIndexDocument is older than $time.
*
* @since 15.0.0
- *
- * @param int $time
- *
- * @return bool
*/
final public function isOlderThan(int $time): bool {
return ($this->modifiedTime < $time);
@@ -232,10 +175,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* @see IDocumentAccess
*
* @since 15.0.0
- *
- * @param IDocumentAccess $access
- *
- * @return $this
*/
final public function setAccess(IDocumentAccess $access): IIndexDocument {
$this->access = $access;
@@ -247,8 +186,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the IDocumentAccess related to the original document.
*
* @since 15.0.0
- *
- * @return IDocumentAccess
*/
final public function getAccess(): IDocumentAccess {
return $this->access;
@@ -259,10 +196,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Add a tag to the list.
*
* @since 15.0.0
- *
- * @param string $tag
- *
- * @return IIndexDocument
*/
final public function addTag(string $tag): IIndexDocument {
$this->tags[] = $tag;
@@ -274,10 +207,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set the list of tags assigned to the original document.
*
* @since 15.0.0
- *
- * @param array $tags
- *
- * @return IIndexDocument
*/
final public function setTags(array $tags): IIndexDocument {
$this->tags = $tags;
@@ -289,8 +218,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the list of tags assigned to the original document.
*
* @since 15.0.0
- *
- * @return array
*/
final public function getTags(): array {
return $this->tags;
@@ -301,10 +228,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Add a meta tag to the list.
*
* @since 15.0.0
- *
- * @param string $tag
- *
- * @return IIndexDocument
*/
final public function addMetaTag(string $tag): IIndexDocument {
$this->metaTags[] = $tag;
@@ -316,10 +239,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set the list of meta tags assigned to the original document.
*
* @since 15.0.0
- *
- * @param array $tags
- *
- * @return IIndexDocument
*/
final public function setMetaTags(array $tags): IIndexDocument {
$this->metaTags = $tags;
@@ -331,8 +250,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the list of meta tags assigned to the original document.
*
* @since 15.0.0
- *
- * @return array
*/
final public function getMetaTags(): array {
return $this->metaTags;
@@ -343,11 +260,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Add a sub tag to the list.
*
* @since 15.0.0
- *
- * @param string $sub
- * @param string $tag
- *
- * @return IIndexDocument
*/
final public function addSubTag(string $sub, string $tag): IIndexDocument {
if (!array_key_exists($sub, $this->subTags)) {
@@ -364,10 +276,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set the list of sub tags assigned to the original document.
*
* @since 15.0.0
- *
- * @param array $tags
- *
- * @return IIndexDocument
*/
final public function setSubTags(array $tags): IIndexDocument {
$this->subTags = $tags;
@@ -381,10 +289,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* dimensional array.
*
* @since 15.0.0
- *
- * @param bool $formatted
- *
- * @return array
*/
final public function getSubTags(bool $formatted = false): array {
if ($formatted === false) {
@@ -408,10 +312,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set the source of the original document.
*
* @since 15.0.0
- *
- * @param string $source
- *
- * @return IIndexDocument
*/
final public function setSource(string $source): IIndexDocument {
$this->source = $source;
@@ -423,8 +323,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the source of the original document.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getSource(): string {
return $this->source;
@@ -435,10 +333,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set the title of the original document.
*
* @since 15.0.0
- *
- * @param string $title
- *
- * @return IIndexDocument
*/
final public function setTitle(string $title): IIndexDocument {
$this->title = $title;
@@ -450,8 +344,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the title of the original document.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getTitle(): string {
return $this->title;
@@ -464,11 +356,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* encoded in base64.
*
* @since 15.0.0
- *
- * @param string $content
- * @param int $encoded
- *
- * @return IIndexDocument
*/
final public function setContent(string $content, int $encoded = 0): IIndexDocument {
$this->content = $content;
@@ -481,8 +368,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the content of the original document.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getContent(): string {
return $this->content;
@@ -492,8 +377,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Returns the type of the encoding on the content.
*
* @since 15.0.0
- *
- * @return int
*/
final public function isContentEncoded(): int {
return $this->contentEncoded;
@@ -503,8 +386,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Return the size of the content.
*
* @since 15.0.0
- *
- * @return int
*/
final public function getContentSize(): int {
return strlen($this->getContent());
@@ -512,11 +393,9 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
/**
- * Generate an hash, based on the content of the original document.
+ * Generate a hash, based on the content of the original document.
*
* @since 15.0.0
- *
- * @return IIndexDocument
*/
final public function initHash(): IIndexDocument {
if ($this->getContent() === '' || is_null($this->getContent())) {
@@ -532,10 +411,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set the hash of the original document.
*
* @since 15.0.0
- *
- * @param string $hash
- *
- * @return IIndexDocument
*/
final public function setHash(string $hash): IIndexDocument {
$this->hash = $hash;
@@ -547,8 +422,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the hash of the original document.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getHash(): string {
return $this->hash;
@@ -562,11 +435,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* $part string.
*
* @since 15.0.0
- *
- * @param string $part
- * @param string $content
- *
- * @return IIndexDocument
*/
final public function addPart(string $part, string $content): IIndexDocument {
$this->parts[$part] = $content;
@@ -578,10 +446,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set all parts and their content.
*
* @since 15.0.0
- *
- * @param array $parts
- *
- * @return IIndexDocument
*/
final public function setParts(array $parts): IIndexDocument {
$this->parts = $parts;
@@ -593,8 +457,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get all parts of the IIndexDocument.
*
* @since 15.0.0
- *
- * @return array
*/
final public function getParts(): array {
return $this->parts;
@@ -605,10 +467,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Add a link, usable by the frontend.
*
* @since 15.0.0
- *
- * @param string $link
- *
- * @return IIndexDocument
*/
final public function setLink(string $link): IIndexDocument {
$this->link = $link;
@@ -620,8 +478,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the link.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getLink(): string {
return $this->link;
@@ -632,10 +488,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set more information that couldn't be set using other method.
*
* @since 15.0.0
- *
- * @param array $more
- *
- * @return IIndexDocument
*/
final public function setMore(array $more): IIndexDocument {
$this->more = $more;
@@ -647,8 +499,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get more information.
*
* @since 15.0.0
- *
- * @return array
*/
final public function getMore(): array {
return $this->more;
@@ -660,11 +510,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* on the search request.
*
* @since 16.0.0
- *
- * @param string $source
- * @param string $excerpt
- *
- * @return IIndexDocument
*/
final public function addExcerpt(string $source, string $excerpt): IIndexDocument {
$this->excerpts[] =
@@ -681,10 +526,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Set all excerpts of the content of the original document.
*
* @since 16.0.0
- *
- * @param array $excerpts
- *
- * @return IIndexDocument
*/
final public function setExcerpts(array $excerpts): IIndexDocument {
$new = [];
@@ -704,8 +545,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get all excerpts of the content of the original document.
*
* @since 15.0.0
- *
- * @return array
*/
final public function getExcerpts(): array {
return $this->excerpts;
@@ -715,9 +554,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Clean excerpt.
*
* @since 16.0.0
- *
- * @param string $excerpt
- * @return string
*/
private function cleanExcerpt(string $excerpt): string {
$excerpt = str_replace("\\n", ' ', $excerpt);
@@ -736,10 +572,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* request.
*
* @since 15.0.0
- *
- * @param string $score
- *
- * @return IIndexDocument
*/
final public function setScore(string $score): IIndexDocument {
$this->score = $score;
@@ -751,8 +583,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get the score.
*
* @since 15.0.0
- *
- * @return string
*/
final public function getScore(): string {
return $this->score;
@@ -767,11 +597,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* indexing.
*
* @since 15.0.0
- *
- * @param string $info
- * @param string $value
- *
- * @return IIndexDocument
*/
final public function setInfo(string $info, string $value): IIndexDocument {
$this->info[$info] = $value;
@@ -783,11 +608,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get an information about a document. (string)
*
* @since 15.0.0
- *
- * @param string $info
- * @param string $default
- *
- * @return string
*/
final public function getInfo(string $info, string $default = ''): string {
if (!key_exists($info, $this->info)) {
@@ -805,11 +625,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* indexing.
*
* @since 15.0.0
- *
- * @param string $info
- * @param array $value
- *
- * @return IIndexDocument
*/
final public function setInfoArray(string $info, array $value): IIndexDocument {
$this->info[$info] = $value;
@@ -821,11 +636,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get an information about a document. (array)
*
* @since 15.0.0
- *
- * @param string $info
- * @param array $default
- *
- * @return array
*/
final public function getInfoArray(string $info, array $default = []): array {
if (!key_exists($info, $this->info)) {
@@ -843,11 +653,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* indexing.
*
* @since 15.0.0
- *
- * @param string $info
- * @param int $value
- *
- * @return IIndexDocument
*/
final public function setInfoInt(string $info, int $value): IIndexDocument {
$this->info[$info] = $value;
@@ -859,11 +664,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get an information about a document. (int)
*
* @since 15.0.0
- *
- * @param string $info
- * @param int $default
- *
- * @return int
*/
final public function getInfoInt(string $info, int $default = 0): int {
if (!key_exists($info, $this->info)) {
@@ -881,11 +681,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* indexing.
*
* @since 15.0.0
- *
- * @param string $info
- * @param bool $value
- *
- * @return IIndexDocument
*/
final public function setInfoBool(string $info, bool $value): IIndexDocument {
$this->info[$info] = $value;
@@ -897,11 +692,6 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get an information about a document. (bool)
*
* @since 15.0.0
- *
- * @param string $info
- * @param bool $default
- *
- * @return bool
*/
final public function getInfoBool(string $info, bool $default = false): bool {
if (!key_exists($info, $this->info)) {
@@ -915,13 +705,11 @@ class IndexDocument implements IIndexDocument, JsonSerializable {
* Get all info.
*
* @since 15.0.0
- *
- * @return array
*/
final public function getInfoAll(): array {
$info = [];
foreach ($this->info as $k => $v) {
- if (substr($k, 0, 1) === '_') {
+ if (str_starts_with($k, '_')) {
continue;
}
diff --git a/lib/private/FullTextSearch/Model/SearchOption.php b/lib/private/FullTextSearch/Model/SearchOption.php
index 91f45db5fb4..c7769a62138 100644
--- a/lib/private/FullTextSearch/Model/SearchOption.php
+++ b/lib/private/FullTextSearch/Model/SearchOption.php
@@ -1,27 +1,9 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright 2018
- *
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\FullTextSearch\Model;
@@ -36,22 +18,6 @@ use OCP\FullTextSearch\Model\ISearchOption;
* @package OC\FullTextSearch\Model
*/
final class SearchOption implements ISearchOption, JsonSerializable {
- /** @var string */
- private $name = '';
-
- /** @var string */
- private $title = '';
-
- /** @var string */
- private $type = '';
-
- /** @var string */
- private $size = '';
-
- /** @var string */
- private $placeholder = '';
-
-
/**
* *
*
@@ -104,37 +70,28 @@ final class SearchOption implements ISearchOption, JsonSerializable {
/**
* ISearchOption constructor.
*
- * Some value can be setduring the creation of the object.
+ * Some value can be set during the creation of the object.
*
* @since 15.0.0
- *
- * @param string $name
- * @param string $title
- * @param string $type
- * @param string $size
- * @param string $placeholder
*/
- public function __construct(string $name = '', string $title = '', string $type = '', string $size = '', string $placeholder = '') {
- $this->name = $name;
- $this->title = $title;
- $this->type = $type;
- $this->size = $size;
- $this->placeholder = $placeholder;
+ public function __construct(
+ private string $name = '',
+ private string $title = '',
+ private string $type = '',
+ private string $size = '',
+ private string $placeholder = '',
+ ) {
}
/**
* Set the name/key of the option.
- * The string should only contains alphanumerical chars and underscore.
- * The key can be retrieve when using ISearchRequest::getOption
+ * The string should only contain alphanumerical chars and underscore.
+ * The key can be retrieved when using ISearchRequest::getOption
*
* @see ISearchRequest::getOption
*
* @since 15.0.0
- *
- * @param string $name
- *
- * @return ISearchOption
*/
public function setName(string $name): ISearchOption {
$this->name = $name;
@@ -146,8 +103,6 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Get the name/key of the option.
*
* @since 15.0.0
- *
- * @return string
*/
public function getName(): string {
return $this->name;
@@ -158,10 +113,6 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Set the title/display name of the option.
*
* @since 15.0.0
- *
- * @param string $title
- *
- * @return ISearchOption
*/
public function setTitle(string $title): ISearchOption {
$this->title = $title;
@@ -173,8 +124,6 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Get the title of the option.
*
* @since 15.0.0
- *
- * @return string
*/
public function getTitle(): string {
return $this->title;
@@ -186,10 +135,6 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* $type can be ISearchOption::CHECKBOX or ISearchOption::INPUT
*
* @since 15.0.0
- *
- * @param string $type
- *
- * @return ISearchOption
*/
public function setType(string $type): ISearchOption {
$this->type = $type;
@@ -201,8 +146,6 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Get the type of the option.
*
* @since 15.0.0
- *
- * @return string
*/
public function getType(): string {
return $this->type;
@@ -214,10 +157,6 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Value can be ISearchOption::INPUT_SMALL or not defined.
*
* @since 15.0.0
- *
- * @param string $size
- *
- * @return ISearchOption
*/
public function setSize(string $size): ISearchOption {
$this->size = $size;
@@ -229,23 +168,16 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Get the size of the INPUT.
*
* @since 15.0.0
- *
- * @return string
*/
public function getSize(): string {
return $this->size;
}
-
/**
* In case of Type is , set the placeholder to be displayed in the input
* field.
*
* @since 15.0.0
- *
- * @param string $placeholder
- *
- * @return ISearchOption
*/
public function setPlaceholder(string $placeholder): ISearchOption {
$this->placeholder = $placeholder;
@@ -257,18 +189,13 @@ final class SearchOption implements ISearchOption, JsonSerializable {
* Get the placeholder.
*
* @since 15.0.0
- *
- * @return string
*/
public function getPlaceholder(): string {
return $this->placeholder;
}
-
/**
* @since 15.0.0
- *
- * @return array
*/
public function jsonSerialize(): array {
return [
diff --git a/lib/private/FullTextSearch/Model/SearchRequestSimpleQuery.php b/lib/private/FullTextSearch/Model/SearchRequestSimpleQuery.php
index c58d55b9b55..5b075daf7e6 100644
--- a/lib/private/FullTextSearch/Model/SearchRequestSimpleQuery.php
+++ b/lib/private/FullTextSearch/Model/SearchRequestSimpleQuery.php
@@ -1,28 +1,9 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright 2018
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\FullTextSearch\Model;
@@ -37,34 +18,24 @@ use OCP\FullTextSearch\Model\ISearchRequestSimpleQuery;
* @package OC\FullTextSearch\Model
*/
final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonSerializable {
- /** @var int */
- private $type = 0;
-
- /** @var string */
- private $field = '';
-
- /** @var array */
- private $values = [];
+ private array $values = [];
/**
* SearchRequestQuery constructor.
*
- * @param $type
- * @param $field
- *
* @since 17.0.0
*/
- public function __construct(string $field, int $type) {
- $this->field = $field;
- $this->type = $type;
+ public function __construct(
+ private string $field,
+ private int $type,
+ ) {
}
/**
* Get the compare type of the query
*
- * @return int
* @since 17.0.0
*/
public function getType(): int {
@@ -75,7 +46,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Get the field to apply query
*
- * @return string
* @since 17.0.0
*/
public function getField(): string {
@@ -85,9 +55,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Set the field to apply query
*
- * @param string $field
- *
- * @return ISearchRequestSimpleQuery
* @since 17.0.0
*/
public function setField(string $field): ISearchRequestSimpleQuery {
@@ -100,7 +67,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Get the value to compare (string)
*
- * @return array
* @since 17.0.0
*/
public function getValues(): array {
@@ -111,9 +77,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Add value to compare (string)
*
- * @param string $value
- *
- * @return ISearchRequestSimpleQuery
* @since 17.0.0
*/
public function addValue(string $value): ISearchRequestSimpleQuery {
@@ -125,9 +88,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Add value to compare (int)
*
- * @param int $value
- *
- * @return ISearchRequestSimpleQuery
* @since 17.0.0
*/
public function addValueInt(int $value): ISearchRequestSimpleQuery {
@@ -139,9 +99,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Add value to compare (array)
*
- * @param array $value
- *
- * @return ISearchRequestSimpleQuery
* @since 17.0.0
*/
public function addValueArray(array $value): ISearchRequestSimpleQuery {
@@ -153,9 +110,6 @@ final class SearchRequestSimpleQuery implements ISearchRequestSimpleQuery, JsonS
/**
* Add value to compare (bool)
*
- * @param bool $value
- *
- * @return ISearchRequestSimpleQuery
* @since 17.0.0
*/
public function addValueBool(bool $value): ISearchRequestSimpleQuery {
diff --git a/lib/private/FullTextSearch/Model/SearchTemplate.php b/lib/private/FullTextSearch/Model/SearchTemplate.php
index 4bb56f24b58..c2929bea139 100644
--- a/lib/private/FullTextSearch/Model/SearchTemplate.php
+++ b/lib/private/FullTextSearch/Model/SearchTemplate.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018
- *
- * @author Maxence Lange <maxence@artificial-owl.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\FullTextSearch\Model;
@@ -56,21 +39,13 @@ use OCP\FullTextSearch\Model\ISearchTemplate;
* @package OC\FullTextSearch\Model
*/
final class SearchTemplate implements ISearchTemplate, JsonSerializable {
- /** @var string */
- private $icon = '';
-
- /** @var string */
- private $css = '';
-
- /** @var string */
- private $template = '';
+ private string $template = '';
/** @var SearchOption[] */
- private $panelOptions = [];
+ private array $panelOptions = [];
/** @var SearchOption[] */
- private $navigationOptions = [];
-
+ private array $navigationOptions = [];
/**
* ISearchTemplate constructor.
@@ -79,13 +54,11 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* creation of the object.
*
* @since 15.0.0
- *
- * @param string $icon
- * @param string $css
*/
- public function __construct(string $icon = '', string $css = '') {
- $this->icon = $icon;
- $this->css = $css;
+ public function __construct(
+ private string $icon = '',
+ private string $css = '',
+ ) {
}
@@ -94,10 +67,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* FullTextSearch navigation page, in front of the related Content Provider.
*
* @since 15.0.0
- *
- * @param string $class
- *
- * @return ISearchTemplate
*/
public function setIcon(string $class): ISearchTemplate {
$this->icon = $class;
@@ -107,10 +76,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
/**
* Get the class of the icon.
- *
- * @since 15.0.0
- *
- * @return string
*/
public function getIcon(): string {
return $this->icon;
@@ -121,10 +86,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* Set the path of a CSS file that will be loaded when needed.
*
* @since 15.0.0
- *
- * @param string $css
- *
- * @return ISearchTemplate
*/
public function setCss(string $css): ISearchTemplate {
$this->css = $css;
@@ -136,8 +97,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* Get the path of the CSS file.
*
* @since 15.0.0
- *
- * @return string
*/
public function getCss(): string {
return $this->css;
@@ -151,10 +110,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* a way not generated by FullTextSearch
*
* @since 15.0.0
- *
- * @param string $template
- *
- * @return ISearchTemplate
*/
public function setTemplate(string $template): ISearchTemplate {
$this->template = $template;
@@ -166,8 +121,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* Get the path of the template file.
*
* @since 15.0.0
- *
- * @return string
*/
public function getTemplate(): string {
return $this->template;
@@ -181,10 +134,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* @see ISearchOption
*
* @since 15.0.0
- *
- * @param ISearchOption $option
- *
- * @return ISearchTemplate
*/
public function addPanelOption(ISearchOption $option): ISearchTemplate {
$this->panelOptions[] = $option;
@@ -210,10 +159,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* @see ISearchOption
*
* @since 15.0.0
- *
- * @param ISearchOption $option
- *
- * @return ISearchTemplate
*/
public function addNavigationOption(ISearchOption $option): ISearchTemplate {
$this->navigationOptions[] = $option;
@@ -225,8 +170,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
* Get all options to be displayed in the FullTextSearch navigation page.
*
* @since 15.0.0
- *
- * @return array
*/
public function getNavigationOptions(): array {
return $this->navigationOptions;
@@ -235,8 +178,6 @@ final class SearchTemplate implements ISearchTemplate, JsonSerializable {
/**
* @since 15.0.0
- *
- * @return array
*/
public function jsonSerialize(): array {
return [
diff --git a/lib/private/GlobalScale/Config.php b/lib/private/GlobalScale/Config.php
index 66abbfc15db..02acc1ab50a 100644
--- a/lib/private/GlobalScale/Config.php
+++ b/lib/private/GlobalScale/Config.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\GlobalScale;
diff --git a/lib/private/Group/Backend.php b/lib/private/Group/Backend.php
index 1e3e5ef1164..f6844308a15 100644
--- a/lib/private/Group/Backend.php
+++ b/lib/private/Group/Backend.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Knut Ahlers <knut@ahlers.me>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Group;
diff --git a/lib/private/Group/Database.php b/lib/private/Group/Database.php
index ef5641d8137..925b5bb0bdd 100644
--- a/lib/private/Group/Database.php
+++ b/lib/private/Group/Database.php
@@ -1,51 +1,30 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Leuker <j.leuker@hosting.de>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Loki3000 <github@labcms.ru>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author tgrant <tom.grant760@gmail.com>
- * @author Tom Grant <TomG736@users.noreply.github.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Group;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
+use OC\User\LazyUser;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Group\Backend\ABackend;
use OCP\Group\Backend\IAddToGroupBackend;
+use OCP\Group\Backend\IBatchMethodsBackend;
use OCP\Group\Backend\ICountDisabledInGroup;
use OCP\Group\Backend\ICountUsersBackend;
-use OCP\Group\Backend\ICreateGroupBackend;
+use OCP\Group\Backend\ICreateNamedGroupBackend;
use OCP\Group\Backend\IDeleteGroupBackend;
use OCP\Group\Backend\IGetDisplayNameBackend;
use OCP\Group\Backend\IGroupDetailsBackend;
+use OCP\Group\Backend\INamedBackend;
use OCP\Group\Backend\IRemoveFromGroupBackend;
use OCP\Group\Backend\ISearchableGroupBackend;
use OCP\Group\Backend\ISetDisplayNameBackend;
-use OCP\Group\Backend\INamedBackend;
use OCP\IDBConnection;
use OCP\IUserManager;
-use OC\User\LazyUser;
/**
* Class for group management in a SQL Database (e.g. MySQL, SQLite)
@@ -54,26 +33,25 @@ class Database extends ABackend implements
IAddToGroupBackend,
ICountDisabledInGroup,
ICountUsersBackend,
- ICreateGroupBackend,
+ ICreateNamedGroupBackend,
IDeleteGroupBackend,
IGetDisplayNameBackend,
IGroupDetailsBackend,
IRemoveFromGroupBackend,
ISetDisplayNameBackend,
ISearchableGroupBackend,
+ IBatchMethodsBackend,
INamedBackend {
- /** @var string[] */
+ /** @var array<string, array{gid: string, displayname: string}> */
private $groupCache = [];
-
- /** @var IDBConnection */
- private $dbConn;
+ private ?IDBConnection $dbConn;
/**
* \OC\Group\Database constructor.
*
* @param IDBConnection|null $dbConn
*/
- public function __construct(IDBConnection $dbConn = null) {
+ public function __construct(?IDBConnection $dbConn = null) {
$this->dbConn = $dbConn;
}
@@ -86,35 +64,28 @@ class Database extends ABackend implements
}
}
- /**
- * Try to create a new group
- * @param string $gid The name of the group to create
- * @return bool
- *
- * Tries to create a new group. If the group name already exists, false will
- * be returned.
- */
- public function createGroup(string $gid): bool {
+ public function createGroup(string $name): ?string {
$this->fixDI();
+ $gid = $this->computeGid($name);
try {
// Add group
$builder = $this->dbConn->getQueryBuilder();
$result = $builder->insert('groups')
->setValue('gid', $builder->createNamedParameter($gid))
- ->setValue('displayname', $builder->createNamedParameter($gid))
+ ->setValue('displayname', $builder->createNamedParameter($name))
->execute();
} catch (UniqueConstraintViolationException $e) {
- $result = 0;
+ return null;
}
// Add to cache
$this->groupCache[$gid] = [
'gid' => $gid,
- 'displayname' => $gid
+ 'displayname' => $name
];
- return $result === 1;
+ return $gid;
}
/**
@@ -270,7 +241,7 @@ class Database extends ABackend implements
$this->fixDI();
$query = $this->dbConn->getQueryBuilder();
- $query->select('gid')
+ $query->select('gid', 'displayname')
->from('groups')
->orderBy('gid', 'ASC');
@@ -293,6 +264,10 @@ class Database extends ABackend implements
$groups = [];
while ($row = $result->fetch()) {
+ $this->groupCache[$row['gid']] = [
+ 'displayname' => $row['displayname'],
+ 'gid' => $row['gid'],
+ ];
$groups[] = $row['gid'];
}
$result->closeCursor();
@@ -332,6 +307,43 @@ class Database extends ABackend implements
}
/**
+ * {@inheritdoc}
+ */
+ public function groupsExists(array $gids): array {
+ $notFoundGids = [];
+ $existingGroups = [];
+
+ // In case the data is already locally accessible, not need to do SQL query
+ // or do a SQL query but with a smaller in clause
+ foreach ($gids as $gid) {
+ if (isset($this->groupCache[$gid])) {
+ $existingGroups[] = $gid;
+ } else {
+ $notFoundGids[] = $gid;
+ }
+ }
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->select('gid', 'displayname')
+ ->from('groups')
+ ->where($qb->expr()->in('gid', $qb->createParameter('ids')));
+ foreach (array_chunk($notFoundGids, 1000) as $chunk) {
+ $qb->setParameter('ids', $chunk, IQueryBuilder::PARAM_STR_ARRAY);
+ $result = $qb->executeQuery();
+ while ($row = $result->fetch()) {
+ $this->groupCache[(string)$row['gid']] = [
+ 'displayname' => (string)$row['displayname'],
+ 'gid' => (string)$row['gid'],
+ ];
+ $existingGroups[] = (string)$row['gid'];
+ }
+ $result->closeCursor();
+ }
+
+ return $existingGroups;
+ }
+
+ /**
* Get a list of all users in a group
* @param string $gid
* @param string $search
@@ -488,6 +500,43 @@ class Database extends ABackend implements
return [];
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroupsDetails(array $gids): array {
+ $notFoundGids = [];
+ $details = [];
+
+ // In case the data is already locally accessible, not need to do SQL query
+ // or do a SQL query but with a smaller in clause
+ foreach ($gids as $gid) {
+ if (isset($this->groupCache[$gid])) {
+ $details[$gid] = ['displayName' => $this->groupCache[$gid]['displayname']];
+ } else {
+ $notFoundGids[] = $gid;
+ }
+ }
+
+ foreach (array_chunk($notFoundGids, 1000) as $chunk) {
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select('gid', 'displayname')
+ ->from('groups')
+ ->where($query->expr()->in('gid', $query->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)));
+
+ $result = $query->executeQuery();
+ while ($row = $result->fetch()) {
+ $details[(string)$row['gid']] = ['displayName' => (string)$row['displayname']];
+ $this->groupCache[(string)$row['gid']] = [
+ 'displayname' => (string)$row['displayname'],
+ 'gid' => (string)$row['gid'],
+ ];
+ }
+ $result->closeCursor();
+ }
+
+ return $details;
+ }
+
public function setDisplayName(string $gid, string $displayName): bool {
if (!$this->groupExists($gid)) {
return false;
@@ -517,4 +566,13 @@ class Database extends ABackend implements
public function getBackendName(): string {
return 'Database';
}
+
+ /**
+ * Compute group ID from display name (GIDs are limited to 64 characters in database)
+ */
+ private function computeGid(string $displayName): string {
+ return mb_strlen($displayName) > 64
+ ? hash('sha256', $displayName)
+ : $displayName;
+ }
}
diff --git a/lib/private/Group/DisplayNameCache.php b/lib/private/Group/DisplayNameCache.php
index 4eb8211be6e..fef8d40a05f 100644
--- a/lib/private/Group/DisplayNameCache.php
+++ b/lib/private/Group/DisplayNameCache.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright 2022 Anna Larch <anna.larch@gmx.net>
- * @author Anna Larch <anna.larch@gmx.net>
- *
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
-
namespace OC\Group;
use OCP\Cache\CappedMemoryCache;
@@ -38,6 +20,7 @@ use OCP\IGroupManager;
* Class that cache the relation Group ID -> Display name
*
* This saves fetching the group from the backend for "just" the display name
+ * @template-implements IEventListener<GroupChangedEvent|GroupDeletedEvent>
*/
class DisplayNameCache implements IEventListener {
private CappedMemoryCache $cache;
diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php
index 441ee64604d..dcda7c29bb5 100644
--- a/lib/private/Group/Group.php
+++ b/lib/private/Group/Group.php
@@ -1,47 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Leuker <j.leuker@hosting.de>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Group;
use OC\Hooks\PublicEmitter;
use OC\User\LazyUser;
use OCP\EventDispatcher\IEventDispatcher;
-use OCP\Group\Events\BeforeGroupDeletedEvent;
-use OCP\Group\Events\BeforeUserAddedEvent;
-use OCP\Group\Events\BeforeUserRemovedEvent;
-use OCP\Group\Events\GroupDeletedEvent;
-use OCP\Group\Events\UserAddedEvent;
-use OCP\Group\Events\UserRemovedEvent;
-use OCP\GroupInterface;
use OCP\Group\Backend\ICountDisabledInGroup;
use OCP\Group\Backend\IGetDisplayNameBackend;
use OCP\Group\Backend\IHideFromCollaborationBackend;
@@ -49,7 +17,14 @@ use OCP\Group\Backend\INamedBackend;
use OCP\Group\Backend\ISearchableGroupBackend;
use OCP\Group\Backend\ISetDisplayNameBackend;
use OCP\Group\Events\BeforeGroupChangedEvent;
+use OCP\Group\Events\BeforeGroupDeletedEvent;
+use OCP\Group\Events\BeforeUserAddedEvent;
+use OCP\Group\Events\BeforeUserRemovedEvent;
use OCP\Group\Events\GroupChangedEvent;
+use OCP\Group\Events\GroupDeletedEvent;
+use OCP\Group\Events\UserAddedEvent;
+use OCP\Group\Events\UserRemovedEvent;
+use OCP\GroupInterface;
use OCP\IGroup;
use OCP\IUser;
use OCP\IUserManager;
@@ -76,7 +51,7 @@ class Group implements IGroup {
/** @var PublicEmitter */
private $emitter;
- public function __construct(string $gid, array $backends, IEventDispatcher $dispatcher, IUserManager $userManager, PublicEmitter $emitter = null, ?string $displayName = null) {
+ public function __construct(string $gid, array $backends, IEventDispatcher $dispatcher, IUserManager $userManager, ?PublicEmitter $emitter = null, ?string $displayName = null) {
$this->gid = $gid;
$this->backends = $backends;
$this->dispatcher = $dispatcher;
@@ -85,11 +60,11 @@ class Group implements IGroup {
$this->displayName = $displayName;
}
- public function getGID() {
+ public function getGID(): string {
return $this->gid;
}
- public function getDisplayName() {
+ public function getDisplayName(): string {
if (is_null($this->displayName)) {
foreach ($this->backends as $backend) {
if ($backend instanceof IGetDisplayNameBackend) {
@@ -126,7 +101,7 @@ class Group implements IGroup {
*
* @return \OC\User\User[]
*/
- public function getUsers() {
+ public function getUsers(): array {
if ($this->usersLoaded) {
return $this->users;
}
@@ -153,7 +128,7 @@ class Group implements IGroup {
* @param IUser $user
* @return bool
*/
- public function inGroup(IUser $user) {
+ public function inGroup(IUser $user): bool {
if (isset($this->users[$user->getUID()])) {
return true;
}
@@ -171,7 +146,7 @@ class Group implements IGroup {
*
* @param IUser $user
*/
- public function addUser(IUser $user) {
+ public function addUser(IUser $user): void {
if ($this->inGroup($user)) {
return;
}
@@ -184,9 +159,7 @@ class Group implements IGroup {
foreach ($this->backends as $backend) {
if ($backend->implementsActions(\OC\Group\Backend::ADD_TO_GROUP)) {
$backend->addToGroup($user->getUID(), $this->gid);
- if ($this->users) {
- $this->users[$user->getUID()] = $user;
- }
+ $this->users[$user->getUID()] = $user;
$this->dispatcher->dispatchTyped(new UserAddedEvent($this, $user));
@@ -200,10 +173,8 @@ class Group implements IGroup {
/**
* remove a user from the group
- *
- * @param \OC\User\User $user
*/
- public function removeUser($user) {
+ public function removeUser(IUser $user): void {
$result = false;
$this->dispatcher->dispatchTyped(new BeforeUserRemovedEvent($this, $user));
if ($this->emitter) {
@@ -262,7 +233,7 @@ class Group implements IGroup {
* @param string $search
* @return int|bool
*/
- public function count($search = '') {
+ public function count($search = ''): int|bool {
$users = false;
foreach ($this->backends as $backend) {
if ($backend->implementsActions(\OC\Group\Backend::COUNT_USERS)) {
@@ -282,7 +253,7 @@ class Group implements IGroup {
*
* @return int|bool
*/
- public function countDisabled() {
+ public function countDisabled(): int|bool {
$users = false;
foreach ($this->backends as $backend) {
if ($backend instanceof ICountDisabledInGroup) {
@@ -306,7 +277,7 @@ class Group implements IGroup {
* @return IUser[]
* @deprecated 27.0.0 Use searchUsers instead (same implementation)
*/
- public function searchDisplayName($search, $limit = null, $offset = null) {
+ public function searchDisplayName(string $search, ?int $limit = null, ?int $offset = null): array {
return $this->searchUsers($search, $limit, $offset);
}
@@ -315,7 +286,7 @@ class Group implements IGroup {
*
* @return string[]
*/
- public function getBackendNames() {
+ public function getBackendNames(): array {
$backends = [];
foreach ($this->backends as $backend) {
if ($backend instanceof INamedBackend) {
@@ -329,11 +300,11 @@ class Group implements IGroup {
}
/**
- * delete the group
+ * Delete the group
*
* @return bool
*/
- public function delete() {
+ public function delete(): bool {
// Prevent users from deleting group admin
if ($this->getGID() === 'admin') {
return false;
@@ -378,7 +349,7 @@ class Group implements IGroup {
* @return bool
* @since 14.0.0
*/
- public function canRemoveUser() {
+ public function canRemoveUser(): bool {
foreach ($this->backends as $backend) {
if ($backend->implementsActions(GroupInterface::REMOVE_FROM_GOUP)) {
return true;
@@ -391,7 +362,7 @@ class Group implements IGroup {
* @return bool
* @since 14.0.0
*/
- public function canAddUser() {
+ public function canAddUser(): bool {
foreach ($this->backends as $backend) {
if ($backend->implementsActions(GroupInterface::ADD_TO_GROUP)) {
return true;
diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php
index c43b5165a79..0ab64907c8b 100644
--- a/lib/private/Group/Manager.php
+++ b/lib/private/Group/Manager.php
@@ -1,46 +1,17 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Knut Ahlers <knut@ahlers.me>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author macjohnny <estebanmarin@gmx.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Roman Kreisel <mail@romankreisel.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Vinicius Cubas Brand <vinicius@eita.org.br>
- * @author voxsim "Simon Vocella"
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Group;
use OC\Hooks\PublicEmitter;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Group\Backend\IBatchMethodsBackend;
+use OCP\Group\Backend\ICreateNamedGroupBackend;
+use OCP\Group\Backend\IGroupDetailsBackend;
use OCP\Group\Events\BeforeGroupCreatedEvent;
use OCP\Group\Events\GroupCreatedEvent;
use OCP\GroupInterface;
@@ -49,6 +20,7 @@ use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser;
use Psr\Log\LoggerInterface;
+use function is_string;
/**
* Class Manager
@@ -74,10 +46,10 @@ class Manager extends PublicEmitter implements IGroupManager {
private IEventDispatcher $dispatcher;
private LoggerInterface $logger;
- /** @var \OC\Group\Group[] */
+ /** @var array<string, IGroup> */
private $cachedGroups = [];
- /** @var (string[])[] */
+ /** @var array<string, list<string>> */
private $cachedUserGroups = [];
/** @var \OC\SubAdmin */
@@ -85,35 +57,26 @@ class Manager extends PublicEmitter implements IGroupManager {
private DisplayNameCache $displayNameCache;
+ private const MAX_GROUP_LENGTH = 255;
+
public function __construct(\OC\User\Manager $userManager,
- IEventDispatcher $dispatcher,
- LoggerInterface $logger,
- ICacheFactory $cacheFactory) {
+ IEventDispatcher $dispatcher,
+ LoggerInterface $logger,
+ ICacheFactory $cacheFactory) {
$this->userManager = $userManager;
$this->dispatcher = $dispatcher;
$this->logger = $logger;
$this->displayNameCache = new DisplayNameCache($cacheFactory, $this);
- $cachedGroups = &$this->cachedGroups;
- $cachedUserGroups = &$this->cachedUserGroups;
- $this->listen('\OC\Group', 'postDelete', function ($group) use (&$cachedGroups, &$cachedUserGroups) {
- /**
- * @var \OC\Group\Group $group
- */
- unset($cachedGroups[$group->getGID()]);
- $cachedUserGroups = [];
+ $this->listen('\OC\Group', 'postDelete', function (IGroup $group): void {
+ unset($this->cachedGroups[$group->getGID()]);
+ $this->cachedUserGroups = [];
});
- $this->listen('\OC\Group', 'postAddUser', function ($group) use (&$cachedUserGroups) {
- /**
- * @var \OC\Group\Group $group
- */
- $cachedUserGroups = [];
+ $this->listen('\OC\Group', 'postAddUser', function (IGroup $group): void {
+ $this->cachedUserGroups = [];
});
- $this->listen('\OC\Group', 'postRemoveUser', function ($group) use (&$cachedUserGroups) {
- /**
- * @var \OC\Group\Group $group
- */
- $cachedUserGroups = [];
+ $this->listen('\OC\Group', 'postRemoveUser', function (IGroup $group): void {
+ $this->cachedUserGroups = [];
});
}
@@ -185,7 +148,7 @@ class Manager extends PublicEmitter implements IGroupManager {
if ($backend->implementsActions(Backend::GROUP_DETAILS)) {
$groupData = $backend->getGroupDetails($gid);
if (is_array($groupData) && !empty($groupData)) {
- // take the display name from the first backend that has a non-null one
+ // take the display name from the last backend that has a non-null one
if (is_null($displayName) && isset($groupData['displayName'])) {
$displayName = $groupData['displayName'];
}
@@ -198,11 +161,69 @@ class Manager extends PublicEmitter implements IGroupManager {
if (count($backends) === 0) {
return null;
}
+ /** @var GroupInterface[] $backends */
$this->cachedGroups[$gid] = new Group($gid, $backends, $this->dispatcher, $this->userManager, $this, $displayName);
return $this->cachedGroups[$gid];
}
/**
+ * @brief Batch method to create group objects
+ *
+ * @param list<string> $gids List of groupIds for which we want to create a IGroup object
+ * @param array<string, string> $displayNames Array containing already know display name for a groupId
+ * @return array<string, IGroup>
+ */
+ protected function getGroupsObjects(array $gids, array $displayNames = []): array {
+ $backends = [];
+ $groups = [];
+ foreach ($gids as $gid) {
+ $backends[$gid] = [];
+ if (!isset($displayNames[$gid])) {
+ $displayNames[$gid] = null;
+ }
+ }
+ foreach ($this->backends as $backend) {
+ if ($backend instanceof IGroupDetailsBackend || $backend->implementsActions(GroupInterface::GROUP_DETAILS)) {
+ /** @var IGroupDetailsBackend $backend */
+ if ($backend instanceof IBatchMethodsBackend) {
+ $groupDatas = $backend->getGroupsDetails($gids);
+ } else {
+ $groupDatas = [];
+ foreach ($gids as $gid) {
+ $groupDatas[$gid] = $backend->getGroupDetails($gid);
+ }
+ }
+ foreach ($groupDatas as $gid => $groupData) {
+ if (!empty($groupData)) {
+ // take the display name from the last backend that has a non-null one
+ if (isset($groupData['displayName'])) {
+ $displayNames[$gid] = $groupData['displayName'];
+ }
+ $backends[$gid][] = $backend;
+ }
+ }
+ } else {
+ if ($backend instanceof IBatchMethodsBackend) {
+ $existingGroups = $backend->groupsExists($gids);
+ } else {
+ $existingGroups = array_filter($gids, fn (string $gid): bool => $backend->groupExists($gid));
+ }
+ foreach ($existingGroups as $group) {
+ $backends[$group][] = $backend;
+ }
+ }
+ }
+ foreach ($gids as $gid) {
+ if (count($backends[$gid]) === 0) {
+ continue;
+ }
+ $this->cachedGroups[$gid] = new Group($gid, $backends[$gid], $this->dispatcher, $this->userManager, $this, $displayNames[$gid]);
+ $groups[$gid] = $this->cachedGroups[$gid];
+ }
+ return $groups;
+ }
+
+ /**
* @param string $gid
* @return bool
*/
@@ -219,12 +240,22 @@ class Manager extends PublicEmitter implements IGroupManager {
return null;
} elseif ($group = $this->get($gid)) {
return $group;
+ } elseif (mb_strlen($gid) > self::MAX_GROUP_LENGTH) {
+ throw new \Exception('Group name is limited to '. self::MAX_GROUP_LENGTH.' characters');
} else {
$this->dispatcher->dispatchTyped(new BeforeGroupCreatedEvent($gid));
$this->emit('\OC\Group', 'preCreate', [$gid]);
foreach ($this->backends as $backend) {
if ($backend->implementsActions(Backend::CREATE_GROUP)) {
- if ($backend->createGroup($gid)) {
+ if ($backend instanceof ICreateNamedGroupBackend) {
+ $groupName = $gid;
+ if (($gid = $backend->createGroup($groupName)) !== null) {
+ $group = $this->getGroupObject($gid);
+ $this->dispatcher->dispatchTyped(new GroupCreatedEvent($group));
+ $this->emit('\OC\Group', 'postCreate', [$group]);
+ return $group;
+ }
+ } elseif ($backend->createGroup($gid)) {
$group = $this->getGroupObject($gid);
$this->dispatcher->dispatchTyped(new GroupCreatedEvent($group));
$this->emit('\OC\Group', 'postCreate', [$group]);
@@ -246,13 +277,9 @@ class Manager extends PublicEmitter implements IGroupManager {
$groups = [];
foreach ($this->backends as $backend) {
$groupIds = $backend->getGroups($search, $limit ?? -1, $offset ?? 0);
- foreach ($groupIds as $groupId) {
- $aGroup = $this->get($groupId);
- if ($aGroup instanceof IGroup) {
- $groups[$groupId] = $aGroup;
- } else {
- $this->logger->debug('Group "' . $groupId . '" was returned by search but not found through direct access', ['app' => 'core']);
- }
+ $newGroups = $this->getGroupsObjects($groupIds);
+ foreach ($newGroups as $groupId => $group) {
+ $groups[$groupId] = $group;
}
if (!is_null($limit) and $limit <= 0) {
return array_values($groups);
@@ -265,7 +292,7 @@ class Manager extends PublicEmitter implements IGroupManager {
* @param IUser|null $user
* @return \OC\Group\Group[]
*/
- public function getUserGroups(IUser $user = null) {
+ public function getUserGroups(?IUser $user = null) {
if (!$user instanceof IUser) {
return [];
}
@@ -299,7 +326,7 @@ class Manager extends PublicEmitter implements IGroupManager {
*/
public function isAdmin($userId) {
foreach ($this->backends as $backend) {
- if ($backend->implementsActions(Backend::IS_ADMIN) && $backend->isAdmin($userId)) {
+ if (is_string($userId) && $backend->implementsActions(Backend::IS_ADMIN) && $backend->isAdmin($userId)) {
return true;
}
}
@@ -314,7 +341,7 @@ class Manager extends PublicEmitter implements IGroupManager {
* @return bool if in group
*/
public function isInGroup($userId, $group) {
- return array_search($group, $this->getUserIdGroupIds($userId)) !== false;
+ return in_array($group, $this->getUserIdGroupIds($userId));
}
/**
diff --git a/lib/private/Group/MetaData.php b/lib/private/Group/MetaData.php
index a58d7e78bfc..638dc184812 100644
--- a/lib/private/Group/MetaData.php
+++ b/lib/private/Group/MetaData.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stephan Peijnik <speijnik@anexia-it.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Group;
@@ -57,11 +35,11 @@ class MetaData {
* @param bool $isAdmin whether the current users is an admin
*/
public function __construct(
- string $user,
- bool $isAdmin,
- IGroupManager $groupManager,
- IUserSession $userSession
- ) {
+ string $user,
+ bool $isAdmin,
+ IGroupManager $groupManager,
+ IUserSession $userSession
+ ) {
$this->user = $user;
$this->isAdmin = $isAdmin;
$this->groupManager = $groupManager;
diff --git a/lib/private/HintException.php b/lib/private/HintException.php
index 20f7142d1c0..c63e4b76ae5 100644
--- a/lib/private/HintException.php
+++ b/lib/private/HintException.php
@@ -2,25 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Gary Kim <gary@garykim.dev>
- *
- * @author Gary Kim <gary@garykim.dev>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/Hooks/BasicEmitter.php b/lib/private/Hooks/BasicEmitter.php
index 61b5184a804..c9444b40473 100644
--- a/lib/private/Hooks/BasicEmitter.php
+++ b/lib/private/Hooks/BasicEmitter.php
@@ -1,24 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Hooks;
diff --git a/lib/private/Hooks/Emitter.php b/lib/private/Hooks/Emitter.php
index bc5af2b60a2..8a63ac9ed3a 100644
--- a/lib/private/Hooks/Emitter.php
+++ b/lib/private/Hooks/Emitter.php
@@ -1,26 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Hooks;
@@ -49,5 +31,5 @@ interface Emitter {
* @return void
* @deprecated 18.0.0 use \OCP\EventDispatcher\IEventDispatcher::removeListener
*/
- public function removeListener($scope = null, $method = null, callable $callback = null);
+ public function removeListener($scope = null, $method = null, ?callable $callback = null);
}
diff --git a/lib/private/Hooks/EmitterTrait.php b/lib/private/Hooks/EmitterTrait.php
index da4e3da2bd6..8bffb6f7c3b 100644
--- a/lib/private/Hooks/EmitterTrait.php
+++ b/lib/private/Hooks/EmitterTrait.php
@@ -1,25 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Hooks;
@@ -43,7 +26,7 @@ trait EmitterTrait {
if (!isset($this->listeners[$eventName])) {
$this->listeners[$eventName] = [];
}
- if (array_search($callback, $this->listeners[$eventName], true) === false) {
+ if (!in_array($callback, $this->listeners[$eventName], true)) {
$this->listeners[$eventName][] = $callback;
}
}
@@ -54,7 +37,7 @@ trait EmitterTrait {
* @param callable $callback optional
* @deprecated 18.0.0 use \OCP\EventDispatcher\IEventDispatcher::removeListener
*/
- public function removeListener($scope = null, $method = null, callable $callback = null) {
+ public function removeListener($scope = null, $method = null, ?callable $callback = null) {
$names = [];
$allNames = array_keys($this->listeners);
if ($scope and $method) {
diff --git a/lib/private/Hooks/PublicEmitter.php b/lib/private/Hooks/PublicEmitter.php
index b72b12dbbbf..042b616e264 100644
--- a/lib/private/Hooks/PublicEmitter.php
+++ b/lib/private/Hooks/PublicEmitter.php
@@ -1,26 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Hooks;
diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php
index 3bf43e6c07e..7cadf3fdf6e 100644
--- a/lib/private/Http/Client/Client.php
+++ b/lib/private/Http/Client/Client.php
@@ -1,35 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Carlos Ferreira <carlos@reendex.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Mohammed Abdellatif <m.latief@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Scott Shambarger <devel@shambarger.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Http\Client;
@@ -192,7 +167,7 @@ class Client implements IClient {
throw new LocalServerException('Could not detect any host');
}
if (!$this->remoteHostValidator->isValid($host)) {
- throw new LocalServerException('Host violates local access rules');
+ throw new LocalServerException('Host "'.$host.'" violates local access rules');
}
}
@@ -339,6 +314,41 @@ class Client implements IClient {
}
/**
+ * Sends a PATCH request
+ *
+ * @param string $uri
+ * @param array $options Array such as
+ * 'body' => [
+ * 'field' => 'abc',
+ * 'other_field' => '123',
+ * 'file_name' => fopen('/path/to/file', 'r'),
+ * ],
+ * 'headers' => [
+ * 'foo' => 'bar',
+ * ],
+ * 'cookies' => [
+ * 'foo' => 'bar',
+ * ],
+ * 'allow_redirects' => [
+ * 'max' => 10, // allow at most 10 redirects.
+ * 'strict' => true, // use "strict" RFC compliant redirects.
+ * 'referer' => true, // add a Referer header
+ * 'protocols' => ['https'] // only allow https URLs
+ * ],
+ * 'sink' => '/path/to/file', // save to a file or a stream
+ * 'verify' => true, // bool or string to CA file
+ * 'debug' => true,
+ * 'timeout' => 5,
+ * @return IResponse
+ * @throws \Exception If the request could not get completed
+ */
+ public function patch(string $uri, array $options = []): IResponse {
+ $this->preventLocalAddress($uri, $options);
+ $response = $this->client->request('patch', $uri, $this->buildRequestOptions($options));
+ return new Response($response);
+ }
+
+ /**
* Sends a DELETE request
*
* @param string $uri
@@ -408,6 +418,59 @@ class Client implements IClient {
return new Response($response);
}
+ /**
+ * Get the response of a Throwable thrown by the request methods when possible
+ *
+ * @param \Throwable $e
+ * @return IResponse
+ * @throws \Throwable When $e did not have a response
+ * @since 29.0.0
+ */
+ public function getResponseFromThrowable(\Throwable $e): IResponse {
+ if (method_exists($e, 'hasResponse') && method_exists($e, 'getResponse') && $e->hasResponse()) {
+ return new Response($e->getResponse());
+ }
+
+ throw $e;
+ }
+
+ /**
+ * Sends a HTTP request
+ *
+ * @param string $method The HTTP method to use
+ * @param string $uri
+ * @param array $options Array such as
+ * 'query' => [
+ * 'field' => 'abc',
+ * 'other_field' => '123',
+ * 'file_name' => fopen('/path/to/file', 'r'),
+ * ],
+ * 'headers' => [
+ * 'foo' => 'bar',
+ * ],
+ * 'cookies' => [
+ * 'foo' => 'bar',
+ * ],
+ * 'allow_redirects' => [
+ * 'max' => 10, // allow at most 10 redirects.
+ * 'strict' => true, // use "strict" RFC compliant redirects.
+ * 'referer' => true, // add a Referer header
+ * 'protocols' => ['https'] // only allow https URLs
+ * ],
+ * 'sink' => '/path/to/file', // save to a file or a stream
+ * 'verify' => true, // bool or string to CA file
+ * 'debug' => true,
+ * 'timeout' => 5,
+ * @return IResponse
+ * @throws \Exception If the request could not get completed
+ */
+ public function request(string $method, string $uri, array $options = []): IResponse {
+ $this->preventLocalAddress($uri, $options);
+ $response = $this->client->request($method, $uri, $this->buildRequestOptions($options));
+ $isStream = isset($options['stream']) && $options['stream'];
+ return new Response($response, $isStream);
+ }
+
protected function wrapGuzzlePromise(PromiseInterface $promise): IPromise {
return new GuzzlePromiseAdapter(
$promise,
diff --git a/lib/private/Http/Client/ClientService.php b/lib/private/Http/Client/ClientService.php
index 532aa7f566a..9a170be8752 100644
--- a/lib/private/Http/Client/ClientService.php
+++ b/lib/private/Http/Client/ClientService.php
@@ -1,34 +1,16 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Http\Client;
use GuzzleHttp\Client as GuzzleClient;
-use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
+use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use OCP\Diagnostics\IEventLogger;
use OCP\Http\Client\IClient;
@@ -75,7 +57,9 @@ class ClientService implements IClientService {
public function newClient(): IClient {
$handler = new CurlHandler();
$stack = HandlerStack::create($handler);
- $stack->push($this->dnsPinMiddleware->addDnsPinning());
+ if ($this->config->getSystemValueBool('dns_pinning', true)) {
+ $stack->push($this->dnsPinMiddleware->addDnsPinning());
+ }
$stack->push(Middleware::tap(function (RequestInterface $request) {
$this->eventLogger->start('http:request', $request->getMethod() . " request to " . $request->getRequestTarget());
}, function () {
diff --git a/lib/private/Http/Client/DnsPinMiddleware.php b/lib/private/Http/Client/DnsPinMiddleware.php
index c6a58972fdd..fcf0818ebb9 100644
--- a/lib/private/Http/Client/DnsPinMiddleware.php
+++ b/lib/private/Http/Client/DnsPinMiddleware.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Http\Client;
@@ -55,7 +38,7 @@ class DnsPinMiddleware {
$second = array_pop($labels);
$hostname = $second . '.' . $top;
- $responses = dns_get_record($hostname, DNS_SOA);
+ $responses = $this->dnsGetRecord($hostname, DNS_SOA);
if ($responses === false || count($responses) === 0) {
return null;
@@ -75,13 +58,15 @@ class DnsPinMiddleware {
$soaDnsEntry = $this->soaRecord($target);
$dnsNegativeTtl = $soaDnsEntry['minimum-ttl'] ?? null;
- $dnsTypes = [DNS_A, DNS_AAAA, DNS_CNAME];
+ $dnsTypes = \defined('AF_INET6') || @inet_pton('::1')
+ ? [DNS_A, DNS_AAAA, DNS_CNAME]
+ : [DNS_A, DNS_CNAME];
foreach ($dnsTypes as $dnsType) {
if ($this->negativeDnsCache->isNegativeCached($target, $dnsType)) {
continue;
}
- $dnsResponses = dns_get_record($target, $dnsType);
+ $dnsResponses = $this->dnsGetRecord($target, $dnsType);
$canHaveCnameRecord = true;
if ($dnsResponses !== false && count($dnsResponses) > 0) {
foreach ($dnsResponses as $dnsResponse) {
@@ -104,6 +89,13 @@ class DnsPinMiddleware {
return $targetIps;
}
+ /**
+ * Wrapper for dns_get_record
+ */
+ protected function dnsGetRecord(string $hostname, int $type): array|false {
+ return \dns_get_record($hostname, $type);
+ }
+
public function addDnsPinning() {
return function (callable $handler) {
return function (
@@ -128,6 +120,10 @@ class DnsPinMiddleware {
$targetIps = $this->dnsResolve(idn_to_utf8($hostName), 0);
+ if (empty($targetIps)) {
+ throw new LocalServerException('No DNS record found for ' . $hostName);
+ }
+
$curlResolves = [];
foreach ($ports as $port) {
@@ -136,7 +132,7 @@ class DnsPinMiddleware {
foreach ($targetIps as $ip) {
if ($this->ipAddressClassifier->isLocalAddress($ip)) {
// TODO: continue with all non-local IPs?
- throw new LocalServerException('Host violates local access rules');
+ throw new LocalServerException('Host "'.$ip.'" ('.$hostName.':'.$port.') violates local access rules');
}
$curlResolves["$hostName:$port"][] = $ip;
}
diff --git a/lib/private/Http/Client/GuzzlePromiseAdapter.php b/lib/private/Http/Client/GuzzlePromiseAdapter.php
index 9d0b89bfd17..dc8be9bd2e0 100644
--- a/lib/private/Http/Client/GuzzlePromiseAdapter.php
+++ b/lib/private/Http/Client/GuzzlePromiseAdapter.php
@@ -3,23 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023, Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Http\Client;
diff --git a/lib/private/Http/Client/NegativeDnsCache.php b/lib/private/Http/Client/NegativeDnsCache.php
index 6c7585b11e3..d5e32fa7c2d 100644
--- a/lib/private/Http/Client/NegativeDnsCache.php
+++ b/lib/private/Http/Client/NegativeDnsCache.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Http\Client;
diff --git a/lib/private/Http/Client/Response.php b/lib/private/Http/Client/Response.php
index 054c902fcc5..adf83306d07 100644
--- a/lib/private/Http/Client/Response.php
+++ b/lib/private/Http/Client/Response.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Http\Client;
diff --git a/lib/private/Http/CookieHelper.php b/lib/private/Http/CookieHelper.php
index 720a1e9185d..9d07ff4534c 100644
--- a/lib/private/Http/CookieHelper.php
+++ b/lib/private/Http/CookieHelper.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Marco Ziech <marco@ziech.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Http;
@@ -33,13 +14,13 @@ class CookieHelper {
public const SAMESITE_STRICT = 2;
public static function setCookie(string $name,
- string $value = '',
- int $maxAge = 0,
- string $path = '',
- string $domain = '',
- bool $secure = false,
- bool $httponly = false,
- int $samesite = self::SAMESITE_NONE) {
+ string $value = '',
+ int $maxAge = 0,
+ string $path = '',
+ string $domain = '',
+ bool $secure = false,
+ bool $httponly = false,
+ int $samesite = self::SAMESITE_NONE) {
$header = sprintf(
'Set-Cookie: %s=%s',
$name,
diff --git a/lib/private/Http/WellKnown/RequestManager.php b/lib/private/Http/WellKnown/RequestManager.php
index b83ff2ada50..38dde0eade2 100644
--- a/lib/private/Http/WellKnown/RequestManager.php
+++ b/lib/private/Http/WellKnown/RequestManager.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Http\WellKnown;
@@ -49,8 +32,8 @@ class RequestManager {
private $logger;
public function __construct(Coordinator $coordinator,
- IServerContainer $container,
- LoggerInterface $logger) {
+ IServerContainer $container,
+ LoggerInterface $logger) {
$this->coordinator = $coordinator;
$this->container = $container;
$this->logger = $logger;
diff --git a/lib/private/InitialStateService.php b/lib/private/InitialStateService.php
index c10442a5267..8d364a90f84 100644
--- a/lib/private/InitialStateService.php
+++ b/lib/private/InitialStateService.php
@@ -3,28 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/Installer.php b/lib/private/Installer.php
index dc81135b644..ad80b26d8bc 100644
--- a/lib/private/Installer.php
+++ b/lib/private/Installer.php
@@ -1,41 +1,11 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author acsfer <carlos@reendex.com>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Kamil Domanski <kdomanski@kdemail.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author root "root@oc.(none)"
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -53,6 +23,7 @@ use OCP\HintException;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\ITempManager;
+use OCP\Migration\IOutput;
use phpseclib\File\X509;
use Psr\Log\LoggerInterface;
@@ -60,37 +31,17 @@ use Psr\Log\LoggerInterface;
* This class provides the functionality needed to install, update and remove apps
*/
class Installer {
- /** @var AppFetcher */
- private $appFetcher;
- /** @var IClientService */
- private $clientService;
- /** @var ITempManager */
- private $tempManager;
- /** @var LoggerInterface */
- private $logger;
- /** @var IConfig */
- private $config;
- /** @var array - for caching the result of app fetcher */
- private $apps = null;
- /** @var bool|null - for caching the result of the ready status */
- private $isInstanceReadyForUpdates = null;
- /** @var bool */
- private $isCLI;
+ private ?bool $isInstanceReadyForUpdates = null;
+ private ?array $apps = null;
public function __construct(
- AppFetcher $appFetcher,
- IClientService $clientService,
- ITempManager $tempManager,
- LoggerInterface $logger,
- IConfig $config,
- bool $isCLI
+ private AppFetcher $appFetcher,
+ private IClientService $clientService,
+ private ITempManager $tempManager,
+ private LoggerInterface $logger,
+ private IConfig $config,
+ private bool $isCLI,
) {
- $this->appFetcher = $appFetcher;
- $this->clientService = $clientService;
- $this->tempManager = $tempManager;
- $this->logger = $logger;
- $this->config = $config;
- $this->isCLI = $isCLI;
}
/**
@@ -113,7 +64,7 @@ class Installer {
throw new \Exception('The appinfo/database.xml file is not longer supported. Used in ' . $appId);
}
- $l = \OC::$server->getL10N('core');
+ $l = \OCP\Util::getL10N('core');
$info = \OCP\Server::get(IAppManager::class)->getAppInfo($basedir . '/appinfo/info.xml', true, $l->getLanguageCode());
if (!is_array($info)) {
@@ -150,7 +101,7 @@ class Installer {
}
//install the database
- $ms = new MigrationService($info['id'], \OC::$server->get(Connection::class));
+ $ms = new MigrationService($info['id'], \OCP\Server::get(Connection::class));
$ms->migrate('latest', !$previousVersion);
if ($previousVersion) {
@@ -164,16 +115,17 @@ class Installer {
OC_App::executeRepairSteps($appId, $info['repair-steps']['install']);
+ $config = \OCP\Server::get(IConfig::class);
//set the installed version
- \OC::$server->getConfig()->setAppValue($info['id'], 'installed_version', \OCP\Server::get(IAppManager::class)->getAppVersion($info['id'], false));
- \OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no');
+ $config->setAppValue($info['id'], 'installed_version', \OCP\Server::get(IAppManager::class)->getAppVersion($info['id'], false));
+ $config->setAppValue($info['id'], 'enabled', 'no');
//set remote/public handlers
foreach ($info['remote'] as $name => $path) {
- \OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
+ $config->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
}
foreach ($info['public'] as $name => $path) {
- \OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
+ $config->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
}
OC_App::setAppTypes($info['id']);
@@ -184,11 +136,9 @@ class Installer {
/**
* Updates the specified app from the appstore
*
- * @param string $appId
- * @param bool [$allowUnstable] Allow unstable releases
- * @return bool
+ * @param bool $allowUnstable Allow unstable releases
*/
- public function updateAppstoreApp($appId, $allowUnstable = false) {
+ public function updateAppstoreApp(string $appId, bool $allowUnstable = false): bool {
if ($this->isUpdateAvailable($appId, $allowUnstable)) {
try {
$this->downloadApp($appId, $allowUnstable);
@@ -224,7 +174,7 @@ class Installer {
*
* @throws \Exception If the installation was not successful
*/
- public function downloadApp($appId, $allowUnstable = false) {
+ public function downloadApp(string $appId, bool $allowUnstable = false): void {
$appId = strtolower($appId);
$apps = $this->appFetcher->get($allowUnstable);
@@ -297,11 +247,7 @@ class Installer {
// Check if the signature actually matches the downloaded content
$certificate = openssl_get_publickey($app['certificate']);
- $verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
- // PHP 8+ deprecates openssl_free_key and automatically destroys the key instance when it goes out of scope
- if ((PHP_VERSION_ID < 80000)) {
- openssl_free_key($certificate);
- }
+ $verified = openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512) === 1;
if ($verified === true) {
// Seems to match, let's proceed
@@ -322,6 +268,15 @@ class Installer {
$folders = array_diff($allFiles, ['.', '..']);
$folders = array_values($folders);
+ if (count($folders) < 1) {
+ throw new \Exception(
+ sprintf(
+ 'Extracted app %s has no folders',
+ $appId
+ )
+ );
+ }
+
if (count($folders) > 1) {
throw new \Exception(
sprintf(
@@ -332,13 +287,17 @@ class Installer {
}
// Check if appinfo/info.xml has the same app ID as well
- if ((PHP_VERSION_ID < 80000)) {
- $loadEntities = libxml_disable_entity_loader(false);
- $xml = simplexml_load_string(file_get_contents($extractDir . '/' . $folders[0] . '/appinfo/info.xml'));
- libxml_disable_entity_loader($loadEntities);
- } else {
- $xml = simplexml_load_string(file_get_contents($extractDir . '/' . $folders[0] . '/appinfo/info.xml'));
+ $xml = simplexml_load_string(file_get_contents($extractDir . '/' . $folders[0] . '/appinfo/info.xml'));
+
+ if ($xml === false) {
+ throw new \Exception(
+ sprintf(
+ 'Failed to load info.xml for app id %s',
+ $appId,
+ )
+ );
}
+
if ((string)$xml->id !== $appId) {
throw new \Exception(
sprintf(
@@ -400,10 +359,10 @@ class Installer {
* @param bool $allowUnstable
* @return string|false false or the version number of the update
*/
- public function isUpdateAvailable($appId, $allowUnstable = false) {
+ public function isUpdateAvailable($appId, $allowUnstable = false): string|false {
if ($this->isInstanceReadyForUpdates === null) {
$installPath = OC_App::getInstallPath();
- if ($installPath === false || $installPath === null) {
+ if ($installPath === null) {
$this->isInstanceReadyForUpdates = false;
} else {
$this->isInstanceReadyForUpdates = true;
@@ -443,12 +402,10 @@ class Installer {
/**
* Check if app has been installed from git
- * @param string $name name of the application to remove
- * @return boolean
*
* The function will check if the path contains a .git folder
*/
- private function isInstalledFromGit($appId) {
+ private function isInstalledFromGit(string $appId): bool {
$app = \OC_App::findAppInDirectories($appId);
if ($app === false) {
return false;
@@ -459,12 +416,10 @@ class Installer {
/**
* Check if app is already downloaded
- * @param string $name name of the application to remove
- * @return boolean
*
* The function will check if the app is already downloaded in the apps repository
*/
- public function isDownloaded($name) {
+ public function isDownloaded(string $name): bool {
foreach (\OC::$APPSROOTS as $dir) {
$dirToTest = $dir['path'];
$dirToTest .= '/';
@@ -481,9 +436,6 @@ class Installer {
/**
* Removes an app
- * @param string $appId ID of the application to remove
- * @return boolean
- *
*
* This function works as follows
* -# call uninstall repair steps
@@ -492,9 +444,9 @@ class Installer {
* The function will not delete preferences, tables and the configuration,
* this has to be done by the function oc_app_uninstall().
*/
- public function removeApp($appId) {
+ public function removeApp(string $appId): bool {
if ($this->isDownloaded($appId)) {
- if (\OC::$server->getAppManager()->isShipped($appId)) {
+ if (\OCP\Server::get(IAppManager::class)->isShipped($appId)) {
return false;
}
$appDir = OC_App::getInstallPath() . '/' . $appId;
@@ -510,10 +462,9 @@ class Installer {
/**
* Installs the app within the bundle and marks the bundle as installed
*
- * @param Bundle $bundle
* @throws \Exception If app could not get installed
*/
- public function installAppBundle(Bundle $bundle) {
+ public function installAppBundle(Bundle $bundle): void {
$appIds = $bundle->getAppIdentifiers();
foreach ($appIds as $appId) {
if (!$this->isDownloaded($appId)) {
@@ -536,9 +487,12 @@ class Installer {
* working ownCloud at the end instead of an aborted update.
* @return array Array of error messages (appid => Exception)
*/
- public static function installShippedApps($softErrors = false) {
- $appManager = \OC::$server->getAppManager();
- $config = \OC::$server->getConfig();
+ public static function installShippedApps(bool $softErrors = false, ?IOutput $output = null): array {
+ if ($output instanceof IOutput) {
+ $output->debug('Installing shipped apps');
+ }
+ $appManager = \OCP\Server::get(IAppManager::class);
+ $config = \OCP\Server::get(IConfig::class);
$errors = [];
foreach (\OC::$APPSROOTS as $app_dir) {
if ($dir = opendir($app_dir['path'])) {
@@ -551,7 +505,7 @@ class Installer {
&& $config->getAppValue($filename, 'enabled') !== 'no') {
if ($softErrors) {
try {
- Installer::installShippedApp($filename);
+ Installer::installShippedApp($filename, $output);
} catch (HintException $e) {
if ($e->getPrevious() instanceof TableExistsException) {
$errors[$filename] = $e;
@@ -560,7 +514,7 @@ class Installer {
throw $e;
}
} else {
- Installer::installShippedApp($filename);
+ Installer::installShippedApp($filename, $output);
}
$config->setAppValue($filename, 'enabled', 'yes');
}
@@ -577,17 +531,22 @@ class Installer {
/**
* install an app already placed in the app folder
- * @param string $app id of the app to install
- * @return integer
*/
- public static function installShippedApp($app) {
- //install the database
- $appPath = OC_App::getAppPath($app);
- \OC_App::registerAutoloading($app, $appPath);
+ public static function installShippedApp(string $app, ?IOutput $output = null): string|false {
+ if ($output instanceof IOutput) {
+ $output->debug('Installing ' . $app);
+ }
+
+ $appManager = \OCP\Server::get(IAppManager::class);
+ $config = \OCP\Server::get(IConfig::class);
- $config = \OC::$server->getConfig();
+ $appPath = $appManager->getAppPath($app);
+ \OC_App::registerAutoloading($app, $appPath);
- $ms = new MigrationService($app, \OC::$server->get(Connection::class));
+ $ms = new MigrationService($app, \OCP\Server::get(Connection::class));
+ if ($output instanceof IOutput) {
+ $ms->setOutput($output);
+ }
$previousVersion = $config->getAppValue($app, 'installed_version', false);
$ms->migrate('latest', !$previousVersion);
@@ -598,6 +557,9 @@ class Installer {
if (is_null($info)) {
return false;
}
+ if ($output instanceof IOutput) {
+ $output->debug('Registering tasks of ' . $app);
+ }
\OC_App::setupBackgroundJobs($info['background-jobs']);
OC_App::executeRepairSteps($app, $info['repair-steps']['install']);
@@ -620,10 +582,7 @@ class Installer {
return $info['id'];
}
- /**
- * @param string $script
- */
- private static function includeAppScript($script) {
+ private static function includeAppScript(string $script): void {
if (file_exists($script)) {
include $script;
}
diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php
index a2ff62e4070..a6de3cf6030 100644
--- a/lib/private/IntegrityCheck/Checker.php
+++ b/lib/private/IntegrityCheck/Checker.php
@@ -1,33 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Xheni Myrtaj <myrtajxheni@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck;
@@ -40,6 +17,7 @@ use OC\IntegrityCheck\Iterator\ExcludeFileByNameFilterIterator;
use OC\IntegrityCheck\Iterator\ExcludeFoldersByPathFilterIterator;
use OCP\App\IAppManager;
use OCP\Files\IMimeTypeDetector;
+use OCP\IAppConfig;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
@@ -58,44 +36,20 @@ use phpseclib\File\X509;
*/
class Checker {
public const CACHE_KEY = 'oc.integritycheck.checker';
- /** @var EnvironmentHelper */
- private $environmentHelper;
- /** @var AppLocator */
- private $appLocator;
- /** @var FileAccessHelper */
- private $fileAccessHelper;
- /** @var IConfig|null */
- private $config;
- /** @var ICache */
- private $cache;
- /** @var IAppManager|null */
- private $appManager;
- /** @var IMimeTypeDetector */
- private $mimeTypeDetector;
- /**
- * @param EnvironmentHelper $environmentHelper
- * @param FileAccessHelper $fileAccessHelper
- * @param AppLocator $appLocator
- * @param IConfig|null $config
- * @param ICacheFactory $cacheFactory
- * @param IAppManager|null $appManager
- * @param IMimeTypeDetector $mimeTypeDetector
- */
- public function __construct(EnvironmentHelper $environmentHelper,
- FileAccessHelper $fileAccessHelper,
- AppLocator $appLocator,
- ?IConfig $config,
- ICacheFactory $cacheFactory,
- ?IAppManager $appManager,
- IMimeTypeDetector $mimeTypeDetector) {
- $this->environmentHelper = $environmentHelper;
- $this->fileAccessHelper = $fileAccessHelper;
- $this->appLocator = $appLocator;
- $this->config = $config;
+ private ICache $cache;
+
+ public function __construct(
+ private EnvironmentHelper $environmentHelper,
+ private FileAccessHelper $fileAccessHelper,
+ private AppLocator $appLocator,
+ private ?IConfig $config,
+ private ?IAppConfig $appConfig,
+ ICacheFactory $cacheFactory,
+ private ?IAppManager $appManager,
+ private IMimeTypeDetector $mimeTypeDetector,
+ ) {
$this->cache = $cacheFactory->createDistributed(self::CACHE_KEY);
- $this->appManager = $appManager;
- $this->mimeTypeDetector = $mimeTypeDetector;
}
/**
@@ -114,15 +68,7 @@ class Checker {
* applicable for very specific scenarios and we should not advertise it
* too prominent. So please do not add it to config.sample.php.
*/
- $isIntegrityCheckDisabled = false;
- if ($this->config !== null) {
- $isIntegrityCheckDisabled = $this->config->getSystemValueBool('integrity.check.disabled', false);
- }
- if ($isIntegrityCheckDisabled) {
- return false;
- }
-
- return true;
+ return !($this->config?->getSystemValueBool('integrity.check.disabled', false) ?? false);
}
/**
@@ -161,7 +107,7 @@ class Checker {
* @return array Array of hashes.
*/
private function generateHashes(\RecursiveIteratorIterator $iterator,
- string $path): array {
+ string $path): array {
$hashes = [];
$baseDirectoryLength = \strlen($path);
@@ -223,8 +169,8 @@ class Checker {
* @return array
*/
private function createSignatureData(array $hashes,
- X509 $certificate,
- RSA $privateKey): array {
+ X509 $certificate,
+ RSA $privateKey): array {
ksort($hashes);
$privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
@@ -249,8 +195,8 @@ class Checker {
* @throws \Exception
*/
public function writeAppSignature($path,
- X509 $certificate,
- RSA $privateKey) {
+ X509 $certificate,
+ RSA $privateKey) {
$appInfoDir = $path . '/appinfo';
try {
$this->fileAccessHelper->assertDirectoryExists($appInfoDir);
@@ -279,8 +225,8 @@ class Checker {
* @throws \Exception
*/
public function writeCoreSignature(X509 $certificate,
- RSA $rsa,
- $path) {
+ RSA $rsa,
+ $path) {
$coreDir = $path . '/core';
try {
$this->fileAccessHelper->assertDirectoryExists($coreDir);
@@ -443,10 +389,7 @@ class Checker {
return json_decode($cachedResults, true);
}
- if ($this->config !== null) {
- return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
- }
- return [];
+ return $this->appConfig?->getValueArray('core', self::CACHE_KEY, lazy: true) ?? [];
}
/**
@@ -461,9 +404,7 @@ class Checker {
if (!empty($result)) {
$resultArray[$scope] = $result;
}
- if ($this->config !== null) {
- $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
- }
+ $this->appConfig?->setValueArray('core', self::CACHE_KEY, $resultArray, lazy: true);
$this->cache->set(self::CACHE_KEY, json_encode($resultArray));
}
@@ -472,7 +413,7 @@ class Checker {
* Clean previous results for a proper rescanning. Otherwise
*/
private function cleanResults() {
- $this->config->deleteAppValue('core', self::CACHE_KEY);
+ $this->appConfig->deleteKey('core', self::CACHE_KEY);
$this->cache->remove(self::CACHE_KEY);
}
diff --git a/lib/private/IntegrityCheck/Exceptions/InvalidSignatureException.php b/lib/private/IntegrityCheck/Exceptions/InvalidSignatureException.php
index 18a4ba40e1a..25f8b0dcbf7 100644
--- a/lib/private/IntegrityCheck/Exceptions/InvalidSignatureException.php
+++ b/lib/private/IntegrityCheck/Exceptions/InvalidSignatureException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck\Exceptions;
diff --git a/lib/private/IntegrityCheck/Helpers/AppLocator.php b/lib/private/IntegrityCheck/Helpers/AppLocator.php
index 9980fbdf497..3da5cc13227 100644
--- a/lib/private/IntegrityCheck/Helpers/AppLocator.php
+++ b/lib/private/IntegrityCheck/Helpers/AppLocator.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck\Helpers;
diff --git a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
index 5b6d0448703..dcdc7839f8e 100644
--- a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
+++ b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
@@ -1,27 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck\Helpers;
diff --git a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
index cd16a619915..c6e57d5d935 100644
--- a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
+++ b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck\Helpers;
diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
index 6d26a40aef4..e2e68008a35 100644
--- a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
+++ b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Romain Rivière <lecoyote@lecoyote.org>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck\Iterator;
diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php
index a0b48158b9f..f6d4c7afd4a 100644
--- a/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php
+++ b/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author RealRancor <Fisch.666@gmx.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\IntegrityCheck\Iterator;
diff --git a/lib/private/KnownUser/KnownUser.php b/lib/private/KnownUser/KnownUser.php
index 532d3ccb565..808c0400c6e 100644
--- a/lib/private/KnownUser/KnownUser.php
+++ b/lib/private/KnownUser/KnownUser.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\KnownUser;
diff --git a/lib/private/KnownUser/KnownUserMapper.php b/lib/private/KnownUser/KnownUserMapper.php
index fd8f22cd0aa..4c3bbb0b436 100644
--- a/lib/private/KnownUser/KnownUserMapper.php
+++ b/lib/private/KnownUser/KnownUserMapper.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\KnownUser;
diff --git a/lib/private/KnownUser/KnownUserService.php b/lib/private/KnownUser/KnownUserService.php
index fec24542007..aff0c097d98 100644
--- a/lib/private/KnownUser/KnownUserService.php
+++ b/lib/private/KnownUser/KnownUserService.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\KnownUser;
diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php
index 778124c4c38..1825719fb75 100644
--- a/lib/private/L10N/Factory.php
+++ b/lib/private/L10N/Factory.php
@@ -1,45 +1,15 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- * @copyright 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author GretaD <gretadoci@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\L10N;
+use OCP\App\AppPathNotFoundException;
+use OCP\App\IAppManager;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
@@ -88,38 +58,17 @@ class Factory implements IFactory {
'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
];
- /** @var IConfig */
- protected $config;
-
- /** @var IRequest */
- protected $request;
-
- /** @var IUserSession */
- protected IUserSession $userSession;
-
private ICache $cache;
- /** @var string */
- protected $serverRoot;
-
- /**
- * @param IConfig $config
- * @param IRequest $request
- * @param IUserSession $userSession
- * @param string $serverRoot
- */
public function __construct(
- IConfig $config,
- IRequest $request,
- IUserSession $userSession,
+ protected IConfig $config,
+ protected IRequest $request,
+ protected IUserSession $userSession,
ICacheFactory $cacheFactory,
- $serverRoot
+ protected string $serverRoot,
+ protected IAppManager $appManager,
) {
- $this->config = $config;
- $this->request = $request;
- $this->userSession = $userSession;
$this->cache = $cacheFactory->createLocal('L10NFactory');
- $this->serverRoot = $serverRoot;
}
/**
@@ -233,7 +182,7 @@ class Factory implements IFactory {
return 'en';
}
- public function findGenericLanguage(string $appId = null): string {
+ public function findGenericLanguage(?string $appId = null): string {
// Step 1: Forced language always has precedence over anything else
$forcedLanguage = $this->config->getSystemValue('force_language', false);
if ($forcedLanguage !== false) {
@@ -283,9 +232,9 @@ class Factory implements IFactory {
}
if ($this->config->getSystemValueBool('installed', false)) {
- $userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null;
+ $userId = $this->userSession->getUser() !== null ? $this->userSession->getUser()->getUID() : null;
$userLocale = null;
- if (null !== $userId) {
+ if ($userId !== null) {
$userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
}
} else {
@@ -304,7 +253,7 @@ class Factory implements IFactory {
}
// If no user locale set, use lang as locale
- if (null !== $lang && $this->localeExists($lang)) {
+ if ($lang !== null && $this->localeExists($lang)) {
return $lang;
}
@@ -319,7 +268,7 @@ class Factory implements IFactory {
* @param string $locale
* @return null|string
*/
- public function findLanguageFromLocale(string $app = 'core', string $locale = null) {
+ public function findLanguageFromLocale(string $app = 'core', ?string $locale = null) {
if ($this->languageExists($app, $locale)) {
return $locale;
}
@@ -358,7 +307,7 @@ class Factory implements IFactory {
$files = scandir($dir);
if ($files !== false) {
foreach ($files as $file) {
- if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
+ if (str_ends_with($file, '.json') && !str_starts_with($file, 'l10n')) {
$available[] = substr($file, 0, -5);
}
}
@@ -374,7 +323,7 @@ class Factory implements IFactory {
$files = scandir($themeDir);
if ($files !== false) {
foreach ($files as $file) {
- if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
+ if (str_ends_with($file, '.json') && !str_starts_with($file, 'l10n')) {
$available[] = substr($file, 0, -5);
}
}
@@ -415,7 +364,7 @@ class Factory implements IFactory {
return in_array($lang, $languages);
}
- public function getLanguageIterator(IUser $user = null): ILanguageIterator {
+ public function getLanguageIterator(?IUser $user = null): ILanguageIterator {
$user = $user ?? $this->userSession->getUser();
if ($user === null) {
throw new \RuntimeException('Failed to get an IUser instance');
@@ -430,7 +379,7 @@ class Factory implements IFactory {
* @return string
* @since 20.0.0
*/
- public function getUserLanguage(IUser $user = null): string {
+ public function getUserLanguage(?IUser $user = null): string {
$language = $this->config->getSystemValue('force_language', false);
if ($language !== false) {
return $language;
@@ -490,10 +439,14 @@ class Factory implements IFactory {
[$preferred_language] = explode(';', $preference);
$preferred_language = str_replace('-', '_', $preferred_language);
+ $preferred_language_parts = explode('_', $preferred_language);
foreach ($available as $available_language) {
if ($preferred_language === strtolower($available_language)) {
return $this->respectDefaultLanguage($app, $available_language);
}
+ if (strtolower($available_language) === $preferred_language_parts[0].'_'.end($preferred_language_parts)) {
+ return $available_language;
+ }
}
// Fallback from de_De to de
@@ -554,13 +507,9 @@ class Factory implements IFactory {
/**
* Get a list of language files that should be loaded
*
- * @param string $app
- * @param string $lang
* @return string[]
*/
- // FIXME This method is only public, until OC_L10N does not need it anymore,
- // FIXME This is also the reason, why it is not in the public interface
- public function getL10nFilesForApp($app, $lang) {
+ private function getL10nFilesForApp(string $app, string $lang): array {
$languageFiles = [];
$i18nDir = $this->findL10nDir($app);
@@ -568,7 +517,7 @@ class Factory implements IFactory {
if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
|| $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
- || $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/'))
+ || $this->isSubDirectory($transFile, $this->appManager->getAppPath($app) . '/l10n/'))
&& file_exists($transFile)
) {
// load the translations file
@@ -598,9 +547,12 @@ class Factory implements IFactory {
if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
return $this->serverRoot . '/' . $app . '/l10n/';
}
- } elseif ($app && \OC_App::getAppPath($app) !== false) {
- // Check if the app is in the app folder
- return \OC_App::getAppPath($app) . '/l10n/';
+ } elseif ($app) {
+ try {
+ return $this->appManager->getAppPath($app) . '/l10n/';
+ } catch (AppPathNotFoundException) {
+ /* App not found, continue */
+ }
}
return $this->serverRoot . '/core/l10n/';
}
diff --git a/lib/private/L10N/L10N.php b/lib/private/L10N/L10N.php
index ea4aa0527bb..39d778f80d6 100644
--- a/lib/private/L10N/L10N.php
+++ b/lib/private/L10N/L10N.php
@@ -1,35 +1,16 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\L10N;
use OCP\IL10N;
use OCP\L10N\IFactory;
+use Psr\Log\LoggerInterface;
use Punic\Calendar;
use Symfony\Component\Translation\IdentityTranslator;
@@ -156,7 +137,7 @@ class L10N implements IL10N {
* - jsdate: Returns the short JS date format
*/
public function l(string $type, $data = null, array $options = []) {
- if (null === $this->locale) {
+ if ($this->locale === null) {
// Use the language of the instance
$this->locale = $this->getLanguageCode();
}
@@ -234,7 +215,7 @@ class L10N implements IL10N {
$json = json_decode(file_get_contents($translationFile), true);
if (!\is_array($json)) {
$jsonError = json_last_error();
- \OC::$server->getLogger()->warning("Failed to load $translationFile - json error code: $jsonError", ['app' => 'l10n']);
+ \OCP\Server::get(LoggerInterface::class)->warning("Failed to load $translationFile - json error code: $jsonError", ['app' => 'l10n']);
return false;
}
diff --git a/lib/private/L10N/L10NString.php b/lib/private/L10N/L10NString.php
index ea64f17eff3..a6515e78f24 100644
--- a/lib/private/L10N/L10NString.php
+++ b/lib/private/L10N/L10NString.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\L10N;
diff --git a/lib/private/L10N/LanguageIterator.php b/lib/private/L10N/LanguageIterator.php
index 8b3aaf10210..531eea5866b 100644
--- a/lib/private/L10N/LanguageIterator.php
+++ b/lib/private/L10N/LanguageIterator.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\L10N;
diff --git a/lib/private/L10N/LanguageNotFoundException.php b/lib/private/L10N/LanguageNotFoundException.php
index d483fd799dd..31b08b2ec14 100644
--- a/lib/private/L10N/LanguageNotFoundException.php
+++ b/lib/private/L10N/LanguageNotFoundException.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\L10N;
diff --git a/lib/private/L10N/LazyL10N.php b/lib/private/L10N/LazyL10N.php
index 3226c1a604b..0d72f638632 100644
--- a/lib/private/L10N/LazyL10N.php
+++ b/lib/private/L10N/LazyL10N.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\L10N;
diff --git a/lib/private/LDAP/NullLDAPProviderFactory.php b/lib/private/LDAP/NullLDAPProviderFactory.php
index 23dfe78952c..55561b5692e 100644
--- a/lib/private/LDAP/NullLDAPProviderFactory.php
+++ b/lib/private/LDAP/NullLDAPProviderFactory.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\LDAP;
diff --git a/lib/private/LargeFileHelper.php b/lib/private/LargeFileHelper.php
index 40cf2ecd5ff..4d96e79ead4 100755
--- a/lib/private/LargeFileHelper.php
+++ b/lib/private/LargeFileHelper.php
@@ -1,31 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author marco44 <cousinmarc@gmail.com>
- * @author Michael Roitzsch <reactorcontrol@icloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Lock/AbstractLockingProvider.php b/lib/private/Lock/AbstractLockingProvider.php
index 6e8289db12e..aa203f6a90b 100644
--- a/lib/private/Lock/AbstractLockingProvider.php
+++ b/lib/private/Lock/AbstractLockingProvider.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Lock;
@@ -33,14 +15,18 @@ use OCP\Lock\ILockingProvider;
* to release any leftover locks at the end of the request
*/
abstract class AbstractLockingProvider implements ILockingProvider {
- /** how long until we clear stray locks in seconds */
- protected int $ttl;
-
- protected $acquiredLocks = [
+ protected array $acquiredLocks = [
'shared' => [],
'exclusive' => []
];
+ /**
+ *
+ * @param int $ttl how long until we clear stray locks in seconds
+ */
+ public function __construct(protected int $ttl) {
+ }
+
/** @inheritDoc */
protected function hasAcquiredLock(string $path, int $type): bool {
if ($type === self::LOCK_SHARED) {
diff --git a/lib/private/Lock/DBLockingProvider.php b/lib/private/Lock/DBLockingProvider.php
index fb8af8ac55b..d19f2cf3791 100644
--- a/lib/private/Lock/DBLockingProvider.php
+++ b/lib/private/Lock/DBLockingProvider.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Individual IT Services <info@individual-it.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Ole Ostergaard <ole.c.ostergaard@gmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Lock;
@@ -39,21 +18,15 @@ use OCP\Lock\LockedException;
* Locking provider that stores the locks in the database
*/
class DBLockingProvider extends AbstractLockingProvider {
- private IDBConnection $connection;
- private ITimeFactory $timeFactory;
private array $sharedLocks = [];
- private bool $cacheSharedLocks;
public function __construct(
- IDBConnection $connection,
- ITimeFactory $timeFactory,
+ private IDBConnection $connection,
+ private ITimeFactory $timeFactory,
int $ttl = 3600,
- bool $cacheSharedLocks = true
+ private bool $cacheSharedLocks = true
) {
- $this->connection = $connection;
- $this->timeFactory = $timeFactory;
- $this->ttl = $ttl;
- $this->cacheSharedLocks = $cacheSharedLocks;
+ parent::__construct($ttl);
}
/**
diff --git a/lib/private/Lock/MemcacheLockingProvider.php b/lib/private/Lock/MemcacheLockingProvider.php
index d4eebd7c302..883abb5da98 100644
--- a/lib/private/Lock/MemcacheLockingProvider.php
+++ b/lib/private/Lock/MemcacheLockingProvider.php
@@ -1,47 +1,49 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jaakko Salo <jaakkos@gmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Lock;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IMemcache;
use OCP\IMemcacheTTL;
use OCP\Lock\LockedException;
class MemcacheLockingProvider extends AbstractLockingProvider {
- private IMemcache $memcache;
+ /** @var array<string, array{time: int, ttl: int}> */
+ private array $oldTTLs = [];
+
+ public function __construct(
+ private IMemcache $memcache,
+ private ITimeFactory $timeFactory,
+ int $ttl = 3600,
+ ) {
+ parent::__construct($ttl);
+ }
- public function __construct(IMemcache $memcache, int $ttl = 3600) {
- $this->memcache = $memcache;
- $this->ttl = $ttl;
+ private function setTTL(string $path, ?int $ttl = null, ?int $compare = null): void {
+ if (is_null($ttl)) {
+ $ttl = $this->ttl;
+ }
+ if ($this->memcache instanceof IMemcacheTTL) {
+ if ($compare !== null) {
+ $this->memcache->compareSetTTL($path, $compare, $ttl);
+ } else {
+ $this->memcache->setTTL($path, $ttl);
+ }
+ }
}
- private function setTTL(string $path): void {
+ private function getTTL(string $path): int {
if ($this->memcache instanceof IMemcacheTTL) {
- $this->memcache->setTTL($path, $this->ttl);
+ $ttl = $this->memcache->getTTL($path);
+ return $ttl === false ? -1 : $ttl;
+ } else {
+ return -1;
}
}
@@ -58,14 +60,22 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
public function acquireLock(string $path, int $type, ?string $readablePath = null): void {
if ($type === self::LOCK_SHARED) {
+ // save the old TTL to for `restoreTTL`
+ $this->oldTTLs[$path] = [
+ "ttl" => $this->getTTL($path),
+ "time" => $this->timeFactory->getTime()
+ ];
if (!$this->memcache->inc($path)) {
throw new LockedException($path, null, $this->getExistingLockForException($path), $readablePath);
}
} else {
+ // when getting exclusive locks, we know there are no old TTLs to restore
$this->memcache->add($path, 0);
+ // ttl is updated automatically when the `set` succeeds
if (!$this->memcache->cas($path, 0, 'exclusive')) {
throw new LockedException($path, null, $this->getExistingLockForException($path), $readablePath);
}
+ unset($this->oldTTLs[$path]);
}
$this->setTTL($path);
$this->markAcquire($path, $type);
@@ -88,6 +98,12 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
$newValue = $this->memcache->dec($path);
}
+ if ($newValue > 0) {
+ $this->restoreTTL($path);
+ } else {
+ unset($this->oldTTLs[$path]);
+ }
+
// if we somehow release more locks then exists, reset the lock
if ($newValue < 0) {
$this->memcache->cad($path, $newValue);
@@ -106,13 +122,52 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
} elseif ($targetType === self::LOCK_EXCLUSIVE) {
// we can only change a shared lock to an exclusive if there's only a single owner of the shared lock
if (!$this->memcache->cas($path, 1, 'exclusive')) {
+ $this->restoreTTL($path);
throw new LockedException($path, null, $this->getExistingLockForException($path));
}
+ unset($this->oldTTLs[$path]);
}
$this->setTTL($path);
$this->markChange($path, $targetType);
}
+ /**
+ * With shared locks, each time the lock is acquired, the ttl for the path is reset.
+ *
+ * Due to this "ttl extension" when a shared lock isn't freed correctly for any reason
+ * the lock won't expire until no shared locks are required for the path for 1h.
+ * This can lead to a client repeatedly trying to upload a file, and failing forever
+ * because the lock never gets the opportunity to expire.
+ *
+ * To help the lock expire in this case, we lower the TTL back to what it was before we
+ * took the shared lock *only* if nobody else got a shared lock after we did.
+ *
+ * This doesn't handle all cases where multiple requests are acquiring shared locks
+ * but it should handle some of the more common ones and not hurt things further
+ */
+ private function restoreTTL(string $path): void {
+ if (isset($this->oldTTLs[$path])) {
+ $saved = $this->oldTTLs[$path];
+ $elapsed = $this->timeFactory->getTime() - $saved['time'];
+
+ // old value to compare to when setting ttl in case someone else changes the lock in the middle of this function
+ $value = $this->memcache->get($path);
+
+ $currentTtl = $this->getTTL($path);
+
+ // what the old ttl would be given the time elapsed since we acquired the lock
+ // note that if this gets negative the key will be expired directly when we set the ttl
+ $remainingOldTtl = $saved['ttl'] - $elapsed;
+ // what the currently ttl would be if nobody else acquired a lock since we did (+1 to cover rounding errors)
+ $expectedTtl = $this->ttl - $elapsed + 1;
+
+ // check if another request has acquired a lock (and didn't release it yet)
+ if ($currentTtl <= $expectedTtl) {
+ $this->setTTL($path, $remainingOldTtl, $value);
+ }
+ }
+ }
+
private function getExistingLockForException(string $path): string {
$existing = $this->memcache->get($path);
if (!$existing) {
diff --git a/lib/private/Lock/NoopLockingProvider.php b/lib/private/Lock/NoopLockingProvider.php
index 542cb5c028e..42f1f9ae5ec 100644
--- a/lib/private/Lock/NoopLockingProvider.php
+++ b/lib/private/Lock/NoopLockingProvider.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Lock;
diff --git a/lib/private/Lockdown/Filesystem/NullCache.php b/lib/private/Lockdown/Filesystem/NullCache.php
index 4fde9668ded..e84ff40e00c 100644
--- a/lib/private/Lockdown/Filesystem/NullCache.php
+++ b/lib/private/Lockdown/Filesystem/NullCache.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Lockdown\Filesystem;
diff --git a/lib/private/Lockdown/Filesystem/NullStorage.php b/lib/private/Lockdown/Filesystem/NullStorage.php
index a3976733b1a..7175594a01d 100644
--- a/lib/private/Lockdown/Filesystem/NullStorage.php
+++ b/lib/private/Lockdown/Filesystem/NullStorage.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Lockdown\Filesystem;
diff --git a/lib/private/Lockdown/LockdownManager.php b/lib/private/Lockdown/LockdownManager.php
index bb76d801725..779b1ea2650 100644
--- a/lib/private/Lockdown/LockdownManager.php
+++ b/lib/private/Lockdown/LockdownManager.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Lockdown;
diff --git a/lib/private/Log.php b/lib/private/Log.php
index d6750491d92..c7684a1aefd 100644
--- a/lib/private/Log.php
+++ b/lib/private/Log.php
@@ -1,43 +1,17 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
use Exception;
use Nextcloud\LogNormalizer\Normalizer;
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\Log\ExceptionSerializer;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ILogger;
use OCP\IUserSession;
@@ -46,8 +20,6 @@ use OCP\Log\IDataLogger;
use OCP\Log\IFileBased;
use OCP\Log\IWriter;
use OCP\Support\CrashReport\IRegistry;
-use OC\AppFramework\Bootstrap\Coordinator;
-use OC\Log\ExceptionSerializer;
use Throwable;
use function array_merge;
use function strtr;
@@ -62,42 +34,22 @@ use function strtr;
* MonoLog is an example implementing this interface.
*/
class Log implements ILogger, IDataLogger {
- private IWriter $logger;
- private ?SystemConfig $config;
private ?bool $logConditionSatisfied = null;
- private ?Normalizer $normalizer;
- private ?IRegistry $crashReporters;
- private ?IEventDispatcher $eventDispatcher;
+ private ?IEventDispatcher $eventDispatcher = null;
- /**
- * @param IWriter $logger The logger that should be used
- * @param SystemConfig $config the system config object
- * @param Normalizer|null $normalizer
- * @param IRegistry|null $registry
- */
public function __construct(
- IWriter $logger,
- SystemConfig $config = null,
- Normalizer $normalizer = null,
- IRegistry $registry = null
+ private IWriter $logger,
+ private SystemConfig $config,
+ private ?Normalizer $normalizer = null,
+ private ?IRegistry $crashReporters = null
) {
- // FIXME: Add this for backwards compatibility, should be fixed at some point probably
- if ($config === null) {
- $config = \OC::$server->getSystemConfig();
- }
-
- $this->config = $config;
- $this->logger = $logger;
+ // FIXME: php8.1 allows "private Normalizer $normalizer = new Normalizer()," in initializer
if ($normalizer === null) {
$this->normalizer = new Normalizer();
- } else {
- $this->normalizer = $normalizer;
}
- $this->crashReporters = $registry;
- $this->eventDispatcher = null;
}
- public function setEventDispatcher(IEventDispatcher $eventDispatcher) {
+ public function setEventDispatcher(IEventDispatcher $eventDispatcher): void {
$this->eventDispatcher = $eventDispatcher;
}
@@ -106,9 +58,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function emergency(string $message, array $context = []) {
+ public function emergency(string $message, array $context = []): void {
$this->log(ILogger::FATAL, $message, $context);
}
@@ -120,9 +71,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function alert(string $message, array $context = []) {
+ public function alert(string $message, array $context = []): void {
$this->log(ILogger::ERROR, $message, $context);
}
@@ -133,9 +83,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function critical(string $message, array $context = []) {
+ public function critical(string $message, array $context = []): void {
$this->log(ILogger::ERROR, $message, $context);
}
@@ -145,9 +94,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function error(string $message, array $context = []) {
+ public function error(string $message, array $context = []): void {
$this->log(ILogger::ERROR, $message, $context);
}
@@ -159,9 +107,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function warning(string $message, array $context = []) {
+ public function warning(string $message, array $context = []): void {
$this->log(ILogger::WARN, $message, $context);
}
@@ -170,9 +117,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function notice(string $message, array $context = []) {
+ public function notice(string $message, array $context = []): void {
$this->log(ILogger::INFO, $message, $context);
}
@@ -183,9 +129,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function info(string $message, array $context = []) {
+ public function info(string $message, array $context = []): void {
$this->log(ILogger::INFO, $message, $context);
}
@@ -194,9 +139,8 @@ class Log implements ILogger, IDataLogger {
*
* @param string $message
* @param array $context
- * @return void
*/
- public function debug(string $message, array $context = []) {
+ public function debug(string $message, array $context = []): void {
$this->log(ILogger::DEBUG, $message, $context);
}
@@ -207,19 +151,21 @@ class Log implements ILogger, IDataLogger {
* @param int $level
* @param string $message
* @param array $context
- * @return void
*/
- public function log(int $level, string $message, array $context = []) {
+ public function log(int $level, string $message, array $context = []): void {
$minLevel = $this->getLogLevel($context);
+ if ($level < $minLevel
+ && (($this->crashReporters?->hasReporters() ?? false) === false)
+ && (($this->eventDispatcher?->hasListeners(BeforeMessageLoggedEvent::class) ?? false) === false)) {
+ return; // no crash reporter, no listeners, we can stop for lower log level
+ }
array_walk($context, [$this->normalizer, 'format']);
$app = $context['app'] ?? 'no app in context';
$entry = $this->interpolateMessage($context, $message);
- if ($this->eventDispatcher) {
- $this->eventDispatcher->dispatchTyped(new BeforeMessageLoggedEvent($app, $level, $entry));
- }
+ $this->eventDispatcher?->dispatchTyped(new BeforeMessageLoggedEvent($app, $level, $entry));
$hasBacktrace = isset($entry['exception']);
$logBacktrace = $this->config->getValue('log.backtrace', false);
@@ -241,16 +187,14 @@ class Log implements ILogger, IDataLogger {
$this->crashReporters->delegateMessage($entry['message'], $messageContext);
}
} else {
- if ($this->crashReporters !== null) {
- $this->crashReporters->delegateBreadcrumb($entry['message'], 'log', $context);
- }
+ $this->crashReporters?->delegateBreadcrumb($entry['message'], 'log', $context);
}
} catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
- public function getLogLevel($context) {
+ public function getLogLevel($context): int {
$logCondition = $this->config->getValue('log.condition', []);
/**
@@ -300,20 +244,23 @@ class Log implements ILogger, IDataLogger {
}
if (isset($context['app'])) {
- $app = $context['app'];
-
/**
* check log condition based on the context of each log message
* once this is met -> change the required log level to debug
*/
- if (!empty($logCondition)
- && isset($logCondition['apps'])
- && in_array($app, $logCondition['apps'], true)) {
+ if (in_array($context['app'], $logCondition['apps'] ?? [], true)) {
return ILogger::DEBUG;
}
}
- return min($this->config->getValue('loglevel', ILogger::WARN), ILogger::FATAL);
+ $configLogLevel = $this->config->getValue('loglevel', ILogger::WARN);
+ if (is_numeric($configLogLevel)) {
+ return min((int)$configLogLevel, ILogger::FATAL);
+ }
+
+ // Invalid configuration, warn the user and fall back to default level of WARN
+ error_log('Nextcloud configuration: "loglevel" is not a valid integer');
+ return ILogger::WARN;
}
/**
@@ -324,13 +271,15 @@ class Log implements ILogger, IDataLogger {
* @return void
* @since 8.2.0
*/
- public function logException(Throwable $exception, array $context = []) {
+ public function logException(Throwable $exception, array $context = []): void {
$app = $context['app'] ?? 'no app in context';
$level = $context['level'] ?? ILogger::ERROR;
$minLevel = $this->getLogLevel($context);
- if ($level < $minLevel && ($this->crashReporters === null || !$this->crashReporters->hasReporters())) {
- return;
+ if ($level < $minLevel
+ && (($this->crashReporters?->hasReporters() ?? false) === false)
+ && (($this->eventDispatcher?->hasListeners(BeforeMessageLoggedEvent::class) ?? false) === false)) {
+ return; // no crash reporter, no listeners, we can stop for lower log level
}
// if an error is raised before the autoloader is properly setup, we can't serialize exceptions
@@ -344,14 +293,11 @@ class Log implements ILogger, IDataLogger {
unset($data['app']);
unset($data['level']);
$data = array_merge($serializer->serializeException($exception), $data);
- $data = $this->interpolateMessage($data, $context['message'] ?? '--', 'CustomMessage');
-
+ $data = $this->interpolateMessage($data, isset($context['message']) && $context['message'] !== '' ? $context['message'] : ('Exception thrown: ' . get_class($exception)), 'CustomMessage');
array_walk($context, [$this->normalizer, 'format']);
- if ($this->eventDispatcher) {
- $this->eventDispatcher->dispatchTyped(new BeforeMessageLoggedEvent($app, $level, $data));
- }
+ $this->eventDispatcher?->dispatchTyped(new BeforeMessageLoggedEvent($app, $level, $data));
try {
if ($level >= $minLevel) {
@@ -399,7 +345,7 @@ class Log implements ILogger, IDataLogger {
* @param string|array $entry
* @param int $level
*/
- protected function writeLog(string $app, $entry, int $level) {
+ protected function writeLog(string $app, $entry, int $level): void {
$this->logger->write($app, $entry, $level);
}
diff --git a/lib/private/Log/ErrorHandler.php b/lib/private/Log/ErrorHandler.php
index c4b9631e75a..e1faf336118 100644
--- a/lib/private/Log/ErrorHandler.php
+++ b/lib/private/Log/ErrorHandler.php
@@ -1,32 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Log;
@@ -36,10 +14,9 @@ use Psr\Log\LoggerInterface;
use Throwable;
class ErrorHandler {
- private LoggerInterface $logger;
-
- public function __construct(LoggerInterface $logger) {
- $this->logger = $logger;
+ public function __construct(
+ private LoggerInterface $logger,
+ ) {
}
/**
@@ -94,20 +71,11 @@ class ErrorHandler {
}
private static function errnoToLogLevel(int $errno): int {
- switch ($errno) {
- case E_USER_WARNING:
- return ILogger::WARN;
-
- case E_DEPRECATED:
- case E_USER_DEPRECATED:
- return ILogger::DEBUG;
-
- case E_USER_NOTICE:
- return ILogger::INFO;
-
- case E_USER_ERROR:
- default:
- return ILogger::ERROR;
- }
+ return match ($errno) {
+ E_USER_WARNING => ILogger::WARN,
+ E_DEPRECATED, E_USER_DEPRECATED => ILogger::DEBUG,
+ E_USER_NOTICE => ILogger::INFO,
+ default => ILogger::ERROR,
+ };
}
}
diff --git a/lib/private/Log/Errorlog.php b/lib/private/Log/Errorlog.php
index 72d11aa098c..d53b8b151a1 100644
--- a/lib/private/Log/Errorlog.php
+++ b/lib/private/Log/Errorlog.php
@@ -1,53 +1,31 @@
<?php
declare(strict_types=1);
-
/**
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Christian Kampka <christian@kampka.net>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2014 Christian Kampka <christian@kampka.net>
+ * SPDX-License-Identifier: MIT
*/
-
namespace OC\Log;
use OC\SystemConfig;
use OCP\Log\IWriter;
class Errorlog extends LogDetails implements IWriter {
- /** @var string */
- protected $tag;
-
- public function __construct(SystemConfig $config, string $tag = 'nextcloud') {
+ public function __construct(
+ SystemConfig $config,
+ protected string $tag = 'nextcloud',
+ ) {
parent::__construct($config);
- $this->tag = $tag;
}
/**
* Write a message in the log
*
- * @param string $app
* @param string|array $message
- * @param int $level
*/
- public function write(string $app, $message, int $level) {
+ public function write(string $app, $message, int $level): void {
error_log('[' . $this->tag . ']['.$app.']['.$level.'] '.$this->logDetailsAsJSON($app, $message, $level));
}
}
diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php
index b585461e8d9..03beed7cce1 100644
--- a/lib/private/Log/ExceptionSerializer.php
+++ b/lib/private/Log/ExceptionSerializer.php
@@ -1,30 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Log;
@@ -112,11 +89,9 @@ class ExceptionSerializer {
];
- /** @var SystemConfig */
- private $systemConfig;
-
- public function __construct(SystemConfig $systemConfig) {
- $this->systemConfig = $systemConfig;
+ public function __construct(
+ private SystemConfig $systemConfig,
+ ) {
}
protected array $methodsWithSensitiveParametersByClass = [
@@ -219,7 +194,7 @@ class ExceptionSerializer {
}, $trace);
}
- private function removeValuesFromArgs($args, $values) {
+ private function removeValuesFromArgs($args, $values): array {
$workArgs = [];
foreach ($args as $arg) {
if (in_array($arg, $values, true)) {
@@ -279,7 +254,7 @@ class ExceptionSerializer {
return $arg;
}
- public function serializeException(\Throwable $exception) {
+ public function serializeException(\Throwable $exception): array {
$data = [
'Exception' => get_class($exception),
'Message' => $exception->getMessage(),
diff --git a/lib/private/Log/File.php b/lib/private/Log/File.php
index a33667c9b68..28cc856b980 100644
--- a/lib/private/Log/File.php
+++ b/lib/private/Log/File.php
@@ -1,38 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author duritong <peter.meier+github@immerda.ch>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Roland Tapken <roland@bitarbeiter.net>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Pulzer <t.pulzer@kniel.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Log;
@@ -48,14 +19,15 @@ use OCP\Log\IWriter;
*/
class File extends LogDetails implements IWriter, IFileBased {
- /** @var string */
- protected $logFile;
- /** @var int */
- protected $logFileMode;
- /** @var SystemConfig */
- private $config;
+ protected string $logFile;
+
+ protected int $logFileMode;
- public function __construct(string $path, string $fallbackPath, SystemConfig $config) {
+ public function __construct(
+ string $path,
+ string $fallbackPath,
+ private SystemConfig $config,
+ ) {
parent::__construct($config);
$this->logFile = $path;
if (!file_exists($this->logFile)) {
@@ -69,17 +41,14 @@ class File extends LogDetails implements IWriter, IFileBased {
$this->logFile = $fallbackPath;
}
}
- $this->config = $config;
$this->logFileMode = $config->getValue('logfilemode', 0640);
}
/**
* write a message in the log
- * @param string $app
* @param string|array $message
- * @param int $level
*/
- public function write(string $app, $message, int $level) {
+ public function write(string $app, $message, int $level): void {
$entry = $this->logDetailsAsJSON($app, $message, $level);
$handle = @fopen($this->logFile, 'a');
if ($this->logFileMode > 0 && is_file($this->logFile) && (fileperms($this->logFile) & 0777) != $this->logFileMode) {
@@ -102,11 +71,8 @@ class File extends LogDetails implements IWriter, IFileBased {
/**
* get entries from the log in reverse chronological order
- * @param int $limit
- * @param int $offset
- * @return array
*/
- public function getEntries(int $limit = 50, int $offset = 0):array {
+ public function getEntries(int $limit = 50, int $offset = 0): array {
$minLevel = $this->config->getValue("loglevel", ILogger::WARN);
$entries = [];
$handle = @fopen($this->logFile, 'rb');
@@ -148,9 +114,6 @@ class File extends LogDetails implements IWriter, IFileBased {
return $entries;
}
- /**
- * @return string
- */
public function getLogFilePath():string {
return $this->logFile;
}
diff --git a/lib/private/Log/LogDetails.php b/lib/private/Log/LogDetails.php
index c82904d7cea..bf2c1a22c49 100644
--- a/lib/private/Log/LogDetails.php
+++ b/lib/private/Log/LogDetails.php
@@ -1,38 +1,16 @@
<?php
/**
- * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Log;
use OC\SystemConfig;
abstract class LogDetails {
- /** @var SystemConfig */
- private $config;
-
- public function __construct(SystemConfig $config) {
- $this->config = $config;
+ public function __construct(
+ private SystemConfig $config,
+ ) {
}
public function logDetails(string $app, $message, int $level): array {
@@ -108,7 +86,7 @@ abstract class LogDetails {
if (is_string($value)) {
$testEncode = json_encode($value, JSON_UNESCAPED_SLASHES);
if ($testEncode === false) {
- $entry[$key] = utf8_encode($value);
+ $entry[$key] = mb_convert_encoding($value, 'UTF-8', mb_detect_encoding($value));
}
}
}
diff --git a/lib/private/Log/LogFactory.php b/lib/private/Log/LogFactory.php
index a5008f5ef77..a5a7290bd9c 100644
--- a/lib/private/Log/LogFactory.php
+++ b/lib/private/Log/LogFactory.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Johannes Ernst <jernst@indiecomputing.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Log;
@@ -33,57 +14,37 @@ use OCP\Log\IWriter;
use Psr\Log\LoggerInterface;
class LogFactory implements ILogFactory {
- /** @var IServerContainer */
- private $c;
- /** @var SystemConfig */
- private $systemConfig;
-
- public function __construct(IServerContainer $c, SystemConfig $systemConfig) {
- $this->c = $c;
- $this->systemConfig = $systemConfig;
+ public function __construct(
+ private IServerContainer $c,
+ private SystemConfig $systemConfig,
+ ) {
}
/**
* @throws \OCP\AppFramework\QueryException
*/
public function get(string $type):IWriter {
- switch (strtolower($type)) {
- case 'errorlog':
- return new Errorlog($this->systemConfig);
- case 'syslog':
- return $this->c->resolve(Syslog::class);
- case 'systemd':
- return $this->c->resolve(Systemdlog::class);
- case 'file':
- return $this->buildLogFile();
-
- // Backwards compatibility for old and fallback for unknown log types
- case 'owncloud':
- case 'nextcloud':
- default:
- return $this->buildLogFile();
- }
+ return match (strtolower($type)) {
+ 'errorlog' => new Errorlog($this->systemConfig),
+ 'syslog' => $this->c->resolve(Syslog::class),
+ 'systemd' => $this->c->resolve(Systemdlog::class),
+ 'file' => $this->buildLogFile(),
+ default => $this->buildLogFile(),
+ };
}
- public function getCustomLogger(string $path):ILogger {
+ public function getCustomLogger(string $path): ILogger {
$log = $this->buildLogFile($path);
return new Log($log, $this->systemConfig);
}
protected function createNewLogger(string $type, string $tag, string $path): IWriter {
- switch (strtolower($type)) {
- case 'errorlog':
- return new Errorlog($this->systemConfig, $tag);
- case 'syslog':
- return new Syslog($this->systemConfig, $tag);
- case 'systemd':
- return new Systemdlog($this->systemConfig, $tag);
- case 'file':
- case 'owncloud':
- case 'nextcloud':
- default:
- return $this->buildLogFile($path);
- }
+ return match (strtolower($type)) {
+ 'errorlog' => new Errorlog($this->systemConfig, $tag),
+ 'syslog' => new Syslog($this->systemConfig, $tag),
+ 'systemd' => new Systemdlog($this->systemConfig, $tag),
+ default => $this->buildLogFile($path),
+ };
}
public function getCustomPsrLogger(string $path, string $type = 'file', string $tag = 'Nextcloud'): LoggerInterface {
@@ -93,7 +54,7 @@ class LogFactory implements ILogFactory {
);
}
- protected function buildLogFile(string $logFile = ''):File {
+ protected function buildLogFile(string $logFile = ''): File {
$defaultLogFile = $this->systemConfig->getValue('datadirectory', \OC::$SERVERROOT.'/data').'/nextcloud.log';
if ($logFile === '') {
$logFile = $this->systemConfig->getValue('logfile', $defaultLogFile);
diff --git a/lib/private/Log/PsrLoggerAdapter.php b/lib/private/Log/PsrLoggerAdapter.php
index 07a898e2528..16e609eefdb 100644
--- a/lib/private/Log/PsrLoggerAdapter.php
+++ b/lib/private/Log/PsrLoggerAdapter.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Log;
@@ -36,14 +19,12 @@ use function array_key_exists;
use function array_merge;
final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
- /** @var Log */
- private $logger;
-
- public function __construct(Log $logger) {
- $this->logger = $logger;
+ public function __construct(
+ private Log $logger,
+ ) {
}
- public function setEventDispatcher(IEventDispatcher $eventDispatcher) {
+ public function setEventDispatcher(IEventDispatcher $eventDispatcher): void {
$this->logger->setEventDispatcher($eventDispatcher);
}
@@ -54,22 +35,20 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
/**
* System is unusable.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
public function emergency($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::FATAL,
],
$context
));
} else {
- $this->logger->emergency($message, $context);
+ $this->logger->emergency((string)$message, $context);
}
}
@@ -79,22 +58,20 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function alert($message, array $context = []) {
+ public function alert($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::ERROR,
],
$context
));
} else {
- $this->logger->alert($message, $context);
+ $this->logger->alert((string)$message, $context);
}
}
@@ -103,22 +80,20 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
*
* Example: Application component unavailable, unexpected exception.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function critical($message, array $context = []) {
+ public function critical($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::ERROR,
],
$context
));
} else {
- $this->logger->critical($message, $context);
+ $this->logger->critical((string)$message, $context);
}
}
@@ -126,22 +101,20 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function error($message, array $context = []) {
+ public function error($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::ERROR,
],
$context
));
} else {
- $this->logger->error($message, $context);
+ $this->logger->error((string)$message, $context);
}
}
@@ -151,44 +124,40 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function warning($message, array $context = []) {
+ public function warning($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::WARN,
],
$context
));
} else {
- $this->logger->warning($message, $context);
+ $this->logger->warning((string)$message, $context);
}
}
/**
* Normal but significant events.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function notice($message, array $context = []) {
+ public function notice($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::INFO,
],
$context
));
} else {
- $this->logger->notice($message, $context);
+ $this->logger->notice((string)$message, $context);
}
}
@@ -197,44 +166,40 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
*
* Example: User logs in, SQL logs.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function info($message, array $context = []) {
+ public function info($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::INFO,
],
$context
));
} else {
- $this->logger->info($message, $context);
+ $this->logger->info((string)$message, $context);
}
}
/**
* Detailed debug information.
*
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*/
- public function debug($message, array $context = []) {
+ public function debug($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => ILogger::DEBUG,
],
$context
));
} else {
- $this->logger->debug($message, $context);
+ $this->logger->debug((string)$message, $context);
}
}
@@ -242,27 +207,25 @@ final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
* Logs with an arbitrary level.
*
* @param mixed $level
- * @param string $message
- * @param array $context
- *
- * @return void
+ * @param $message
+ * @param mixed[] $context
*
* @throws InvalidArgumentException
*/
- public function log($level, $message, array $context = []) {
+ public function log($level, $message, array $context = []): void {
if (!is_int($level) || $level < ILogger::DEBUG || $level > ILogger::FATAL) {
throw new InvalidArgumentException('Nextcloud allows only integer log levels');
}
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
- 'message' => $message,
+ 'message' => (string)$message,
'level' => $level,
],
$context
));
} else {
- $this->logger->log($level, $message, $context);
+ $this->logger->log($level, (string)$message, $context);
}
}
diff --git a/lib/private/Log/Rotate.php b/lib/private/Log/Rotate.php
index dfb588837f3..f2fdb83623d 100644
--- a/lib/private/Log/Rotate.php
+++ b/lib/private/Log/Rotate.php
@@ -1,30 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Log;
+use OCP\IConfig;
use OCP\Log\RotationTrait;
+use Psr\Log\LoggerInterface;
/**
* This rotates the current logfile to a new name, this way the total log usage
@@ -35,15 +20,15 @@ use OCP\Log\RotationTrait;
class Rotate extends \OCP\BackgroundJob\Job {
use RotationTrait;
- public function run($dummy) {
- $systemConfig = \OC::$server->getSystemConfig();
- $this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
+ public function run($argument): void {
+ $config = \OCP\Server::get(IConfig::class);
+ $this->filePath = $config->getSystemValueString('logfile', $config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
- $this->maxSize = \OC::$server->getConfig()->getSystemValueInt('log_rotate_size', 100 * 1024 * 1024);
+ $this->maxSize = $config->getSystemValueInt('log_rotate_size', 100 * 1024 * 1024);
if ($this->shouldRotateBySize()) {
$rotatedFile = $this->rotate();
$msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
- \OC::$server->getLogger()->warning($msg, ['app' => Rotate::class]);
+ \OCP\Server::get(LoggerInterface::class)->info($msg, ['app' => Rotate::class]);
}
}
}
diff --git a/lib/private/Log/Syslog.php b/lib/private/Log/Syslog.php
index f4ba857742f..bd2c39509b1 100644
--- a/lib/private/Log/Syslog.php
+++ b/lib/private/Log/Syslog.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Log;
@@ -30,7 +12,7 @@ use OCP\ILogger;
use OCP\Log\IWriter;
class Syslog extends LogDetails implements IWriter {
- protected $levels = [
+ protected array $levels = [
ILogger::DEBUG => LOG_DEBUG,
ILogger::INFO => LOG_INFO,
ILogger::WARN => LOG_WARNING,
@@ -38,7 +20,10 @@ class Syslog extends LogDetails implements IWriter {
ILogger::FATAL => LOG_CRIT,
];
- public function __construct(SystemConfig $config, ?string $tag = null) {
+ public function __construct(
+ SystemConfig $config,
+ ?string $tag = null,
+ ) {
parent::__construct($config);
if ($tag === null) {
$tag = $config->getValue('syslog_tag', 'Nextcloud');
@@ -52,11 +37,9 @@ class Syslog extends LogDetails implements IWriter {
/**
* write a message in the log
- * @param string $app
* @param string|array $message
- * @param int $level
*/
- public function write(string $app, $message, int $level) {
+ public function write(string $app, $message, int $level): void {
$syslog_level = $this->levels[$level];
syslog($syslog_level, $this->logDetailsAsJSON($app, $message, $level));
}
diff --git a/lib/private/Log/Systemdlog.php b/lib/private/Log/Systemdlog.php
index 8619cb5e4dd..4e33a4e5419 100644
--- a/lib/private/Log/Systemdlog.php
+++ b/lib/private/Log/Systemdlog.php
@@ -1,27 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018, Johannes Ernst
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Johannes Ernst <jernst@indiecomputing.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Log;
@@ -46,7 +26,7 @@ use OCP\Log\IWriter;
// Syslog compatibility fields
class Systemdlog extends LogDetails implements IWriter {
- protected $levels = [
+ protected array $levels = [
ILogger::DEBUG => 7,
ILogger::INFO => 6,
ILogger::WARN => 4,
@@ -54,9 +34,12 @@ class Systemdlog extends LogDetails implements IWriter {
ILogger::FATAL => 2,
];
- protected $syslogId;
+ protected string $syslogId;
- public function __construct(SystemConfig $config, ?string $tag = null) {
+ public function __construct(
+ SystemConfig $config,
+ ?string $tag = null,
+ ) {
parent::__construct($config);
if (!function_exists('sd_journal_send')) {
throw new HintException(
@@ -71,11 +54,9 @@ class Systemdlog extends LogDetails implements IWriter {
/**
* Write a message to the log.
- * @param string $app
* @param string|array $message
- * @param int $level
*/
- public function write(string $app, $message, int $level) {
+ public function write(string $app, $message, int $level): void {
$journal_level = $this->levels[$level];
sd_journal_send('PRIORITY='.$journal_level,
'SYSLOG_IDENTIFIER='.$this->syslogId,
diff --git a/lib/private/Mail/Attachment.php b/lib/private/Mail/Attachment.php
index a39161b2505..8dede9714f8 100644
--- a/lib/private/Mail/Attachment.php
+++ b/lib/private/Mail/Attachment.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Mail;
diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php
index bb60f761450..80740e14aca 100644
--- a/lib/private/Mail/EMailTemplate.php
+++ b/lib/private/Mail/EMailTemplate.php
@@ -3,38 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2017, Morris Jobke <hey@morrisjobke.de>
- * @copyright 2017, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author brad2014 <brad2014@users.noreply.github.com>
- * @author Brad Rubenstein <brad@wbr.tech>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Liam JACK <liamjack@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author medcloud <42641918+medcloud@users.noreply.github.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tomasz Paluszkiewicz <tomasz.paluszkiewicz@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Mail;
diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php
index e4c3467f854..041ab8b0ff7 100644
--- a/lib/private/Mail/Mailer.php
+++ b/lib/private/Mail/Mailer.php
@@ -1,37 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arne Hamann <kontakt+github@arne.email>
- * @author Branko Kokanovic <branko@kokanovic.org>
- * @author Carsten Wiedmann <carsten_sttgt@gmx.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jared Boone <jared.boone@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author kevin147147 <kevintamool@gmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tekhnee <info@tekhnee.org>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Mail;
@@ -331,7 +304,7 @@ class Mailer implements IMailer {
}
$binaryParam = match ($this->config->getSystemValueString('mail_sendmailmode', 'smtp')) {
- 'pipe' => ' -t',
+ 'pipe' => ' -t -i',
default => ' -bs',
};
diff --git a/lib/private/Mail/Message.php b/lib/private/Mail/Message.php
index 15d4da793dd..faeba469e20 100644
--- a/lib/private/Mail/Message.php
+++ b/lib/private/Mail/Message.php
@@ -1,33 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arne Hamann <kontakt+github@arne.email>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jared Boone <jared.boone@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Mail;
@@ -73,7 +50,7 @@ class Message implements IMessage {
* {@inheritDoc}
* @since 26.0.0
*/
- public function attachInline(string $body, string $name, string $contentType = null): IMessage {
+ public function attachInline(string $body, string $name, ?string $contentType = null): IMessage {
# To be sure this works with iCalendar messages, we encode with 8bit instead of
# quoted-printable encoding. We save the current encoder, replace the current
# encoder with an 8bit encoder and after we've finished, we reset the encoder
diff --git a/lib/private/Memcache/APCu.php b/lib/private/Memcache/APCu.php
index f3221fc7b77..7f6a73354ee 100644
--- a/lib/private/Memcache/APCu.php
+++ b/lib/private/Memcache/APCu.php
@@ -1,29 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
diff --git a/lib/private/Memcache/ArrayCache.php b/lib/private/Memcache/ArrayCache.php
index 8c0af399116..4cac60c272c 100644
--- a/lib/private/Memcache/ArrayCache.php
+++ b/lib/private/Memcache/ArrayCache.php
@@ -1,26 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
diff --git a/lib/private/Memcache/CADTrait.php b/lib/private/Memcache/CADTrait.php
index a0843fc7731..bb010e238dc 100644
--- a/lib/private/Memcache/CADTrait.php
+++ b/lib/private/Memcache/CADTrait.php
@@ -1,23 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
diff --git a/lib/private/Memcache/CASTrait.php b/lib/private/Memcache/CASTrait.php
index 13688651043..945f1539f99 100644
--- a/lib/private/Memcache/CASTrait.php
+++ b/lib/private/Memcache/CASTrait.php
@@ -1,23 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
diff --git a/lib/private/Memcache/Cache.php b/lib/private/Memcache/Cache.php
index 1d54a705098..2a2a6e2a23f 100644
--- a/lib/private/Memcache/Cache.php
+++ b/lib/private/Memcache/Cache.php
@@ -1,29 +1,14 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
+/**
+ * @template-implements \ArrayAccess<string,mixed>
+ */
abstract class Cache implements \ArrayAccess, \OCP\ICache {
/**
* @var string $prefix
diff --git a/lib/private/Memcache/Factory.php b/lib/private/Memcache/Factory.php
index 788a7c2e8c9..c0f4f787200 100644
--- a/lib/private/Memcache/Factory.php
+++ b/lib/private/Memcache/Factory.php
@@ -1,40 +1,16 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Markus Goetz <markus@woboq.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Richard Steinmetz <richard@steinmetz.cloud>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
-use OCP\Profiler\IProfiler;
+use OCP\Cache\CappedMemoryCache;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IMemcache;
+use OCP\Profiler\IProfiler;
use Psr\Log\LoggerInterface;
class Factory implements ICacheFactory {
@@ -184,13 +160,8 @@ class Factory implements ICacheFactory {
return $this->distributedCacheClass !== self::NULL_CACHE;
}
- /**
- * @see \OC\Memcache\Factory::createLocal()
- * @param string $prefix
- * @return ICache
- */
- public function createLowLatency(string $prefix = ''): ICache {
- return $this->createLocal($prefix);
+ public function createInMemory(int $capacity = 512): ICache {
+ return new CappedMemoryCache($capacity);
}
/**
diff --git a/lib/private/Memcache/LoggerWrapperCache.php b/lib/private/Memcache/LoggerWrapperCache.php
index 55c0e76db79..11497e2a5d8 100644
--- a/lib/private/Memcache/LoggerWrapperCache.php
+++ b/lib/private/Memcache/LoggerWrapperCache.php
@@ -2,25 +2,8 @@
declare(strict_types = 1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Memcache;
@@ -75,7 +58,7 @@ class LoggerWrapperCache extends Cache implements IMemcacheTTL {
FILE_APPEND
);
- return $this->wrappedCache->set($key, $value, $$ttl);
+ return $this->wrappedCache->set($key, $value, $ttl);
}
/** @inheritDoc */
@@ -167,10 +150,18 @@ class LoggerWrapperCache extends Cache implements IMemcacheTTL {
}
/** @inheritDoc */
- public function setTTL($key, $ttl) {
+ public function setTTL(string $key, int $ttl) {
$this->wrappedCache->setTTL($key, $ttl);
}
+ public function getTTL(string $key): int|false {
+ return $this->wrappedCache->getTTL($key);
+ }
+
+ public function compareSetTTL(string $key, mixed $value, int $ttl): bool {
+ return $this->wrappedCache->compareSetTTL($key, $value, $ttl);
+ }
+
public static function isAvailable(): bool {
return true;
}
diff --git a/lib/private/Memcache/Memcached.php b/lib/private/Memcache/Memcached.php
index 7d512d4d1ae..620013feda6 100644
--- a/lib/private/Memcache/Memcached.php
+++ b/lib/private/Memcache/Memcached.php
@@ -1,33 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
diff --git a/lib/private/Memcache/NullCache.php b/lib/private/Memcache/NullCache.php
index fc41595dfe1..ab5c491913a 100644
--- a/lib/private/Memcache/NullCache.php
+++ b/lib/private/Memcache/NullCache.php
@@ -1,28 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
diff --git a/lib/private/Memcache/ProfilerWrapperCache.php b/lib/private/Memcache/ProfilerWrapperCache.php
index 6e76989dddd..84e3d880a0c 100644
--- a/lib/private/Memcache/ProfilerWrapperCache.php
+++ b/lib/private/Memcache/ProfilerWrapperCache.php
@@ -2,25 +2,8 @@
declare(strict_types = 1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Memcache;
@@ -32,6 +15,7 @@ use OCP\IMemcacheTTL;
/**
* Cache wrapper that logs profiling information
+ * @template-implements \ArrayAccess<string,mixed>
*/
class ProfilerWrapperCache extends AbstractDataCollector implements IMemcacheTTL, \ArrayAccess {
/** @var Redis $wrappedCache*/
@@ -183,10 +167,18 @@ class ProfilerWrapperCache extends AbstractDataCollector implements IMemcacheTTL
}
/** @inheritDoc */
- public function setTTL($key, $ttl) {
+ public function setTTL(string $key, int $ttl) {
$this->wrappedCache->setTTL($key, $ttl);
}
+ public function getTTL(string $key): int|false {
+ return $this->wrappedCache->getTTL($key);
+ }
+
+ public function compareSetTTL(string $key, mixed $value, int $ttl): bool {
+ return $this->wrappedCache->compareSetTTL($key, $value, $ttl);
+ }
+
public function offsetExists($offset): bool {
return $this->hasKey($offset);
}
@@ -207,7 +199,7 @@ class ProfilerWrapperCache extends AbstractDataCollector implements IMemcacheTTL
$this->remove($offset);
}
- public function collect(Request $request, Response $response, \Throwable $exception = null): void {
+ public function collect(Request $request, Response $response, ?\Throwable $exception = null): void {
// Nothing to do here $data is already ready
}
diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php
index bde25a3385a..cbafadc3b1b 100644
--- a/lib/private/Memcache/Redis.php
+++ b/lib/private/Memcache/Redis.php
@@ -1,31 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Memcache;
@@ -46,8 +23,15 @@ class Redis extends Cache implements IMemcacheTTL {
'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',
'cf0e94b2e9ffc7e04395cf88f7583fc309985910',
],
+ 'caSetTtl' => [
+ 'if redis.call("get", KEYS[1]) == ARGV[1] then redis.call("expire", KEYS[1], ARGV[2]) return 1 else return 0 end',
+ 'fa4acbc946d23ef41d7d3910880b60e6e4972d72',
+ ],
];
+ private const DEFAULT_TTL = 24 * 60 * 60; // 1 day
+ private const MAX_TTL = 30 * 24 * 60 * 60; // 1 month
+
/**
* @var \Redis|\RedisCluster $cache
*/
@@ -63,7 +47,7 @@ class Redis extends Cache implements IMemcacheTTL {
*/
public function getCache() {
if (is_null(self::$cache)) {
- self::$cache = \OC::$server->getGetRedisFactory()->getInstance();
+ self::$cache = \OC::$server->get('RedisFactory')->getInstance();
}
return self::$cache;
}
@@ -79,11 +63,12 @@ class Redis extends Cache implements IMemcacheTTL {
public function set($key, $value, $ttl = 0) {
$value = self::encodeValue($value);
- if ($ttl > 0) {
- return $this->getCache()->setex($this->getPrefix() . $key, $ttl, $value);
- } else {
- return $this->getCache()->set($this->getPrefix() . $key, $value);
+ if ($ttl === 0) {
+ // having infinite TTL can lead to leaked keys as the prefix changes with version upgrades
+ $ttl = self::DEFAULT_TTL;
}
+ $ttl = min($ttl, self::MAX_TTL);
+ return $this->getCache()->setex($this->getPrefix() . $key, $ttl, $value);
}
public function hasKey($key) {
@@ -117,11 +102,14 @@ class Redis extends Cache implements IMemcacheTTL {
*/
public function add($key, $value, $ttl = 0) {
$value = self::encodeValue($value);
+ if ($ttl === 0) {
+ // having infinite TTL can lead to leaked keys as the prefix changes with version upgrades
+ $ttl = self::DEFAULT_TTL;
+ }
+ $ttl = min($ttl, self::MAX_TTL);
$args = ['nx'];
- if ($ttl !== 0 && is_int($ttl)) {
- $args['ex'] = $ttl;
- }
+ $args['ex'] = $ttl;
return $this->getCache()->set($this->getPrefix() . $key, $value, $args);
}
@@ -178,11 +166,27 @@ class Redis extends Cache implements IMemcacheTTL {
}
public function setTTL($key, $ttl) {
+ if ($ttl === 0) {
+ // having infinite TTL can lead to leaked keys as the prefix changes with version upgrades
+ $ttl = self::DEFAULT_TTL;
+ }
+ $ttl = min($ttl, self::MAX_TTL);
$this->getCache()->expire($this->getPrefix() . $key, $ttl);
}
+ public function getTTL(string $key): int|false {
+ $ttl = $this->getCache()->ttl($this->getPrefix() . $key);
+ return $ttl > 0 ? (int)$ttl : false;
+ }
+
+ public function compareSetTTL(string $key, mixed $value, int $ttl): bool {
+ $value = self::encodeValue($value);
+
+ return $this->evalLua('caSetTtl', [$key], [$value, $ttl]) > 0;
+ }
+
public static function isAvailable(): bool {
- return \OC::$server->getGetRedisFactory()->isAvailable();
+ return \OC::$server->get('RedisFactory')->isAvailable();
}
protected function evalLua(string $scriptName, array $keys, array $args) {
@@ -191,7 +195,7 @@ class Redis extends Cache implements IMemcacheTTL {
$script = self::LUA_SCRIPTS[$scriptName];
$result = $this->getCache()->evalSha($script[1], $args, count($keys));
- if (false === $result) {
+ if ($result === false) {
$result = $this->getCache()->eval($script[0], $args, count($keys));
}
diff --git a/lib/private/Memcache/WithLocalCache.php b/lib/private/Memcache/WithLocalCache.php
index 5b7ccc10e39..0fc5d310801 100644
--- a/lib/private/Memcache/WithLocalCache.php
+++ b/lib/private/Memcache/WithLocalCache.php
@@ -1,5 +1,9 @@
<?php
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
namespace OC\Memcache;
use OCP\Cache\CappedMemoryCache;
diff --git a/lib/private/MemoryInfo.php b/lib/private/MemoryInfo.php
index 266fb15a573..a90739a6643 100644
--- a/lib/private/MemoryInfo.php
+++ b/lib/private/MemoryInfo.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Michael Weimann (<mail@michael-weimann.eu>)
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Michael Weimann <mail@michael-weimann.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/Metadata/Capabilities.php b/lib/private/Metadata/Capabilities.php
deleted file mode 100644
index 2fa0006f581..00000000000
--- a/lib/private/Metadata/Capabilities.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Metadata;
-
-use OCP\Capabilities\IPublicCapability;
-use OCP\IConfig;
-
-class Capabilities implements IPublicCapability {
- private IMetadataManager $manager;
- private IConfig $config;
-
- public function __construct(IMetadataManager $manager, IConfig $config) {
- $this->manager = $manager;
- $this->config = $config;
- }
-
- public function getCapabilities() {
- if ($this->config->getSystemValueBool('enable_file_metadata', true)) {
- return ['metadataAvailable' => $this->manager->getCapabilities()];
- }
-
- return [];
- }
-}
diff --git a/lib/private/Metadata/FileEventListener.php b/lib/private/Metadata/FileEventListener.php
deleted file mode 100644
index 162e85ff3aa..00000000000
--- a/lib/private/Metadata/FileEventListener.php
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-
-declare(strict_types=1);
-/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Metadata;
-
-use OC\Files\Filesystem;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
-use OCP\Files\Events\Node\NodeDeletedEvent;
-use OCP\Files\Events\Node\NodeWrittenEvent;
-use OCP\Files\Events\NodeRemovedFromCache;
-use OCP\Files\File;
-use OCP\Files\Node;
-use OCP\Files\NotFoundException;
-use OCP\Files\FileInfo;
-use Psr\Log\LoggerInterface;
-
-/**
- * @template-implements IEventListener<NodeRemovedFromCache>
- * @template-implements IEventListener<NodeDeletedEvent>
- * @template-implements IEventListener<NodeWrittenEvent>
- */
-class FileEventListener implements IEventListener {
- private IMetadataManager $manager;
- private LoggerInterface $logger;
-
- public function __construct(IMetadataManager $manager, LoggerInterface $logger) {
- $this->manager = $manager;
- $this->logger = $logger;
- }
-
- private function shouldExtractMetadata(Node $node): bool {
- try {
- if ($node->getMimetype() === 'httpd/unix-directory') {
- return false;
- }
- } catch (NotFoundException $e) {
- return false;
- }
- if ($node->getSize(false) <= 0) {
- return false;
- }
-
- $path = $node->getPath();
- return $this->isCorrectPath($path);
- }
-
- private function isCorrectPath(string $path): bool {
- // TODO make this more dynamic, we have the same issue in other places
- return !str_starts_with($path, 'appdata_') && !str_starts_with($path, 'files_versions/') && !str_starts_with($path, 'files_trashbin/');
- }
-
- public function handle(Event $event): void {
- if ($event instanceof NodeRemovedFromCache) {
- if (!$this->isCorrectPath($event->getPath())) {
- // Don't listen to paths for which we don't extract metadata
- return;
- }
- $view = Filesystem::getView();
- if (!$view) {
- // Should not happen since a scan in the user folder should setup
- // the file system.
- $e = new \Exception(); // don't trigger, just get backtrace
- $this->logger->error('Detecting deletion of a file with possible metadata but file system setup is not setup', [
- 'exception' => $e,
- 'app' => 'metadata'
- ]);
- return;
- }
- $info = $view->getFileInfo($event->getPath());
- if ($info && $info->getType() === FileInfo::TYPE_FILE) {
- $this->manager->clearMetadata($info->getId());
- }
- }
-
- if ($event instanceof NodeDeletedEvent) {
- $node = $event->getNode();
- if ($this->shouldExtractMetadata($node)) {
- /** @var File $node */
- $this->manager->clearMetadata($event->getNode()->getId());
- }
- }
-
- if ($event instanceof NodeWrittenEvent) {
- $node = $event->getNode();
- if ($this->shouldExtractMetadata($node)) {
- /** @var File $node */
- $this->manager->generateMetadata($event->getNode(), false);
- }
- }
- }
-}
diff --git a/lib/private/Metadata/FileMetadata.php b/lib/private/Metadata/FileMetadata.php
deleted file mode 100644
index a9808a86998..00000000000
--- a/lib/private/Metadata/FileMetadata.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-declare(strict_types=1);
-/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Metadata;
-
-use OCP\AppFramework\Db\Entity;
-use OCP\DB\Types;
-
-/**
- * @method string getGroupName()
- * @method void setGroupName(string $groupName)
- * @method string getValue()
- * @method void setValue(string $value)
- * @see \OC\Core\Migrations\Version240000Date20220404230027
- */
-class FileMetadata extends Entity {
- protected ?string $groupName = null;
- protected ?string $value = null;
-
- public function __construct() {
- $this->addType('groupName', 'string');
- $this->addType('value', Types::STRING);
- }
-
- public function getDecodedValue(): array {
- return json_decode($this->getValue(), true) ?? [];
- }
-
- public function setArrayAsValue(array $value): void {
- $this->setValue(json_encode($value, JSON_THROW_ON_ERROR));
- }
-}
diff --git a/lib/private/Metadata/FileMetadataMapper.php b/lib/private/Metadata/FileMetadataMapper.php
deleted file mode 100644
index 003ab13126e..00000000000
--- a/lib/private/Metadata/FileMetadataMapper.php
+++ /dev/null
@@ -1,177 +0,0 @@
-<?php
-
-declare(strict_types=1);
-/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @copyright Copyright 2022 Louis Chmn <louis@chmn.me>
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Metadata;
-
-use OCP\AppFramework\Db\DoesNotExistException;
-use OCP\AppFramework\Db\MultipleObjectsReturnedException;
-use OCP\AppFramework\Db\QBMapper;
-use OCP\AppFramework\Db\Entity;
-use OCP\DB\Exception;
-use OCP\DB\QueryBuilder\IQueryBuilder;
-use OCP\IDBConnection;
-
-/**
- * @template-extends QBMapper<FileMetadata>
- */
-class FileMetadataMapper extends QBMapper {
- public function __construct(IDBConnection $db) {
- parent::__construct($db, 'file_metadata', FileMetadata::class);
- }
-
- /**
- * @return FileMetadata[]
- * @throws Exception
- */
- public function findForFile(int $fileId): array {
- $qb = $this->db->getQueryBuilder();
- $qb->select('*')
- ->from($this->getTableName())
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
-
- return $this->findEntities($qb);
- }
-
- /**
- * @throws DoesNotExistException
- * @throws MultipleObjectsReturnedException
- * @throws Exception
- */
- public function findForGroupForFile(int $fileId, string $groupName): FileMetadata {
- $qb = $this->db->getQueryBuilder();
- $qb->select('*')
- ->from($this->getTableName())
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)))
- ->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, IQueryBuilder::PARAM_STR)));
-
- return $this->findEntity($qb);
- }
-
- /**
- * @return array<int, FileMetadata>
- * @throws Exception
- */
- public function findForGroupForFiles(array $fileIds, string $groupName): array {
- $qb = $this->db->getQueryBuilder();
- $qb->select('*')
- ->from($this->getTableName())
- ->where($qb->expr()->in('id', $qb->createParameter('fileIds')))
- ->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, IQueryBuilder::PARAM_STR)));
-
- $metadata = [];
- foreach (array_chunk($fileIds, 1000) as $fileIdsChunk) {
- $qb->setParameter('fileIds', $fileIdsChunk, IQueryBuilder::PARAM_INT_ARRAY);
- /** @var FileMetadata[] $rawEntities */
- $rawEntities = $this->findEntities($qb);
- foreach ($rawEntities as $entity) {
- $metadata[$entity->getId()] = $entity;
- }
- }
-
- foreach ($fileIds as $id) {
- if (isset($metadata[$id])) {
- continue;
- }
- $empty = new FileMetadata();
- $empty->setValue('');
- $empty->setGroupName($groupName);
- $empty->setId($id);
- $metadata[$id] = $empty;
- }
- return $metadata;
- }
-
- public function clear(int $fileId): void {
- $qb = $this->db->getQueryBuilder();
- $qb->delete($this->getTableName())
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
-
- $qb->executeStatement();
- }
-
- /**
- * Updates an entry in the db from an entity
- *
- * @param FileMetadata $entity the entity that should be created
- * @return FileMetadata the saved entity with the set id
- * @throws Exception
- * @throws \InvalidArgumentException if entity has no id
- */
- public function update(Entity $entity): FileMetadata {
- if (!($entity instanceof FileMetadata)) {
- throw new \Exception("Entity should be a FileMetadata entity");
- }
-
- // entity needs an id
- $id = $entity->getId();
- if ($id === null) {
- throw new \InvalidArgumentException('Entity which should be updated has no id');
- }
-
- // entity needs an group_name
- $groupName = $entity->getGroupName();
- if ($groupName === null) {
- throw new \InvalidArgumentException('Entity which should be updated has no group_name');
- }
-
- $idType = $this->getParameterTypeForProperty($entity, 'id');
- $groupNameType = $this->getParameterTypeForProperty($entity, 'groupName');
- $value = $entity->getValue();
- $valueType = $this->getParameterTypeForProperty($entity, 'value');
-
- $qb = $this->db->getQueryBuilder();
-
- $qb->update($this->tableName)
- ->set('value', $qb->createNamedParameter($value, $valueType))
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, $idType)))
- ->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, $groupNameType)))
- ->executeStatement();
-
- return $entity;
- }
-
- /**
- * Override the insertOrUpdate as we could be in a transaction in which case we can not afford on error.
- *
- * @param FileMetadata $entity the entity that should be created/updated
- * @return FileMetadata the saved entity with the (new) id
- * @throws Exception
- * @throws \InvalidArgumentException if entity has no id
- */
- public function insertOrUpdate(Entity $entity): FileMetadata {
- try {
- $existingEntity = $this->findForGroupForFile($entity->getId(), $entity->getGroupName());
- } catch (\Throwable) {
- $existingEntity = null;
- }
-
- if ($existingEntity !== null) {
- if ($entity->getValue() !== $existingEntity->getValue()) {
- return $this->update($entity);
- } else {
- return $existingEntity;
- }
- } else {
- return parent::insertOrUpdate($entity);
- }
- }
-}
diff --git a/lib/private/Metadata/IMetadataManager.php b/lib/private/Metadata/IMetadataManager.php
deleted file mode 100644
index fa0bcc22801..00000000000
--- a/lib/private/Metadata/IMetadataManager.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace OC\Metadata;
-
-use OCP\Files\File;
-
-/**
- * Interface to manage additional metadata for files
- */
-interface IMetadataManager {
- /**
- * @param class-string<IMetadataProvider> $className
- */
- public function registerProvider(string $className): void;
-
- /**
- * Generate the metadata for one file
- */
- public function generateMetadata(File $file, bool $checkExisting = false): void;
-
- /**
- * Clear the metadata for one file
- */
- public function clearMetadata(int $fileId): void;
-
- /** @return array<int, FileMetadata> */
- public function fetchMetadataFor(string $group, array $fileIds): array;
-
- /**
- * Get the capabilities as an array of mimetype regex to the type provided
- */
- public function getCapabilities(): array;
-}
diff --git a/lib/private/Metadata/IMetadataProvider.php b/lib/private/Metadata/IMetadataProvider.php
deleted file mode 100644
index 7cbe102a538..00000000000
--- a/lib/private/Metadata/IMetadataProvider.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-namespace OC\Metadata;
-
-use OCP\Files\File;
-
-/**
- * Interface for the metadata providers. If you want an application to provide
- * some metadata, you can use this to store them.
- */
-interface IMetadataProvider {
- /**
- * The list of groups that this metadata provider is able to provide.
- *
- * @return string[]
- */
- public static function groupsProvided(): array;
-
- /**
- * Check if the metadata provider is available. A metadata provider might be
- * unavailable due to a php extension not being installed.
- */
- public static function isAvailable(): bool;
-
- /**
- * Get the mimetypes supported as a regex.
- */
- public static function getMimetypesSupported(): string;
-
- /**
- * Execute the extraction on the specified file. The metadata should be
- * grouped by metadata
- *
- * Each group should be json serializable and the string representation
- * shouldn't be longer than 4000 characters.
- *
- * @param File $file The file to extract the metadata from
- * @param array<string, FileMetadata> An array containing all the metadata fetched.
- */
- public function execute(File $file): array;
-}
diff --git a/lib/private/Metadata/MetadataManager.php b/lib/private/Metadata/MetadataManager.php
deleted file mode 100644
index 6d96ff1ab68..00000000000
--- a/lib/private/Metadata/MetadataManager.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Metadata;
-
-use OC\Metadata\Provider\ExifProvider;
-use OCP\Files\File;
-
-class MetadataManager implements IMetadataManager {
- /** @var array<string, IMetadataProvider> */
- private array $providers;
- private array $providerClasses;
- private FileMetadataMapper $fileMetadataMapper;
-
- public function __construct(
- FileMetadataMapper $fileMetadataMapper
- ) {
- $this->providers = [];
- $this->providerClasses = [];
- $this->fileMetadataMapper = $fileMetadataMapper;
-
- // TODO move to another place, where?
- $this->registerProvider(ExifProvider::class);
- }
-
- /**
- * @param class-string<IMetadataProvider> $className
- */
- public function registerProvider(string $className):void {
- if (in_array($className, $this->providerClasses)) {
- return;
- }
-
- if (call_user_func([$className, 'isAvailable'])) {
- $this->providers[call_user_func([$className, 'getMimetypesSupported'])] = \OC::$server->get($className);
- }
- }
-
- public function generateMetadata(File $file, bool $checkExisting = false): void {
- $existingMetadataGroups = [];
-
- if ($checkExisting) {
- $existingMetadata = $this->fileMetadataMapper->findForFile($file->getId());
- foreach ($existingMetadata as $metadata) {
- $existingMetadataGroups[] = $metadata->getGroupName();
- }
- }
-
- foreach ($this->providers as $supportedMimetype => $provider) {
- if (preg_match($supportedMimetype, $file->getMimeType())) {
- if (count(array_diff($provider::groupsProvided(), $existingMetadataGroups)) > 0) {
- $metaDataGroup = $provider->execute($file);
- foreach ($metaDataGroup as $group => $metadata) {
- $this->fileMetadataMapper->insertOrUpdate($metadata);
- }
- }
- }
- }
- }
-
- public function clearMetadata(int $fileId): void {
- $this->fileMetadataMapper->clear($fileId);
- }
-
- /**
- * @return array<int, FileMetadata>
- */
- public function fetchMetadataFor(string $group, array $fileIds): array {
- return $this->fileMetadataMapper->findForGroupForFiles($fileIds, $group);
- }
-
- public function getCapabilities(): array {
- $capabilities = [];
- foreach ($this->providers as $supportedMimetype => $provider) {
- foreach ($provider::groupsProvided() as $group) {
- if (isset($capabilities[$group])) {
- $capabilities[$group][] = $supportedMimetype;
- }
- $capabilities[$group] = [$supportedMimetype];
- }
- }
- return $capabilities;
- }
-}
diff --git a/lib/private/Metadata/Provider/ExifProvider.php b/lib/private/Metadata/Provider/ExifProvider.php
deleted file mode 100644
index b1598abbbc8..00000000000
--- a/lib/private/Metadata/Provider/ExifProvider.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-declare(strict_types=1);
-/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @copyright Copyright 2022 Louis Chmn <louis@chmn.me>
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Metadata\Provider;
-
-use OC\Metadata\FileMetadata;
-use OC\Metadata\IMetadataProvider;
-use OCP\Files\File;
-use Psr\Log\LoggerInterface;
-
-class ExifProvider implements IMetadataProvider {
- private LoggerInterface $logger;
-
- public function __construct(
- LoggerInterface $logger
- ) {
- $this->logger = $logger;
- }
-
- public static function groupsProvided(): array {
- return ['size', 'gps'];
- }
-
- public static function isAvailable(): bool {
- return extension_loaded('exif');
- }
-
- /** @return array{'gps'?: FileMetadata, 'size'?: FileMetadata} */
- public function execute(File $file): array {
- $exifData = [];
- $fileDescriptor = $file->fopen('rb');
-
- if ($fileDescriptor === false) {
- return [];
- }
-
- $data = null;
- try {
- // Needed to make reading exif data reliable.
- // This is to trigger this condition: https://github.com/php/php-src/blob/d64aa6f646a7b5e58359dc79479860164239580a/main/streams/streams.c#L710
- // But I don't understand why 1 as a special meaning.
- // Revert right after reading the exif data.
- $oldBufferSize = stream_set_chunk_size($fileDescriptor, 1);
- $data = @exif_read_data($fileDescriptor, 'ANY_TAG', true);
- stream_set_chunk_size($fileDescriptor, $oldBufferSize);
- } catch (\Exception $ex) {
- $this->logger->info("Couldn't extract metadata for ".$file->getId(), ['exception' => $ex]);
- }
-
- $size = new FileMetadata();
- $size->setGroupName('size');
- $size->setId($file->getId());
- $size->setArrayAsValue([]);
-
- if (!$data) {
- $sizeResult = getimagesizefromstring($file->getContent());
- if ($sizeResult !== false) {
- $size->setArrayAsValue([
- 'width' => $sizeResult[0],
- 'height' => $sizeResult[1],
- ]);
-
- $exifData['size'] = $size;
- }
- } elseif (array_key_exists('COMPUTED', $data)) {
- if (array_key_exists('Width', $data['COMPUTED']) && array_key_exists('Height', $data['COMPUTED'])) {
- $size->setArrayAsValue([
- 'width' => $data['COMPUTED']['Width'],
- 'height' => $data['COMPUTED']['Height'],
- ]);
-
- $exifData['size'] = $size;
- }
- }
-
- if ($data && array_key_exists('GPS', $data)
- && array_key_exists('GPSLatitude', $data['GPS']) && array_key_exists('GPSLatitudeRef', $data['GPS'])
- && array_key_exists('GPSLongitude', $data['GPS']) && array_key_exists('GPSLongitudeRef', $data['GPS'])
- ) {
- $gps = new FileMetadata();
- $gps->setGroupName('gps');
- $gps->setId($file->getId());
- $gps->setArrayAsValue([
- 'latitude' => $this->gpsDegreesToDecimal($data['GPS']['GPSLatitude'], $data['GPS']['GPSLatitudeRef']),
- 'longitude' => $this->gpsDegreesToDecimal($data['GPS']['GPSLongitude'], $data['GPS']['GPSLongitudeRef']),
- ]);
-
- $exifData['gps'] = $gps;
- }
-
- return $exifData;
- }
-
- public static function getMimetypesSupported(): string {
- return '/image\/(png|jpeg|heif|webp|tiff)/';
- }
-
- /**
- * @param array|string $coordinates
- */
- private static function gpsDegreesToDecimal($coordinates, ?string $hemisphere): float {
- if (is_string($coordinates)) {
- $coordinates = array_map("trim", explode(",", $coordinates));
- }
-
- if (count($coordinates) !== 3) {
- throw new \Exception('Invalid coordinate format: ' . json_encode($coordinates));
- }
-
- [$degrees, $minutes, $seconds] = array_map(function (string $rawDegree) {
- $parts = explode('/', $rawDegree);
-
- if ($parts[1] === '0') {
- return 0;
- }
-
- return floatval($parts[0]) / floatval($parts[1] ?? 1);
- }, $coordinates);
-
- $sign = ($hemisphere === 'W' || $hemisphere === 'S') ? -1 : 1;
- return $sign * ($degrees + $minutes / 60 + $seconds / 3600);
- }
-}
diff --git a/lib/private/Migration/BackgroundRepair.php b/lib/private/Migration/BackgroundRepair.php
index 579ba494e58..cbc21e4fe12 100644
--- a/lib/private/Migration/BackgroundRepair.php
+++ b/lib/private/Migration/BackgroundRepair.php
@@ -1,38 +1,18 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Migration;
-use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\BackgroundJob\IJobList;
-use OCP\BackgroundJob\TimedJob;
-use OCP\EventDispatcher\IEventDispatcher;
use OC\NeedsUpdateException;
use OC\Repair;
use OC_App;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\IJobList;
+use OCP\BackgroundJob\TimedJob;
use Psr\Log\LoggerInterface;
/**
@@ -41,15 +21,13 @@ use Psr\Log\LoggerInterface;
* @package OC\Migration
*/
class BackgroundRepair extends TimedJob {
- private IJobList $jobList;
- private LoggerInterface $logger;
- private IEventDispatcher $dispatcher;
-
- public function __construct(IEventDispatcher $dispatcher, ITimeFactory $time, LoggerInterface $logger, IJobList $jobList) {
+ public function __construct(
+ private Repair $repair,
+ ITimeFactory $time,
+ private LoggerInterface $logger,
+ private IJobList $jobList,
+ ) {
parent::__construct($time);
- $this->dispatcher = $dispatcher;
- $this->logger = $logger;
- $this->jobList = $jobList;
$this->setInterval(15 * 60);
}
@@ -58,7 +36,7 @@ class BackgroundRepair extends TimedJob {
* @throws \Exception
* @throws \OC\NeedsUpdateException
*/
- protected function run($argument) {
+ protected function run($argument): void {
if (!isset($argument['app']) || !isset($argument['step'])) {
// remove the job - we can never execute it
$this->jobList->remove($this, $this->argument);
@@ -75,9 +53,9 @@ class BackgroundRepair extends TimedJob {
}
$step = $argument['step'];
- $repair = new Repair([], $this->dispatcher, \OC::$server->get(LoggerInterface::class));
+ $this->repair->setRepairSteps([]);
try {
- $repair->addStep($step);
+ $this->repair->addStep($step);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage(), [
'app' => 'migration',
@@ -90,7 +68,7 @@ class BackgroundRepair extends TimedJob {
}
// execute the repair step
- $repair->run();
+ $this->repair->run();
// remove the job once executed successfully
$this->jobList->remove($this, $this->argument);
@@ -101,7 +79,7 @@ class BackgroundRepair extends TimedJob {
* @param $app
* @throws NeedsUpdateException
*/
- protected function loadApp($app) {
+ protected function loadApp($app): void {
OC_App::loadApp($app);
}
}
diff --git a/lib/private/Migration/ConsoleOutput.php b/lib/private/Migration/ConsoleOutput.php
index 9e3396f2a75..7ccc4e7825a 100644
--- a/lib/private/Migration/ConsoleOutput.php
+++ b/lib/private/Migration/ConsoleOutput.php
@@ -1,23 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2015 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Migration;
@@ -34,34 +19,35 @@ use Symfony\Component\Console\Output\OutputInterface;
* @package OC\Migration
*/
class ConsoleOutput implements IOutput {
- /** @var OutputInterface */
- private $output;
+ private ?ProgressBar $progressBar = null;
- /** @var ProgressBar */
- private $progressBar;
+ public function __construct(
+ private OutputInterface $output,
+ ) {
+ }
- public function __construct(OutputInterface $output) {
- $this->output = $output;
+ public function debug(string $message): void {
+ $this->output->writeln($message, OutputInterface::VERBOSITY_VERBOSE);
}
/**
* @param string $message
*/
- public function info($message) {
+ public function info($message): void {
$this->output->writeln("<info>$message</info>");
}
/**
* @param string $message
*/
- public function warning($message) {
+ public function warning($message): void {
$this->output->writeln("<comment>$message</comment>");
}
/**
* @param int $max
*/
- public function startProgress($max = 0) {
+ public function startProgress($max = 0): void {
if (!is_null($this->progressBar)) {
$this->progressBar->finish();
}
@@ -73,7 +59,7 @@ class ConsoleOutput implements IOutput {
* @param int $step
* @param string $description
*/
- public function advance($step = 1, $description = '') {
+ public function advance($step = 1, $description = ''): void {
if (is_null($this->progressBar)) {
$this->progressBar = new ProgressBar($this->output);
$this->progressBar->start();
@@ -84,7 +70,7 @@ class ConsoleOutput implements IOutput {
}
}
- public function finishProgress() {
+ public function finishProgress(): void {
if (is_null($this->progressBar)) {
return;
}
diff --git a/lib/private/Migration/SimpleOutput.php b/lib/private/Migration/SimpleOutput.php
index f97bcb767f8..31420d49932 100644
--- a/lib/private/Migration/SimpleOutput.php
+++ b/lib/private/Migration/SimpleOutput.php
@@ -1,23 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2015 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Migration;
@@ -33,19 +18,21 @@ use Psr\Log\LoggerInterface;
* @package OC\Migration
*/
class SimpleOutput implements IOutput {
- private LoggerInterface $logger;
- private $appName;
+ public function __construct(
+ private LoggerInterface $logger,
+ private $appName,
+ ) {
+ }
- public function __construct(LoggerInterface $logger, $appName) {
- $this->logger = $logger;
- $this->appName = $appName;
+ public function debug(string $message): void {
+ $this->logger->debug($message, ['app' => $this->appName]);
}
/**
* @param string $message
* @since 9.1.0
*/
- public function info($message) {
+ public function info($message): void {
$this->logger->info($message, ['app' => $this->appName]);
}
@@ -53,7 +40,7 @@ class SimpleOutput implements IOutput {
* @param string $message
* @since 9.1.0
*/
- public function warning($message) {
+ public function warning($message): void {
$this->logger->warning($message, ['app' => $this->appName]);
}
@@ -61,7 +48,7 @@ class SimpleOutput implements IOutput {
* @param int $max
* @since 9.1.0
*/
- public function startProgress($max = 0) {
+ public function startProgress($max = 0): void {
}
/**
@@ -69,12 +56,12 @@ class SimpleOutput implements IOutput {
* @param string $description
* @since 9.1.0
*/
- public function advance($step = 1, $description = '') {
+ public function advance($step = 1, $description = ''): void {
}
/**
* @since 9.1.0
*/
- public function finishProgress() {
+ public function finishProgress(): void {
}
}
diff --git a/lib/private/NaturalSort.php b/lib/private/NaturalSort.php
index 976db4e7803..120e05a8eb2 100644
--- a/lib/private/NaturalSort.php
+++ b/lib/private/NaturalSort.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author AW-UC <git@a-wesemann.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/NaturalSort_DefaultCollator.php b/lib/private/NaturalSort_DefaultCollator.php
index 35bed8a37c7..d688a34133a 100644
--- a/lib/private/NaturalSort_DefaultCollator.php
+++ b/lib/private/NaturalSort_DefaultCollator.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author AW-UC <git@a-wesemann.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php
index 56f55e80331..05a3a9c85fe 100644
--- a/lib/private/NavigationManager.php
+++ b/lib/private/NavigationManager.php
@@ -1,33 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud GmbH
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -65,19 +41,25 @@ class NavigationManager implements INavigationManager {
private $groupManager;
/** @var IConfig */
private $config;
+ /** The default app for the current user (cached for the `add` function) */
+ private ?string $defaultApp;
+ /** User defined app order (cached for the `add` function) */
+ private array $customAppOrder;
public function __construct(IAppManager $appManager,
- IURLGenerator $urlGenerator,
- IFactory $l10nFac,
- IUserSession $userSession,
- IGroupManager $groupManager,
- IConfig $config) {
+ IURLGenerator $urlGenerator,
+ IFactory $l10nFac,
+ IUserSession $userSession,
+ IGroupManager $groupManager,
+ IConfig $config) {
$this->appManager = $appManager;
$this->urlGenerator = $urlGenerator;
$this->l10nFac = $l10nFac;
$this->userSession = $userSession;
$this->groupManager = $groupManager;
$this->config = $config;
+
+ $this->defaultApp = null;
}
/**
@@ -88,8 +70,12 @@ class NavigationManager implements INavigationManager {
$this->closureEntries[] = $entry;
return;
}
+ $this->init();
+
+ $id = $entry['id'];
$entry['active'] = false;
+ $entry['unread'] = $this->unreadCounters[$id] ?? 0;
if (!isset($entry['icon'])) {
$entry['icon'] = '';
}
@@ -100,8 +86,17 @@ class NavigationManager implements INavigationManager {
$entry['type'] = 'link';
}
- $id = $entry['id'];
- $entry['unread'] = isset($this->unreadCounters[$id]) ? $this->unreadCounters[$id] : 0;
+ if ($entry['type'] === 'link') {
+ // app might not be set when using closures, in this case try to fallback to ID
+ if (!isset($entry['app']) && $this->appManager->isEnabledForUser($id)) {
+ $entry['app'] = $id;
+ }
+
+ // This is the default app that will always be shown first
+ $entry['default'] = ($entry['app'] ?? false) === $this->defaultApp;
+ // Set order from user defined app order
+ $entry['order'] = $this->customAppOrder[$id]['order'] ?? $entry['order'] ?? 100;
+ }
$this->entries[$id] = $entry;
}
@@ -123,26 +118,44 @@ class NavigationManager implements INavigationManager {
});
}
- return $this->proceedNavigation($result);
+ return $this->proceedNavigation($result, $type);
}
/**
- * Sort navigation entries by order, name and set active flag
+ * Sort navigation entries default app is always sorted first, then by order, name and set active flag
*
* @param array $list
* @return array
*/
- private function proceedNavigation(array $list): array {
+ private function proceedNavigation(array $list, string $type): array {
uasort($list, function ($a, $b) {
- if (isset($a['order']) && isset($b['order'])) {
+ if (($a['default'] ?? false) xor ($b['default'] ?? false)) {
+ // Always sort the default app first
+ return ($a['default'] ?? false) ? -1 : 1;
+ } elseif (isset($a['order']) && isset($b['order'])) {
+ // Sort by order
return ($a['order'] < $b['order']) ? -1 : 1;
} elseif (isset($a['order']) || isset($b['order'])) {
+ // Sort the one that has an order property first
return isset($a['order']) ? -1 : 1;
} else {
+ // Sort by name otherwise
return ($a['name'] < $b['name']) ? -1 : 1;
}
});
+ if ($type === 'all' || $type === 'link') {
+ // There might be the case that no default app was set, in this case the first app is the default app.
+ // Otherwise the default app is already the ordered first, so setting the default prop will make no difference.
+ foreach ($list as $index => &$navEntry) {
+ if ($navEntry['type'] === 'link') {
+ $navEntry['default'] = true;
+ break;
+ }
+ }
+ unset($navEntry);
+ }
+
$activeApp = $this->getActiveEntry();
if ($activeApp !== null) {
foreach ($list as $index => &$navEntry) {
@@ -171,8 +184,8 @@ class NavigationManager implements INavigationManager {
/**
* @inheritDoc
*/
- public function setActiveEntry($id) {
- $this->activeEntry = $id;
+ public function setActiveEntry($appId) {
+ $this->activeEntry = $appId;
}
/**
@@ -195,12 +208,26 @@ class NavigationManager implements INavigationManager {
'id' => 'help',
'order' => 99998,
'href' => $this->urlGenerator->linkToRoute('settings.Help.help'),
- 'name' => $l->t('Help'),
+ 'name' => $l->t('Help & privacy'),
'icon' => $this->urlGenerator->imagePath('settings', 'help.svg'),
]);
}
+ $this->defaultApp = $this->appManager->getDefaultAppForUser($this->userSession->getUser(), false);
+
if ($this->userSession->isLoggedIn()) {
+ // Profile
+ $this->add([
+ 'type' => 'settings',
+ 'id' => 'profile',
+ 'order' => 1,
+ 'href' => $this->urlGenerator->linkToRoute(
+ 'core.ProfilePage.index',
+ ['targetUserId' => $this->userSession->getUser()->getUID()],
+ ),
+ 'name' => $l->t('View profile'),
+ ]);
+
// Accessibility settings
if ($this->appManager->isEnabledForUser('theming', $this->userSession->getUser())) {
$this->add([
@@ -212,6 +239,7 @@ class NavigationManager implements INavigationManager {
'icon' => $this->urlGenerator->imagePath('theming', 'accessibility-dark.svg'),
]);
}
+
if ($this->isAdmin()) {
// App management
$this->add([
@@ -274,20 +302,19 @@ class NavigationManager implements INavigationManager {
'id' => 'core_users',
'order' => 6,
'href' => $this->urlGenerator->linkToRoute('settings.Users.usersList'),
- 'name' => $l->t('Users'),
+ 'name' => $l->t('Accounts'),
'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
]);
}
}
- if ($this->appManager === 'null') {
- return;
- }
-
if ($this->userSession->isLoggedIn()) {
- $apps = $this->appManager->getEnabledAppsForUser($this->userSession->getUser());
+ $user = $this->userSession->getUser();
+ $apps = $this->appManager->getEnabledAppsForUser($user);
+ $this->customAppOrder = json_decode($this->config->getUserValue($user->getUID(), 'core', 'apporder', '[]'), true, flags:JSON_THROW_ON_ERROR);
} else {
$apps = $this->appManager->getInstalledApps();
+ $this->customAppOrder = [];
}
foreach ($apps as $app) {
@@ -309,36 +336,48 @@ class NavigationManager implements INavigationManager {
if (!isset($nav['route']) && $nav['type'] !== 'settings') {
continue;
}
- $role = isset($nav['@attributes']['role']) ? $nav['@attributes']['role'] : 'all';
+ $role = $nav['@attributes']['role'] ?? 'all';
if ($role === 'admin' && !$this->isAdmin()) {
continue;
}
$l = $this->l10nFac->get($app);
$id = $nav['id'] ?? $app . ($key === 0 ? '' : $key);
- $order = isset($nav['order']) ? $nav['order'] : 100;
+ $order = $nav['order'] ?? 100;
$type = $nav['type'];
$route = !empty($nav['route']) ? $this->urlGenerator->linkToRoute($nav['route']) : '';
- $icon = isset($nav['icon']) ? $nav['icon'] : 'app.svg';
- foreach ([$icon, "$app.svg"] as $i) {
+ $icon = $nav['icon'] ?? null;
+ if ($icon !== null) {
try {
- $icon = $this->urlGenerator->imagePath($app, $i);
- break;
+ $icon = $this->urlGenerator->imagePath($app, $icon);
} catch (\RuntimeException $ex) {
- // no icon? - ignore it then
+ // ignore
}
}
if ($icon === null) {
+ $icon = $this->appManager->getAppIcon($app);
+ }
+ if ($icon === null) {
$icon = $this->urlGenerator->imagePath('core', 'default-app-icon');
}
- $this->add([
+ $this->add(array_merge([
+ // Navigation id
'id' => $id,
+ // Order where this entry should be shown
'order' => $order,
+ // Target of the navigation entry
'href' => $route,
+ // The icon used for the naviation entry
'icon' => $icon,
+ // Type of the navigation entry ('link' vs 'settings')
'type' => $type,
+ // Localized name of the navigation entry
'name' => $l->t($nav['name']),
- ]);
+ ], $type === 'link' ? [
+ // App that registered this navigation entry (not necessarly the same as the id)
+ 'app' => $app,
+ ] : []
+ ));
}
}
}
diff --git a/lib/private/NeedsUpdateException.php b/lib/private/NeedsUpdateException.php
index fcf63a6b373..da467d96299 100644
--- a/lib/private/NeedsUpdateException.php
+++ b/lib/private/NeedsUpdateException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Net/HostnameClassifier.php b/lib/private/Net/HostnameClassifier.php
index 626aa47083e..e0f1435d6f1 100644
--- a/lib/private/Net/HostnameClassifier.php
+++ b/lib/private/Net/HostnameClassifier.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Net;
@@ -52,10 +36,6 @@ class HostnameClassifier {
* Check host identifier for local hostname
*
* IP addresses are not considered local. Use the IpAddressClassifier for those.
- *
- * @param string $hostname
- *
- * @return bool
*/
public function isLocalHostname(string $hostname): bool {
// Disallow local network top-level domains from RFC 6762
diff --git a/lib/private/Net/IpAddressClassifier.php b/lib/private/Net/IpAddressClassifier.php
index d4698864ec8..5f41f4a086a 100644
--- a/lib/private/Net/IpAddressClassifier.php
+++ b/lib/private/Net/IpAddressClassifier.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Net;
@@ -46,10 +30,6 @@ class IpAddressClassifier {
* Check host identifier for local IPv4 and IPv6 address ranges
*
* Hostnames are not considered local. Use the HostnameClassifier for those.
- *
- * @param string $ip
- *
- * @return bool
*/
public function isLocalAddress(string $ip): bool {
$parsedIp = Factory::parseAddressString(
diff --git a/lib/private/NotSquareException.php b/lib/private/NotSquareException.php
index 40957e7d924..7be7ad09521 100644
--- a/lib/private/NotSquareException.php
+++ b/lib/private/NotSquareException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christopher Schäpers <kondou@ts.unde.re>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Notification/Action.php b/lib/private/Notification/Action.php
index ff9cf9e38f5..e2a75bea030 100644
--- a/lib/private/Notification/Action.php
+++ b/lib/private/Notification/Action.php
@@ -1,106 +1,61 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Notification;
use OCP\Notification\IAction;
+use OCP\Notification\InvalidValueException;
class Action implements IAction {
- /** @var string */
- protected $label;
-
- /** @var string */
- protected $labelParsed;
-
- /** @var string */
- protected $link;
-
- /** @var string */
- protected $requestType;
-
- /** @var string */
- protected $icon;
-
- /** @var bool */
- protected $primary;
-
- public function __construct() {
- $this->label = '';
- $this->labelParsed = '';
- $this->link = '';
- $this->requestType = '';
- $this->primary = false;
- }
+ protected string $label = '';
+ protected string $labelParsed = '';
+ protected string $link = '';
+ protected string $requestType = '';
+ protected bool $primary = false;
/**
- * @param string $label
- * @return $this
- * @throws \InvalidArgumentException if the label is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setLabel(string $label): IAction {
if ($label === '' || isset($label[32])) {
- throw new \InvalidArgumentException('The given label is invalid');
+ throw new InvalidValueException('label');
}
$this->label = $label;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getLabel(): string {
return $this->label;
}
/**
- * @param string $label
- * @return $this
- * @throws \InvalidArgumentException if the label is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setParsedLabel(string $label): IAction {
if ($label === '') {
- throw new \InvalidArgumentException('The given parsed label is invalid');
+ throw new InvalidValueException('parsedLabel');
}
$this->labelParsed = $label;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getParsedLabel(): string {
return $this->labelParsed;
}
/**
- * @param $primary bool
- * @return $this
- * @since 9.0.0
+ * {@inheritDoc}
*/
public function setPrimary(bool $primary): IAction {
$this->primary = $primary;
@@ -108,23 +63,18 @@ class Action implements IAction {
}
/**
- * @return bool
- * @since 9.0.0
+ * {@inheritDoc}
*/
public function isPrimary(): bool {
return $this->primary;
}
/**
- * @param string $link
- * @param string $requestType
- * @return $this
- * @throws \InvalidArgumentException if the link is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setLink(string $link, string $requestType): IAction {
if ($link === '' || isset($link[256])) {
- throw new \InvalidArgumentException('The given link is invalid');
+ throw new InvalidValueException('link');
}
if (!in_array($requestType, [
self::TYPE_GET,
@@ -133,7 +83,7 @@ class Action implements IAction {
self::TYPE_DELETE,
self::TYPE_WEB,
], true)) {
- throw new \InvalidArgumentException('The given request type is invalid');
+ throw new InvalidValueException('requestType');
}
$this->link = $link;
$this->requestType = $requestType;
@@ -141,30 +91,28 @@ class Action implements IAction {
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getLink(): string {
return $this->link;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getRequestType(): string {
return $this->requestType;
}
/**
- * @return bool
+ * {@inheritDoc}
*/
public function isValid(): bool {
return $this->label !== '' && $this->link !== '';
}
/**
- * @return bool
+ * {@inheritDoc}
*/
public function isValidParsed(): bool {
return $this->labelParsed !== '' && $this->link !== '';
diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php
index 3d77f643d93..7d042e6f8d8 100644
--- a/lib/private/Notification/Manager.php
+++ b/lib/private/Notification/Manager.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Notification;
@@ -35,56 +17,46 @@ use OCP\Notification\IApp;
use OCP\Notification\IDeferrableApp;
use OCP\Notification\IDismissableNotifier;
use OCP\Notification\IManager;
+use OCP\Notification\IncompleteNotificationException;
+use OCP\Notification\IncompleteParsedNotificationException;
use OCP\Notification\INotification;
use OCP\Notification\INotifier;
+use OCP\Notification\UnknownNotificationException;
use OCP\RichObjectStrings\IValidator;
use OCP\Support\Subscription\IRegistry;
use Psr\Container\ContainerExceptionInterface;
use Psr\Log\LoggerInterface;
class Manager implements IManager {
- /** @var IValidator */
- protected $validator;
- /** @var IUserManager */
- private $userManager;
/** @var ICache */
- protected $cache;
- /** @var IRegistry */
- protected $subscription;
- /** @var LoggerInterface */
- protected $logger;
- /** @var Coordinator */
- private $coordinator;
+ protected ICache $cache;
/** @var IApp[] */
- protected $apps;
+ protected array $apps;
/** @var string[] */
- protected $appClasses;
+ protected array $appClasses;
/** @var INotifier[] */
- protected $notifiers;
+ protected array $notifiers;
/** @var string[] */
- protected $notifierClasses;
+ protected array $notifierClasses;
/** @var bool */
- protected $preparingPushNotification;
+ protected bool $preparingPushNotification;
/** @var bool */
- protected $deferPushing;
+ protected bool $deferPushing;
/** @var bool */
- private $parsedRegistrationContext;
-
- public function __construct(IValidator $validator,
- IUserManager $userManager,
- ICacheFactory $cacheFactory,
- IRegistry $subscription,
- LoggerInterface $logger,
- Coordinator $coordinator) {
- $this->validator = $validator;
- $this->userManager = $userManager;
+ private bool $parsedRegistrationContext;
+
+ public function __construct(
+ protected IValidator $validator,
+ private IUserManager $userManager,
+ ICacheFactory $cacheFactory,
+ protected IRegistry $subscription,
+ protected LoggerInterface $logger,
+ private Coordinator $coordinator,
+ ) {
$this->cache = $cacheFactory->createDistributed('notifications');
- $this->subscription = $subscription;
- $this->logger = $logger;
- $this->coordinator = $coordinator;
$this->apps = [];
$this->notifiers = [];
@@ -111,7 +83,7 @@ class Manager implements IManager {
* @deprecated 17.0.0 use registerNotifierService instead.
* @since 8.2.0 - Parameter $info was added in 9.0.0
*/
- public function registerNotifier(\Closure $service, \Closure $info) {
+ public function registerNotifier(\Closure $service, \Closure $info): void {
$infoData = $info();
$exception = new \InvalidArgumentException(
'Notifier ' . $infoData['name'] . ' (id: ' . $infoData['id'] . ') is not considered because it is using the old way to register.'
@@ -313,13 +285,11 @@ class Manager implements IManager {
}
/**
- * @param INotification $notification
- * @throws \InvalidArgumentException When the notification is not valid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function notify(INotification $notification): void {
if (!$notification->isValid()) {
- throw new \InvalidArgumentException('The given notification is invalid');
+ throw new IncompleteNotificationException('The given notification is invalid');
}
$apps = $this->getApps();
@@ -327,7 +297,11 @@ class Manager implements IManager {
foreach ($apps as $app) {
try {
$app->notify($notification);
+ } catch (IncompleteNotificationException) {
} catch (\InvalidArgumentException $e) {
+ // todo 33.0.0 Log as warning
+ // todo 39.0.0 Log as error
+ $this->logger->debug(get_class($app) . '::notify() threw \InvalidArgumentException which is deprecated. Throw \OCP\Notification\IncompleteNotificationException when the notification is incomplete for your app and otherwise handle all \InvalidArgumentException yourself.');
}
}
}
@@ -353,12 +327,7 @@ class Manager implements IManager {
}
/**
- * @param INotification $notification
- * @param string $languageCode The code of the language that should be used to prepare the notification
- * @return INotification
- * @throws \InvalidArgumentException When the notification was not prepared by a notifier
- * @throws AlreadyProcessedException When the notification is not needed anymore and should be deleted
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function prepare(INotification $notification, string $languageCode): INotification {
$notifiers = $this->getNotifiers();
@@ -366,20 +335,44 @@ class Manager implements IManager {
foreach ($notifiers as $notifier) {
try {
$notification = $notifier->prepare($notification, $languageCode);
- } catch (\InvalidArgumentException $e) {
- continue;
} catch (AlreadyProcessedException $e) {
$this->markProcessed($notification);
- throw new \InvalidArgumentException('The given notification has been processed');
+ throw $e;
+ } catch (UnknownNotificationException) {
+ continue;
+ } catch (\InvalidArgumentException $e) {
+ // todo 33.0.0 Log as warning
+ // todo 39.0.0 Log as error
+ $this->logger->debug(get_class($notifier) . '::prepare() threw \InvalidArgumentException which is deprecated. Throw \OCP\Notification\UnknownNotificationException when the notification is not known to your notifier and otherwise handle all \InvalidArgumentException yourself.');
+ continue;
}
if (!$notification->isValidParsed()) {
- throw new \InvalidArgumentException('The given notification has not been handled');
+ $this->logger->info('Notification was claimed to be parsed, but was not fully parsed by ' . get_class($notifier) . ' [app: ' . $notification->getApp() . ', subject: ' . $notification->getSubject() . ']');
+ throw new IncompleteParsedNotificationException();
}
}
if (!$notification->isValidParsed()) {
- throw new \InvalidArgumentException('The given notification has not been handled');
+ $this->logger->info('Notification was not parsed by any notifier [app: ' . $notification->getApp() . ', subject: ' . $notification->getSubject() . ']');
+ throw new IncompleteParsedNotificationException();
+ }
+
+ $link = $notification->getLink();
+ if ($link !== '' && !str_starts_with($link, 'http://') && !str_starts_with($link, 'https://')) {
+ $this->logger->warning('Link of notification is not an absolute URL and does not work in mobile and desktop clients [app: ' . $notification->getApp() . ', subject: ' . $notification->getSubject() . ']');
+ }
+
+ $icon = $notification->getIcon();
+ if ($icon !== '' && !str_starts_with($icon, 'http://') && !str_starts_with($icon, 'https://')) {
+ $this->logger->warning('Icon of notification is not an absolute URL and does not work in mobile and desktop clients [app: ' . $notification->getApp() . ', subject: ' . $notification->getSubject() . ']');
+ }
+
+ foreach ($notification->getParsedActions() as $action) {
+ $link = $action->getLink();
+ if ($link !== '' && !str_starts_with($link, 'http://') && !str_starts_with($link, 'https://')) {
+ $this->logger->warning('Link of action is not an absolute URL and does not work in mobile and desktop clients [app: ' . $notification->getApp() . ', subject: ' . $notification->getSubject() . ']');
+ }
}
return $notification;
@@ -411,6 +404,9 @@ class Manager implements IManager {
return $count;
}
+ /**
+ * {@inheritDoc}
+ */
public function dismissNotification(INotification $notification): void {
$notifiers = $this->getNotifiers();
@@ -418,7 +414,12 @@ class Manager implements IManager {
if ($notifier instanceof IDismissableNotifier) {
try {
$notifier->dismissNotification($notification);
+ } catch (UnknownNotificationException) {
+ continue;
} catch (\InvalidArgumentException $e) {
+ // todo 33.0.0 Log as warning
+ // todo 39.0.0 Log as error
+ $this->logger->debug(get_class($notifier) . '::dismissNotification() threw \InvalidArgumentException which is deprecated. Throw \OCP\Notification\UnknownNotificationException when the notification is not known to your notifier and otherwise handle all \InvalidArgumentException yourself.');
continue;
}
}
diff --git a/lib/private/Notification/Notification.php b/lib/private/Notification/Notification.php
index 2291c4ae34f..19c836c2044 100644
--- a/lib/private/Notification/Notification.php
+++ b/lib/private/Notification/Notification.php
@@ -1,239 +1,139 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Notification;
use OCP\Notification\IAction;
use OCP\Notification\INotification;
+use OCP\Notification\InvalidValueException;
use OCP\RichObjectStrings\InvalidObjectExeption;
use OCP\RichObjectStrings\IValidator;
class Notification implements INotification {
- /** @var IValidator */
- protected $richValidator;
-
- /** @var string */
- protected $app;
-
- /** @var string */
- protected $user;
-
- /** @var \DateTime */
- protected $dateTime;
-
- /** @var string */
- protected $objectType;
-
- /** @var string */
- protected $objectId;
-
- /** @var string */
- protected $subject;
-
- /** @var array */
- protected $subjectParameters;
-
- /** @var string */
- protected $subjectParsed;
-
- /** @var string */
- protected $subjectRich;
-
- /** @var array */
- protected $subjectRichParameters;
-
- /** @var string */
- protected $message;
-
- /** @var array */
- protected $messageParameters;
-
- /** @var string */
- protected $messageParsed;
-
- /** @var string */
- protected $messageRich;
-
- /** @var array */
- protected $messageRichParameters;
-
- /** @var string */
- protected $link;
-
- /** @var string */
- protected $icon;
-
- /** @var array */
- protected $actions;
-
- /** @var array */
- protected $actionsParsed;
-
- /** @var bool */
- protected $hasPrimaryAction;
-
- /** @var bool */
- protected $hasPrimaryParsedAction;
-
- public function __construct(IValidator $richValidator) {
- $this->richValidator = $richValidator;
- $this->app = '';
- $this->user = '';
+ protected string $app = '';
+ protected string $user = '';
+ protected \DateTime $dateTime;
+ protected string $objectType = '';
+ protected string $objectId = '';
+ protected string $subject = '';
+ protected array $subjectParameters = [];
+ protected string $subjectParsed = '';
+ protected string $subjectRich = '';
+ protected array $subjectRichParameters = [];
+ protected string $message = '';
+ protected array $messageParameters = [];
+ protected string $messageParsed = '';
+ protected string $messageRich = '';
+ protected array $messageRichParameters = [];
+ protected string $link = '';
+ protected string $icon = '';
+ protected array $actions = [];
+ protected array $actionsParsed = [];
+ protected bool $hasPrimaryAction = false;
+ protected bool $hasPrimaryParsedAction = false;
+
+ public function __construct(
+ protected IValidator $richValidator,
+ ) {
$this->dateTime = new \DateTime();
$this->dateTime->setTimestamp(0);
- $this->objectType = '';
- $this->objectId = '';
- $this->subject = '';
- $this->subjectParameters = [];
- $this->subjectParsed = '';
- $this->subjectRich = '';
- $this->subjectRichParameters = [];
- $this->message = '';
- $this->messageParameters = [];
- $this->messageParsed = '';
- $this->messageRich = '';
- $this->messageRichParameters = [];
- $this->link = '';
- $this->icon = '';
- $this->actions = [];
- $this->actionsParsed = [];
- }
-
- /**
- * @param string $app
- * @return $this
- * @throws \InvalidArgumentException if the app id is invalid
- * @since 8.2.0
+ }
+
+ /**
+ * {@inheritDoc}
*/
public function setApp(string $app): INotification {
if ($app === '' || isset($app[32])) {
- throw new \InvalidArgumentException('The given app name is invalid');
+ throw new InvalidValueException('app');
}
$this->app = $app;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getApp(): string {
return $this->app;
}
/**
- * @param string $user
- * @return $this
- * @throws \InvalidArgumentException if the user id is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setUser(string $user): INotification {
if ($user === '' || isset($user[64])) {
- throw new \InvalidArgumentException('The given user id is invalid');
+ throw new InvalidValueException('user');
}
$this->user = $user;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getUser(): string {
return $this->user;
}
/**
- * @param \DateTime $dateTime
- * @return $this
- * @throws \InvalidArgumentException if the $dateTime is invalid
- * @since 9.0.0
+ * {@inheritDoc}
*/
public function setDateTime(\DateTime $dateTime): INotification {
if ($dateTime->getTimestamp() === 0) {
- throw new \InvalidArgumentException('The given date time is invalid');
+ throw new InvalidValueException('dateTime');
}
$this->dateTime = $dateTime;
return $this;
}
/**
- * @return \DateTime
- * @since 9.0.0
+ * {@inheritDoc}
*/
public function getDateTime(): \DateTime {
return $this->dateTime;
}
/**
- * @param string $type
- * @param string $id
- * @return $this
- * @throws \InvalidArgumentException if the object type or id is invalid
- * @since 8.2.0 - 9.0.0: Type of $id changed to string
+ * {@inheritDoc}
*/
public function setObject(string $type, string $id): INotification {
if ($type === '' || isset($type[64])) {
- throw new \InvalidArgumentException('The given object type is invalid');
+ throw new InvalidValueException('objectType');
}
$this->objectType = $type;
if ($id === '' || isset($id[64])) {
- throw new \InvalidArgumentException('The given object id is invalid');
+ throw new InvalidValueException('objectId');
}
$this->objectId = $id;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getObjectType(): string {
return $this->objectType;
}
/**
- * @return string
- * @since 8.2.0 - 9.0.0: Return type changed to string
+ * {@inheritDoc}
*/
public function getObjectId(): string {
return $this->objectId;
}
/**
- * @param string $subject
- * @param array $parameters
- * @return $this
- * @throws \InvalidArgumentException if the subject or parameters are invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setSubject(string $subject, array $parameters = []): INotification {
if ($subject === '' || isset($subject[64])) {
- throw new \InvalidArgumentException('The given subject is invalid');
+ throw new InvalidValueException('subject');
}
$this->subject = $subject;
@@ -243,60 +143,54 @@ class Notification implements INotification {
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getSubject(): string {
return $this->subject;
}
/**
- * @return array
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getSubjectParameters(): array {
return $this->subjectParameters;
}
/**
- * @param string $subject
- * @return $this
- * @throws \InvalidArgumentException if the subject is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setParsedSubject(string $subject): INotification {
if ($subject === '') {
- throw new \InvalidArgumentException('The given parsed subject is invalid');
+ throw new InvalidValueException('parsedSubject');
}
$this->subjectParsed = $subject;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getParsedSubject(): string {
return $this->subjectParsed;
}
/**
- * @param string $subject
- * @param array $parameters
- * @return $this
- * @throws \InvalidArgumentException if the subject or parameters are invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setRichSubject(string $subject, array $parameters = []): INotification {
if ($subject === '') {
- throw new \InvalidArgumentException('The given parsed subject is invalid');
+ throw new InvalidValueException('richSubject');
}
$this->subjectRich = $subject;
$this->subjectRichParameters = $parameters;
if ($this->subjectParsed === '') {
- $this->subjectParsed = $this->richToParsed($subject, $parameters);
+ try {
+ $this->subjectParsed = $this->richToParsed($subject, $parameters);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidValueException('richSubjectParameters', $e);
+ }
}
return $this;
@@ -327,31 +221,25 @@ class Notification implements INotification {
}
/**
- * @return string
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getRichSubject(): string {
return $this->subjectRich;
}
/**
- * @return array[]
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getRichSubjectParameters(): array {
return $this->subjectRichParameters;
}
/**
- * @param string $message
- * @param array $parameters
- * @return $this
- * @throws \InvalidArgumentException if the message or parameters are invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setMessage(string $message, array $parameters = []): INotification {
if ($message === '' || isset($message[64])) {
- throw new \InvalidArgumentException('The given message is invalid');
+ throw new InvalidValueException('message');
}
$this->message = $message;
@@ -361,147 +249,127 @@ class Notification implements INotification {
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getMessage(): string {
return $this->message;
}
/**
- * @return array
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getMessageParameters(): array {
return $this->messageParameters;
}
/**
- * @param string $message
- * @return $this
- * @throws \InvalidArgumentException if the message is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setParsedMessage(string $message): INotification {
if ($message === '') {
- throw new \InvalidArgumentException('The given parsed message is invalid');
+ throw new InvalidValueException('parsedMessage');
}
$this->messageParsed = $message;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getParsedMessage(): string {
return $this->messageParsed;
}
/**
- * @param string $message
- * @param array $parameters
- * @return $this
- * @throws \InvalidArgumentException if the message or parameters are invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setRichMessage(string $message, array $parameters = []): INotification {
if ($message === '') {
- throw new \InvalidArgumentException('The given parsed message is invalid');
+ throw new InvalidValueException('richMessage');
}
$this->messageRich = $message;
$this->messageRichParameters = $parameters;
if ($this->messageParsed === '') {
- $this->messageParsed = $this->richToParsed($message, $parameters);
+ try {
+ $this->messageParsed = $this->richToParsed($message, $parameters);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidValueException('richMessageParameters', $e);
+ }
}
return $this;
}
/**
- * @return string
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getRichMessage(): string {
return $this->messageRich;
}
/**
- * @return array[]
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getRichMessageParameters(): array {
return $this->messageRichParameters;
}
/**
- * @param string $link
- * @return $this
- * @throws \InvalidArgumentException if the link is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function setLink(string $link): INotification {
if ($link === '' || isset($link[4000])) {
- throw new \InvalidArgumentException('The given link is invalid');
+ throw new InvalidValueException('link');
}
$this->link = $link;
return $this;
}
/**
- * @return string
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getLink(): string {
return $this->link;
}
/**
- * @param string $icon
- * @return $this
- * @throws \InvalidArgumentException if the icon is invalid
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function setIcon(string $icon): INotification {
if ($icon === '' || isset($icon[4000])) {
- throw new \InvalidArgumentException('The given icon is invalid');
+ throw new InvalidValueException('icon');
}
$this->icon = $icon;
return $this;
}
/**
- * @return string
- * @since 11.0.0
+ * {@inheritDoc}
*/
public function getIcon(): string {
return $this->icon;
}
/**
- * @return IAction
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function createAction(): IAction {
return new Action();
}
/**
- * @param IAction $action
- * @return $this
- * @throws \InvalidArgumentException if the action is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function addAction(IAction $action): INotification {
if (!$action->isValid()) {
- throw new \InvalidArgumentException('The given action is invalid');
+ throw new InvalidValueException('action');
}
if ($action->isPrimary()) {
if ($this->hasPrimaryAction) {
- throw new \InvalidArgumentException('The notification already has a primary action');
+ throw new InvalidValueException('primaryAction');
}
$this->hasPrimaryAction = true;
@@ -512,27 +380,23 @@ class Notification implements INotification {
}
/**
- * @return IAction[]
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getActions(): array {
return $this->actions;
}
/**
- * @param IAction $action
- * @return $this
- * @throws \InvalidArgumentException if the action is invalid
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function addParsedAction(IAction $action): INotification {
if (!$action->isValidParsed()) {
- throw new \InvalidArgumentException('The given parsed action is invalid');
+ throw new InvalidValueException('action');
}
if ($action->isPrimary()) {
if ($this->hasPrimaryParsedAction) {
- throw new \InvalidArgumentException('The notification already has a primary action');
+ throw new InvalidValueException('primaryAction');
}
$this->hasPrimaryParsedAction = true;
@@ -547,16 +411,14 @@ class Notification implements INotification {
}
/**
- * @return IAction[]
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function getParsedActions(): array {
return $this->actionsParsed;
}
/**
- * @return bool
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function isValid(): bool {
return
@@ -567,8 +429,7 @@ class Notification implements INotification {
}
/**
- * @return bool
- * @since 8.2.0
+ * {@inheritDoc}
*/
public function isValidParsed(): bool {
if ($this->getRichSubject() !== '' || !empty($this->getRichSubjectParameters())) {
diff --git a/lib/private/OCM/Model/OCMProvider.php b/lib/private/OCM/Model/OCMProvider.php
new file mode 100644
index 00000000000..17a356428f7
--- /dev/null
+++ b/lib/private/OCM/Model/OCMProvider.php
@@ -0,0 +1,217 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\OCM\Model;
+
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\OCM\Events\ResourceTypeRegisterEvent;
+use OCP\OCM\Exceptions\OCMArgumentException;
+use OCP\OCM\Exceptions\OCMProviderException;
+use OCP\OCM\IOCMProvider;
+use OCP\OCM\IOCMResource;
+
+/**
+ * @since 28.0.0
+ */
+class OCMProvider implements IOCMProvider {
+ private bool $enabled = false;
+ private string $apiVersion = '';
+ private string $endPoint = '';
+ /** @var IOCMResource[] */
+ private array $resourceTypes = [];
+
+ private bool $emittedEvent = false;
+
+ public function __construct(
+ protected IEventDispatcher $dispatcher,
+ ) {
+ }
+
+ /**
+ * @param bool $enabled
+ *
+ * @return $this
+ */
+ public function setEnabled(bool $enabled): static {
+ $this->enabled = $enabled;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isEnabled(): bool {
+ return $this->enabled;
+ }
+
+ /**
+ * @param string $apiVersion
+ *
+ * @return $this
+ */
+ public function setApiVersion(string $apiVersion): static {
+ $this->apiVersion = $apiVersion;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getApiVersion(): string {
+ return $this->apiVersion;
+ }
+
+ /**
+ * @param string $endPoint
+ *
+ * @return $this
+ */
+ public function setEndPoint(string $endPoint): static {
+ $this->endPoint = $endPoint;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getEndPoint(): string {
+ return $this->endPoint;
+ }
+
+ /**
+ * create a new resource to later add it with {@see IOCMProvider::addResourceType()}
+ * @return IOCMResource
+ */
+ public function createNewResourceType(): IOCMResource {
+ return new OCMResource();
+ }
+
+ /**
+ * @param IOCMResource $resource
+ *
+ * @return $this
+ */
+ public function addResourceType(IOCMResource $resource): static {
+ $this->resourceTypes[] = $resource;
+
+ return $this;
+ }
+
+ /**
+ * @param IOCMResource[] $resourceTypes
+ *
+ * @return $this
+ */
+ public function setResourceTypes(array $resourceTypes): static {
+ $this->resourceTypes = $resourceTypes;
+
+ return $this;
+ }
+
+ /**
+ * @return IOCMResource[]
+ */
+ public function getResourceTypes(): array {
+ if (!$this->emittedEvent) {
+ $this->emittedEvent = true;
+ $event = new ResourceTypeRegisterEvent($this);
+ $this->dispatcher->dispatchTyped($event);
+ }
+
+ return $this->resourceTypes;
+ }
+
+ /**
+ * @param string $resourceName
+ * @param string $protocol
+ *
+ * @return string
+ * @throws OCMArgumentException
+ */
+ public function extractProtocolEntry(string $resourceName, string $protocol): string {
+ foreach ($this->getResourceTypes() as $resource) {
+ if ($resource->getName() === $resourceName) {
+ $entry = $resource->getProtocols()[$protocol] ?? null;
+ if (is_null($entry)) {
+ throw new OCMArgumentException('protocol not found');
+ }
+
+ return (string)$entry;
+ }
+ }
+
+ throw new OCMArgumentException('resource not found');
+ }
+
+ /**
+ * import data from an array
+ *
+ * @param array $data
+ *
+ * @return $this
+ * @throws OCMProviderException in case a descent provider cannot be generated from data
+ * @see self::jsonSerialize()
+ */
+ public function import(array $data): static {
+ $this->setEnabled(is_bool($data['enabled'] ?? '') ? $data['enabled'] : false)
+ ->setApiVersion((string)($data['apiVersion'] ?? ''))
+ ->setEndPoint($data['endPoint'] ?? '');
+
+ $resources = [];
+ foreach (($data['resourceTypes'] ?? []) as $resourceData) {
+ $resource = new OCMResource();
+ $resources[] = $resource->import($resourceData);
+ }
+ $this->setResourceTypes($resources);
+
+ if (!$this->looksValid()) {
+ throw new OCMProviderException('remote provider does not look valid');
+ }
+
+ return $this;
+ }
+
+
+ /**
+ * @return bool
+ */
+ private function looksValid(): bool {
+ return ($this->getApiVersion() !== '' && $this->getEndPoint() !== '');
+ }
+
+
+ /**
+ * @return array{
+ * enabled: bool,
+ * apiVersion: string,
+ * endPoint: string,
+ * resourceTypes: array{
+ * name: string,
+ * shareTypes: string[],
+ * protocols: array<string, string>
+ * }[]
+ * }
+ */
+ public function jsonSerialize(): array {
+ $resourceTypes = [];
+ foreach ($this->getResourceTypes() as $res) {
+ $resourceTypes[] = $res->jsonSerialize();
+ }
+
+ return [
+ 'enabled' => $this->isEnabled(),
+ 'apiVersion' => $this->getApiVersion(),
+ 'endPoint' => $this->getEndPoint(),
+ 'resourceTypes' => $resourceTypes
+ ];
+ }
+}
diff --git a/lib/private/OCM/Model/OCMResource.php b/lib/private/OCM/Model/OCMResource.php
new file mode 100644
index 00000000000..c69763ca4ba
--- /dev/null
+++ b/lib/private/OCM/Model/OCMResource.php
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\OCM\Model;
+
+use OCP\OCM\IOCMResource;
+
+/**
+ * @since 28.0.0
+ */
+class OCMResource implements IOCMResource {
+ private string $name = '';
+ /** @var string[] */
+ private array $shareTypes = [];
+ /** @var array<string, string> */
+ private array $protocols = [];
+
+ /**
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function setName(string $name): static {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName(): string {
+ return $this->name;
+ }
+
+ /**
+ * @param string[] $shareTypes
+ *
+ * @return $this
+ */
+ public function setShareTypes(array $shareTypes): static {
+ $this->shareTypes = $shareTypes;
+
+ return $this;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getShareTypes(): array {
+ return $this->shareTypes;
+ }
+
+ /**
+ * @param array<string, string> $protocols
+ *
+ * @return $this
+ */
+ public function setProtocols(array $protocols): static {
+ $this->protocols = $protocols;
+
+ return $this;
+ }
+
+ /**
+ * @return array<string, string>
+ */
+ public function getProtocols(): array {
+ return $this->protocols;
+ }
+
+ /**
+ * import data from an array
+ *
+ * @param array $data
+ *
+ * @return $this
+ * @see self::jsonSerialize()
+ */
+ public function import(array $data): static {
+ return $this->setName((string)($data['name'] ?? ''))
+ ->setShareTypes($data['shareTypes'] ?? [])
+ ->setProtocols($data['protocols'] ?? []);
+ }
+
+ /**
+ * @return array{
+ * name: string,
+ * shareTypes: string[],
+ * protocols: array<string, string>
+ * }
+ */
+ public function jsonSerialize(): array {
+ return [
+ 'name' => $this->getName(),
+ 'shareTypes' => $this->getShareTypes(),
+ 'protocols' => $this->getProtocols()
+ ];
+ }
+}
diff --git a/lib/private/OCM/OCMDiscoveryService.php b/lib/private/OCM/OCMDiscoveryService.php
new file mode 100644
index 00000000000..62313a9af80
--- /dev/null
+++ b/lib/private/OCM/OCMDiscoveryService.php
@@ -0,0 +1,120 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\OCM;
+
+use JsonException;
+use OCP\AppFramework\Http;
+use OCP\Http\Client\IClientService;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+use OCP\OCM\Exceptions\OCMProviderException;
+use OCP\OCM\IOCMDiscoveryService;
+use OCP\OCM\IOCMProvider;
+use Psr\Log\LoggerInterface;
+
+/**
+ * @since 28.0.0
+ */
+class OCMDiscoveryService implements IOCMDiscoveryService {
+ private ICache $cache;
+ private array $supportedAPIVersion =
+ [
+ '1.0-proposal1',
+ '1.0',
+ '1.1'
+ ];
+
+ public function __construct(
+ ICacheFactory $cacheFactory,
+ private IClientService $clientService,
+ private IConfig $config,
+ private IOCMProvider $provider,
+ private LoggerInterface $logger,
+ ) {
+ $this->cache = $cacheFactory->createDistributed('ocm-discovery');
+ }
+
+
+ /**
+ * @param string $remote
+ * @param bool $skipCache
+ *
+ * @return IOCMProvider
+ * @throws OCMProviderException
+ */
+ public function discover(string $remote, bool $skipCache = false): IOCMProvider {
+ $remote = rtrim($remote, '/');
+
+ if (!$skipCache) {
+ try {
+ $this->provider->import(json_decode($this->cache->get($remote) ?? '', true, 8, JSON_THROW_ON_ERROR) ?? []);
+ if ($this->supportedAPIVersion($this->provider->getApiVersion())) {
+ return $this->provider; // if cache looks valid, we use it
+ }
+ } catch (JsonException|OCMProviderException $e) {
+ // we ignore cache on issues
+ }
+ }
+
+ $client = $this->clientService->newClient();
+ try {
+ $response = $client->get(
+ $remote . '/ocm-provider/',
+ [
+ 'timeout' => 10,
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates'),
+ 'connect_timeout' => 10,
+ ]
+ );
+
+ if ($response->getStatusCode() === Http::STATUS_OK) {
+ $body = $response->getBody();
+ // update provider with data returned by the request
+ $this->provider->import(json_decode($body, true, 8, JSON_THROW_ON_ERROR) ?? []);
+ $this->cache->set($remote, $body, 60 * 60 * 24);
+ }
+ } catch (JsonException|OCMProviderException $e) {
+ throw new OCMProviderException('data returned by remote seems invalid - ' . ($body ?? ''));
+ } catch (\Exception $e) {
+ $this->logger->warning('error while discovering ocm provider', [
+ 'exception' => $e,
+ 'remote' => $remote
+ ]);
+ throw new OCMProviderException('error while requesting remote ocm provider');
+ }
+
+ if (!$this->supportedAPIVersion($this->provider->getApiVersion())) {
+ throw new OCMProviderException('API version not supported');
+ }
+
+ return $this->provider;
+ }
+
+ /**
+ * Check the version from remote is supported.
+ * The minor version of the API will be ignored:
+ * 1.0.1 is identified as 1.0
+ *
+ * @param string $version
+ *
+ * @return bool
+ */
+ private function supportedAPIVersion(string $version): bool {
+ $dot1 = strpos($version, '.');
+ $dot2 = strpos($version, '.', $dot1 + 1);
+
+ if ($dot2 > 0) {
+ $version = substr($version, 0, $dot2);
+ }
+
+ return (in_array($version, $this->supportedAPIVersion));
+ }
+}
diff --git a/lib/private/OCS/CoreCapabilities.php b/lib/private/OCS/CoreCapabilities.php
index 9cead57c6a3..3d988a8662e 100644
--- a/lib/private/OCS/CoreCapabilities.php
+++ b/lib/private/OCS/CoreCapabilities.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\OCS;
@@ -32,26 +17,35 @@ use OCP\IURLGenerator;
* @package OC\OCS
*/
class CoreCapabilities implements ICapability {
- /** @var IConfig */
- private $config;
-
/**
* @param IConfig $config
*/
- public function __construct(IConfig $config) {
- $this->config = $config;
+ public function __construct(
+ private IConfig $config,
+ ) {
}
/**
* Return this classes capabilities
+ *
+ * @return array{
+ * core: array{
+ * pollinterval: int,
+ * webdav-root: string,
+ * reference-api: boolean,
+ * reference-regex: string,
+ * mod-rewrite-working: boolean,
+ * },
+ * }
*/
- public function getCapabilities() {
+ public function getCapabilities(): array {
return [
'core' => [
- 'pollinterval' => $this->config->getSystemValue('pollinterval', 60),
- 'webdav-root' => $this->config->getSystemValue('webdav-root', 'remote.php/webdav'),
+ 'pollinterval' => $this->config->getSystemValueInt('pollinterval', 60),
+ 'webdav-root' => $this->config->getSystemValueString('webdav-root', 'remote.php/webdav'),
'reference-api' => true,
'reference-regex' => IURLGenerator::URL_REGEX_NO_MODIFIERS,
+ 'mod-rewrite-working' => $this->config->getSystemValueBool('htaccess.IgnoreFrontController') || getenv('front_controller_active') === 'true',
],
];
}
diff --git a/lib/private/OCS/DiscoveryService.php b/lib/private/OCS/DiscoveryService.php
index 8f98ff7d5ae..fc9c1bd4796 100644
--- a/lib/private/OCS/DiscoveryService.php
+++ b/lib/private/OCS/DiscoveryService.php
@@ -3,28 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\OCS;
@@ -37,17 +17,17 @@ use OCP\OCS\IDiscoveryService;
class DiscoveryService implements IDiscoveryService {
/** @var ICache */
- private $cache;
+ private ICache $cache;
/** @var IClient */
- private $client;
+ private IClient $client;
/**
* @param ICacheFactory $cacheFactory
* @param IClientService $clientService
*/
public function __construct(ICacheFactory $cacheFactory,
- IClientService $clientService
+ IClientService $clientService
) {
$this->cache = $cacheFactory->createDistributed('ocs-discovery');
$this->client = $clientService->newClient();
diff --git a/lib/private/OCS/Exception.php b/lib/private/OCS/Exception.php
index ca3c3f70430..eca8ec26df0 100644
--- a/lib/private/OCS/Exception.php
+++ b/lib/private/OCS/Exception.php
@@ -1,37 +1,19 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\OCS;
class Exception extends \Exception {
- /** @var Result */
- private $result;
-
- public function __construct(Result $result) {
+ public function __construct(
+ private Result $result,
+ ) {
parent::__construct();
- $this->result = $result;
}
- public function getResult() {
+ public function getResult(): Result {
return $this->result;
}
}
diff --git a/lib/private/OCS/Provider.php b/lib/private/OCS/Provider.php
index 5e7a86a1341..23547da9433 100644
--- a/lib/private/OCS/Provider.php
+++ b/lib/private/OCS/Provider.php
@@ -1,49 +1,33 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\OCS;
-class Provider extends \OCP\AppFramework\Controller {
- /** @var \OCP\App\IAppManager */
- private $appManager;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\IRequest;
+class Provider extends Controller {
/**
* @param string $appName
- * @param \OCP\IRequest $request
- * @param \OCP\App\IAppManager $appManager
+ * @param IRequest $request
+ * @param IAppManager $appManager
*/
public function __construct($appName,
- \OCP\IRequest $request,
- \OCP\App\IAppManager $appManager) {
+ \OCP\IRequest $request,
+ private \OCP\App\IAppManager $appManager) {
parent::__construct($appName, $request);
- $this->appManager = $appManager;
}
/**
- * @return \OCP\AppFramework\Http\JSONResponse
+ * @return JSONResponse
*/
- public function buildProviderList() {
+ public function buildProviderList(): JSONResponse {
$services = [
'PRIVATE_DATA' => [
'version' => 1,
@@ -108,7 +92,7 @@ class Provider extends \OCP\AppFramework\Controller {
];
}
- return new \OCP\AppFramework\Http\JSONResponse([
+ return new JSONResponse([
'version' => 2,
'services' => $services,
]);
diff --git a/lib/private/OCS/Result.php b/lib/private/OCS/Result.php
index d77e360e6d2..5460a8b275c 100644
--- a/lib/private/OCS/Result.php
+++ b/lib/private/OCS/Result.php
@@ -1,44 +1,20 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tom Needham <tom@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\OCS;
class Result {
- /** @var array */
- protected $data;
+ protected array $data;
/** @var null|string */
- protected $message;
+ protected ?string $message;
/** @var int */
- protected $statusCode;
+ protected int $statusCode;
/** @var integer */
protected $items;
@@ -47,16 +23,17 @@ class Result {
protected $perPage;
/** @var array */
- private $headers = [];
+ private array $headers = [];
/**
* create the OCS_Result object
- * @param mixed $data the data to return
+ *
+ * @param mixed|null $data the data to return
* @param int $code
- * @param null|string $message
+ * @param string|null $message
* @param array $headers
*/
- public function __construct($data = null, $code = 100, $message = null, $headers = []) {
+ public function __construct(mixed $data = null, int $code = 100, ?string $message = null, array $headers = []) {
if ($data === null) {
$this->data = [];
} elseif (!is_array($data)) {
@@ -71,17 +48,19 @@ class Result {
/**
* optionally set the total number of items available
+ *
* @param int $items
*/
- public function setTotalItems($items) {
+ public function setTotalItems(int $items): void {
$this->items = $items;
}
/**
- * optionally set the the number of items per page
+ * optionally set the number of items per page
+ *
* @param int $items
*/
- public function setItemsPerPage($items) {
+ public function setItemsPerPage(int $items): void {
$this->perPage = $items;
}
@@ -89,7 +68,7 @@ class Result {
* get the status code
* @return int
*/
- public function getStatusCode() {
+ public function getStatusCode(): int {
return $this->statusCode;
}
@@ -97,7 +76,7 @@ class Result {
* get the meta data for the result
* @return array
*/
- public function getMeta() {
+ public function getMeta(): array {
$meta = [];
$meta['status'] = $this->succeeded() ? 'ok' : 'failure';
$meta['statuscode'] = $this->statusCode;
@@ -115,7 +94,7 @@ class Result {
* get the result data
* @return array
*/
- public function getData() {
+ public function getData(): array {
return $this->data;
}
@@ -123,17 +102,18 @@ class Result {
* return bool Whether the method succeeded
* @return bool
*/
- public function succeeded() {
+ public function succeeded(): bool {
return ($this->statusCode == 100);
}
/**
* Adds a new header to the response
+ *
* @param string $name The name of the HTTP header
* @param string $value The value, null will delete it
* @return $this
*/
- public function addHeader($name, $value) {
+ public function addHeader(string $name, ?string $value): static {
$name = trim($name); // always remove leading and trailing whitespace
// to be able to reliably check for security
// headers
@@ -151,7 +131,7 @@ class Result {
* Returns the set headers
* @return array the headers
*/
- public function getHeaders() {
+ public function getHeaders(): array {
return $this->headers;
}
}
diff --git a/lib/private/PhoneNumberUtil.php b/lib/private/PhoneNumberUtil.php
new file mode 100644
index 00000000000..e53c7a51a1b
--- /dev/null
+++ b/lib/private/PhoneNumberUtil.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC;
+
+use libphonenumber\NumberParseException;
+use libphonenumber\PhoneNumberFormat;
+use OCP\IPhoneNumberUtil;
+
+/**
+ * @since 28.0.0
+ */
+class PhoneNumberUtil implements IPhoneNumberUtil {
+ /**
+ * {@inheritDoc}
+ */
+ public function getCountryCodeForRegion(string $regionCode): ?int {
+ $phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
+ $countryCode = $phoneUtil->getCountryCodeForRegion($regionCode);
+ return $countryCode === 0 ? null : $countryCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function convertToStandardFormat(string $input, ?string $defaultRegion = null): ?string {
+ $phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
+ try {
+ $phoneNumber = $phoneUtil->parse($input, $defaultRegion);
+ if ($phoneUtil->isValidNumber($phoneNumber)) {
+ return $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
+ }
+ } catch (NumberParseException) {
+ }
+
+ return null;
+ }
+}
diff --git a/lib/private/Preview/BMP.php b/lib/private/Preview/BMP.php
index c429f31f0e2..f275aecf0cf 100644
--- a/lib/private/Preview/BMP.php
+++ b/lib/private/Preview/BMP.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/BackgroundCleanupJob.php b/lib/private/Preview/BackgroundCleanupJob.php
index 4eba96d1a82..49ff01486a3 100644
--- a/lib/private/Preview/BackgroundCleanupJob.php
+++ b/lib/private/Preview/BackgroundCleanupJob.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -48,10 +31,10 @@ class BackgroundCleanupJob extends TimedJob {
private $mimeTypeLoader;
public function __construct(ITimeFactory $timeFactory,
- IDBConnection $connection,
- Root $previewFolder,
- IMimeTypeLoader $mimeTypeLoader,
- bool $isCLI) {
+ IDBConnection $connection,
+ Root $previewFolder,
+ IMimeTypeLoader $mimeTypeLoader,
+ bool $isCLI) {
parent::__construct($timeFactory);
// Run at most once an hour
$this->setInterval(3600);
diff --git a/lib/private/Preview/Bitmap.php b/lib/private/Preview/Bitmap.php
index 84c7b4a8968..c9fad50841f 100644
--- a/lib/private/Preview/Bitmap.php
+++ b/lib/private/Preview/Bitmap.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -38,6 +19,18 @@ use Psr\Log\LoggerInterface;
*/
abstract class Bitmap extends ProviderV2 {
/**
+ * List of MIME types that this preview provider is allowed to process.
+ *
+ * These should correspond to the MIME types *identified* by Imagemagick
+ * for files to be processed by this provider. These do / will not
+ * necessarily need to match the MIME types stored in the database
+ * (which are identified by IMimeTypeDetector).
+ *
+ * @return string Regular expression
+ */
+ abstract protected function getAllowedMimeTypes(): string;
+
+ /**
* {@inheritDoc}
*/
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
@@ -86,10 +79,19 @@ abstract class Bitmap extends ProviderV2 {
* @param int $maxY
*
* @return \Imagick
+ *
+ * @throws \Exception
*/
private function getResizedPreview($tmpPath, $maxX, $maxY) {
$bp = new Imagick();
+ // Validate mime type
+ $bp->pingImage($tmpPath . '[0]');
+ $mimeType = $bp->getImageMimeType();
+ if (!preg_match($this->getAllowedMimeTypes(), $mimeType)) {
+ throw new \Exception('File mime type does not match the preview provider: ' . $mimeType);
+ }
+
// Layer 0 contains either the bitmap or a flat representation of all vector layers
$bp->readImage($tmpPath . '[0]');
diff --git a/lib/private/Preview/Bundled.php b/lib/private/Preview/Bundled.php
index 2a408b90c4e..836dc4bd357 100644
--- a/lib/private/Preview/Bundled.php
+++ b/lib/private/Preview/Bundled.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/EMF.php b/lib/private/Preview/EMF.php
new file mode 100644
index 00000000000..a3c48e7d8aa
--- /dev/null
+++ b/lib/private/Preview/EMF.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Preview;
+
+class EMF extends Office {
+ public function getMimeType(): string {
+ return '/image\/emf/';
+ }
+}
diff --git a/lib/private/Preview/Font.php b/lib/private/Preview/Font.php
index baf29e1defc..79e537f6ffb 100644
--- a/lib/private/Preview/Font.php
+++ b/lib/private/Preview/Font.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -30,4 +15,11 @@ class Font extends Bitmap {
public function getMimeType(): string {
return '/application\/(?:font-sfnt|x-font$)/';
}
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/(application|image)\/(?:font-sfnt|x-font|x-otf|x-ttf|x-pfb$)/';
+ }
}
diff --git a/lib/private/Preview/GIF.php b/lib/private/Preview/GIF.php
index 482f014e3dc..941ef68648a 100644
--- a/lib/private/Preview/GIF.php
+++ b/lib/private/Preview/GIF.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php
index 4e4571f0857..4083b9f4f61 100644
--- a/lib/private/Preview/Generator.php
+++ b/lib/private/Preview/Generator.php
@@ -1,31 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Elijah Martin-Merrill <elijah@nyp-itsours.com>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Scott Dutton <scott@exussum.co.uk>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -139,23 +115,6 @@ class Generator {
$previewVersion = $file->getPreviewVersion() . '-';
}
- // If imaginary is enabled, and we request a small thumbnail,
- // let's not generate the max preview for performance reasons
- if (count($specifications) === 1
- && ($specifications[0]['width'] <= 256 || $specifications[0]['height'] <= 256)
- && preg_match(Imaginary::supportedMimeTypes(), $mimeType)
- && $this->config->getSystemValueString('preview_imaginary_url', 'invalid') !== 'invalid') {
- $crop = $specifications[0]['crop'] ?? false;
- $preview = $this->getSmallImagePreview($previewFolder, $previewFiles, $file, $mimeType, $previewVersion, $crop);
-
- if ($preview->getSize() === 0) {
- $preview->delete();
- throw new NotFoundException('Cached preview size 0, invalid!');
- }
-
- return $preview;
- }
-
// Get the max preview and infer the max preview sizes from that
$maxPreview = $this->getMaxPreview($previewFolder, $previewFiles, $file, $mimeType, $previewVersion);
$maxPreviewImage = null; // only load the image when we need it
@@ -232,32 +191,13 @@ class Generator {
}
/**
- * Generate a small image straight away without generating a max preview first
- * Preview generated is 256x256
- *
- * @param ISimpleFile[] $previewFiles
- *
- * @throws NotFoundException
- */
- private function getSmallImagePreview(ISimpleFolder $previewFolder, array $previewFiles, File $file, string $mimeType, string $prefix, bool $crop): ISimpleFile {
- $width = 256;
- $height = 256;
-
- try {
- return $this->getCachedPreview($previewFiles, $width, $height, $crop, $mimeType, $prefix);
- } catch (NotFoundException $e) {
- return $this->generateProviderPreview($previewFolder, $file, $width, $height, $crop, false, $mimeType, $prefix);
- }
- }
-
- /**
* Acquire a semaphore of the specified id and concurrency, blocking if necessary.
* Return an identifier of the semaphore on success, which can be used to release it via
* {@see Generator::unguardWithSemaphore()}.
*
* @param int $semId
* @param int $concurrency
- * @return false|resource the semaphore on success or false on failure
+ * @return false|\SysvSemaphore the semaphore on success or false on failure
*/
public static function guardWithSemaphore(int $semId, int $concurrency) {
if (!extension_loaded('sysvsem')) {
@@ -276,11 +216,11 @@ class Generator {
/**
* Releases the semaphore acquired from {@see Generator::guardWithSemaphore()}.
*
- * @param resource|bool $semId the semaphore identifier returned by guardWithSemaphore
+ * @param false|\SysvSemaphore $semId the semaphore identifier returned by guardWithSemaphore
* @return bool
*/
- public static function unguardWithSemaphore($semId): bool {
- if (!is_resource($semId) || !extension_loaded('sysvsem')) {
+ public static function unguardWithSemaphore(false|\SysvSemaphore $semId): bool {
+ if ($semId === false || !($semId instanceof \SysvSemaphore)) {
return false;
}
return sem_release($semId);
@@ -293,9 +233,15 @@ class Generator {
*/
public static function getHardwareConcurrency(): int {
static $width;
+
if (!isset($width)) {
- if (is_file("/proc/cpuinfo")) {
- $width = substr_count(file_get_contents("/proc/cpuinfo"), "processor");
+ if (function_exists('ini_get')) {
+ $openBasedir = ini_get('open_basedir');
+ if (empty($openBasedir) || strpos($openBasedir, '/proc/cpuinfo') !== false) {
+ $width = is_readable('/proc/cpuinfo') ? substr_count(file_get_contents('/proc/cpuinfo'), 'processor') : 0;
+ } else {
+ $width = 0;
+ }
} else {
$width = 0;
}
@@ -319,7 +265,7 @@ class Generator {
* @return int number of concurrent preview generations, or -1 if $type is invalid
*/
public function getNumConcurrentPreviews(string $type): int {
- static $cached = array();
+ static $cached = [];
if (array_key_exists($type, $cached)) {
return $cached[$type];
}
@@ -651,6 +597,8 @@ class Generator {
return 'png';
case 'image/jpeg':
return 'jpg';
+ case 'image/webp':
+ return 'webp';
case 'image/gif':
return 'gif';
default:
diff --git a/lib/private/Preview/GeneratorHelper.php b/lib/private/Preview/GeneratorHelper.php
index 64714a9f899..5f43c94b624 100644
--- a/lib/private/Preview/GeneratorHelper.php
+++ b/lib/private/Preview/GeneratorHelper.php
@@ -1,27 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/HEIC.php b/lib/private/Preview/HEIC.php
index 71df98f9ac6..d198f11fdef 100644
--- a/lib/private/Preview/HEIC.php
+++ b/lib/private/Preview/HEIC.php
@@ -3,29 +3,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018, ownCloud GmbH
- * @copyright Copyright (c) 2018, Sebastian Steinmetz (me@sebastiansteinmetz.ch)
- *
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sebastian Steinmetz <462714+steiny2k@users.noreply.github.com>
- * @author Sebastian Steinmetz <me@sebastiansteinmetz.ch>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2018 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -44,7 +24,7 @@ class HEIC extends ProviderV2 {
* {@inheritDoc}
*/
public function getMimeType(): string {
- return '/image\/hei(f|c)/';
+ return '/image\/(x-)?hei(f|c)/';
}
/**
@@ -108,10 +88,20 @@ class HEIC extends ProviderV2 {
* @param int $maxY
*
* @return \Imagick
+ *
+ * @throws \Exception
*/
private function getResizedPreview($tmpPath, $maxX, $maxY) {
$bp = new \Imagick();
+ // Some HEIC files just contain (or at least are identified as) other formats
+ // like JPEG. We just need to check if the image is safe to process.
+ $bp->pingImage($tmpPath . '[0]');
+ $mimeType = $bp->getImageMimeType();
+ if (!preg_match('/^image\/(x-)?(png|jpeg|gif|bmp|tiff|webp|hei(f|c)|avif)$/', $mimeType)) {
+ throw new \Exception('File mime type does not match the preview provider: ' . $mimeType);
+ }
+
// Layer 0 contains either the bitmap or a flat representation of all vector layers
$bp->readImage($tmpPath . '[0]');
diff --git a/lib/private/Preview/IMagickSupport.php b/lib/private/Preview/IMagickSupport.php
index e22ae93ab94..8225b1e7644 100644
--- a/lib/private/Preview/IMagickSupport.php
+++ b/lib/private/Preview/IMagickSupport.php
@@ -1,5 +1,9 @@
<?php
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
namespace OC\Preview;
use OCP\ICache;
diff --git a/lib/private/Preview/Illustrator.php b/lib/private/Preview/Illustrator.php
index 3d926c304c5..bff556a3177 100644
--- a/lib/private/Preview/Illustrator.php
+++ b/lib/private/Preview/Illustrator.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -31,4 +15,11 @@ class Illustrator extends Bitmap {
public function getMimeType(): string {
return '/application\/illustrator/';
}
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/application\/(illustrator|pdf)/';
+ }
}
diff --git a/lib/private/Preview/Image.php b/lib/private/Preview/Image.php
index 95b66a922fd..69841f07929 100644
--- a/lib/private/Preview/Image.php
+++ b/lib/private/Preview/Image.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author josh4trunks <joshruehlig@gmail.com>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/Imaginary.php b/lib/private/Preview/Imaginary.php
index da4864b1a22..23459be3b51 100644
--- a/lib/private/Preview/Imaginary.php
+++ b/lib/private/Preview/Imaginary.php
@@ -1,35 +1,18 @@
<?php
/**
- * @copyright Copyright (c) 2020, Nextcloud, GmbH.
- *
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
+use OC\StreamImage;
use OCP\Files\File;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\IImage;
-use OCP\Image;
-use OC\StreamImage;
+use OCP\Image;
use Psr\Log\LoggerInterface;
class Imaginary extends ProviderV2 {
@@ -78,6 +61,9 @@ class Imaginary extends ProviderV2 {
// Object store
$stream = $file->fopen('r');
+ if (!$stream || !is_resource($stream) || feof($stream)) {
+ return null;
+ }
$httpClient = $this->service->newClient();
@@ -106,6 +92,15 @@ class Imaginary extends ProviderV2 {
$mimeType = 'jpeg';
}
+ $preview_format = $this->config->getSystemValueString('preview_format', 'jpeg');
+
+ switch ($preview_format) { // Change the format to the correct one
+ case 'webp':
+ $mimeType = 'webp';
+ break;
+ default:
+ }
+
$operations = [];
if ($convert) {
@@ -121,7 +116,16 @@ class Imaginary extends ProviderV2 {
];
}
- $quality = $this->config->getAppValue('preview', 'jpeg_quality', '80');
+ switch ($mimeType) {
+ case 'jpeg':
+ $quality = $this->config->getAppValue('preview', 'jpeg_quality', '80');
+ break;
+ case 'webp':
+ $quality = $this->config->getAppValue('preview', 'webp_quality', '80');
+ break;
+ default:
+ $quality = $this->config->getAppValue('preview', 'jpeg_quality', '80');
+ }
$operations[] = [
'operation' => ($crop ? 'smartcrop' : 'fit'),
@@ -147,7 +151,7 @@ class Imaginary extends ProviderV2 {
'timeout' => 120,
'connect_timeout' => 3,
]);
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$this->logger->info('Imaginary preview generation failed: ' . $e->getMessage(), [
'exception' => $e,
]);
diff --git a/lib/private/Preview/JPEG.php b/lib/private/Preview/JPEG.php
index 14ae95690c0..a1a394f81c9 100644
--- a/lib/private/Preview/JPEG.php
+++ b/lib/private/Preview/JPEG.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/Krita.php b/lib/private/Preview/Krita.php
index eb25db9928c..2e77c7befd2 100644
--- a/lib/private/Preview/Krita.php
+++ b/lib/private/Preview/Krita.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/MP3.php b/lib/private/Preview/MP3.php
index 4c5f932f477..59b791950b8 100644
--- a/lib/private/Preview/MP3.php
+++ b/lib/private/Preview/MP3.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/MSOffice2003.php b/lib/private/Preview/MSOffice2003.php
index 34cee499ff8..a52e618d484 100644
--- a/lib/private/Preview/MSOffice2003.php
+++ b/lib/private/Preview/MSOffice2003.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/MSOffice2007.php b/lib/private/Preview/MSOffice2007.php
index 3d3049e1c12..317f2dcc7f1 100644
--- a/lib/private/Preview/MSOffice2007.php
+++ b/lib/private/Preview/MSOffice2007.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/MSOfficeDoc.php b/lib/private/Preview/MSOfficeDoc.php
index e04503629e1..2e1044395f1 100644
--- a/lib/private/Preview/MSOfficeDoc.php
+++ b/lib/private/Preview/MSOfficeDoc.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/MarkDown.php b/lib/private/Preview/MarkDown.php
index d3806ce6c0e..41a79455042 100644
--- a/lib/private/Preview/MarkDown.php
+++ b/lib/private/Preview/MarkDown.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/MimeIconProvider.php b/lib/private/Preview/MimeIconProvider.php
index 1e44e8ca80a..167dd21b262 100644
--- a/lib/private/Preview/MimeIconProvider.php
+++ b/lib/private/Preview/MimeIconProvider.php
@@ -1,23 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -47,7 +31,7 @@ class MimeIconProvider implements IMimeIconProvider {
$aliases = $this->mimetypeDetector->getAllAliases();
// Remove comments
- $aliases = array_filter($aliases, static function ($key) {
+ $aliases = array_filter($aliases, static function (string $key) {
return !($key === '' || $key[0] === '_');
}, ARRAY_FILTER_USE_KEY);
@@ -82,7 +66,7 @@ class MimeIconProvider implements IMimeIconProvider {
}
}
- // Previously, we used to pass thi through Theming
+ // Previously, we used to pass this through Theming
// But it was only used to colour icons containing
// 0082c9. Since with vue we moved to inline svg icons,
// we can just use the default core icons.
diff --git a/lib/private/Preview/Movie.php b/lib/private/Preview/Movie.php
index 13d868cd583..cfc05b8cce9 100644
--- a/lib/private/Preview/Movie.php
+++ b/lib/private/Preview/Movie.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Alexander A. Klimov <grandmaster@al2klimov.de>
- * @author Daniel Schneider <daniel@schneidoa.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -163,7 +141,7 @@ class Movie extends ProviderV2 {
if ($second === 0) {
$logger = \OC::$server->get(LoggerInterface::class);
- $logger->error('Movie preview generation failed Output: {output}', ['app' => 'core', 'output' => $output]);
+ $logger->info('Movie preview generation failed Output: {output}', ['app' => 'core', 'output' => $output]);
}
unlink($tmpPath);
diff --git a/lib/private/Preview/Office.php b/lib/private/Preview/Office.php
index 3ba7c5a21a0..20fbef6eb23 100644
--- a/lib/private/Preview/Office.php
+++ b/lib/private/Preview/Office.php
@@ -1,37 +1,17 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tor Lillqvist <tml@collabora.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\IImage;
-use Psr\Log\LoggerInterface;
+use OCP\ITempManager;
+use OCP\Server;
abstract class Office extends ProviderV2 {
/**
@@ -49,51 +29,60 @@ abstract class Office extends ProviderV2 {
return null;
}
- $absPath = $this->getLocalFile($file);
-
- $tmpDir = \OC::$server->getTempManager()->getTempBaseDir();
+ $tempManager = Server::get(ITempManager::class);
- $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId() . '/') . ' --headless --nologo --nofirststartwizard --invisible --norestore --convert-to png --outdir ';
- $clParameters = \OC::$server->getConfig()->getSystemValue('preview_office_cl_parameters', $defaultParameters);
+ // The file to generate the preview for.
+ $absPath = $this->getLocalFile($file);
- $cmd = $this->options['officeBinary'] . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath);
+ // The destination for the LibreOffice user profile.
+ // LibreOffice can rune once per user profile and therefore instance id and file id are included.
+ $profile = $tempManager->getTemporaryFolder(
+ 'nextcloud-office-profile-' . \OC_Util::getInstanceId() . '-' . $file->getId()
+ );
- exec($cmd, $output, $returnCode);
+ // The destination for the LibreOffice convert result.
+ $outdir = $tempManager->getTemporaryFolder(
+ 'nextcloud-office-preview-' . \OC_Util::getInstanceId() . '-' . $file->getId()
+ );
- if ($returnCode !== 0) {
+ if ($profile === false || $outdir === false) {
$this->cleanTmpFiles();
return null;
}
- //create imagick object from png
- $pngPreview = null;
- try {
- [$dirname, , , $filename] = array_values(pathinfo($absPath));
- $pngPreview = $tmpDir . '/' . $filename . '.png';
+ $parameters = [
+ $this->options['officeBinary'],
+ '-env:UserInstallation=file://' . escapeshellarg($profile),
+ '--headless',
+ '--nologo',
+ '--nofirststartwizard',
+ '--invisible',
+ '--norestore',
+ '--convert-to png',
+ '--outdir ' . escapeshellarg($outdir),
+ escapeshellarg($absPath),
+ ];
- $png = new \Imagick($pngPreview . '[0]');
- $png->setImageFormat('jpg');
- } catch (\Exception $e) {
+ $cmd = implode(' ', $parameters);
+ exec($cmd, $output, $returnCode);
+
+ if ($returnCode !== 0) {
$this->cleanTmpFiles();
- unlink($pngPreview);
- \OC::$server->get(LoggerInterface::class)->error($e->getMessage(), [
- 'exception' => $e,
- 'app' => 'core',
- ]);
return null;
}
+ $preview = $outdir . pathinfo($absPath, PATHINFO_FILENAME) . '.png';
+
$image = new \OCP\Image();
- $image->loadFromData((string) $png);
+ $image->loadFromFile($preview);
$this->cleanTmpFiles();
- unlink($pngPreview);
if ($image->valid()) {
$image->scaleDownToFit($maxX, $maxY);
-
return $image;
}
+
return null;
}
}
diff --git a/lib/private/Preview/OpenDocument.php b/lib/private/Preview/OpenDocument.php
index 5f27e325d31..f590eb6a59c 100644
--- a/lib/private/Preview/OpenDocument.php
+++ b/lib/private/Preview/OpenDocument.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/PDF.php b/lib/private/Preview/PDF.php
index 405fd1545f9..9de14685925 100644
--- a/lib/private/Preview/PDF.php
+++ b/lib/private/Preview/PDF.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -31,4 +15,11 @@ class PDF extends Bitmap {
public function getMimeType(): string {
return '/application\/pdf/';
}
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/application\/pdf/';
+ }
}
diff --git a/lib/private/Preview/PNG.php b/lib/private/Preview/PNG.php
index 5a3f2136575..49d0cd059ba 100644
--- a/lib/private/Preview/PNG.php
+++ b/lib/private/Preview/PNG.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/Photoshop.php b/lib/private/Preview/Photoshop.php
index 9d79abf8191..b7209120530 100644
--- a/lib/private/Preview/Photoshop.php
+++ b/lib/private/Preview/Photoshop.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -31,4 +15,11 @@ class Photoshop extends Bitmap {
public function getMimeType(): string {
return '/application\/x-photoshop/';
}
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/(application|image)\/(x-photoshop|x-psd)/';
+ }
}
diff --git a/lib/private/Preview/Postscript.php b/lib/private/Preview/Postscript.php
index 06ea7fc8037..04c667926aa 100644
--- a/lib/private/Preview/Postscript.php
+++ b/lib/private/Preview/Postscript.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -31,4 +15,11 @@ class Postscript extends Bitmap {
public function getMimeType(): string {
return '/application\/postscript/';
}
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/application\/postscript/';
+ }
}
diff --git a/lib/private/Preview/Provider.php b/lib/private/Preview/Provider.php
index e87aded4786..26f0ac09f08 100644
--- a/lib/private/Preview/Provider.php
+++ b/lib/private/Preview/Provider.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/ProviderV1Adapter.php b/lib/private/Preview/ProviderV1Adapter.php
index 5e50db9d8da..ba8826ef765 100644
--- a/lib/private/Preview/ProviderV1Adapter.php
+++ b/lib/private/Preview/ProviderV1Adapter.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/ProviderV2.php b/lib/private/Preview/ProviderV2.php
index 0cb7eb59e21..ca10aa67b36 100644
--- a/lib/private/Preview/ProviderV2.php
+++ b/lib/private/Preview/ProviderV2.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -83,7 +66,7 @@ abstract class ProviderV2 implements IProviderV2 {
* @param int $maxSize maximum size for temporary files
* @return string|false
*/
- protected function getLocalFile(File $file, int $maxSize = null) {
+ protected function getLocalFile(File $file, ?int $maxSize = null) {
if ($this->useTempFile($file)) {
$absPath = \OC::$server->getTempManager()->getTemporaryFile();
diff --git a/lib/private/Preview/SGI.php b/lib/private/Preview/SGI.php
index 9f392d2252f..06ea9c0c69a 100644
--- a/lib/private/Preview/SGI.php
+++ b/lib/private/Preview/SGI.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2021 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -28,6 +11,13 @@ class SGI extends Bitmap {
* {@inheritDoc}
*/
public function getMimeType(): string {
- return '/image\/sgi/';
+ return '/image\/(x-)?sgi/';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/image\/(x-)?sgi/';
}
}
diff --git a/lib/private/Preview/SVG.php b/lib/private/Preview/SVG.php
index fd472083533..73dc0488bf1 100644
--- a/lib/private/Preview/SVG.php
+++ b/lib/private/Preview/SVG.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -44,26 +24,35 @@ class SVG extends ProviderV2 {
*/
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
try {
- $svg = new \Imagick();
- $svg->setBackgroundColor(new \ImagickPixel('transparent'));
-
$content = stream_get_contents($file->fopen('r'));
if (substr($content, 0, 5) !== '<?xml') {
$content = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . $content;
}
// Do not parse SVG files with references
- if (stripos($content, 'xlink:href') !== false) {
+ if (preg_match('/["\s](xlink:)?href\s*=/i', $content)) {
return null;
}
+ $svg = new \Imagick();
+
+ $svg->pingImageBlob($content);
+ $mimeType = $svg->getImageMimeType();
+ if (!preg_match($this->getMimeType(), $mimeType)) {
+ throw new \Exception('File mime type does not match the preview provider: ' . $mimeType);
+ }
+
+ $svg->setBackgroundColor(new \ImagickPixel('transparent'));
$svg->readImageBlob($content);
$svg->setImageFormat('png32');
} catch (\Exception $e) {
- \OC::$server->get(LoggerInterface::class)->error($e->getMessage(), [
- 'exception' => $e,
- 'app' => 'core',
- ]);
+ \OC::$server->get(LoggerInterface::class)->error(
+ 'File: ' . $file->getPath() . ' Imagick says:',
+ [
+ 'exception' => $e,
+ 'app' => 'core',
+ ]
+ );
return null;
}
diff --git a/lib/private/Preview/StarOffice.php b/lib/private/Preview/StarOffice.php
index 58f210d2ff6..9ea540dc912 100644
--- a/lib/private/Preview/StarOffice.php
+++ b/lib/private/Preview/StarOffice.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/Storage/Root.php b/lib/private/Preview/Storage/Root.php
index c4191228ec7..41378653962 100644
--- a/lib/private/Preview/Storage/Root.php
+++ b/lib/private/Preview/Storage/Root.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview\Storage;
diff --git a/lib/private/Preview/TGA.php b/lib/private/Preview/TGA.php
index cb591be2231..62e5aadc2af 100644
--- a/lib/private/Preview/TGA.php
+++ b/lib/private/Preview/TGA.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2021 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -28,6 +11,13 @@ class TGA extends Bitmap {
* {@inheritDoc}
*/
public function getMimeType(): string {
- return '/image\/t(ar)?ga/';
+ return '/image\/(x-)?t(ar)?ga/';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/image\/(x-)?t(ar)?ga/';
}
}
diff --git a/lib/private/Preview/TIFF.php b/lib/private/Preview/TIFF.php
index 1a5d957d3ee..cd81e611d0b 100644
--- a/lib/private/Preview/TIFF.php
+++ b/lib/private/Preview/TIFF.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
@@ -31,4 +15,11 @@ class TIFF extends Bitmap {
public function getMimeType(): string {
return '/image\/tiff/';
}
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getAllowedMimeTypes(): string {
+ return '/image\/tiff/';
+ }
}
diff --git a/lib/private/Preview/TXT.php b/lib/private/Preview/TXT.php
index f5a68f92be4..68597f8dbd0 100644
--- a/lib/private/Preview/TXT.php
+++ b/lib/private/Preview/TXT.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Nmz <nemesiz@nmz.lt>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/Watcher.php b/lib/private/Preview/Watcher.php
index 7f4593f9fe3..abddd7b5acb 100644
--- a/lib/private/Preview/Watcher.php
+++ b/lib/private/Preview/Watcher.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -61,6 +44,9 @@ class Watcher {
}
try {
+ if (is_null($node->getId())) {
+ return;
+ }
$folder = $this->appData->getFolder((string)$node->getId());
$folder->delete();
} catch (NotFoundException $e) {
diff --git a/lib/private/Preview/WatcherConnector.php b/lib/private/Preview/WatcherConnector.php
index ffbdf825211..ae2a136ca78 100644
--- a/lib/private/Preview/WatcherConnector.php
+++ b/lib/private/Preview/WatcherConnector.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
@@ -43,7 +26,7 @@ class WatcherConnector {
* @param SystemConfig $config
*/
public function __construct(IRootFolder $root,
- SystemConfig $config) {
+ SystemConfig $config) {
$this->root = $root;
$this->config = $config;
}
diff --git a/lib/private/Preview/WebP.php b/lib/private/Preview/WebP.php
index c8f8d11c393..25b922e9190 100644
--- a/lib/private/Preview/WebP.php
+++ b/lib/private/Preview/WebP.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Preview;
diff --git a/lib/private/Preview/XBitmap.php b/lib/private/Preview/XBitmap.php
index e0adb48b881..c8337cc252d 100644
--- a/lib/private/Preview/XBitmap.php
+++ b/lib/private/Preview/XBitmap.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Preview;
diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php
index 3af6848686e..21dd8f8a8ab 100644
--- a/lib/private/PreviewManager.php
+++ b/lib/private/PreviewManager.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sebastian Steinmetz <462714+steiny2k@users.noreply.github.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -366,7 +343,7 @@ class PreviewManager implements IPreview {
$this->registerCoreProvider(Preview\OpenDocument::class, '/application\/vnd.oasis.opendocument.*/');
$this->registerCoreProvider(Preview\Imaginary::class, Preview\Imaginary::supportedMimeTypes());
- // SVG, Office and Bitmap require imagick
+ // SVG and Bitmap require imagick
if ($this->imagickSupport->hasExtension()) {
$imagickProviders = [
'SVG' => ['mimetype' => '/image\/svg\+xml/', 'class' => Preview\SVG::class],
@@ -376,9 +353,9 @@ class PreviewManager implements IPreview {
'PSD' => ['mimetype' => '/application\/x-photoshop/', 'class' => Preview\Photoshop::class],
'EPS' => ['mimetype' => '/application\/postscript/', 'class' => Preview\Postscript::class],
'TTF' => ['mimetype' => '/application\/(?:font-sfnt|x-font$)/', 'class' => Preview\Font::class],
- 'HEIC' => ['mimetype' => '/image\/hei(f|c)/', 'class' => Preview\HEIC::class],
- 'TGA' => ['mimetype' => '/image\/t(ar)?ga/', 'class' => Preview\TGA::class],
- 'SGI' => ['mimetype' => '/image\/sgi/', 'class' => Preview\SGI::class],
+ 'HEIC' => ['mimetype' => '/image\/(x-)?hei(f|c)/', 'class' => Preview\HEIC::class],
+ 'TGA' => ['mimetype' => '/image\/(x-)?t(ar)?ga/', 'class' => Preview\TGA::class],
+ 'SGI' => ['mimetype' => '/image\/(x-)?sgi/', 'class' => Preview\SGI::class],
];
foreach ($imagickProviders as $queryFormat => $provider) {
@@ -391,27 +368,10 @@ class PreviewManager implements IPreview {
$this->registerCoreProvider($class, $provider['mimetype']);
}
}
-
- if ($this->imagickSupport->supportsFormat('PDF')) {
- // Office requires openoffice or libreoffice
- $officeBinary = $this->config->getSystemValue('preview_libreoffice_path', null);
- if (!is_string($officeBinary)) {
- $officeBinary = $this->binaryFinder->findBinaryPath('libreoffice');
- }
- if (!is_string($officeBinary)) {
- $officeBinary = $this->binaryFinder->findBinaryPath('openoffice');
- }
-
- if (is_string($officeBinary)) {
- $this->registerCoreProvider(Preview\MSOfficeDoc::class, '/application\/msword/', ["officeBinary" => $officeBinary]);
- $this->registerCoreProvider(Preview\MSOffice2003::class, '/application\/vnd.ms-.*/', ["officeBinary" => $officeBinary]);
- $this->registerCoreProvider(Preview\MSOffice2007::class, '/application\/vnd.openxmlformats-officedocument.*/', ["officeBinary" => $officeBinary]);
- $this->registerCoreProvider(Preview\OpenDocument::class, '/application\/vnd.oasis.opendocument.*/', ["officeBinary" => $officeBinary]);
- $this->registerCoreProvider(Preview\StarOffice::class, '/application\/vnd.sun.xml.*/', ["officeBinary" => $officeBinary]);
- }
- }
}
+ $this->registerCoreProvidersOffice();
+
// Video requires avconv or ffmpeg
if (in_array(Preview\Movie::class, $this->getEnabledDefaultProvider())) {
$movieBinary = $this->config->getSystemValue('preview_ffmpeg_path', null);
@@ -429,6 +389,43 @@ class PreviewManager implements IPreview {
}
}
+ private function registerCoreProvidersOffice(): void {
+ $officeProviders = [
+ ['mimetype' => '/application\/msword/', 'class' => Preview\MSOfficeDoc::class],
+ ['mimetype' => '/application\/vnd.ms-.*/', 'class' => Preview\MSOffice2003::class],
+ ['mimetype' => '/application\/vnd.openxmlformats-officedocument.*/', 'class' => Preview\MSOffice2007::class],
+ ['mimetype' => '/application\/vnd.oasis.opendocument.*/', 'class' => Preview\OpenDocument::class],
+ ['mimetype' => '/application\/vnd.sun.xml.*/', 'class' => Preview\StarOffice::class],
+ ['mimetype' => '/image\/emf/', 'class' => Preview\EMF::class],
+ ];
+
+ $findBinary = true;
+ $officeBinary = false;
+
+ foreach ($officeProviders as $provider) {
+ $class = $provider['class'];
+ if (!in_array(trim($class, '\\'), $this->getEnabledDefaultProvider())) {
+ continue;
+ }
+
+ if ($findBinary) {
+ // Office requires openoffice or libreoffice
+ $officeBinary = $this->config->getSystemValue('preview_libreoffice_path', false);
+ if ($officeBinary === false) {
+ $officeBinary = $this->binaryFinder->findBinaryPath('libreoffice');
+ }
+ if ($officeBinary === false) {
+ $officeBinary = $this->binaryFinder->findBinaryPath('openoffice');
+ }
+ $findBinary = false;
+ }
+
+ if ($officeBinary) {
+ $this->registerCoreProvider($class, $provider['mimetype'], ['officeBinary' => $officeBinary]);
+ }
+ }
+ }
+
private function registerBootstrapProviders(): void {
$context = $this->bootstrapCoordinator->getRegistrationContext();
diff --git a/lib/private/PreviewNotAvailableException.php b/lib/private/PreviewNotAvailableException.php
index f4564546ea8..b1fec912769 100644
--- a/lib/private/PreviewNotAvailableException.php
+++ b/lib/private/PreviewNotAvailableException.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC;
diff --git a/lib/private/Profile/Actions/EmailAction.php b/lib/private/Profile/Actions/EmailAction.php
index 8ab4939b515..c01f368b476 100644
--- a/lib/private/Profile/Actions/EmailAction.php
+++ b/lib/private/Profile/Actions/EmailAction.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile\Actions;
@@ -33,26 +16,13 @@ use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
class EmailAction implements ILinkAction {
- /** @var string */
- private $value;
-
- /** @var IAccountManager */
- private $accountManager;
-
- /** @var IFactory */
- private $l10nFactory;
-
- /** @var IUrlGenerator */
- private $urlGenerator;
+ private string $value = '';
public function __construct(
- IAccountManager $accountManager,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator
+ private IAccountManager $accountManager,
+ private IFactory $l10nFactory,
+ private IURLGenerator $urlGenerator,
) {
- $this->accountManager = $accountManager;
- $this->l10nFactory = $l10nFactory;
- $this->urlGenerator = $urlGenerator;
}
public function preload(IUser $targetUser): void {
diff --git a/lib/private/Profile/Actions/FediverseAction.php b/lib/private/Profile/Actions/FediverseAction.php
index ed3fcd80b52..1076027629d 100644
--- a/lib/private/Profile/Actions/FediverseAction.php
+++ b/lib/private/Profile/Actions/FediverseAction.php
@@ -3,50 +3,27 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile\Actions;
-use function Safe\substr;
use OCP\Accounts\IAccountManager;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
+use function substr;
class FediverseAction implements ILinkAction {
- private ?string $value = null;
- private IAccountManager $accountManager;
- private IFactory $l10nFactory;
- private IURLGenerator $urlGenerator;
+ private string $value = '';
public function __construct(
- IAccountManager $accountManager,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator
+ private IAccountManager $accountManager,
+ private IFactory $l10nFactory,
+ private IURLGenerator $urlGenerator,
) {
- $this->accountManager = $accountManager;
- $this->l10nFactory = $l10nFactory;
- $this->urlGenerator = $urlGenerator;
}
public function preload(IUser $targetUser): void {
diff --git a/lib/private/Profile/Actions/PhoneAction.php b/lib/private/Profile/Actions/PhoneAction.php
index 6081a04ad7e..598cdc49051 100644
--- a/lib/private/Profile/Actions/PhoneAction.php
+++ b/lib/private/Profile/Actions/PhoneAction.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile\Actions;
@@ -33,26 +16,13 @@ use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
class PhoneAction implements ILinkAction {
- /** @var string */
- private $value;
-
- /** @var IAccountManager */
- private $accountManager;
-
- /** @var IFactory */
- private $l10nFactory;
-
- /** @var IUrlGenerator */
- private $urlGenerator;
+ private string $value = '';
public function __construct(
- IAccountManager $accountManager,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator
+ private IAccountManager $accountManager,
+ private IFactory $l10nFactory,
+ private IURLGenerator $urlGenerator,
) {
- $this->accountManager = $accountManager;
- $this->l10nFactory = $l10nFactory;
- $this->urlGenerator = $urlGenerator;
}
public function preload(IUser $targetUser): void {
diff --git a/lib/private/Profile/Actions/TwitterAction.php b/lib/private/Profile/Actions/TwitterAction.php
index 041da42e539..78e7137f64b 100644
--- a/lib/private/Profile/Actions/TwitterAction.php
+++ b/lib/private/Profile/Actions/TwitterAction.php
@@ -3,57 +3,27 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile\Actions;
-use function Safe\substr;
use OCP\Accounts\IAccountManager;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
+use function substr;
class TwitterAction implements ILinkAction {
- /** @var string */
- private $value;
-
- /** @var IAccountManager */
- private $accountManager;
-
- /** @var IFactory */
- private $l10nFactory;
-
- /** @var IUrlGenerator */
- private $urlGenerator;
+ private string $value = '';
public function __construct(
- IAccountManager $accountManager,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator
+ private IAccountManager $accountManager,
+ private IFactory $l10nFactory,
+ private IURLGenerator $urlGenerator,
) {
- $this->accountManager = $accountManager;
- $this->l10nFactory = $l10nFactory;
- $this->urlGenerator = $urlGenerator;
}
public function preload(IUser $targetUser): void {
diff --git a/lib/private/Profile/Actions/WebsiteAction.php b/lib/private/Profile/Actions/WebsiteAction.php
index 6b052be57bd..4f5dcb568e7 100644
--- a/lib/private/Profile/Actions/WebsiteAction.php
+++ b/lib/private/Profile/Actions/WebsiteAction.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile\Actions;
@@ -33,26 +16,13 @@ use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
class WebsiteAction implements ILinkAction {
- /** @var string */
- private $value;
-
- /** @var IAccountManager */
- private $accountManager;
-
- /** @var IFactory */
- private $l10nFactory;
-
- /** @var IUrlGenerator */
- private $urlGenerator;
+ private string $value = '';
public function __construct(
- IAccountManager $accountManager,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator
+ private IAccountManager $accountManager,
+ private IFactory $l10nFactory,
+ private IURLGenerator $urlGenerator,
) {
- $this->accountManager = $accountManager;
- $this->l10nFactory = $l10nFactory;
- $this->urlGenerator = $urlGenerator;
}
public function preload(IUser $targetUser): void {
diff --git a/lib/private/Profile/ProfileManager.php b/lib/private/Profile/ProfileManager.php
index f20ae74768e..e575740f970 100644
--- a/lib/private/Profile/ProfileManager.php
+++ b/lib/private/Profile/ProfileManager.php
@@ -3,85 +3,42 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile;
-use function Safe\array_flip;
-use function Safe\usort;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\Core\Db\ProfileConfig;
use OC\Core\Db\ProfileConfigMapper;
use OC\KnownUser\KnownUserService;
use OC\Profile\Actions\EmailAction;
+use OC\Profile\Actions\FediverseAction;
use OC\Profile\Actions\PhoneAction;
use OC\Profile\Actions\TwitterAction;
-use OC\Profile\Actions\FediverseAction;
use OC\Profile\Actions\WebsiteAction;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\App\IAppManager;
use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\Cache\CappedMemoryCache;
use OCP\IConfig;
use OCP\IUser;
use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
-use OCP\Cache\CappedMemoryCache;
+use OCP\Profile\IProfileManager;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
+use function array_flip;
+use function usort;
-class ProfileManager {
- /** @var IAccountManager */
- private $accountManager;
-
- /** @var IAppManager */
- private $appManager;
-
- /** @var IConfig */
- private $config;
-
- /** @var ProfileConfigMapper */
- private $configMapper;
-
- /** @var ContainerInterface */
- private $container;
-
- /** @var KnownUserService */
- private $knownUserService;
-
- /** @var IFactory */
- private $l10nFactory;
-
- /** @var LoggerInterface */
- private $logger;
-
- /** @var Coordinator */
- private $coordinator;
-
+class ProfileManager implements IProfileManager {
/** @var ILinkAction[] */
- private $actions = [];
+ private array $actions = [];
/** @var null|ILinkAction[] */
- private $sortedActions = null;
+ private ?array $sortedActions = null;
/** @var CappedMemoryCache<ProfileConfig> */
private CappedMemoryCache $configCache;
@@ -112,32 +69,23 @@ class ProfileManager {
];
public function __construct(
- IAccountManager $accountManager,
- IAppManager $appManager,
- IConfig $config,
- ProfileConfigMapper $configMapper,
- ContainerInterface $container,
- KnownUserService $knownUserService,
- IFactory $l10nFactory,
- LoggerInterface $logger,
- Coordinator $coordinator
+ private IAccountManager $accountManager,
+ private IAppManager $appManager,
+ private IConfig $config,
+ private ProfileConfigMapper $configMapper,
+ private ContainerInterface $container,
+ private KnownUserService $knownUserService,
+ private IFactory $l10nFactory,
+ private LoggerInterface $logger,
+ private Coordinator $coordinator,
) {
- $this->accountManager = $accountManager;
- $this->appManager = $appManager;
- $this->config = $config;
- $this->configMapper = $configMapper;
- $this->container = $container;
- $this->knownUserService = $knownUserService;
- $this->l10nFactory = $l10nFactory;
- $this->logger = $logger;
- $this->coordinator = $coordinator;
$this->configCache = new CappedMemoryCache();
}
/**
* If no user is passed as an argument return whether profile is enabled globally in `config.php`
*/
- public function isProfileEnabled(?IUser $user = null): ?bool {
+ public function isProfileEnabled(?IUser $user = null): bool {
$profileEnabledGlobally = $this->config->getSystemValueBool('profile.enabled', true);
if (empty($user) || !$profileEnabledGlobally) {
@@ -145,7 +93,7 @@ class ProfileManager {
}
$account = $this->accountManager->getAccount($user);
- return filter_var(
+ return (bool) filter_var(
$account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue(),
FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE,
@@ -229,57 +177,54 @@ class ProfileManager {
* Return whether the profile parameter of the target user
* is visible to the visiting user
*/
- private function isParameterVisible(string $paramId, IUser $targetUser, ?IUser $visitingUser): bool {
+ public function isProfileFieldVisible(string $profileField, IUser $targetUser, ?IUser $visitingUser): bool {
try {
$account = $this->accountManager->getAccount($targetUser);
- $scope = $account->getProperty($paramId)->getScope();
+ $scope = $account->getProperty($profileField)->getScope();
} catch (PropertyDoesNotExistException $e) {
// Allow the exception as not all profile parameters are account properties
}
- $visibility = $this->getProfileConfig($targetUser, $visitingUser)[$paramId]['visibility'];
+ $visibility = $this->getProfileConfig($targetUser, $visitingUser)[$profileField]['visibility'];
// Handle profile visibility and account property scope
- switch ($visibility) {
- case ProfileConfig::VISIBILITY_HIDE:
- return false;
- case ProfileConfig::VISIBILITY_SHOW_USERS_ONLY:
- if (!empty($scope)) {
- switch ($scope) {
- case IAccountManager::SCOPE_PRIVATE:
- return $visitingUser !== null && $this->knownUserService->isKnownToUser($targetUser->getUID(), $visitingUser->getUID());
- case IAccountManager::SCOPE_LOCAL:
- case IAccountManager::SCOPE_FEDERATED:
- case IAccountManager::SCOPE_PUBLISHED:
- return $visitingUser !== null;
- default:
- return false;
- }
- }
+
+ if ($visibility === self::VISIBILITY_SHOW_USERS_ONLY) {
+ if (empty($scope)) {
return $visitingUser !== null;
- case ProfileConfig::VISIBILITY_SHOW:
- if (!empty($scope)) {
- switch ($scope) {
- case IAccountManager::SCOPE_PRIVATE:
- return $visitingUser !== null && $this->knownUserService->isKnownToUser($targetUser->getUID(), $visitingUser->getUID());
- case IAccountManager::SCOPE_LOCAL:
- case IAccountManager::SCOPE_FEDERATED:
- case IAccountManager::SCOPE_PUBLISHED:
- return true;
- default:
- return false;
- }
- }
+ }
+
+ return match ($scope) {
+ IAccountManager::SCOPE_PRIVATE => $visitingUser !== null && $this->knownUserService->isKnownToUser($targetUser->getUID(), $visitingUser->getUID()),
+ IAccountManager::SCOPE_LOCAL,
+ IAccountManager::SCOPE_FEDERATED,
+ IAccountManager::SCOPE_PUBLISHED => $visitingUser !== null,
+ default => false,
+ };
+ }
+
+ if ($visibility === self::VISIBILITY_SHOW) {
+ if (empty($scope)) {
return true;
- default:
- return false;
+ }
+
+ return match ($scope) {
+ IAccountManager::SCOPE_PRIVATE => $visitingUser !== null && $this->knownUserService->isKnownToUser($targetUser->getUID(), $visitingUser->getUID()),
+ IAccountManager::SCOPE_LOCAL,
+ IAccountManager::SCOPE_FEDERATED,
+ IAccountManager::SCOPE_PUBLISHED => true,
+ default => false,
+ };
}
+
+ return false;
}
/**
* Return the profile parameters of the target user that are visible to the visiting user
* in an associative array
+ * @return array{userId: string, address?: string|null, biography?: string|null, displayname?: string|null, headline?: string|null, isUserAvatarVisible?: bool, organisation?: string|null, role?: string|null, actions: list<array{id: string, icon: string, title: string, target: ?string}>}
*/
- public function getProfileParams(IUser $targetUser, ?IUser $visitingUser): array {
+ public function getProfileFields(IUser $targetUser, ?IUser $visitingUser): array {
$account = $this->accountManager->getAccount($targetUser);
// Initialize associative array of profile parameters
@@ -297,14 +242,14 @@ class ProfileManager {
case IAccountManager::PROPERTY_ORGANISATION:
case IAccountManager::PROPERTY_ROLE:
$profileParameters[$property] =
- $this->isParameterVisible($property, $targetUser, $visitingUser)
+ $this->isProfileFieldVisible($property, $targetUser, $visitingUser)
// Explicitly set to null when value is empty string
? ($account->getProperty($property)->getValue() ?: null)
: null;
break;
case IAccountManager::PROPERTY_AVATAR:
// Add avatar visibility
- $profileParameters['isUserAvatarVisible'] = $this->isParameterVisible($property, $targetUser, $visitingUser);
+ $profileParameters['isUserAvatarVisible'] = $this->isProfileFieldVisible($property, $targetUser, $visitingUser);
break;
}
}
@@ -324,7 +269,7 @@ class ProfileManager {
array_filter(
$this->getActions($targetUser, $visitingUser),
function (ILinkAction $action) use ($targetUser, $visitingUser) {
- return $this->isParameterVisible($action->getId(), $targetUser, $visitingUser);
+ return $this->isProfileFieldVisible($action->getId(), $targetUser, $visitingUser);
}
),
)
@@ -356,12 +301,12 @@ class ProfileManager {
// Construct the default config for actions
$actionsConfig = [];
foreach ($this->getActions($targetUser, $visitingUser) as $action) {
- $actionsConfig[$action->getId()] = ['visibility' => ProfileConfig::DEFAULT_VISIBILITY];
+ $actionsConfig[$action->getId()] = ['visibility' => self::DEFAULT_VISIBILITY];
}
// Construct the default config for account properties
$propertiesConfig = [];
- foreach (ProfileConfig::DEFAULT_PROPERTY_VISIBILITY as $property => $visibility) {
+ foreach (self::DEFAULT_PROPERTY_VISIBILITY as $property => $visibility) {
$propertiesConfig[$property] = ['visibility' => $visibility];
}
diff --git a/lib/private/Profile/TProfileHelper.php b/lib/private/Profile/TProfileHelper.php
index 5b57e1c9d5c..ad24d82445c 100644
--- a/lib/private/Profile/TProfileHelper.php
+++ b/lib/private/Profile/TProfileHelper.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2022 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profile;
diff --git a/lib/private/Profiler/FileProfilerStorage.php b/lib/private/Profiler/FileProfilerStorage.php
index d7f3df752a6..8cb6f2e6f79 100644
--- a/lib/private/Profiler/FileProfilerStorage.php
+++ b/lib/private/Profiler/FileProfilerStorage.php
@@ -2,26 +2,8 @@
declare(strict_types = 1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- * @author Alexandre Salomé <alexandre.salome@gmail.com>
- *
- * @license AGPL-3.0-or-later AND MIT
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profiler;
@@ -45,12 +27,12 @@ class FileProfilerStorage {
public function __construct(string $folder) {
$this->folder = $folder;
- if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) {
+ if (!is_dir($this->folder) && @mkdir($this->folder, 0777, true) === false && !is_dir($this->folder)) {
throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder));
}
}
- public function find(?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array {
+ public function find(?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null, ?string $statusCode = null): array {
$file = $this->getIndexFilename();
if (!file_exists($file)) {
@@ -130,7 +112,7 @@ class FileProfilerStorage {
if (!$profileIndexed) {
// Create directory
$dir = \dirname($file);
- if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
+ if (!is_dir($dir) && @mkdir($dir, 0777, true) === false && !is_dir($dir)) {
throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir));
}
}
@@ -162,7 +144,7 @@ class FileProfilerStorage {
stream_context_set_option($context, 'zlib', 'level', 3);
}
- if (false === file_put_contents($file, serialize($data), 0, $context)) {
+ if (file_put_contents($file, serialize($data), 0, $context) === false) {
return false;
}
@@ -221,7 +203,7 @@ class FileProfilerStorage {
$line = '';
$position = ftell($file);
- if (0 === $position) {
+ if ($position === 0) {
return null;
}
@@ -230,7 +212,7 @@ class FileProfilerStorage {
$position -= $chunkSize;
fseek($file, $position);
- if (0 === $chunkSize) {
+ if ($chunkSize === 0) {
// bof reached
break;
}
@@ -246,15 +228,15 @@ class FileProfilerStorage {
$line = substr($buffer, $upTo + 1).$line;
fseek($file, max(0, $position), \SEEK_SET);
- if ('' !== $line) {
+ if ($line !== '') {
break;
}
}
- return '' === $line ? null : $line;
+ return $line === '' ? null : $line;
}
- protected function createProfileFromData(string $token, array $data, IProfile $parent = null): IProfile {
+ protected function createProfileFromData(string $token, array $data, ?IProfile $parent = null): IProfile {
$profile = new Profile($token);
$profile->setMethod($data['method']);
$profile->setUrl($data['url']);
diff --git a/lib/private/Profiler/Profile.php b/lib/private/Profiler/Profile.php
index 648c49c0330..c611d79e259 100644
--- a/lib/private/Profiler/Profile.php
+++ b/lib/private/Profiler/Profile.php
@@ -2,25 +2,8 @@
declare(strict_types = 1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profiler;
diff --git a/lib/private/Profiler/Profiler.php b/lib/private/Profiler/Profiler.php
index 40050b7bf43..84a4e3eff34 100644
--- a/lib/private/Profiler/Profiler.php
+++ b/lib/private/Profiler/Profiler.php
@@ -3,35 +3,18 @@
declare(strict_types = 1);
/**
- * @copyright 2021 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profiler;
use OC\AppFramework\Http\Request;
+use OC\SystemConfig;
use OCP\AppFramework\Http\Response;
use OCP\DataCollector\IDataCollector;
-use OCP\Profiler\IProfiler;
use OCP\Profiler\IProfile;
-use OC\SystemConfig;
+use OCP\Profiler\IProfiler;
class Profiler implements IProfiler {
/** @var array<string, IDataCollector> */
@@ -44,7 +27,7 @@ class Profiler implements IProfiler {
public function __construct(SystemConfig $config) {
$this->enabled = $config->getValue('profiler', false);
if ($this->enabled) {
- $this->storage = new FileProfilerStorage($config->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/profiler');
+ $this->storage = new FileProfilerStorage($config->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/__profiler');
}
}
@@ -95,7 +78,7 @@ class Profiler implements IProfiler {
* @return array[]
*/
public function find(?string $url, ?int $limit, ?string $method, ?int $start, ?int $end,
- string $statusCode = null): array {
+ ?string $statusCode = null): array {
if ($this->storage) {
return $this->storage->find($url, $limit, $method, $start, $end, $statusCode);
} else {
diff --git a/lib/private/Profiler/RoutingDataCollector.php b/lib/private/Profiler/RoutingDataCollector.php
index e6659230879..c8952c76a38 100644
--- a/lib/private/Profiler/RoutingDataCollector.php
+++ b/lib/private/Profiler/RoutingDataCollector.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Profiler;
@@ -41,7 +24,7 @@ class RoutingDataCollector extends AbstractDataCollector {
$this->actionName = $actionName;
}
- public function collect(Request $request, Response $response, \Throwable $exception = null): void {
+ public function collect(Request $request, Response $response, ?\Throwable $exception = null): void {
$this->data = [
'appName' => $this->appName,
'controllerName' => $this->controllerName,
diff --git a/lib/private/RedisFactory.php b/lib/private/RedisFactory.php
index 4903a8713df..abfec608a39 100644
--- a/lib/private/RedisFactory.php
+++ b/lib/private/RedisFactory.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Alejandro Varela <epma01@gmail.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Remote/Api/ApiBase.php b/lib/private/Remote/Api/ApiBase.php
index af114bd9498..dff3edb51b9 100644
--- a/lib/private/Remote/Api/ApiBase.php
+++ b/lib/private/Remote/Api/ApiBase.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote\Api;
diff --git a/lib/private/Remote/Api/ApiCollection.php b/lib/private/Remote/Api/ApiCollection.php
index 261f7e6c9b0..65039f4b5aa 100644
--- a/lib/private/Remote/Api/ApiCollection.php
+++ b/lib/private/Remote/Api/ApiCollection.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote\Api;
diff --git a/lib/private/Remote/Api/ApiFactory.php b/lib/private/Remote/Api/ApiFactory.php
index 27eaa163496..7daddd16011 100644
--- a/lib/private/Remote/Api/ApiFactory.php
+++ b/lib/private/Remote/Api/ApiFactory.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote\Api;
diff --git a/lib/private/Remote/Api/NotFoundException.php b/lib/private/Remote/Api/NotFoundException.php
index 8d226b00120..5251313f5f0 100644
--- a/lib/private/Remote/Api/NotFoundException.php
+++ b/lib/private/Remote/Api/NotFoundException.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote\Api;
diff --git a/lib/private/Remote/Api/OCS.php b/lib/private/Remote/Api/OCS.php
index e6ee65378c4..de07eb8bc56 100644
--- a/lib/private/Remote/Api/OCS.php
+++ b/lib/private/Remote/Api/OCS.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote\Api;
diff --git a/lib/private/Remote/Credentials.php b/lib/private/Remote/Credentials.php
index 56cf745c34c..fb0f03ae148 100644
--- a/lib/private/Remote/Credentials.php
+++ b/lib/private/Remote/Credentials.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote;
diff --git a/lib/private/Remote/Instance.php b/lib/private/Remote/Instance.php
index 591bc3d6ae0..4ae734521cf 100644
--- a/lib/private/Remote/Instance.php
+++ b/lib/private/Remote/Instance.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote;
diff --git a/lib/private/Remote/InstanceFactory.php b/lib/private/Remote/InstanceFactory.php
index 6941d06cb2e..f3047b851b2 100644
--- a/lib/private/Remote/InstanceFactory.php
+++ b/lib/private/Remote/InstanceFactory.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote;
diff --git a/lib/private/Remote/User.php b/lib/private/Remote/User.php
index 5590fcfba38..5c8e9d3ca4e 100644
--- a/lib/private/Remote/User.php
+++ b/lib/private/Remote/User.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Remote;
@@ -92,7 +74,7 @@ class User implements IUser {
* @return string
*/
public function getTwitter() {
- return isset($this->data['twitter']) ? $this->data['twitter'] : '';
+ return $this->data['twitter'] ?? '';
}
/**
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index 05624a2423a..fa279325453 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -1,52 +1,21 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
-use OC\Repair\AddRemoveOldTasksBackgroundJob;
-use OC\Repair\CleanUpAbandonedApps;
-use OCP\AppFramework\QueryException;
-use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\Collaboration\Resources\IManager;
-use OCP\EventDispatcher\IEventDispatcher;
-use OCP\Migration\IOutput;
-use OCP\Migration\IRepairStep;
use OC\DB\Connection;
use OC\DB\ConnectionAdapter;
+use OC\Repair\AddAppConfigLazyMigration;
use OC\Repair\AddBruteForceCleanupJob;
use OC\Repair\AddCleanupUpdaterBackupsJob;
+use OC\Repair\AddMetadataGenerationJob;
+use OC\Repair\AddRemoveOldTasksBackgroundJob;
use OC\Repair\CleanTags;
+use OC\Repair\CleanUpAbandonedApps;
use OC\Repair\ClearFrontendCaches;
use OC\Repair\ClearGeneratedAvatarCache;
use OC\Repair\Collation;
@@ -84,30 +53,31 @@ use OC\Repair\RemoveLinkShares;
use OC\Repair\RepairDavShares;
use OC\Repair\RepairInvalidShares;
use OC\Repair\RepairMimeTypes;
-use OC\Repair\SqliteAutoincrement;
use OC\Template\JSCombiner;
+use OCP\AppFramework\QueryException;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Collaboration\Resources\IManager;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
use Psr\Log\LoggerInterface;
use Throwable;
class Repair implements IOutput {
/** @var IRepairStep[] */
- private array $repairSteps;
-
- private IEventDispatcher $dispatcher;
+ private array $repairSteps = [];
private string $currentStep;
- private LoggerInterface $logger;
+ public function __construct(
+ private IEventDispatcher $dispatcher,
+ private LoggerInterface $logger
+ ) {
+ }
- /**
- * Creates a new repair step runner
- *
- * @param IRepairStep[] $repairSteps array of RepairStep instances
- */
- public function __construct(array $repairSteps, IEventDispatcher $dispatcher, LoggerInterface $logger) {
+ /** @param IRepairStep[] $repairSteps */
+ public function setRepairSteps(array $repairSteps): void {
$this->repairSteps = $repairSteps;
- $this->dispatcher = $dispatcher;
- $this->logger = $logger;
}
/**
@@ -212,6 +182,8 @@ class Repair implements IOutput {
\OCP\Server::get(CleanUpAbandonedApps::class),
\OCP\Server::get(AddMissingSecretJob::class),
\OCP\Server::get(AddRemoveOldTasksBackgroundJob::class),
+ \OCP\Server::get(AddMetadataGenerationJob::class),
+ \OCP\Server::get(AddAppConfigLazyMigration::class),
];
}
@@ -235,14 +207,11 @@ class Repair implements IOutput {
* @return IRepairStep[]
*/
public static function getBeforeUpgradeRepairSteps() {
- /** @var Connection $connection */
- $connection = \OC::$server->get(Connection::class);
/** @var ConnectionAdapter $connectionAdapter */
$connectionAdapter = \OC::$server->get(ConnectionAdapter::class);
$config = \OC::$server->getConfig();
$steps = [
new Collation(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), $connectionAdapter, true),
- new SqliteAutoincrement($connection),
new SaveAccountsTableData($connectionAdapter, $config),
new DropAccountTermsTable($connectionAdapter),
];
@@ -250,6 +219,9 @@ class Repair implements IOutput {
return $steps;
}
+ public function debug(string $message): void {
+ }
+
/**
* @param string $message
*/
diff --git a/lib/private/Repair/AddAppConfigLazyMigration.php b/lib/private/Repair/AddAppConfigLazyMigration.php
new file mode 100644
index 00000000000..7ae83e87669
--- /dev/null
+++ b/lib/private/Repair/AddAppConfigLazyMigration.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Repair;
+
+use OCP\IAppConfig;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+use Psr\Log\LoggerInterface;
+
+class AddAppConfigLazyMigration implements IRepairStep {
+ /**
+ * Just add config values that needs to be migrated to lazy loading
+ */
+ private static array $lazyAppConfig = [
+ 'core' => [
+ 'oc.integritycheck.checker',
+ ],
+ ];
+
+ public function __construct(
+ private IAppConfig $appConfig,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ public function getName() {
+ return 'migrate lazy config values';
+ }
+
+ public function run(IOutput $output) {
+ $c = 0;
+ foreach (self::$lazyAppConfig as $appId => $configKeys) {
+ foreach ($configKeys as $configKey) {
+ $c += (int)$this->appConfig->updateLazy($appId, $configKey, true);
+ }
+ }
+
+ $this->logger->notice('core/BackgroundJobs/AppConfigLazyMigration: ' . $c . ' config values updated');
+ }
+}
diff --git a/lib/private/Repair/AddBruteForceCleanupJob.php b/lib/private/Repair/AddBruteForceCleanupJob.php
index 5584e5b81c7..dd08e36a597 100644
--- a/lib/private/Repair/AddBruteForceCleanupJob.php
+++ b/lib/private/Repair/AddBruteForceCleanupJob.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/AddCleanupUpdaterBackupsJob.php b/lib/private/Repair/AddCleanupUpdaterBackupsJob.php
index 3642931694a..8bd938b7e3a 100644
--- a/lib/private/Repair/AddCleanupUpdaterBackupsJob.php
+++ b/lib/private/Repair/AddCleanupUpdaterBackupsJob.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/AddMetadataGenerationJob.php b/lib/private/Repair/AddMetadataGenerationJob.php
new file mode 100644
index 00000000000..4535fb0c9e0
--- /dev/null
+++ b/lib/private/Repair/AddMetadataGenerationJob.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Repair;
+
+use OC\Core\BackgroundJobs\GenerateMetadataJob;
+use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class AddMetadataGenerationJob implements IRepairStep {
+ public function __construct(
+ private IJobList $jobList,
+ ) {
+ }
+
+ public function getName() {
+ return 'Queue a job to generate metadata';
+ }
+
+ public function run(IOutput $output) {
+ $this->jobList->add(GenerateMetadataJob::class);
+ }
+}
diff --git a/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php b/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php
index 94ae39f2183..4ad320a0311 100644
--- a/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php
+++ b/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php
@@ -3,29 +3,14 @@
declare(strict_types=1);
/**
- * @copyright 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
-use OC\TextProcessing\RemoveOldTasksBackgroundJob;
+use OC\TaskProcessing\RemoveOldTasksBackgroundJob;
+use OC\TextProcessing\RemoveOldTasksBackgroundJob as RemoveOldTextProcessingTasksBackgroundJob;
+use OC\TextToImage\RemoveOldTasksBackgroundJob as RemoveOldTextToImageTasksBackgroundJob;
use OCP\BackgroundJob\IJobList;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
@@ -38,10 +23,12 @@ class AddRemoveOldTasksBackgroundJob implements IRepairStep {
}
public function getName(): string {
- return 'Add language model tasks cleanup job';
+ return 'Add AI tasks cleanup jobs';
}
public function run(IOutput $output) {
+ $this->jobList->add(RemoveOldTextProcessingTasksBackgroundJob::class);
+ $this->jobList->add(RemoveOldTextToImageTasksBackgroundJob::class);
$this->jobList->add(RemoveOldTasksBackgroundJob::class);
}
}
diff --git a/lib/private/Repair/CleanTags.php b/lib/private/Repair/CleanTags.php
index 531fcc1112f..f2fc8156f29 100644
--- a/lib/private/Repair/CleanTags.php
+++ b/lib/private/Repair/CleanTags.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/CleanUpAbandonedApps.php b/lib/private/Repair/CleanUpAbandonedApps.php
index ed8fa8d7d28..718f625be86 100644
--- a/lib/private/Repair/CleanUpAbandonedApps.php
+++ b/lib/private/Repair/CleanUpAbandonedApps.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2022 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Repair;
use OCP\IConfig;
diff --git a/lib/private/Repair/ClearFrontendCaches.php b/lib/private/Repair/ClearFrontendCaches.php
index bf94e5bfbff..77a3df5598a 100644
--- a/lib/private/Repair/ClearFrontendCaches.php
+++ b/lib/private/Repair/ClearFrontendCaches.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
@@ -37,7 +18,7 @@ class ClearFrontendCaches implements IRepairStep {
protected $jsCombiner;
public function __construct(ICacheFactory $cacheFactory,
- JSCombiner $JSCombiner) {
+ JSCombiner $JSCombiner) {
$this->cacheFactory = $cacheFactory;
$this->jsCombiner = $JSCombiner;
}
diff --git a/lib/private/Repair/ClearGeneratedAvatarCache.php b/lib/private/Repair/ClearGeneratedAvatarCache.php
index fb3b42847dc..2dea4bd2d61 100644
--- a/lib/private/Repair/ClearGeneratedAvatarCache.php
+++ b/lib/private/Repair/ClearGeneratedAvatarCache.php
@@ -1,32 +1,13 @@
<?php
/**
- * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Michael Weimann <mail@michael-weimann.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
use OC\Avatar\AvatarManager;
-use OCP\IConfig;
use OCP\BackgroundJob\IJobList;
+use OCP\IConfig;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
diff --git a/lib/private/Repair/ClearGeneratedAvatarCacheJob.php b/lib/private/Repair/ClearGeneratedAvatarCacheJob.php
index e8513e7a933..38cf03b731a 100644
--- a/lib/private/Repair/ClearGeneratedAvatarCacheJob.php
+++ b/lib/private/Repair/ClearGeneratedAvatarCacheJob.php
@@ -1,28 +1,13 @@
<?php
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
-use OCP\BackgroundJob\QueuedJob;
-use OCP\AppFramework\Utility\ITimeFactory;
use OC\Avatar\AvatarManager;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\QueuedJob;
class ClearGeneratedAvatarCacheJob extends QueuedJob {
protected AvatarManager $avatarManager;
diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php
index 6f7dde68865..0affb3b1ca9 100644
--- a/lib/private/Repair/Collation.php
+++ b/lib/private/Repair/Collation.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin Müller <coder-hugo@users.noreply.github.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/Events/RepairAdvanceEvent.php b/lib/private/Repair/Events/RepairAdvanceEvent.php
index 174d4ec48cd..c4be72ce530 100644
--- a/lib/private/Repair/Events/RepairAdvanceEvent.php
+++ b/lib/private/Repair/Events/RepairAdvanceEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/Events/RepairErrorEvent.php b/lib/private/Repair/Events/RepairErrorEvent.php
index 7f8a87cfda3..8cd5d41b1b4 100644
--- a/lib/private/Repair/Events/RepairErrorEvent.php
+++ b/lib/private/Repair/Events/RepairErrorEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/Events/RepairFinishEvent.php b/lib/private/Repair/Events/RepairFinishEvent.php
index abdc2acd1ce..767a7506e6f 100644
--- a/lib/private/Repair/Events/RepairFinishEvent.php
+++ b/lib/private/Repair/Events/RepairFinishEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/Events/RepairInfoEvent.php b/lib/private/Repair/Events/RepairInfoEvent.php
index 5c2a53fce4f..c48b295a9a9 100644
--- a/lib/private/Repair/Events/RepairInfoEvent.php
+++ b/lib/private/Repair/Events/RepairInfoEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/Events/RepairStartEvent.php b/lib/private/Repair/Events/RepairStartEvent.php
index 7bb270595c5..e154df5e6e1 100644
--- a/lib/private/Repair/Events/RepairStartEvent.php
+++ b/lib/private/Repair/Events/RepairStartEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/Events/RepairStepEvent.php b/lib/private/Repair/Events/RepairStepEvent.php
index 82af670b950..7140d13687d 100644
--- a/lib/private/Repair/Events/RepairStepEvent.php
+++ b/lib/private/Repair/Events/RepairStepEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/Events/RepairWarningEvent.php b/lib/private/Repair/Events/RepairWarningEvent.php
index 2aaa44d4719..403eec87158 100644
--- a/lib/private/Repair/Events/RepairWarningEvent.php
+++ b/lib/private/Repair/Events/RepairWarningEvent.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair\Events;
diff --git a/lib/private/Repair/MoveUpdaterStepFile.php b/lib/private/Repair/MoveUpdaterStepFile.php
index fc3b9dce1f3..c9b51b308c4 100644
--- a/lib/private/Repair/MoveUpdaterStepFile.php
+++ b/lib/private/Repair/MoveUpdaterStepFile.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/NC11/FixMountStorages.php b/lib/private/Repair/NC11/FixMountStorages.php
index 4cf721e9b13..b1663102d2f 100644
--- a/lib/private/Repair/NC11/FixMountStorages.php
+++ b/lib/private/Repair/NC11/FixMountStorages.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC11;
diff --git a/lib/private/Repair/NC13/AddLogRotateJob.php b/lib/private/Repair/NC13/AddLogRotateJob.php
index e0156ff873c..8fe68a42819 100644
--- a/lib/private/Repair/NC13/AddLogRotateJob.php
+++ b/lib/private/Repair/NC13/AddLogRotateJob.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC13;
diff --git a/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php b/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php
index e12f2771903..417bc5e6adc 100644
--- a/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php
+++ b/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC14;
diff --git a/lib/private/Repair/NC16/AddClenupLoginFlowV2BackgroundJob.php b/lib/private/Repair/NC16/AddClenupLoginFlowV2BackgroundJob.php
index 217141cf0b9..ab5f93415fc 100644
--- a/lib/private/Repair/NC16/AddClenupLoginFlowV2BackgroundJob.php
+++ b/lib/private/Repair/NC16/AddClenupLoginFlowV2BackgroundJob.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC16;
diff --git a/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php b/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php
index 394e47dfcda..a9cbbb4cbbf 100644
--- a/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php
+++ b/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Daniel Kesselberg (mail@danielkesselberg.de)
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC16;
diff --git a/lib/private/Repair/NC16/ClearCollectionsAccessCache.php b/lib/private/Repair/NC16/ClearCollectionsAccessCache.php
index 076e27a6ceb..1627ed40b98 100644
--- a/lib/private/Repair/NC16/ClearCollectionsAccessCache.php
+++ b/lib/private/Repair/NC16/ClearCollectionsAccessCache.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC16;
diff --git a/lib/private/Repair/NC18/ResetGeneratedAvatarFlag.php b/lib/private/Repair/NC18/ResetGeneratedAvatarFlag.php
index d5ae1d7ab63..b0dfec295e7 100644
--- a/lib/private/Repair/NC18/ResetGeneratedAvatarFlag.php
+++ b/lib/private/Repair/NC18/ResetGeneratedAvatarFlag.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC18;
@@ -37,7 +20,7 @@ class ResetGeneratedAvatarFlag implements IRepairStep {
private $connection;
public function __construct(IConfig $config,
- IDBConnection $connection) {
+ IDBConnection $connection) {
$this->config = $config;
$this->connection = $connection;
}
diff --git a/lib/private/Repair/NC20/EncryptionLegacyCipher.php b/lib/private/Repair/NC20/EncryptionLegacyCipher.php
index a7d008e87be..89473ffd5e8 100644
--- a/lib/private/Repair/NC20/EncryptionLegacyCipher.php
+++ b/lib/private/Repair/NC20/EncryptionLegacyCipher.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC20;
@@ -38,7 +20,7 @@ class EncryptionLegacyCipher implements IRepairStep {
private $manager;
public function __construct(IConfig $config,
- IManager $manager) {
+ IManager $manager) {
$this->config = $config;
$this->manager = $manager;
}
diff --git a/lib/private/Repair/NC20/EncryptionMigration.php b/lib/private/Repair/NC20/EncryptionMigration.php
index 239a62c2718..6de143747b3 100644
--- a/lib/private/Repair/NC20/EncryptionMigration.php
+++ b/lib/private/Repair/NC20/EncryptionMigration.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC20;
@@ -38,7 +20,7 @@ class EncryptionMigration implements IRepairStep {
private $manager;
public function __construct(IConfig $config,
- IManager $manager) {
+ IManager $manager) {
$this->config = $config;
$this->manager = $manager;
}
diff --git a/lib/private/Repair/NC20/ShippedDashboardEnable.php b/lib/private/Repair/NC20/ShippedDashboardEnable.php
index a9713d49a6f..955011a8c84 100644
--- a/lib/private/Repair/NC20/ShippedDashboardEnable.php
+++ b/lib/private/Repair/NC20/ShippedDashboardEnable.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC20;
diff --git a/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php b/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php
index ee413ce12ca..4f80b3809e8 100644
--- a/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php
+++ b/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2020 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC21;
diff --git a/lib/private/Repair/NC21/ValidatePhoneNumber.php b/lib/private/Repair/NC21/ValidatePhoneNumber.php
index b3534dbeae8..3a6ace37bd2 100644
--- a/lib/private/Repair/NC21/ValidatePhoneNumber.php
+++ b/lib/private/Repair/NC21/ValidatePhoneNumber.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC21;
@@ -42,8 +24,8 @@ class ValidatePhoneNumber implements IRepairStep {
private $accountManager;
public function __construct(IUserManager $userManager,
- IAccountManager $accountManager,
- IConfig $config) {
+ IAccountManager $accountManager,
+ IConfig $config) {
$this->config = $config;
$this->userManager = $userManager;
$this->accountManager = $accountManager;
diff --git a/lib/private/Repair/NC22/LookupServerSendCheck.php b/lib/private/Repair/NC22/LookupServerSendCheck.php
index eb320593d98..540dc2a730d 100644
--- a/lib/private/Repair/NC22/LookupServerSendCheck.php
+++ b/lib/private/Repair/NC22/LookupServerSendCheck.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC22;
diff --git a/lib/private/Repair/NC24/AddTokenCleanupJob.php b/lib/private/Repair/NC24/AddTokenCleanupJob.php
index 97539c5692f..f1dac2d4e12 100644
--- a/lib/private/Repair/NC24/AddTokenCleanupJob.php
+++ b/lib/private/Repair/NC24/AddTokenCleanupJob.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
- *
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC24;
diff --git a/lib/private/Repair/NC25/AddMissingSecretJob.php b/lib/private/Repair/NC25/AddMissingSecretJob.php
index d3a438b89c1..b407ef2a2a9 100644
--- a/lib/private/Repair/NC25/AddMissingSecretJob.php
+++ b/lib/private/Repair/NC25/AddMissingSecretJob.php
@@ -3,22 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\NC25;
diff --git a/lib/private/Repair/OldGroupMembershipShares.php b/lib/private/Repair/OldGroupMembershipShares.php
index be507debbd9..54f2078395e 100644
--- a/lib/private/Repair/OldGroupMembershipShares.php
+++ b/lib/private/Repair/OldGroupMembershipShares.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/Owncloud/CleanPreviews.php b/lib/private/Repair/Owncloud/CleanPreviews.php
index 853a94c8adc..86e173cf402 100644
--- a/lib/private/Repair/Owncloud/CleanPreviews.php
+++ b/lib/private/Repair/Owncloud/CleanPreviews.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
@@ -47,8 +30,8 @@ class CleanPreviews implements IRepairStep {
* @param IConfig $config
*/
public function __construct(IJobList $jobList,
- IUserManager $userManager,
- IConfig $config) {
+ IUserManager $userManager,
+ IConfig $config) {
$this->jobList = $jobList;
$this->userManager = $userManager;
$this->config = $config;
diff --git a/lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php b/lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php
index 7f4bbc35c17..6c606453bb9 100644
--- a/lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php
+++ b/lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php
@@ -1,30 +1,16 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
-use OC\BackgroundJob\QueuedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
+use OCP\BackgroundJob\QueuedJob;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
@@ -33,33 +19,14 @@ use OCP\IUserManager;
use Psr\Log\LoggerInterface;
class CleanPreviewsBackgroundJob extends QueuedJob {
- /** @var IRootFolder */
- private $rootFolder;
-
- private LoggerInterface $logger;
-
- /** @var IJobList */
- private $jobList;
-
- /** @var ITimeFactory */
- private $timeFactory;
-
- /** @var IUserManager */
- private $userManager;
-
- /**
- * CleanPreviewsBackgroundJob constructor.
- */
- public function __construct(IRootFolder $rootFolder,
- LoggerInterface $logger,
- IJobList $jobList,
- ITimeFactory $timeFactory,
- IUserManager $userManager) {
- $this->rootFolder = $rootFolder;
- $this->logger = $logger;
- $this->jobList = $jobList;
- $this->timeFactory = $timeFactory;
- $this->userManager = $userManager;
+ public function __construct(
+ private IRootFolder $rootFolder,
+ private LoggerInterface $logger,
+ private IJobList $jobList,
+ ITimeFactory $timeFactory,
+ private IUserManager $userManager,
+ ) {
+ parent::__construct($timeFactory);
}
public function run($arguments) {
@@ -80,10 +47,9 @@ class CleanPreviewsBackgroundJob extends QueuedJob {
}
/**
- * @param $uid
- * @return bool
+ * @param string $uid
*/
- private function cleanupPreviews($uid) {
+ private function cleanupPreviews($uid): bool {
try {
$userFolder = $this->rootFolder->getUserFolder($uid);
} catch (NotFoundException $e) {
@@ -101,7 +67,7 @@ class CleanPreviewsBackgroundJob extends QueuedJob {
$thumbnails = $thumbnailFolder->getDirectoryListing();
- $start = $this->timeFactory->getTime();
+ $start = $this->time->getTime();
foreach ($thumbnails as $thumbnail) {
try {
$thumbnail->delete();
@@ -109,7 +75,7 @@ class CleanPreviewsBackgroundJob extends QueuedJob {
// Ignore
}
- if (($this->timeFactory->getTime() - $start) > 15) {
+ if (($this->time->getTime() - $start) > 15) {
return false;
}
}
diff --git a/lib/private/Repair/Owncloud/DropAccountTermsTable.php b/lib/private/Repair/Owncloud/DropAccountTermsTable.php
index d5c01d64131..18f169c9b49 100644
--- a/lib/private/Repair/Owncloud/DropAccountTermsTable.php
+++ b/lib/private/Repair/Owncloud/DropAccountTermsTable.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
diff --git a/lib/private/Repair/Owncloud/MigrateOauthTables.php b/lib/private/Repair/Owncloud/MigrateOauthTables.php
index 5bf0816d8de..e8728cd2f66 100644
--- a/lib/private/Repair/Owncloud/MigrateOauthTables.php
+++ b/lib/private/Repair/Owncloud/MigrateOauthTables.php
@@ -1,30 +1,15 @@
<?php
/**
- * @copyright 2021 Louis Chemineau <louis@chmn.me>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
-use OCP\Migration\IOutput;
-use OCP\Migration\IRepairStep;
use OC\DB\Connection;
use OC\DB\SchemaWrapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
class MigrateOauthTables implements IRepairStep {
/** @var Connection */
diff --git a/lib/private/Repair/Owncloud/MoveAvatars.php b/lib/private/Repair/Owncloud/MoveAvatars.php
index 44ba9b7643b..7fdabae7a66 100644
--- a/lib/private/Repair/Owncloud/MoveAvatars.php
+++ b/lib/private/Repair/Owncloud/MoveAvatars.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
@@ -41,7 +24,7 @@ class MoveAvatars implements IRepairStep {
* @param IConfig $config
*/
public function __construct(IJobList $jobList,
- IConfig $config) {
+ IConfig $config) {
$this->jobList = $jobList;
$this->config = $config;
}
diff --git a/lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php b/lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php
index 83c78c2cba4..e145fb71863 100644
--- a/lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php
+++ b/lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php
@@ -1,32 +1,18 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
-use OC\BackgroundJob\QueuedJob;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\QueuedJob;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
-use OCP\Files\Storage;
+use OCP\Files\Storage\IStorage;
use OCP\IAvatarManager;
use OCP\IUser;
use OCP\IUserManager;
@@ -34,22 +20,16 @@ use Psr\Log\LoggerInterface;
use function is_resource;
class MoveAvatarsBackgroundJob extends QueuedJob {
- /** @var IUserManager */
- private $userManager;
-
- /** @var LoggerInterface */
- private $logger;
-
- /** @var IAvatarManager */
- private $avatarManager;
-
- /** @var Storage */
- private $owncloudAvatarStorage;
+ private ?IStorage $owncloudAvatarStorage = null;
- public function __construct(IUserManager $userManager, LoggerInterface $logger, IAvatarManager $avatarManager, IRootFolder $rootFolder) {
- $this->userManager = $userManager;
- $this->logger = $logger;
- $this->avatarManager = $avatarManager;
+ public function __construct(
+ private IUserManager $userManager,
+ private LoggerInterface $logger,
+ private IAvatarManager $avatarManager,
+ private IRootFolder $rootFolder,
+ ITimeFactory $time,
+ ) {
+ parent::__construct($time);
try {
$this->owncloudAvatarStorage = $rootFolder->get('avatars')->getStorage();
} catch (\Exception $e) {
@@ -69,7 +49,7 @@ class MoveAvatarsBackgroundJob extends QueuedJob {
}
$counter = 0;
- $this->userManager->callForSeenUsers(function (IUser $user) use ($counter) {
+ $this->userManager->callForSeenUsers(function (IUser $user) use (&$counter) {
$uid = $user->getUID();
$path = 'avatars/' . $this->buildOwnCloudAvatarPath($uid);
diff --git a/lib/private/Repair/Owncloud/SaveAccountsTableData.php b/lib/private/Repair/Owncloud/SaveAccountsTableData.php
index 94fd1554293..1b6da7c858f 100644
--- a/lib/private/Repair/Owncloud/SaveAccountsTableData.php
+++ b/lib/private/Repair/Owncloud/SaveAccountsTableData.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
diff --git a/lib/private/Repair/Owncloud/UpdateLanguageCodes.php b/lib/private/Repair/Owncloud/UpdateLanguageCodes.php
index e08a0b55a9a..e27ab06b2f3 100644
--- a/lib/private/Repair/Owncloud/UpdateLanguageCodes.php
+++ b/lib/private/Repair/Owncloud/UpdateLanguageCodes.php
@@ -1,24 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair\Owncloud;
@@ -40,7 +23,7 @@ class UpdateLanguageCodes implements IRepairStep {
* @param IConfig $config
*/
public function __construct(IDBConnection $connection,
- IConfig $config) {
+ IConfig $config) {
$this->connection = $connection;
$this->config = $config;
}
diff --git a/lib/private/Repair/RemoveLinkShares.php b/lib/private/Repair/RemoveLinkShares.php
index b45a1d83a56..f128b6f731b 100644
--- a/lib/private/Repair/RemoveLinkShares.php
+++ b/lib/private/Repair/RemoveLinkShares.php
@@ -3,29 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
@@ -54,10 +33,10 @@ class RemoveLinkShares implements IRepairStep {
private $timeFactory;
public function __construct(IDBConnection $connection,
- IConfig $config,
- IGroupManager $groupManager,
- IManager $notificationManager,
- ITimeFactory $timeFactory) {
+ IConfig $config,
+ IGroupManager $groupManager,
+ IManager $notificationManager,
+ ITimeFactory $timeFactory) {
$this->connection = $connection;
$this->config = $config;
$this->groupManager = $groupManager;
diff --git a/lib/private/Repair/RepairDavShares.php b/lib/private/Repair/RepairDavShares.php
index 467adc2b0d9..792fdd4033e 100644
--- a/lib/private/Repair/RepairDavShares.php
+++ b/lib/private/Repair/RepairDavShares.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php
index 9255034f6fe..f28ae1c45fb 100644
--- a/lib/private/Repair/RepairInvalidShares.php
+++ b/lib/private/Repair/RepairInvalidShares.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair;
diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php
index ee5a84ad65c..103ce9c13fc 100644
--- a/lib/private/Repair/RepairMimeTypes.php
+++ b/lib/private/Repair/RepairMimeTypes.php
@@ -1,35 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author nik gaffney <nik@fo.am>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Rello <Rello@users.noreply.github.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Ebert <thomas.ebert@usability.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair;
@@ -49,7 +23,7 @@ class RepairMimeTypes implements IRepairStep {
protected $folderMimeTypeId;
public function __construct(IConfig $config,
- IDBConnection $connection) {
+ IDBConnection $connection) {
$this->config = $config;
$this->connection = $connection;
}
@@ -229,6 +203,38 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
+ private function introduceEnhancedMetafileFormatType() {
+ $updatedMimetypes = [
+ 'emf' => 'image/emf',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+ private function introduceEmlAndMsgFormatType() {
+ $updatedMimetypes = [
+ 'eml' => 'message/rfc822',
+ 'msg' => 'application/vnd.ms-outlook',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+ private function introduceAacAudioType() {
+ $updatedMimetypes = [
+ 'aac' => 'audio/aac',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+ private function introduceReStructuredTextFormatType() {
+ $updatedMimetypes = [
+ 'rst' => 'text/x-rst',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
/**
* Fix mime types
@@ -286,5 +292,21 @@ class RepairMimeTypes implements IRepairStep {
if (version_compare($ocVersionFromBeforeUpdate, '26.0.0.1', '<') && $this->introduceAsciidocType()) {
$out->info('Fixed AsciiDoc mime types');
}
+
+ if (version_compare($ocVersionFromBeforeUpdate, '28.0.0.5', '<') && $this->introduceEnhancedMetafileFormatType()) {
+ $out->info('Fixed Enhanced Metafile Format mime types');
+ }
+
+ if (version_compare($ocVersionFromBeforeUpdate, '29.0.0.2', '<') && $this->introduceEmlAndMsgFormatType()) {
+ $out->info('Fixed eml and msg mime type');
+ }
+
+ if (version_compare($ocVersionFromBeforeUpdate, '29.0.0.6', '<') && $this->introduceAacAudioType()) {
+ $out->info('Fixed aac mime type');
+ }
+
+ if (version_compare($ocVersionFromBeforeUpdate, '29.0.0.10', '<') && $this->introduceReStructuredTextFormatType()) {
+ $out->info('Fixed ReStructured Text mime type');
+ }
}
}
diff --git a/lib/private/Repair/SqliteAutoincrement.php b/lib/private/Repair/SqliteAutoincrement.php
deleted file mode 100644
index 4a8b2a45d3f..00000000000
--- a/lib/private/Repair/SqliteAutoincrement.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\Repair;
-
-use Doctrine\DBAL\Platforms\SqlitePlatform;
-use Doctrine\DBAL\Schema\ColumnDiff;
-use Doctrine\DBAL\Schema\SchemaDiff;
-use Doctrine\DBAL\Schema\SchemaException;
-use Doctrine\DBAL\Schema\TableDiff;
-use OCP\Migration\IOutput;
-use OCP\Migration\IRepairStep;
-
-/**
- * Fixes Sqlite autoincrement by forcing the SQLite table schemas to be
- * altered in order to retrigger SQL schema generation through OCSqlitePlatform.
- */
-class SqliteAutoincrement implements IRepairStep {
- /**
- * @var \OC\DB\Connection
- */
- protected $connection;
-
- /**
- * @param \OC\DB\Connection $connection
- */
- public function __construct($connection) {
- $this->connection = $connection;
- }
-
- public function getName() {
- return 'Repair SQLite autoincrement';
- }
-
- /**
- * Fix mime types
- */
- public function run(IOutput $out) {
- if (!$this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
- return;
- }
-
- $sourceSchema = $this->connection->getSchemaManager()->createSchema();
-
- $schemaDiff = new SchemaDiff();
-
- foreach ($sourceSchema->getTables() as $tableSchema) {
- $primaryKey = $tableSchema->getPrimaryKey();
- if (!$primaryKey) {
- continue;
- }
-
- $columnNames = $primaryKey->getColumns();
-
- // add a column diff for every primary key column,
- // but do not actually change anything, this will
- // force the generation of SQL statements to alter
- // those tables, which will then trigger the
- // specific SQL code from OCSqlitePlatform
- try {
- $tableDiff = new TableDiff($tableSchema->getName());
- $tableDiff->fromTable = $tableSchema;
- foreach ($columnNames as $columnName) {
- $columnSchema = $tableSchema->getColumn($columnName);
- $columnDiff = new ColumnDiff($columnSchema->getName(), $columnSchema);
- $tableDiff->changedColumns[$columnSchema->getName()] = $columnDiff;
- $schemaDiff->changedTables[] = $tableDiff;
- }
- } catch (SchemaException $e) {
- // ignore
- }
- }
-
- $this->connection->beginTransaction();
- foreach ($schemaDiff->toSql($this->connection->getDatabasePlatform()) as $sql) {
- $this->connection->query($sql);
- }
- $this->connection->commit();
- }
-}
diff --git a/lib/private/RepairException.php b/lib/private/RepairException.php
index 6cce3b0e0d6..bd6d4600bfb 100644
--- a/lib/private/RepairException.php
+++ b/lib/private/RepairException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/RichObjectStrings/Validator.php b/lib/private/RichObjectStrings/Validator.php
index 4585cbfc814..41c2456ba27 100644
--- a/lib/private/RichObjectStrings/Validator.php
+++ b/lib/private/RichObjectStrings/Validator.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\RichObjectStrings;
@@ -95,7 +76,7 @@ class Validator implements IValidator {
$missingKeys = array_diff($requiredParameters, array_keys($parameter));
if (!empty($missingKeys)) {
- throw new InvalidObjectExeption('Object is invalid');
+ throw new InvalidObjectExeption('Object is invalid, missing keys:'.json_encode($missingKeys));
}
}
diff --git a/lib/private/Route/CachingRouter.php b/lib/private/Route/CachingRouter.php
index 69fb3c986c9..7dd26827d3c 100644
--- a/lib/private/Route/CachingRouter.php
+++ b/lib/private/Route/CachingRouter.php
@@ -1,29 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Route;
+use OCP\App\IAppManager;
use OCP\Diagnostics\IEventLogger;
use OCP\ICache;
use OCP\ICacheFactory;
@@ -41,10 +25,11 @@ class CachingRouter extends Router {
IRequest $request,
IConfig $config,
IEventLogger $eventLogger,
- ContainerInterface $container
+ ContainerInterface $container,
+ IAppManager $appManager,
) {
$this->cache = $cacheFactory->createLocal('route');
- parent::__construct($logger, $request, $config, $eventLogger, $container);
+ parent::__construct($logger, $request, $config, $eventLogger, $container, $appManager);
}
/**
diff --git a/lib/private/Route/Route.php b/lib/private/Route/Route.php
index ad440a001af..2fef3b10806 100644
--- a/lib/private/Route/Route.php
+++ b/lib/private/Route/Route.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author David Prévot <taffit@debian.org>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Route;
diff --git a/lib/private/Route/Router.php b/lib/private/Route/Router.php
index fe97623176d..b04b6a4d21c 100644
--- a/lib/private/Route/Router.php
+++ b/lib/private/Route/Router.php
@@ -1,39 +1,18 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Route;
+use DirectoryIterator;
use OC\AppFramework\Routing\RouteParser;
+use OCP\App\AppPathNotFoundException;
+use OCP\App\IAppManager;
use OCP\AppFramework\App;
+use OCP\AppFramework\Http\Attribute\Route as RouteAttribute;
use OCP\Diagnostics\IEventLogger;
use OCP\IConfig;
use OCP\IRequest;
@@ -41,6 +20,9 @@ use OCP\Route\IRouter;
use OCP\Util;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
+use ReflectionAttribute;
+use ReflectionClass;
+use ReflectionException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Generator\UrlGenerator;
@@ -65,22 +47,17 @@ class Router implements IRouter {
protected $loaded = false;
/** @var array */
protected $loadedApps = [];
- protected LoggerInterface $logger;
/** @var RequestContext */
protected $context;
- private IEventLogger $eventLogger;
- private IConfig $config;
- private ContainerInterface $container;
public function __construct(
- LoggerInterface $logger,
+ protected LoggerInterface $logger,
IRequest $request,
- IConfig $config,
- IEventLogger $eventLogger,
- ContainerInterface $container
+ private IConfig $config,
+ private IEventLogger $eventLogger,
+ private ContainerInterface $container,
+ private IAppManager $appManager,
) {
- $this->logger = $logger;
- $this->config = $config;
$baseUrl = \OC::$WEBROOT;
if (!($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
$baseUrl .= '/index.php';
@@ -95,8 +72,6 @@ class Router implements IRouter {
$this->context = new RequestContext($baseUrl, $method, $host, $schema);
// TODO cache
$this->root = $this->getCollection('root');
- $this->eventLogger = $eventLogger;
- $this->container = $container;
}
/**
@@ -108,12 +83,14 @@ class Router implements IRouter {
if ($this->routingFiles === null) {
$this->routingFiles = [];
foreach (\OC_APP::getEnabledApps() as $app) {
- $appPath = \OC_App::getAppPath($app);
- if ($appPath !== false) {
+ try {
+ $appPath = $this->appManager->getAppPath($app);
$file = $appPath . '/appinfo/routes.php';
if (file_exists($file)) {
$this->routingFiles[$app] = $file;
}
+ } catch (AppPathNotFoundException) {
+ /* ignore */
}
}
}
@@ -150,6 +127,22 @@ class Router implements IRouter {
}
}
$this->eventLogger->start('route:load:' . $requestedApp, 'Loading Routes for ' . $requestedApp);
+
+ if ($requestedApp !== null && in_array($requestedApp, \OC_App::getEnabledApps())) {
+ $routes = $this->getAttributeRoutes($requestedApp);
+ if (count($routes) > 0) {
+ $this->useCollection($requestedApp);
+ $this->setupRoutes($routes, $requestedApp);
+ $collection = $this->getCollection($requestedApp);
+ $this->root->addCollection($collection);
+
+ // Also add the OCS collection
+ $collection = $this->getCollection($requestedApp . '.ocs');
+ $collection->addPrefix('/ocsapp');
+ $this->root->addCollection($collection);
+ }
+ }
+
foreach ($routingFiles as $app => $file) {
if (!isset($this->loadedApps[$app])) {
if (!\OC_App::isAppLoaded($app)) {
@@ -173,6 +166,7 @@ class Router implements IRouter {
if (!isset($this->loadedApps['core'])) {
$this->loadedApps['core'] = true;
$this->useCollection('root');
+ $this->setupRoutes($this->getAttributeRoutes('core'), 'core');
require_once __DIR__ . '/../../../core/routes.php';
// Also add the OCS collection
@@ -230,9 +224,9 @@ class Router implements IRouter {
* @return \OC\Route\Route
*/
public function create($name,
- $pattern,
- array $defaults = [],
- array $requirements = []) {
+ $pattern,
+ array $defaults = [],
+ array $requirements = []) {
$route = new Route($pattern, $defaults, $requirements);
$this->collection->add($name, $route);
return $route;
@@ -247,23 +241,23 @@ class Router implements IRouter {
*/
public function findMatchingRoute(string $url): array {
$this->eventLogger->start('route:match', 'Match route');
- if (substr($url, 0, 6) === '/apps/') {
+ if (str_starts_with($url, '/apps/')) {
// empty string / 'apps' / $app / rest of the route
[, , $app,] = explode('/', $url, 4);
$app = \OC_App::cleanAppId($app);
\OC::$REQUESTEDAPP = $app;
$this->loadRoutes($app);
- } elseif (substr($url, 0, 13) === '/ocsapp/apps/') {
+ } elseif (str_starts_with($url, '/ocsapp/apps/')) {
// empty string / 'ocsapp' / 'apps' / $app / rest of the route
[, , , $app,] = explode('/', $url, 5);
$app = \OC_App::cleanAppId($app);
\OC::$REQUESTEDAPP = $app;
$this->loadRoutes($app);
- } elseif (substr($url, 0, 10) === '/settings/') {
+ } elseif (str_starts_with($url, '/settings/')) {
$this->loadRoutes('settings');
- } elseif (substr($url, 0, 6) === '/core/') {
+ } elseif (str_starts_with($url, '/core/')) {
\OC::$REQUESTEDAPP = $url;
if (!$this->config->getSystemValueBool('maintenance') && !Util::needUpgrade()) {
\OC_App::loadApps();
@@ -277,7 +271,7 @@ class Router implements IRouter {
try {
$parameters = $matcher->match($url);
} catch (ResourceNotFoundException $e) {
- if (substr($url, -1) !== '/') {
+ if (!str_ends_with($url, '/')) {
// We allow links to apps/files? for backwards compatibility reasons
// However, since Symfony does not allow empty route names, the route
// we need to match is '/', so we need to append the '/' here.
@@ -338,7 +332,7 @@ class Router implements IRouter {
*
*/
public function getGenerator() {
- if (null !== $this->generator) {
+ if ($this->generator !== null) {
return $this->generator;
}
@@ -354,12 +348,19 @@ class Router implements IRouter {
* @return string
*/
public function generate($name,
- $parameters = [],
- $absolute = false) {
+ $parameters = [],
+ $absolute = false) {
$referenceType = UrlGenerator::ABSOLUTE_URL;
if ($absolute === false) {
$referenceType = UrlGenerator::ABSOLUTE_PATH;
}
+ /*
+ * The route name has to be lowercase, for symfony to match it correctly.
+ * This is required because smyfony allows mixed casing for controller names in the routes.
+ * To avoid breaking all the existing route names, registering and matching will only use the lowercase names.
+ * This is also safe on the PHP side because class and method names collide regardless of the casing.
+ */
+ $name = strtolower($name);
$name = $this->fixLegacyRootName($name);
if (str_contains($name, '.')) {
[$appName, $other] = explode('.', $name, 3);
@@ -385,34 +386,79 @@ class Router implements IRouter {
}
protected function fixLegacyRootName(string $routeName): string {
- if ($routeName === 'files.viewcontroller.showFile') {
- return 'files.View.showFile';
+ if ($routeName === 'files.viewcontroller.showfile') {
+ return 'files.view.showfile';
}
- if ($routeName === 'files_sharing.sharecontroller.showShare') {
- return 'files_sharing.Share.showShare';
+ if ($routeName === 'files_sharing.sharecontroller.showshare') {
+ return 'files_sharing.share.showshare';
}
- if ($routeName === 'files_sharing.sharecontroller.showAuthenticate') {
- return 'files_sharing.Share.showAuthenticate';
+ if ($routeName === 'files_sharing.sharecontroller.showauthenticate') {
+ return 'files_sharing.share.showauthenticate';
}
if ($routeName === 'files_sharing.sharecontroller.authenticate') {
- return 'files_sharing.Share.authenticate';
+ return 'files_sharing.share.authenticate';
}
- if ($routeName === 'files_sharing.sharecontroller.downloadShare') {
- return 'files_sharing.Share.downloadShare';
+ if ($routeName === 'files_sharing.sharecontroller.downloadshare') {
+ return 'files_sharing.share.downloadshare';
}
- if ($routeName === 'files_sharing.publicpreview.directLink') {
- return 'files_sharing.PublicPreview.directLink';
+ if ($routeName === 'files_sharing.publicpreview.directlink') {
+ return 'files_sharing.publicpreview.directlink';
}
- if ($routeName === 'cloud_federation_api.requesthandlercontroller.addShare') {
- return 'cloud_federation_api.RequestHandler.addShare';
+ if ($routeName === 'cloud_federation_api.requesthandlercontroller.addshare') {
+ return 'cloud_federation_api.requesthandler.addshare';
}
- if ($routeName === 'cloud_federation_api.requesthandlercontroller.receiveNotification') {
- return 'cloud_federation_api.RequestHandler.receiveNotification';
+ if ($routeName === 'cloud_federation_api.requesthandlercontroller.receivenotification') {
+ return 'cloud_federation_api.requesthandler.receivenotification';
}
return $routeName;
}
/**
+ * @throws ReflectionException
+ */
+ private function getAttributeRoutes(string $app): array {
+ $routes = [];
+
+ if ($app === 'core') {
+ $appControllerPath = __DIR__ . '/../../../core/Controller';
+ $appNameSpace = 'OC\\Core';
+ } else {
+ $appControllerPath = \OC_App::getAppPath($app) . '/lib/Controller';
+ $appNameSpace = App::buildAppNamespace($app);
+ }
+
+ if (!file_exists($appControllerPath)) {
+ return [];
+ }
+
+ $dir = new DirectoryIterator($appControllerPath);
+ foreach ($dir as $file) {
+ if (!str_ends_with($file->getPathname(), 'Controller.php')) {
+ continue;
+ }
+
+ $class = new ReflectionClass($appNameSpace . '\\Controller\\' . basename($file->getPathname(), '.php'));
+
+ foreach ($class->getMethods() as $method) {
+ foreach ($method->getAttributes(RouteAttribute::class, ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
+ $route = $attribute->newInstance();
+
+ $serializedRoute = $route->toArray();
+ // Remove 'Controller' suffix
+ $serializedRoute['name'] = substr($class->getShortName(), 0, -10) . '#' . $method->getName();
+
+ $key = $route->getType();
+
+ $routes[$key] ??= [];
+ $routes[$key][] = $serializedRoute;
+ }
+ }
+ }
+
+ return $routes;
+ }
+
+ /**
* To isolate the variable scope used inside the $file it is required in it's own method
*
* @param string $file the route file location to include
diff --git a/lib/private/Search.php b/lib/private/Search.php
index b1e39843e49..d51a305b331 100644
--- a/lib/private/Search.php
+++ b/lib/private/Search.php
@@ -1,35 +1,16 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andrew Brown <andrew@casabrown.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
use OCP\ISearch;
use OCP\Search\PagedProvider;
use OCP\Search\Provider;
+use Psr\Log\LoggerInterface;
/**
* Provide an interface to all search providers
@@ -65,7 +46,7 @@ class Search implements ISearch {
$results = array_merge($results, $providerResults);
}
} else {
- \OC::$server->getLogger()->warning('Ignoring Unknown search provider', ['provider' => $provider]);
+ \OCP\Server::get(LoggerInterface::class)->warning('Ignoring Unknown search provider', ['provider' => $provider]);
}
}
return $results;
diff --git a/lib/private/Search/Filter/BooleanFilter.php b/lib/private/Search/Filter/BooleanFilter.php
new file mode 100644
index 00000000000..92572a60073
--- /dev/null
+++ b/lib/private/Search/Filter/BooleanFilter.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\Search\IFilter;
+
+class BooleanFilter implements IFilter {
+ private bool $value;
+
+ public function __construct(string $value) {
+ $this->value = match ($value) {
+ 'true', 'yes', 'y', '1' => true,
+ 'false', 'no', 'n', '0', '' => false,
+ default => throw new InvalidArgumentException('Invalid boolean value '. $value),
+ };
+ }
+
+ public function get(): bool {
+ return $this->value;
+ }
+}
diff --git a/lib/private/Search/Filter/DateTimeFilter.php b/lib/private/Search/Filter/DateTimeFilter.php
new file mode 100644
index 00000000000..367af80b505
--- /dev/null
+++ b/lib/private/Search/Filter/DateTimeFilter.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use DateTimeImmutable;
+use OCP\Search\IFilter;
+
+class DateTimeFilter implements IFilter {
+ private DateTimeImmutable $value;
+
+ public function __construct(string $value) {
+ if (filter_var($value, FILTER_VALIDATE_INT)) {
+ $value = '@'.$value;
+ }
+
+ $this->value = new DateTimeImmutable($value);
+ }
+
+ public function get(): DateTimeImmutable {
+ return $this->value;
+ }
+}
diff --git a/lib/private/Search/Filter/FloatFilter.php b/lib/private/Search/Filter/FloatFilter.php
new file mode 100644
index 00000000000..97d767e62cb
--- /dev/null
+++ b/lib/private/Search/Filter/FloatFilter.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\Search\IFilter;
+
+class FloatFilter implements IFilter {
+ private float $value;
+
+ public function __construct(string $value) {
+ $this->value = filter_var($value, FILTER_VALIDATE_FLOAT);
+ if ($this->value === false) {
+ throw new InvalidArgumentException('Invalid float value '. $value);
+ }
+ }
+
+ public function get(): float {
+ return $this->value;
+ }
+}
diff --git a/lib/private/Search/Filter/GroupFilter.php b/lib/private/Search/Filter/GroupFilter.php
new file mode 100644
index 00000000000..e7694a6daa2
--- /dev/null
+++ b/lib/private/Search/Filter/GroupFilter.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\Search\IFilter;
+
+class GroupFilter implements IFilter {
+ private IGroup $group;
+
+ public function __construct(
+ string $value,
+ IGroupManager $groupManager,
+ ) {
+ $group = $groupManager->get($value);
+ if ($group === null) {
+ throw new InvalidArgumentException('Group '.$value.' not found');
+ }
+ $this->group = $group;
+ }
+
+ public function get(): IGroup {
+ return $this->group;
+ }
+}
diff --git a/lib/private/Search/Filter/IntegerFilter.php b/lib/private/Search/Filter/IntegerFilter.php
new file mode 100644
index 00000000000..825c7ddd3eb
--- /dev/null
+++ b/lib/private/Search/Filter/IntegerFilter.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\Search\IFilter;
+
+class IntegerFilter implements IFilter {
+ private int $value;
+
+ public function __construct(string $value) {
+ $this->value = filter_var($value, FILTER_VALIDATE_INT);
+ if ($this->value === false) {
+ throw new InvalidArgumentException('Invalid integer value '. $value);
+ }
+ }
+
+ public function get(): int {
+ return $this->value;
+ }
+}
diff --git a/lib/private/Search/Filter/StringFilter.php b/lib/private/Search/Filter/StringFilter.php
new file mode 100644
index 00000000000..6944a7803f3
--- /dev/null
+++ b/lib/private/Search/Filter/StringFilter.php
@@ -0,0 +1,27 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\Search\IFilter;
+
+class StringFilter implements IFilter {
+ public function __construct(
+ private string $value,
+ ) {
+ if ($value === '') {
+ throw new InvalidArgumentException('String filter can’t be empty');
+ }
+ }
+
+ public function get(): string {
+ return $this->value;
+ }
+}
diff --git a/lib/private/Search/Filter/StringsFilter.php b/lib/private/Search/Filter/StringsFilter.php
new file mode 100644
index 00000000000..8b8fabb5347
--- /dev/null
+++ b/lib/private/Search/Filter/StringsFilter.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\Search\IFilter;
+
+class StringsFilter implements IFilter {
+ /**
+ * @var string[]
+ */
+ private array $values;
+
+ public function __construct(string ...$values) {
+ $this->values = array_unique(array_filter($values));
+ if (empty($this->values)) {
+ throw new InvalidArgumentException('Strings filter can’t be empty');
+ }
+ }
+
+ /**
+ * @return string[]
+ */
+ public function get(): array {
+ return $this->values;
+ }
+}
diff --git a/lib/private/Search/Filter/UserFilter.php b/lib/private/Search/Filter/UserFilter.php
new file mode 100644
index 00000000000..fbbc793e633
--- /dev/null
+++ b/lib/private/Search/Filter/UserFilter.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Search\Filter;
+
+use InvalidArgumentException;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Search\IFilter;
+
+class UserFilter implements IFilter {
+ private IUser $user;
+
+ public function __construct(
+ string $value,
+ IUserManager $userManager,
+ ) {
+ $user = $userManager->get($value);
+ if ($user === null) {
+ throw new InvalidArgumentException('User '.$value.' not found');
+ }
+ $this->user = $user;
+ }
+
+ public function get(): IUser {
+ return $this->user;
+ }
+}
diff --git a/lib/private/Search/FilterCollection.php b/lib/private/Search/FilterCollection.php
new file mode 100644
index 00000000000..173c967245a
--- /dev/null
+++ b/lib/private/Search/FilterCollection.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Search;
+
+use Generator;
+use OCP\Search\IFilter;
+use OCP\Search\IFilterCollection;
+
+/**
+ * Interface for search filters
+ *
+ * @since 28.0.0
+ */
+class FilterCollection implements IFilterCollection {
+ /**
+ * @var IFilter[]
+ */
+ private array $filters;
+
+ public function __construct(IFilter ...$filters) {
+ $this->filters = $filters;
+ }
+
+ public function has(string $name): bool {
+ return isset($this->filters[$name]);
+ }
+
+ public function get(string $name): ?IFilter {
+ return $this->filters[$name] ?? null;
+ }
+
+ public function getIterator(): Generator {
+ foreach ($this->filters as $k => $v) {
+ yield $k => $v;
+ }
+ }
+}
diff --git a/lib/private/Search/FilterFactory.php b/lib/private/Search/FilterFactory.php
new file mode 100644
index 00000000000..1317dd759af
--- /dev/null
+++ b/lib/private/Search/FilterFactory.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Search;
+
+use OCP\IGroupManager;
+use OCP\IUserManager;
+use OCP\Search\FilterDefinition;
+use OCP\Search\IFilter;
+use RuntimeException;
+
+final class FilterFactory {
+ private const PERSON_TYPE_SEPARATOR = '/';
+
+ public static function get(string $type, string|array $filter): IFilter {
+ return match ($type) {
+ FilterDefinition::TYPE_BOOL => new Filter\BooleanFilter($filter),
+ FilterDefinition::TYPE_DATETIME => new Filter\DateTimeFilter($filter),
+ FilterDefinition::TYPE_FLOAT => new Filter\FloatFilter($filter),
+ FilterDefinition::TYPE_INT => new Filter\IntegerFilter($filter),
+ FilterDefinition::TYPE_NC_GROUP => new Filter\GroupFilter($filter, \OC::$server->get(IGroupManager::class)),
+ FilterDefinition::TYPE_NC_USER => new Filter\UserFilter($filter, \OC::$server->get(IUserManager::class)),
+ FilterDefinition::TYPE_PERSON => self::getPerson($filter),
+ FilterDefinition::TYPE_STRING => new Filter\StringFilter($filter),
+ FilterDefinition::TYPE_STRINGS => new Filter\StringsFilter(... (array) $filter),
+ default => throw new RuntimeException('Invalid filter type '. $type),
+ };
+ }
+
+ private static function getPerson(string $person): IFilter {
+ $parts = explode(self::PERSON_TYPE_SEPARATOR, $person, 2);
+
+ return match (count($parts)) {
+ 1 => self::get(FilterDefinition::TYPE_NC_USER, $person),
+ 2 => self::get(... $parts),
+ };
+ }
+}
diff --git a/lib/private/Search/Provider/File.php b/lib/private/Search/Provider/File.php
index 5ec0132cc03..ca4b1b8677f 100644
--- a/lib/private/Search/Provider/File.php
+++ b/lib/private/Search/Provider/File.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andrew Brown <andrew@casabrown.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Search\Provider;
@@ -51,7 +31,7 @@ class File extends PagedProvider {
* @return \OCP\Search\Result[]
* @deprecated 20.0.0
*/
- public function search($query, int $limit = null, int $offset = null) {
+ public function search($query, ?int $limit = null, ?int $offset = null) {
/** @var IRootFolder $rootFolder */
$rootFolder = \OCP\Server::get(IRootFolder::class);
/** @var IUserSession $userSession */
diff --git a/lib/private/Search/Result/Audio.php b/lib/private/Search/Result/Audio.php
index 41afe691e8c..42b8ac75da0 100644
--- a/lib/private/Search/Result/Audio.php
+++ b/lib/private/Search/Result/Audio.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andrew Brown <andrew@casabrown.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Search\Result;
diff --git a/lib/private/Search/Result/File.php b/lib/private/Search/Result/File.php
index 59111b0cee2..f1346481b86 100644
--- a/lib/private/Search/Result/File.php
+++ b/lib/private/Search/Result/File.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andrew Brown <andrew@casabrown.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Search\Result;
diff --git a/lib/private/Search/Result/Folder.php b/lib/private/Search/Result/Folder.php
index 36d0e91c042..37de0a031a7 100644
--- a/lib/private/Search/Result/Folder.php
+++ b/lib/private/Search/Result/Folder.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andrew Brown <andrew@casabrown.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Search\Result;
diff --git a/lib/private/Search/Result/Image.php b/lib/private/Search/Result/Image.php
index 27f5702e39a..e1333424017 100644
--- a/lib/private/Search/Result/Image.php
+++ b/lib/private/Search/Result/Image.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andrew Brown <andrew@casabrown.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Search\Result;
diff --git a/lib/private/Search/SearchComposer.php b/lib/private/Search/SearchComposer.php
index 4ec73ec54e9..8108c6bcde4 100644
--- a/lib/private/Search/SearchComposer.php
+++ b/lib/private/Search/SearchComposer.php
@@ -3,39 +3,26 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Search;
use InvalidArgumentException;
-use OCP\AppFramework\QueryException;
-use OCP\IServerContainer;
+use OC\AppFramework\Bootstrap\Coordinator;
+use OCP\IURLGenerator;
use OCP\IUser;
+use OCP\Search\FilterDefinition;
+use OCP\Search\IFilter;
+use OCP\Search\IFilteringProvider;
+use OCP\Search\IInAppSearch;
use OCP\Search\IProvider;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
-use OC\AppFramework\Bootstrap\Coordinator;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
+use RuntimeException;
use function array_map;
/**
@@ -58,31 +45,40 @@ use function array_map;
* @see IProvider::search() for the arguments of the individual search requests
*/
class SearchComposer {
- /** @var IProvider[] */
- private $providers = [];
-
- /** @var Coordinator */
- private $bootstrapCoordinator;
+ /**
+ * @var array<string, array{appId: string, provider: IProvider}>
+ */
+ private array $providers = [];
- /** @var IServerContainer */
- private $container;
+ private array $commonFilters;
+ private array $customFilters = [];
- private LoggerInterface $logger;
+ private array $handlers = [];
- public function __construct(Coordinator $bootstrapCoordinator,
- IServerContainer $container,
- LoggerInterface $logger) {
- $this->container = $container;
- $this->logger = $logger;
- $this->bootstrapCoordinator = $bootstrapCoordinator;
+ public function __construct(
+ private Coordinator $bootstrapCoordinator,
+ private ContainerInterface $container,
+ private IURLGenerator $urlGenerator,
+ private LoggerInterface $logger
+ ) {
+ $this->commonFilters = [
+ IFilter::BUILTIN_TERM => new FilterDefinition(IFilter::BUILTIN_TERM, FilterDefinition::TYPE_STRING),
+ IFilter::BUILTIN_SINCE => new FilterDefinition(IFilter::BUILTIN_SINCE, FilterDefinition::TYPE_DATETIME),
+ IFilter::BUILTIN_UNTIL => new FilterDefinition(IFilter::BUILTIN_UNTIL, FilterDefinition::TYPE_DATETIME),
+ IFilter::BUILTIN_TITLE_ONLY => new FilterDefinition(IFilter::BUILTIN_TITLE_ONLY, FilterDefinition::TYPE_BOOL, false),
+ IFilter::BUILTIN_PERSON => new FilterDefinition(IFilter::BUILTIN_PERSON, FilterDefinition::TYPE_PERSON),
+ IFilter::BUILTIN_PLACES => new FilterDefinition(IFilter::BUILTIN_PLACES, FilterDefinition::TYPE_STRINGS, false),
+ IFilter::BUILTIN_PROVIDER => new FilterDefinition(IFilter::BUILTIN_PROVIDER, FilterDefinition::TYPE_STRING, false),
+ ];
}
/**
* Load all providers dynamically that were registered through `registerProvider`
*
+ * If $targetProviderId is provided, only this provider is loaded
* If a provider can't be loaded we log it but the operation continues nevertheless
*/
- private function loadLazyProviders(): void {
+ private function loadLazyProviders(?string $targetProviderId = null): void {
$context = $this->bootstrapCoordinator->getRegistrationContext();
if ($context === null) {
// Too early, nothing registered yet
@@ -93,9 +89,20 @@ class SearchComposer {
foreach ($registrations as $registration) {
try {
/** @var IProvider $provider */
- $provider = $this->container->query($registration->getService());
- $this->providers[$provider->getId()] = $provider;
- } catch (QueryException $e) {
+ $provider = $this->container->get($registration->getService());
+ $providerId = $provider->getId();
+ if ($targetProviderId !== null && $targetProviderId !== $providerId) {
+ continue;
+ }
+ $this->providers[$providerId] = [
+ 'appId' => $registration->getAppId(),
+ 'provider' => $provider,
+ ];
+ $this->handlers[$providerId] = [$providerId];
+ if ($targetProviderId !== null) {
+ break;
+ }
+ } catch (ContainerExceptionInterface $e) {
// Log an continue. We can be fault tolerant here.
$this->logger->error('Could not load search provider dynamically: ' . $e->getMessage(), [
'exception' => $e,
@@ -103,6 +110,43 @@ class SearchComposer {
]);
}
}
+
+ $this->loadFilters();
+ }
+
+ private function loadFilters(): void {
+ foreach ($this->providers as $providerId => $providerData) {
+ $appId = $providerData['appId'];
+ $provider = $providerData['provider'];
+ if (!$provider instanceof IFilteringProvider) {
+ continue;
+ }
+
+ foreach ($provider->getCustomFilters() as $filter) {
+ $this->registerCustomFilter($filter, $providerId);
+ }
+ foreach ($provider->getAlternateIds() as $alternateId) {
+ $this->handlers[$alternateId][] = $providerId;
+ }
+ foreach ($provider->getSupportedFilters() as $filterName) {
+ if ($this->getFilterDefinition($filterName, $providerId) === null) {
+ throw new InvalidArgumentException('Invalid filter '. $filterName);
+ }
+ }
+ }
+ }
+
+ private function registerCustomFilter(FilterDefinition $filter, string $providerId): void {
+ $name = $filter->name();
+ if (isset($this->commonFilters[$name])) {
+ throw new InvalidArgumentException('Filter name is already used');
+ }
+
+ if (isset($this->customFilters[$providerId])) {
+ $this->customFilters[$providerId][$name] = $filter;
+ } else {
+ $this->customFilters[$providerId] = [$name => $filter];
+ }
}
/**
@@ -117,26 +161,146 @@ class SearchComposer {
public function getProviders(string $route, array $routeParameters): array {
$this->loadLazyProviders();
- $providers = array_values(
- array_map(function (IProvider $provider) use ($route, $routeParameters) {
+ $providers = array_map(
+ function (array $providerData) use ($route, $routeParameters) {
+ $appId = $providerData['appId'];
+ $provider = $providerData['provider'];
+ $order = $provider->getOrder($route, $routeParameters);
+ if ($order === null) {
+ return;
+ }
+ $triggers = [$provider->getId()];
+ if ($provider instanceof IFilteringProvider) {
+ $triggers += $provider->getAlternateIds();
+ $filters = $provider->getSupportedFilters();
+ } else {
+ $filters = [IFilter::BUILTIN_TERM];
+ }
+
return [
'id' => $provider->getId(),
+ 'appId' => $appId,
'name' => $provider->getName(),
- 'order' => $provider->getOrder($route, $routeParameters),
+ 'icon' => $this->fetchIcon($appId, $provider->getId()),
+ 'order' => $order,
+ 'triggers' => $triggers,
+ 'filters' => $this->getFiltersType($filters, $provider->getId()),
+ 'inAppSearch' => $provider instanceof IInAppSearch,
];
- }, $this->providers)
+ },
+ $this->providers,
);
+ $providers = array_filter($providers);
+ // Sort providers by order and strip associative keys
usort($providers, function ($provider1, $provider2) {
return $provider1['order'] <=> $provider2['order'];
});
- /**
- * Return an array with the IDs, but strip the associative keys
- */
return $providers;
}
+ private function fetchIcon(string $appId, string $providerId): string {
+ $icons = [
+ [$providerId, $providerId.'.svg'],
+ [$providerId, 'app.svg'],
+ [$appId, $providerId.'.svg'],
+ [$appId, $appId.'.svg'],
+ [$appId, 'app.svg'],
+ ['core', 'places/default-app-icon.svg'],
+ ];
+ if ($appId === 'settings' && $providerId === 'users') {
+ // Conflict:
+ // the file /apps/settings/users.svg is already used in black version by top right user menu
+ // Override icon name here
+ $icons = [['settings', 'users-white.svg']];
+ }
+ foreach ($icons as $i => $icon) {
+ try {
+ return $this->urlGenerator->imagePath(... $icon);
+ } catch (RuntimeException $e) {
+ // Ignore error
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * @param $filters string[]
+ * @return array<string, string>
+ */
+ private function getFiltersType(array $filters, string $providerId): array {
+ $filterList = [];
+ foreach ($filters as $filter) {
+ $filterList[$filter] = $this->getFilterDefinition($filter, $providerId)->type();
+ }
+
+ return $filterList;
+ }
+
+ private function getFilterDefinition(string $name, string $providerId): ?FilterDefinition {
+ if (isset($this->commonFilters[$name])) {
+ return $this->commonFilters[$name];
+ }
+ if (isset($this->customFilters[$providerId][$name])) {
+ return $this->customFilters[$providerId][$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * @param array<string, string> $parameters
+ */
+ public function buildFilterList(string $providerId, array $parameters): FilterCollection {
+ $this->loadLazyProviders($providerId);
+
+ $list = [];
+ foreach ($parameters as $name => $value) {
+ $filter = $this->buildFilter($name, $value, $providerId);
+ if ($filter === null) {
+ continue;
+ }
+ $list[$name] = $filter;
+ }
+
+ return new FilterCollection(... $list);
+ }
+
+ private function buildFilter(string $name, string $value, string $providerId): ?IFilter {
+ $filterDefinition = $this->getFilterDefinition($name, $providerId);
+ if ($filterDefinition === null) {
+ $this->logger->debug('Unable to find {name} definition', [
+ 'name' => $name,
+ 'value' => $value,
+ ]);
+
+ return null;
+ }
+
+ if (!$this->filterSupportedByProvider($filterDefinition, $providerId)) {
+ // FIXME Use dedicated exception and handle it
+ throw new UnsupportedFilter($name, $providerId);
+ }
+
+ return FilterFactory::get($filterDefinition->type(), $value);
+ }
+
+ private function filterSupportedByProvider(FilterDefinition $filterDefinition, string $providerId): bool {
+ // Non exclusive filters can be ommited by apps
+ if (!$filterDefinition->exclusive()) {
+ return true;
+ }
+
+ $provider = $this->providers[$providerId]['provider'];
+ $supportedFilters = $provider instanceof IFilteringProvider
+ ? $provider->getSupportedFilters()
+ : [IFilter::BUILTIN_TERM];
+
+ return in_array($filterDefinition->name(), $supportedFilters, true);
+ }
+
/**
* Query an individual search provider for results
*
@@ -147,15 +311,18 @@ class SearchComposer {
* @return SearchResult
* @throws InvalidArgumentException when the $providerId does not correspond to a registered provider
*/
- public function search(IUser $user,
- string $providerId,
- ISearchQuery $query): SearchResult {
- $this->loadLazyProviders();
+ public function search(
+ IUser $user,
+ string $providerId,
+ ISearchQuery $query,
+ ): SearchResult {
+ $this->loadLazyProviders($providerId);
- $provider = $this->providers[$providerId] ?? null;
+ $provider = $this->providers[$providerId]['provider'] ?? null;
if ($provider === null) {
throw new InvalidArgumentException("Provider $providerId is unknown");
}
+
return $provider->search($user, $query);
}
}
diff --git a/lib/private/Search/SearchQuery.php b/lib/private/Search/SearchQuery.php
index c89446d5970..a78443922ae 100644
--- a/lib/private/Search/SearchQuery.php
+++ b/lib/private/Search/SearchQuery.php
@@ -3,113 +3,62 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Search;
+use OCP\Search\IFilter;
+use OCP\Search\IFilterCollection;
use OCP\Search\ISearchQuery;
class SearchQuery implements ISearchQuery {
public const LIMIT_DEFAULT = 5;
- /** @var string */
- private $term;
-
- /** @var int */
- private $sortOrder;
-
- /** @var int */
- private $limit;
-
- /** @var int|string|null */
- private $cursor;
-
- /** @var string */
- private $route;
-
- /** @var array */
- private $routeParameters;
-
/**
- * @param string $term
- * @param int $sortOrder
- * @param int $limit
- * @param int|string|null $cursor
- * @param string $route
- * @param array $routeParameters
+ * @param string[] $params Request query
+ * @param string[] $routeParameters
*/
- public function __construct(string $term,
- int $sortOrder = ISearchQuery::SORT_DATE_DESC,
- int $limit = self::LIMIT_DEFAULT,
- $cursor = null,
- string $route = '',
- array $routeParameters = []) {
- $this->term = $term;
- $this->sortOrder = $sortOrder;
- $this->limit = $limit;
- $this->cursor = $cursor;
- $this->route = $route;
- $this->routeParameters = $routeParameters;
+ public function __construct(
+ private IFilterCollection $filters,
+ private int $sortOrder = ISearchQuery::SORT_DATE_DESC,
+ private int $limit = self::LIMIT_DEFAULT,
+ private int|string|null $cursor = null,
+ private string $route = '',
+ private array $routeParameters = [],
+ ) {
}
- /**
- * @inheritDoc
- */
public function getTerm(): string {
- return $this->term;
+ return $this->getFilter('term')?->get() ?? '';
+ }
+
+ public function getFilter(string $name): ?IFilter {
+ return $this->filters->has($name)
+ ? $this->filters->get($name)
+ : null;
+ }
+
+ public function getFilters(): IFilterCollection {
+ return $this->filters;
}
- /**
- * @inheritDoc
- */
public function getSortOrder(): int {
return $this->sortOrder;
}
- /**
- * @inheritDoc
- */
public function getLimit(): int {
return $this->limit;
}
- /**
- * @inheritDoc
- */
- public function getCursor() {
+ public function getCursor(): int|string|null {
return $this->cursor;
}
- /**
- * @inheritDoc
- */
public function getRoute(): string {
return $this->route;
}
- /**
- * @inheritDoc
- */
public function getRouteParameters(): array {
return $this->routeParameters;
}
diff --git a/lib/private/Search/UnsupportedFilter.php b/lib/private/Search/UnsupportedFilter.php
new file mode 100644
index 00000000000..bf251a91d31
--- /dev/null
+++ b/lib/private/Search/UnsupportedFilter.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Search;
+
+use Exception;
+
+final class UnsupportedFilter extends Exception {
+ public function __construct(string $filerName, $providerId) {
+ parent::__construct('Provider '.$providerId.' doesn’t support filter '.$filerName.'.');
+ }
+}
diff --git a/lib/private/Security/Bruteforce/Backend/DatabaseBackend.php b/lib/private/Security/Bruteforce/Backend/DatabaseBackend.php
index 04f2a7b6397..0e272d94d0d 100644
--- a/lib/private/Security/Bruteforce/Backend/DatabaseBackend.php
+++ b/lib/private/Security/Bruteforce/Backend/DatabaseBackend.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Bruteforce\Backend;
diff --git a/lib/private/Security/Bruteforce/Backend/IBackend.php b/lib/private/Security/Bruteforce/Backend/IBackend.php
index 4b40262e645..7118123cbb5 100644
--- a/lib/private/Security/Bruteforce/Backend/IBackend.php
+++ b/lib/private/Security/Bruteforce/Backend/IBackend.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Bruteforce\Backend;
diff --git a/lib/private/Security/Bruteforce/Backend/MemoryCacheBackend.php b/lib/private/Security/Bruteforce/Backend/MemoryCacheBackend.php
index 432e99700fe..32571c72fae 100644
--- a/lib/private/Security/Bruteforce/Backend/MemoryCacheBackend.php
+++ b/lib/private/Security/Bruteforce/Backend/MemoryCacheBackend.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Bruteforce\Backend;
diff --git a/lib/private/Security/Bruteforce/Capabilities.php b/lib/private/Security/Bruteforce/Capabilities.php
index b50eea0b7af..581b4480a27 100644
--- a/lib/private/Security/Bruteforce/Capabilities.php
+++ b/lib/private/Security/Bruteforce/Capabilities.php
@@ -3,34 +3,13 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Bruteforce;
-use OCP\Capabilities\IPublicCapability;
use OCP\Capabilities\IInitialStateExcludedCapability;
+use OCP\Capabilities\IPublicCapability;
use OCP\IRequest;
use OCP\Security\Bruteforce\IThrottler;
diff --git a/lib/private/Security/Bruteforce/CleanupJob.php b/lib/private/Security/Bruteforce/CleanupJob.php
index 45cfe572acb..e7d981caa08 100644
--- a/lib/private/Security/Bruteforce/CleanupJob.php
+++ b/lib/private/Security/Bruteforce/CleanupJob.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Bruteforce;
@@ -32,19 +15,18 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
class CleanupJob extends TimedJob {
- /** @var IDBConnection */
- private $connection;
-
- public function __construct(ITimeFactory $time, IDBConnection $connection) {
+ public function __construct(
+ ITimeFactory $time,
+ private IDBConnection $connection,
+ ) {
parent::__construct($time);
- $this->connection = $connection;
// Run once a day
$this->setInterval(3600 * 24);
$this->setTimeSensitivity(IJob::TIME_INSENSITIVE);
}
- protected function run($argument) {
+ protected function run($argument): void {
// Delete all entries more than 48 hours old
$time = $this->time->getTime() - (48 * 3600);
diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php
index 2803373e8ba..7e310035ce4 100644
--- a/lib/private/Security/Bruteforce/Throttler.php
+++ b/lib/private/Security/Bruteforce/Throttler.php
@@ -3,33 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Riedel <joeried@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Bruteforce;
@@ -72,8 +47,8 @@ class Throttler implements IThrottler {
* {@inheritDoc}
*/
public function registerAttempt(string $action,
- string $ip,
- array $metadata = []): void {
+ string $ip,
+ array $metadata = []): void {
// No need to log if the bruteforce protection is disabled
if (!$this->config->getSystemValueBool('auth.bruteforce.protection.enabled', true)) {
return;
@@ -106,9 +81,6 @@ class Throttler implements IThrottler {
/**
* Check if the IP is whitelisted
- *
- * @param string $ip
- * @return bool
*/
public function isBypassListed(string $ip): bool {
if (isset($this->ipIsWhitelisted[$ip])) {
diff --git a/lib/private/Security/CSP/ContentSecurityPolicy.php b/lib/private/Security/CSP/ContentSecurityPolicy.php
index e2d115cf34e..890251db040 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicy.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicy.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security\CSP;
@@ -34,33 +16,22 @@ namespace OC\Security\CSP;
* @package OC\Security\CSP
*/
class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy {
- /**
- * @return boolean
- */
public function isInlineScriptAllowed(): bool {
return $this->inlineScriptAllowed;
}
- /**
- * @param boolean $inlineScriptAllowed
- */
- public function setInlineScriptAllowed(bool $inlineScriptAllowed) {
+ public function setInlineScriptAllowed(bool $inlineScriptAllowed): void {
$this->inlineScriptAllowed = $inlineScriptAllowed;
}
- /**
- * @return boolean
- */
public function isEvalScriptAllowed(): bool {
return $this->evalScriptAllowed;
}
/**
- * @param boolean $evalScriptAllowed
- *
* @deprecated 17.0.0 Unsafe eval should not be used anymore.
*/
- public function setEvalScriptAllowed(bool $evalScriptAllowed) {
+ public function setEvalScriptAllowed(bool $evalScriptAllowed): void {
$this->evalScriptAllowed = $evalScriptAllowed;
}
@@ -72,134 +43,79 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
$this->evalWasmAllowed = $evalWasmAllowed;
}
- /**
- * @return array
- */
public function getAllowedScriptDomains(): array {
return $this->allowedScriptDomains;
}
- /**
- * @param array $allowedScriptDomains
- */
- public function setAllowedScriptDomains(array $allowedScriptDomains) {
+ public function setAllowedScriptDomains(array $allowedScriptDomains): void {
$this->allowedScriptDomains = $allowedScriptDomains;
}
- /**
- * @return boolean
- */
public function isInlineStyleAllowed(): bool {
return $this->inlineStyleAllowed;
}
- /**
- * @param boolean $inlineStyleAllowed
- */
- public function setInlineStyleAllowed(bool $inlineStyleAllowed) {
+ public function setInlineStyleAllowed(bool $inlineStyleAllowed): void {
$this->inlineStyleAllowed = $inlineStyleAllowed;
}
- /**
- * @return array
- */
public function getAllowedStyleDomains(): array {
return $this->allowedStyleDomains;
}
- /**
- * @param array $allowedStyleDomains
- */
- public function setAllowedStyleDomains(array $allowedStyleDomains) {
+ public function setAllowedStyleDomains(array $allowedStyleDomains): void {
$this->allowedStyleDomains = $allowedStyleDomains;
}
- /**
- * @return array
- */
public function getAllowedImageDomains(): array {
return $this->allowedImageDomains;
}
- /**
- * @param array $allowedImageDomains
- */
- public function setAllowedImageDomains(array $allowedImageDomains) {
+ public function setAllowedImageDomains(array $allowedImageDomains): void {
$this->allowedImageDomains = $allowedImageDomains;
}
- /**
- * @return array
- */
public function getAllowedConnectDomains(): array {
return $this->allowedConnectDomains;
}
- /**
- * @param array $allowedConnectDomains
- */
- public function setAllowedConnectDomains(array $allowedConnectDomains) {
+ public function setAllowedConnectDomains(array $allowedConnectDomains): void {
$this->allowedConnectDomains = $allowedConnectDomains;
}
- /**
- * @return array
- */
public function getAllowedMediaDomains(): array {
return $this->allowedMediaDomains;
}
- /**
- * @param array $allowedMediaDomains
- */
- public function setAllowedMediaDomains(array $allowedMediaDomains) {
+ public function setAllowedMediaDomains(array $allowedMediaDomains): void {
$this->allowedMediaDomains = $allowedMediaDomains;
}
- /**
- * @return array
- */
public function getAllowedObjectDomains(): array {
return $this->allowedObjectDomains;
}
- /**
- * @param array $allowedObjectDomains
- */
- public function setAllowedObjectDomains(array $allowedObjectDomains) {
+ public function setAllowedObjectDomains(array $allowedObjectDomains): void {
$this->allowedObjectDomains = $allowedObjectDomains;
}
- /**
- * @return array
- */
public function getAllowedFrameDomains(): array {
return $this->allowedFrameDomains;
}
- /**
- * @param array $allowedFrameDomains
- */
- public function setAllowedFrameDomains(array $allowedFrameDomains) {
+ public function setAllowedFrameDomains(array $allowedFrameDomains): void {
$this->allowedFrameDomains = $allowedFrameDomains;
}
- /**
- * @return array
- */
public function getAllowedFontDomains(): array {
return $this->allowedFontDomains;
}
- /**
- * @param array $allowedFontDomains
- */
- public function setAllowedFontDomains($allowedFontDomains) {
+ public function setAllowedFontDomains($allowedFontDomains): void {
$this->allowedFontDomains = $allowedFontDomains;
}
/**
- * @return array
* @deprecated 15.0.0 use FrameDomains and WorkerSrcDomains
*/
public function getAllowedChildSrcDomains(): array {
@@ -210,13 +126,10 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
* @param array $allowedChildSrcDomains
* @deprecated 15.0.0 use FrameDomains and WorkerSrcDomains
*/
- public function setAllowedChildSrcDomains($allowedChildSrcDomains) {
+ public function setAllowedChildSrcDomains($allowedChildSrcDomains): void {
$this->allowedChildSrcDomains = $allowedChildSrcDomains;
}
- /**
- * @return array
- */
public function getAllowedFrameAncestors(): array {
return $this->allowedFrameAncestors;
}
@@ -224,7 +137,7 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
/**
* @param array $allowedFrameAncestors
*/
- public function setAllowedFrameAncestors($allowedFrameAncestors) {
+ public function setAllowedFrameAncestors($allowedFrameAncestors): void {
$this->allowedFrameAncestors = $allowedFrameAncestors;
}
@@ -232,7 +145,7 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
return $this->allowedWorkerSrcDomains;
}
- public function setAllowedWorkerSrcDomains(array $allowedWorkerSrcDomains) {
+ public function setAllowedWorkerSrcDomains(array $allowedWorkerSrcDomains): void {
$this->allowedWorkerSrcDomains = $allowedWorkerSrcDomains;
}
@@ -249,21 +162,23 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
return $this->reportTo;
}
- public function setReportTo(array $reportTo) {
+ public function setReportTo(array $reportTo): void {
$this->reportTo = $reportTo;
}
- /**
- * @return boolean
- */
public function isStrictDynamicAllowed(): bool {
return $this->strictDynamicAllowed;
}
- /**
- * @param boolean $strictDynamicAllowed
- */
- public function setStrictDynamicAllowed(bool $strictDynamicAllowed) {
+ public function setStrictDynamicAllowed(bool $strictDynamicAllowed): void {
$this->strictDynamicAllowed = $strictDynamicAllowed;
}
+
+ public function isStrictDynamicAllowedOnScripts(): bool {
+ return $this->strictDynamicAllowedOnScripts;
+ }
+
+ public function setStrictDynamicAllowedOnScripts(bool $strictDynamicAllowedOnScripts): void {
+ $this->strictDynamicAllowedOnScripts = $strictDynamicAllowedOnScripts;
+ }
}
diff --git a/lib/private/Security/CSP/ContentSecurityPolicyManager.php b/lib/private/Security/CSP/ContentSecurityPolicyManager.php
index 4930dcb759c..77ecceb03c3 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicyManager.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicyManager.php
@@ -3,27 +3,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security\CSP;
@@ -35,25 +17,21 @@ use OCP\Security\IContentSecurityPolicyManager;
class ContentSecurityPolicyManager implements IContentSecurityPolicyManager {
/** @var ContentSecurityPolicy[] */
- private $policies = [];
+ private array $policies = [];
- /** @var IEventDispatcher */
- private $dispatcher;
-
- public function __construct(IEventDispatcher $dispatcher) {
- $this->dispatcher = $dispatcher;
+ public function __construct(
+ private IEventDispatcher $dispatcher,
+ ) {
}
/** {@inheritdoc} */
- public function addDefaultPolicy(EmptyContentSecurityPolicy $policy) {
+ public function addDefaultPolicy(EmptyContentSecurityPolicy $policy): void {
$this->policies[] = $policy;
}
/**
* Get the configured default policy. This is not in the public namespace
* as it is only supposed to be used by core itself.
- *
- * @return ContentSecurityPolicy
*/
public function getDefaultPolicy(): ContentSecurityPolicy {
$event = new AddContentSecurityPolicyEvent($this);
@@ -68,13 +46,11 @@ class ContentSecurityPolicyManager implements IContentSecurityPolicyManager {
/**
* Merges the first given policy with the second one
- *
- * @param ContentSecurityPolicy $defaultPolicy
- * @param EmptyContentSecurityPolicy $originalPolicy
- * @return ContentSecurityPolicy
*/
- public function mergePolicies(ContentSecurityPolicy $defaultPolicy,
- EmptyContentSecurityPolicy $originalPolicy): ContentSecurityPolicy {
+ public function mergePolicies(
+ ContentSecurityPolicy $defaultPolicy,
+ EmptyContentSecurityPolicy $originalPolicy,
+ ): ContentSecurityPolicy {
foreach ((object)(array)$originalPolicy as $name => $value) {
$setter = 'set'.ucfirst($name);
if (\is_array($value)) {
diff --git a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
index 1167b3358d2..0f637e5afd6 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
@@ -3,30 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Pavel Krasikov <klonishe@gmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sam Bull <aa6bs0@sambull.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\CSP;
@@ -38,27 +16,16 @@ use OCP\IRequest;
* @package OC\Security\CSP
*/
class ContentSecurityPolicyNonceManager {
- /** @var CsrfTokenManager */
- private $csrfTokenManager;
- /** @var IRequest */
- private $request;
- /** @var string */
- private $nonce = '';
+ private string $nonce = '';
- /**
- * @param CsrfTokenManager $csrfTokenManager
- * @param IRequest $request
- */
- public function __construct(CsrfTokenManager $csrfTokenManager,
- IRequest $request) {
- $this->csrfTokenManager = $csrfTokenManager;
- $this->request = $request;
+ public function __construct(
+ private CsrfTokenManager $csrfTokenManager,
+ private IRequest $request,
+ ) {
}
/**
- * Returns the current CSP nounce
- *
- * @return string
+ * Returns the current CSP nonce
*/
public function getNonce(): string {
if ($this->nonce === '') {
@@ -74,20 +41,16 @@ class ContentSecurityPolicyNonceManager {
/**
* Check if the browser supports CSP v3
- *
- * @return bool
*/
public function browserSupportsCspV3(): bool {
- $browserWhitelist = [
- Request::USER_AGENT_CHROME,
- Request::USER_AGENT_FIREFOX,
- Request::USER_AGENT_SAFARI,
+ $browserBlocklist = [
+ Request::USER_AGENT_IE,
];
- if ($this->request->isUserAgent($browserWhitelist)) {
- return true;
+ if ($this->request->isUserAgent($browserBlocklist)) {
+ return false;
}
- return false;
+ return true;
}
}
diff --git a/lib/private/Security/CSRF/CsrfToken.php b/lib/private/Security/CSRF/CsrfToken.php
index a76e169e5b9..6aad0cd5944 100644
--- a/lib/private/Security/CSRF/CsrfToken.php
+++ b/lib/private/Security/CSRF/CsrfToken.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Leon Klingele <git@leonklingele.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security\CSRF;
@@ -36,23 +17,19 @@ namespace OC\Security\CSRF;
* @package OC\Security\CSRF
*/
class CsrfToken {
- /** @var string */
- private $value;
- /** @var string */
- private $encryptedValue = '';
+ private string $encryptedValue = '';
/**
* @param string $value Value of the token. Can be encrypted or not encrypted.
*/
- public function __construct(string $value) {
- $this->value = $value;
+ public function __construct(
+ private string $value,
+ ) {
}
/**
* Encrypted value of the token. This is used to mitigate BREACH alike
* vulnerabilities. For display measures do use this functionality.
- *
- * @return string
*/
public function getEncryptedValue(): string {
if ($this->encryptedValue === '') {
@@ -66,8 +43,6 @@ class CsrfToken {
/**
* The unencrypted value of the token. Used for decrypting an already
* encrypted token.
- *
- * @return string
*/
public function getDecryptedValue(): string {
$token = explode(':', $this->value);
diff --git a/lib/private/Security/CSRF/CsrfTokenGenerator.php b/lib/private/Security/CSRF/CsrfTokenGenerator.php
index 0576fda9e06..9e3f15c63d2 100644
--- a/lib/private/Security/CSRF/CsrfTokenGenerator.php
+++ b/lib/private/Security/CSRF/CsrfTokenGenerator.php
@@ -1,27 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security\CSRF;
@@ -34,21 +17,15 @@ use OCP\Security\ISecureRandom;
* @package OC\Security\CSRF
*/
class CsrfTokenGenerator {
- /** @var ISecureRandom */
- private $random;
-
- /**
- * @param ISecureRandom $random
- */
- public function __construct(ISecureRandom $random) {
- $this->random = $random;
+ public function __construct(
+ private ISecureRandom $random,
+ ) {
}
/**
* Generate a new CSRF token.
*
* @param int $length Length of the token in characters.
- * @return string
*/
public function generateToken(int $length = 32): string {
return $this->random->generate($length);
diff --git a/lib/private/Security/CSRF/CsrfTokenManager.php b/lib/private/Security/CSRF/CsrfTokenManager.php
index 2c6dd45866d..00e1be5bedf 100644
--- a/lib/private/Security/CSRF/CsrfTokenManager.php
+++ b/lib/private/Security/CSRF/CsrfTokenManager.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security\CSRF;
@@ -34,27 +16,18 @@ use OC\Security\CSRF\TokenStorage\SessionStorage;
* @package OC\Security\CSRF
*/
class CsrfTokenManager {
- /** @var CsrfTokenGenerator */
- private $tokenGenerator;
- /** @var SessionStorage */
- private $sessionStorage;
- /** @var CsrfToken|null */
- private $csrfToken = null;
+ private SessionStorage $sessionStorage;
+ private ?CsrfToken $csrfToken = null;
- /**
- * @param CsrfTokenGenerator $tokenGenerator
- * @param SessionStorage $storageInterface
- */
- public function __construct(CsrfTokenGenerator $tokenGenerator,
- SessionStorage $storageInterface) {
- $this->tokenGenerator = $tokenGenerator;
+ public function __construct(
+ private CsrfTokenGenerator $tokenGenerator,
+ SessionStorage $storageInterface,
+ ) {
$this->sessionStorage = $storageInterface;
}
/**
* Returns the current CSRF token, if none set it will create a new one.
- *
- * @return CsrfToken
*/
public function getToken(): CsrfToken {
if (!\is_null($this->csrfToken)) {
@@ -74,8 +47,6 @@ class CsrfTokenManager {
/**
* Invalidates any current token and sets a new one.
- *
- * @return CsrfToken
*/
public function refreshToken(): CsrfToken {
$value = $this->tokenGenerator->generateToken();
@@ -87,16 +58,13 @@ class CsrfTokenManager {
/**
* Remove the current token from the storage.
*/
- public function removeToken() {
+ public function removeToken(): void {
$this->csrfToken = null;
$this->sessionStorage->removeToken();
}
/**
* Verifies whether the provided token is valid.
- *
- * @param CsrfToken $token
- * @return bool
*/
public function isTokenValid(CsrfToken $token): bool {
if (!$this->sessionStorage->hasToken()) {
diff --git a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
index ab05d5b1493..1f0f8bcaa0a 100644
--- a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
+++ b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security\CSRF\TokenStorage;
@@ -35,27 +16,18 @@ use OCP\ISession;
* @package OC\Security\CSRF\TokenStorage
*/
class SessionStorage {
- /** @var ISession */
- private $session;
-
- /**
- * @param ISession $session
- */
- public function __construct(ISession $session) {
- $this->session = $session;
+ public function __construct(
+ private ISession $session,
+ ) {
}
- /**
- * @param ISession $session
- */
- public function setSession(ISession $session) {
+ public function setSession(ISession $session): void {
$this->session = $session;
}
/**
* Returns the current token or throws an exception if none is found.
*
- * @return string
* @throws \Exception
*/
public function getToken(): string {
@@ -69,23 +41,20 @@ class SessionStorage {
/**
* Set the valid current token to $value.
- *
- * @param string $value
*/
- public function setToken(string $value) {
+ public function setToken(string $value): void {
$this->session->set('requesttoken', $value);
}
/**
* Removes the current token.
*/
- public function removeToken() {
+ public function removeToken(): void {
$this->session->remove('requesttoken');
}
+
/**
* Whether the storage has a storage.
- *
- * @return bool
*/
public function hasToken(): bool {
return $this->session->exists('requesttoken');
diff --git a/lib/private/Security/Certificate.php b/lib/private/Security/Certificate.php
index fb5b9aa8a93..b9d84caeca3 100644
--- a/lib/private/Security/Certificate.php
+++ b/lib/private/Security/Certificate.php
@@ -1,54 +1,33 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
use OCP\ICertificate;
class Certificate implements ICertificate {
- protected $name;
+ protected string $name;
- protected $commonName;
+ protected ?string $commonName;
- protected $organization;
+ protected ?string $organization;
- protected $serial;
- protected $issueDate;
+ protected \DateTime $issueDate;
- protected $expireDate;
+ protected \DateTime $expireDate;
- protected $issuerName;
+ protected ?string $issuerName;
- protected $issuerOrganization;
+ protected ?string $issuerOrganization;
/**
* @param string $data base64 encoded certificate
- * @param string $name
* @throws \Exception If the certificate could not get parsed
*/
public function __construct(string $data, string $name) {
@@ -66,67 +45,43 @@ class Certificate implements ICertificate {
throw new \Exception('Certificate could not get parsed.');
}
- $this->commonName = isset($info['subject']['CN']) ? $info['subject']['CN'] : null;
- $this->organization = isset($info['subject']['O']) ? $info['subject']['O'] : null;
+ $this->commonName = $info['subject']['CN'] ?? null;
+ $this->organization = $info['subject']['O'] ?? null;
$this->issueDate = new \DateTime('@' . $info['validFrom_time_t'], $gmt);
$this->expireDate = new \DateTime('@' . $info['validTo_time_t'], $gmt);
- $this->issuerName = isset($info['issuer']['CN']) ? $info['issuer']['CN'] : null;
- $this->issuerOrganization = isset($info['issuer']['O']) ? $info['issuer']['O'] : null;
+ $this->issuerName = $info['issuer']['CN'] ?? null;
+ $this->issuerOrganization = $info['issuer']['O'] ?? null;
}
- /**
- * @return string
- */
public function getName(): string {
return $this->name;
}
- /**
- * @return string|null
- */
public function getCommonName(): ?string {
return $this->commonName;
}
- /**
- * @return string|null
- */
public function getOrganization(): ?string {
return $this->organization;
}
- /**
- * @return \DateTime
- */
public function getIssueDate(): \DateTime {
return $this->issueDate;
}
- /**
- * @return \DateTime
- */
public function getExpireDate(): \DateTime {
return $this->expireDate;
}
- /**
- * @return bool
- */
public function isExpired(): bool {
$now = new \DateTime();
return $this->issueDate > $now or $now > $this->expireDate;
}
- /**
- * @return string|null
- */
public function getIssuerName(): ?string {
return $this->issuerName;
}
- /**
- * @return string|null
- */
public function getIssuerOrganization(): ?string {
return $this->issuerOrganization;
}
diff --git a/lib/private/Security/CertificateManager.php b/lib/private/Security/CertificateManager.php
index 3a87b7f1a00..4e3ec96b87b 100644
--- a/lib/private/Security/CertificateManager.php
+++ b/lib/private/Security/CertificateManager.php
@@ -1,34 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
@@ -44,21 +20,14 @@ use Psr\Log\LoggerInterface;
* Manage trusted certificates for users
*/
class CertificateManager implements ICertificateManager {
- protected View $view;
- protected IConfig $config;
- protected LoggerInterface $logger;
- protected ISecureRandom $random;
-
private ?string $bundlePath = null;
- public function __construct(View $view,
- IConfig $config,
- LoggerInterface $logger,
- ISecureRandom $random) {
- $this->view = $view;
- $this->config = $config;
- $this->logger = $logger;
- $this->random = $random;
+ public function __construct(
+ protected View $view,
+ protected IConfig $config,
+ protected LoggerInterface $logger,
+ protected ISecureRandom $random,
+ ) {
}
/**
@@ -178,7 +147,6 @@ class CertificateManager implements ICertificateManager {
*
* @param string $certificate the certificate data
* @param string $name the filename for the certificate
- * @return \OCP\ICertificate
* @throws \Exception If the certificate could not get added
*/
public function addCertificate(string $certificate, string $name): ICertificate {
@@ -205,9 +173,6 @@ class CertificateManager implements ICertificateManager {
/**
* Remove the certificate and re-generate the certificate bundle
- *
- * @param string $name
- * @return bool
*/
public function removeCertificate(string $name): bool {
if (!Filesystem::isValidPath($name)) {
@@ -225,8 +190,6 @@ class CertificateManager implements ICertificateManager {
/**
* Get the path to the certificate bundle
- *
- * @return string
*/
public function getCertificateBundle(): string {
return $this->getPathToCertificates() . 'rootcerts.crt';
@@ -267,8 +230,6 @@ class CertificateManager implements ICertificateManager {
/**
* Check if we need to re-bundle the certificates because one of the sources has updated
- *
- * @return bool
*/
private function needsRebundling(): bool {
$targetBundle = $this->getCertificateBundle();
@@ -282,8 +243,6 @@ class CertificateManager implements ICertificateManager {
/**
* get mtime of ca-bundle shipped by Nextcloud
- *
- * @return int
*/
protected function getFilemtimeOfCaBundle(): int {
return filemtime(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
diff --git a/lib/private/Security/CredentialsManager.php b/lib/private/Security/CredentialsManager.php
index 0bddaeda1b0..fdf2c46ecf8 100644
--- a/lib/private/Security/CredentialsManager.php
+++ b/lib/private/Security/CredentialsManager.php
@@ -1,30 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
@@ -40,26 +20,16 @@ use OCP\Security\ICrypto;
class CredentialsManager implements ICredentialsManager {
public const DB_TABLE = 'storages_credentials';
- /** @var ICrypto */
- protected $crypto;
-
- /** @var IDBConnection */
- protected $dbConnection;
-
- /**
- * @param ICrypto $crypto
- * @param IDBConnection $dbConnection
- */
- public function __construct(ICrypto $crypto, IDBConnection $dbConnection) {
- $this->crypto = $crypto;
- $this->dbConnection = $dbConnection;
+ public function __construct(
+ protected ICrypto $crypto,
+ protected IDBConnection $dbConnection,
+ ) {
}
/**
* Store a set of credentials
*
* @param string $userId empty string for system-wide credentials
- * @param string $identifier
* @param mixed $credentials
*/
public function store(string $userId, string $identifier, $credentials): void {
@@ -77,10 +47,8 @@ class CredentialsManager implements ICredentialsManager {
* Retrieve a set of credentials
*
* @param string $userId empty string for system-wide credentials
- * @param string $identifier
- * @return mixed
*/
- public function retrieve(string $userId, string $identifier) {
+ public function retrieve(string $userId, string $identifier): mixed {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('credentials')
->from(self::DB_TABLE)
@@ -108,7 +76,6 @@ class CredentialsManager implements ICredentialsManager {
* Delete a set of credentials
*
* @param string $userId empty string for system-wide credentials
- * @param string $identifier
* @return int rows removed
*/
public function delete(string $userId, string $identifier): int {
@@ -128,7 +95,6 @@ class CredentialsManager implements ICredentialsManager {
/**
* Erase all credentials stored for a user
*
- * @param string $userId
* @return int rows removed
*/
public function erase(string $userId): int {
diff --git a/lib/private/Security/Crypto.php b/lib/private/Security/Crypto.php
index 2a7905376ef..b03f8a4ddce 100644
--- a/lib/private/Security/Crypto.php
+++ b/lib/private/Security/Crypto.php
@@ -1,38 +1,16 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author lynn-stephenson <lynn.stephenson@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
use Exception;
use OCP\IConfig;
use OCP\Security\ICrypto;
-use OCP\Security\ISecureRandom;
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Hash;
@@ -47,20 +25,13 @@ use phpseclib\Crypt\Hash;
* @package OC\Security
*/
class Crypto implements ICrypto {
- /** @var AES $cipher */
- private $cipher;
- /** @var int */
- private $ivLength = 16;
- /** @var IConfig */
- private $config;
+ private AES $cipher;
+ private int $ivLength = 16;
- /**
- * @param IConfig $config
- * @param ISecureRandom $random
- */
- public function __construct(IConfig $config) {
+ public function __construct(
+ private IConfig $config,
+ ) {
$this->cipher = new AES();
- $this->config = $config;
}
/**
@@ -84,7 +55,6 @@ class Crypto implements ICrypto {
/**
* Encrypts a value and adds an HMAC (Encrypt-Then-MAC)
*
- * @param string $plaintext
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken
* @return string Authenticated ciphertext
* @throws Exception if it was not possible to gather sufficient entropy
@@ -115,9 +85,7 @@ class Crypto implements ICrypto {
/**
* Decrypts a value and verifies the HMAC (Encrypt-Then-Mac)
- * @param string $authenticatedCiphertext
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken
- * @return string plaintext
* @throws Exception If the HMAC does not match
* @throws Exception If the decryption failed
*/
diff --git a/lib/private/Security/FeaturePolicy/FeaturePolicy.php b/lib/private/Security/FeaturePolicy/FeaturePolicy.php
index a0ab2065ece..9b513b80813 100644
--- a/lib/private/Security/FeaturePolicy/FeaturePolicy.php
+++ b/lib/private/Security/FeaturePolicy/FeaturePolicy.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\FeaturePolicy;
diff --git a/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php b/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php
index 3aa93ac3da4..e50aaac0faf 100644
--- a/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php
+++ b/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\FeaturePolicy;
@@ -32,13 +14,11 @@ use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent;
class FeaturePolicyManager {
/** @var EmptyFeaturePolicy[] */
- private $policies = [];
+ private array $policies = [];
- /** @var IEventDispatcher */
- private $dispatcher;
-
- public function __construct(IEventDispatcher $dispatcher) {
- $this->dispatcher = $dispatcher;
+ public function __construct(
+ private IEventDispatcher $dispatcher,
+ ) {
}
public function addDefaultPolicy(EmptyFeaturePolicy $policy): void {
@@ -60,8 +40,10 @@ class FeaturePolicyManager {
* Merges the first given policy with the second one
*
*/
- public function mergePolicies(FeaturePolicy $defaultPolicy,
- EmptyFeaturePolicy $originalPolicy): FeaturePolicy {
+ public function mergePolicies(
+ FeaturePolicy $defaultPolicy,
+ EmptyFeaturePolicy $originalPolicy,
+ ): FeaturePolicy {
foreach ((object)(array)$originalPolicy as $name => $value) {
$setter = 'set' . ucfirst($name);
if (\is_array($value)) {
diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php
index 85f69263925..22e850157fc 100644
--- a/lib/private/Security/Hasher.php
+++ b/lib/private/Security/Hasher.php
@@ -1,30 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author MichaIng <micha@dietpi.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
@@ -42,28 +22,23 @@ use OCP\Security\IHasher;
*
* Usage:
* // Hashing a message
- * $hash = \OC::$server->getHasher()->hash('MessageToHash');
+ * $hash = \OC::$server->get(\OCP\Security\IHasher::class)->hash('MessageToHash');
* // Verifying a message - $newHash will contain the newly calculated hash
* $newHash = null;
- * var_dump(\OC::$server->getHasher()->verify('a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', $newHash));
+ * var_dump(\OC::$server->get(\OCP\Security\IHasher::class)->verify('a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', $newHash));
* var_dump($newHash);
*
* @package OC\Security
*/
class Hasher implements IHasher {
- /** @var IConfig */
- private $config;
- /** @var array Options passed to password_hash and password_needs_rehash */
- private $options = [];
- /** @var string Salt used for legacy passwords */
- private $legacySalt = null;
-
- /**
- * @param IConfig $config
- */
- public function __construct(IConfig $config) {
- $this->config = $config;
-
+ /** Options passed to password_hash and password_needs_rehash */
+ private array $options = [];
+ /** Salt used for legacy passwords */
+ private ?string $legacySalt = null;
+
+ public function __construct(
+ private IConfig $config,
+ ) {
if (\defined('PASSWORD_ARGON2ID') || \defined('PASSWORD_ARGON2I')) {
// password_hash fails, when the minimum values are undershot.
// In this case, apply minimum.
@@ -106,7 +81,7 @@ class Hasher implements IHasher {
* @param string $prefixedHash
* @return null|array Null if the hash is not prefixed, otherwise array('version' => 1, 'hash' => 'foo')
*/
- protected function splitHash(string $prefixedHash) {
+ protected function splitHash(string $prefixedHash): ?array {
$explodedString = explode('|', $prefixedHash, 2);
if (\count($explodedString) === 2) {
if ((int)$explodedString[0] > 0) {
@@ -198,7 +173,7 @@ class Hasher implements IHasher {
return password_needs_rehash($hash, $algorithm, $this->options);
}
- private function getPrefferedAlgorithm() {
+ private function getPrefferedAlgorithm(): string {
$default = PASSWORD_BCRYPT;
if (\defined('PASSWORD_ARGON2I')) {
$default = PASSWORD_ARGON2I;
diff --git a/lib/private/Security/IdentityProof/Key.php b/lib/private/Security/IdentityProof/Key.php
index bde828a3859..0bfcd6bf9ed 100644
--- a/lib/private/Security/IdentityProof/Key.php
+++ b/lib/private/Security/IdentityProof/Key.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\IdentityProof;
diff --git a/lib/private/Security/IdentityProof/Manager.php b/lib/private/Security/IdentityProof/Manager.php
index 49b9bb10c3e..0ce760ccc63 100644
--- a/lib/private/Security/IdentityProof/Manager.php
+++ b/lib/private/Security/IdentityProof/Manager.php
@@ -3,29 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\IdentityProof;
diff --git a/lib/private/Security/IdentityProof/Signer.php b/lib/private/Security/IdentityProof/Signer.php
index 1458390c327..6083cbb5c9b 100644
--- a/lib/private/Security/IdentityProof/Signer.php
+++ b/lib/private/Security/IdentityProof/Signer.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\IdentityProof;
@@ -74,12 +55,12 @@ class Signer {
$user = $this->userManager->get($userId);
if ($user !== null) {
$key = $this->keyManager->getKey($user);
- return (bool)openssl_verify(
+ return openssl_verify(
json_encode($data['message']),
base64_decode($data['signature']),
$key->getPublic(),
OPENSSL_ALGO_SHA512
- );
+ ) === 1;
}
}
diff --git a/lib/private/Security/Normalizer/IpAddress.php b/lib/private/Security/Normalizer/IpAddress.php
index 98d85ce07a1..dc7c784fa4c 100644
--- a/lib/private/Security/Normalizer/IpAddress.php
+++ b/lib/private/Security/Normalizer/IpAddress.php
@@ -3,30 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Konrad Bucheli <kb@open.ch>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\Normalizer;
@@ -37,43 +15,18 @@ namespace OC\Security\Normalizer;
* @package OC\Security\Normalizer
*/
class IpAddress {
- /** @var string */
- private $ip;
-
- /**
- * @param string $ip IP to normalized
- */
- public function __construct(string $ip) {
- $this->ip = $ip;
- }
-
/**
- * Return the given subnet for an IPv4 address and mask bits
- *
- * @param string $ip
- * @param int $maskBits
- * @return string
+ * @param string $ip IP to normalize
*/
- private function getIPv4Subnet(string $ip, int $maskBits = 32): string {
- $binary = \inet_pton($ip);
- for ($i = 32; $i > $maskBits; $i -= 8) {
- $j = \intdiv($i, 8) - 1;
- $k = \min(8, $i - $maskBits);
- $mask = (0xff - ((2 ** $k) - 1));
- $int = \unpack('C', $binary[$j]);
- $binary[$j] = \pack('C', $int[1] & $mask);
- }
- return \inet_ntop($binary).'/'.$maskBits;
+ public function __construct(
+ private string $ip,
+ ) {
}
/**
- * Return the given subnet for an IPv6 address and mask bits
- *
- * @param string $ip
- * @param int $maskBits
- * @return string
+ * Return the given subnet for an IPv6 address (64 first bits)
*/
- private function getIPv6Subnet(string $ip, int $maskBits = 48): string {
+ private function getIPv6Subnet(string $ip): string {
if ($ip[0] === '[' && $ip[-1] === ']') { // If IP is with brackets, for example [::1]
$ip = substr($ip, 1, strlen($ip) - 2);
}
@@ -81,15 +34,11 @@ class IpAddress {
if ($pos !== false) {
$ip = substr($ip, 0, $pos - 1);
}
+
$binary = \inet_pton($ip);
- for ($i = 128; $i > $maskBits; $i -= 8) {
- $j = \intdiv($i, 8) - 1;
- $k = \min(8, $i - $maskBits);
- $mask = (0xff - ((2 ** $k) - 1));
- $int = \unpack('C', $binary[$j]);
- $binary[$j] = \pack('C', $int[1] & $mask);
- }
- return \inet_ntop($binary).'/'.$maskBits;
+ $mask = inet_pton('FFFF:FFFF:FFFF:FFFF::');
+
+ return inet_ntop($binary & $mask).'/64';
}
/**
@@ -103,58 +52,34 @@ class IpAddress {
if (!$binary) {
return null;
}
- for ($i = 0; $i <= 9; $i++) {
- if (unpack('C', $binary[$i])[1] !== 0) {
- return null;
- }
- }
-
- for ($i = 10; $i <= 11; $i++) {
- if (unpack('C', $binary[$i])[1] !== 255) {
- return null;
- }
- }
- $binary4 = '';
- for ($i = 12; $i < 16; $i++) {
- $binary4 .= $binary[$i];
+ $mask = inet_pton('::FFFF:FFFF');
+ if (($binary & ~$mask) !== inet_pton('::FFFF:0.0.0.0')) {
+ return null;
}
- return inet_ntop($binary4);
+ return inet_ntop(substr($binary, -4));
}
/**
* Gets either the /32 (IPv4) or the /64 (IPv6) subnet of an IP address
- *
- * @return string
*/
public function getSubnet(): string {
- if (\preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->ip)) {
- return $this->getIPv4Subnet(
- $this->ip,
- 32
- );
+ if (filter_var($this->ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+ return $this->ip.'/32';
}
$ipv4 = $this->getEmbeddedIpv4($this->ip);
if ($ipv4 !== null) {
- return $this->getIPv4Subnet(
- $ipv4,
- 32
- );
+ return $ipv4.'/32';
}
- return $this->getIPv6Subnet(
- $this->ip,
- 64
- );
+ return $this->getIPv6Subnet($this->ip);
}
/**
* Returns the specified IP address
- *
- * @return string
*/
public function __toString(): string {
return $this->ip;
diff --git a/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php b/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php
index 41f50a90b5c..34fddff539b 100644
--- a/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php
+++ b/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2021 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\RateLimiting\Backend;
diff --git a/lib/private/Security/RateLimiting/Backend/IBackend.php b/lib/private/Security/RateLimiting/Backend/IBackend.php
index 24715391a96..43eff5dcf02 100644
--- a/lib/private/Security/RateLimiting/Backend/IBackend.php
+++ b/lib/private/Security/RateLimiting/Backend/IBackend.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\RateLimiting\Backend;
diff --git a/lib/private/Security/RateLimiting/Backend/MemoryCacheBackend.php b/lib/private/Security/RateLimiting/Backend/MemoryCacheBackend.php
index b59178c7d7b..84eb9fbd084 100644
--- a/lib/private/Security/RateLimiting/Backend/MemoryCacheBackend.php
+++ b/lib/private/Security/RateLimiting/Backend/MemoryCacheBackend.php
@@ -3,30 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\RateLimiting\Backend;
diff --git a/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php b/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php
index 08091e997ca..19defc2d896 100644
--- a/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php
+++ b/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php
@@ -3,32 +3,16 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\RateLimiting\Exception;
use OC\AppFramework\Middleware\Security\Exceptions\SecurityException;
use OCP\AppFramework\Http;
+use OCP\Security\RateLimiting\IRateLimitExceededException;
-class RateLimitExceededException extends SecurityException {
+class RateLimitExceededException extends SecurityException implements IRateLimitExceededException {
public function __construct() {
parent::__construct('Rate limit exceeded', Http::STATUS_TOO_MANY_REQUESTS);
}
diff --git a/lib/private/Security/RateLimiting/Limiter.php b/lib/private/Security/RateLimiting/Limiter.php
index c8c0e2ce101..b7ac26d9132 100644
--- a/lib/private/Security/RateLimiting/Limiter.php
+++ b/lib/private/Security/RateLimiting/Limiter.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security\RateLimiting;
@@ -30,8 +12,9 @@ use OC\Security\Normalizer\IpAddress;
use OC\Security\RateLimiting\Backend\IBackend;
use OC\Security\RateLimiting\Exception\RateLimitExceededException;
use OCP\IUser;
+use OCP\Security\RateLimiting\ILimiter;
-class Limiter {
+class Limiter implements ILimiter {
public function __construct(
private IBackend $backend,
) {
diff --git a/lib/private/Security/RemoteHostValidator.php b/lib/private/Security/RemoteHostValidator.php
index 38129fbd81b..30bd59db2c1 100644
--- a/lib/private/Security/RemoteHostValidator.php
+++ b/lib/private/Security/RemoteHostValidator.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Security;
@@ -38,19 +22,12 @@ use function urldecode;
* @internal
*/
final class RemoteHostValidator implements IRemoteHostValidator {
- private IConfig $config;
- private HostnameClassifier $hostnameClassifier;
- private IpAddressClassifier $ipAddressClassifier;
- private LoggerInterface $logger;
-
- public function __construct(IConfig $config,
- HostnameClassifier $hostnameClassifier,
- IpAddressClassifier $ipAddressClassifier,
- LoggerInterface $logger) {
- $this->config = $config;
- $this->hostnameClassifier = $hostnameClassifier;
- $this->ipAddressClassifier = $ipAddressClassifier;
- $this->logger = $logger;
+ public function __construct(
+ private IConfig $config,
+ private HostnameClassifier $hostnameClassifier,
+ private IpAddressClassifier $ipAddressClassifier,
+ private LoggerInterface $logger,
+ ) {
}
public function isValid(string $host): bool {
@@ -59,6 +36,10 @@ final class RemoteHostValidator implements IRemoteHostValidator {
}
$host = idn_to_utf8(strtolower(urldecode($host)));
+ if ($host === false) {
+ return false;
+ }
+
// Remove brackets from IPv6 addresses
if (str_starts_with($host, '[') && str_ends_with($host, ']')) {
$host = substr($host, 1, -1);
diff --git a/lib/private/Security/SecureRandom.php b/lib/private/Security/SecureRandom.php
index cbd1dc8db6d..f6257779486 100644
--- a/lib/private/Security/SecureRandom.php
+++ b/lib/private/Security/SecureRandom.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
@@ -44,11 +25,12 @@ class SecureRandom implements ISecureRandom {
* @param int $length The length of the generated string
* @param string $characters An optional list of characters to use if no character list is
* specified all valid base64 characters are used.
- * @return string
* @throws \LengthException if an invalid length is requested
*/
- public function generate(int $length,
- string $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'): string {
+ public function generate(
+ int $length,
+ string $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+ ): string {
if ($length <= 0) {
throw new \LengthException('Invalid length specified: ' . $length . ' must be bigger than 0');
}
diff --git a/lib/private/Security/TrustedDomainHelper.php b/lib/private/Security/TrustedDomainHelper.php
index ca6a5cba073..a65779780e8 100644
--- a/lib/private/Security/TrustedDomainHelper.php
+++ b/lib/private/Security/TrustedDomainHelper.php
@@ -1,31 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Johannes Ernst <jernst@indiecomputing.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Security;
@@ -34,19 +13,13 @@ use OCP\IConfig;
use OCP\Security\ITrustedDomainHelper;
class TrustedDomainHelper implements ITrustedDomainHelper {
- /** @var IConfig */
- private $config;
-
- /**
- * @param IConfig $config
- */
- public function __construct(IConfig $config) {
- $this->config = $config;
+ public function __construct(
+ private IConfig $config,
+ ) {
}
/**
* Strips a potential port from a domain (in format domain:port)
- * @param string $host
* @return string $host without appended port
*/
private function getDomainWithoutPort(string $host): string {
diff --git a/lib/private/Security/VerificationToken/CleanUpJob.php b/lib/private/Security/VerificationToken/CleanUpJob.php
index 1f4af046451..ba8f4352f80 100644
--- a/lib/private/Security/VerificationToken/CleanUpJob.php
+++ b/lib/private/Security/VerificationToken/CleanUpJob.php
@@ -1,36 +1,17 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2021 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Security\VerificationToken;
use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\IConfig;
-use OCP\IUserManager;
use OCP\BackgroundJob\IJobList;
use OCP\BackgroundJob\Job;
+use OCP\IConfig;
+use OCP\IUserManager;
use OCP\Security\VerificationToken\InvalidTokenException;
use OCP\Security\VerificationToken\IVerificationToken;
diff --git a/lib/private/Security/VerificationToken/VerificationToken.php b/lib/private/Security/VerificationToken/VerificationToken.php
index 5f606d0e049..f99e6745952 100644
--- a/lib/private/Security/VerificationToken/VerificationToken.php
+++ b/lib/private/Security/VerificationToken/VerificationToken.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2021 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Security\VerificationToken;
use OCP\AppFramework\Utility\ITimeFactory;
diff --git a/lib/private/Server.php b/lib/private/Server.php
index e8ade23d8fe..bcdf482f02d 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -1,54 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arne Hamann <kontakt+github@arne.email>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bernhard Reiter <ockham@raz.or.at>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Damjan Georgievski <gdamjan@gmail.com>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Haertl <jus@bitgrid.net>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lionel Elie Mamane <lionel@mamane.lu>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Maxence Lange <maxence@artificial-owl.com>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Piotr Mrówczyński <mrow4a@yahoo.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author root <root@localhost.localdomain>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Tobia De Koninck <tobia@ledfan.be>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -68,6 +22,7 @@ use OC\Authentication\Listeners\UserLoggedInListener;
use OC\Authentication\LoginCredentials\Store;
use OC\Authentication\Token\IProvider;
use OC\Avatar\AvatarManager;
+use OC\Blurhash\Listener\GenerateBlurhashMetadata;
use OC\Collaboration\Collaborators\GroupPlugin;
use OC\Collaboration\Collaborators\MailPlugin;
use OC\Collaboration\Collaborators\RemoteGroupPlugin;
@@ -85,6 +40,7 @@ use OC\Diagnostics\QueryLogger;
use OC\Federation\CloudFederationFactory;
use OC\Federation\CloudFederationProviderManager;
use OC\Federation\CloudIdManager;
+use OC\Files\Cache\FileAccess;
use OC\Files\Config\MountProviderCollection;
use OC\Files\Config\UserMountCache;
use OC\Files\Config\UserMountCacheListener;
@@ -102,6 +58,7 @@ use OC\Files\Storage\StorageFactory;
use OC\Files\Template\TemplateManager;
use OC\Files\Type\Loader;
use OC\Files\View;
+use OC\FilesMetadata\FilesMetadataManager;
use OC\FullTextSearch\FullTextSearchManager;
use OC\Http\Client\ClientService;
use OC\Http\Client\NegativeDnsCache;
@@ -109,8 +66,8 @@ use OC\IntegrityCheck\Checker;
use OC\IntegrityCheck\Helpers\AppLocator;
use OC\IntegrityCheck\Helpers\EnvironmentHelper;
use OC\IntegrityCheck\Helpers\FileAccessHelper;
-use OC\LDAP\NullLDAPProviderFactory;
use OC\KnownUser\KnownUserService;
+use OC\LDAP\NullLDAPProviderFactory;
use OC\Lock\DBLockingProvider;
use OC\Lock\MemcacheLockingProvider;
use OC\Lock\NoopLockingProvider;
@@ -120,14 +77,15 @@ use OC\Log\PsrLoggerAdapter;
use OC\Mail\Mailer;
use OC\Memcache\ArrayCache;
use OC\Memcache\Factory;
-use OC\Metadata\Capabilities as MetadataCapabilities;
-use OC\Metadata\IMetadataManager;
-use OC\Metadata\MetadataManager;
use OC\Notification\Manager;
+use OC\OCM\Model\OCMProvider;
+use OC\OCM\OCMDiscoveryService;
use OC\OCS\DiscoveryService;
use OC\Preview\GeneratorHelper;
use OC\Preview\IMagickSupport;
use OC\Preview\MimeIconProvider;
+use OC\Profile\ProfileManager;
+use OC\Profiler\Profiler;
use OC\Remote\Api\ApiFactory;
use OC\Remote\InstanceFactory;
use OC\RichObjectStrings\Validator;
@@ -142,27 +100,38 @@ use OC\Security\CSP\ContentSecurityPolicyNonceManager;
use OC\Security\CSRF\CsrfTokenManager;
use OC\Security\CSRF\TokenStorage\SessionStorage;
use OC\Security\Hasher;
+use OC\Security\RateLimiting\Limiter;
use OC\Security\SecureRandom;
use OC\Security\TrustedDomainHelper;
use OC\Security\VerificationToken\VerificationToken;
use OC\Session\CryptoWrapper;
+use OC\Settings\DeclarativeManager;
+use OC\SetupCheck\SetupCheckManager;
use OC\Share20\ProviderFactory;
use OC\Share20\ShareHelper;
use OC\SpeechToText\SpeechToTextManager;
use OC\SystemTag\ManagerFactory as SystemTagManagerFactory;
use OC\Tagging\TagMapper;
use OC\Talk\Broker;
+use OC\Teams\TeamManager;
use OC\Template\JSCombiner;
use OC\Translation\TranslationManager;
+use OC\User\AvailabilityCoordinator;
use OC\User\DisplayNameCache;
use OC\User\Listeners\BeforeUserDeletedListener;
use OC\User\Listeners\UserChangedListener;
use OC\User\Session;
+use OCA\Files_External\Service\BackendService;
+use OCA\Files_External\Service\GlobalStoragesService;
+use OCA\Files_External\Service\UserGlobalStoragesService;
+use OCA\Files_External\Service\UserStoragesService;
use OCA\Theming\ImageManager;
+use OCA\Theming\Service\BackgroundService;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\Authentication\Token\IProvider as OCPIProvider;
use OCP\BackgroundJob\IJobList;
@@ -181,6 +150,7 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudIdManager;
+use OCP\Files\Cache\IFileAccess;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\IMimeTypeDetector;
@@ -190,16 +160,17 @@ use OCP\Files\Lock\ILockManager;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Storage\IStorageFactory;
use OCP\Files\Template\ITemplateManager;
+use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\FullTextSearch\IFullTextSearchManager;
use OCP\GlobalScale\IConfig;
use OCP\Group\ISubAdmin;
use OCP\Http\Client\IClientService;
use OCP\IAppConfig;
use OCP\IAvatarManager;
+use OCP\IBinaryFinder;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\ICertificateManager;
-use OCP\IBinaryFinder;
use OCP\IDateTimeFormatter;
use OCP\IDateTimeZone;
use OCP\IDBConnection;
@@ -209,6 +180,7 @@ use OCP\IInitialStateService;
use OCP\IL10N;
use OCP\ILogger;
use OCP\INavigationManager;
+use OCP\IPhoneNumberUtil;
use OCP\IPreview;
use OCP\IRequest;
use OCP\IRequestId;
@@ -227,6 +199,11 @@ use OCP\Lock\ILockingProvider;
use OCP\Lockdown\ILockdownManager;
use OCP\Log\ILogFactory;
use OCP\Mail\IMailer;
+use OCP\OCM\IOCMDiscoveryService;
+use OCP\OCM\IOCMProvider;
+use OCP\Preview\IMimeIconProvider;
+use OCP\Profile\IProfileManager;
+use OCP\Profiler\IProfiler;
use OCP\Remote\Api\IApiFactory;
use OCP\Remote\IInstanceFactory;
use OCP\RichObjectStrings\IValidator;
@@ -238,12 +215,17 @@ use OCP\Security\ICrypto;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
use OCP\Security\ITrustedDomainHelper;
+use OCP\Security\RateLimiting\ILimiter;
use OCP\Security\VerificationToken\IVerificationToken;
+use OCP\Settings\IDeclarativeManager;
+use OCP\SetupCheck\ISetupCheckManager;
+use OCP\Share\IProviderFactory;
use OCP\Share\IShareHelper;
use OCP\SpeechToText\ISpeechToTextManager;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\Talk\IBroker;
+use OCP\Teams\ITeamManager;
use OCP\Translation\ITranslationManager;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\BeforeUserLoggedInEvent;
@@ -254,16 +236,10 @@ use OCP\User\Events\UserChangedEvent;
use OCP\User\Events\UserLoggedInEvent;
use OCP\User\Events\UserLoggedInWithCookieEvent;
use OCP\User\Events\UserLoggedOutEvent;
+use OCP\User\IAvailabilityCoordinator;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
-use OCA\Files_External\Service\UserStoragesService;
-use OCA\Files_External\Service\UserGlobalStoragesService;
-use OCA\Files_External\Service\GlobalStoragesService;
-use OCA\Files_External\Service\BackendService;
-use OCP\Profiler\IProfiler;
-use OC\Profiler\Profiler;
-use OCP\Preview\IMimeIconProvider;
/**
* Class Server
@@ -430,17 +406,21 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(ISystemTagObjectMapper::class, function (ContainerInterface $c) {
return $c->get('SystemTagManagerFactory')->getObjectMapper();
});
+ $this->registerAlias(IFileAccess::class, FileAccess::class);
$this->registerService('RootFolder', function (ContainerInterface $c) {
$manager = \OC\Files\Filesystem::getMountManager();
$view = new View();
+ /** @var IUserSession $userSession */
+ $userSession = $c->get(IUserSession::class);
$root = new Root(
$manager,
$view,
- null,
+ $userSession->getUser(),
$c->get(IUserMountCache::class),
$this->get(LoggerInterface::class),
$this->get(IUserManager::class),
$this->get(IEventDispatcher::class),
+ $this->get(ICacheFactory::class),
);
$previewConnector = new \OC\Preview\WatcherConnector(
@@ -455,7 +435,8 @@ class Server extends ServerContainer implements IServerContainer {
return new HookConnector(
$c->get(IRootFolder::class),
new View(),
- $c->get(IEventDispatcher::class)
+ $c->get(IEventDispatcher::class),
+ $c->get(LoggerInterface::class)
);
});
@@ -523,7 +504,7 @@ class Server extends ServerContainer implements IServerContainer {
$provider,
$c->get(\OCP\IConfig::class),
$c->get(ISecureRandom::class),
- $c->getLockdownManager(),
+ $c->get('LockdownManager'),
$c->get(LoggerInterface::class),
$c->get(IEventDispatcher::class)
);
@@ -630,7 +611,8 @@ class Server extends ServerContainer implements IServerContainer {
$c->getRequest(),
$c->get(IUserSession::class),
$c->get(ICacheFactory::class),
- \OC::$SERVERROOT
+ \OC::$SERVERROOT,
+ $c->get(IAppManager::class),
);
});
/** @deprecated 19.0.0 */
@@ -701,7 +683,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService('RedisFactory', function (Server $c) {
$systemConfig = $c->get(SystemConfig::class);
- return new RedisFactory($systemConfig, $c->getEventLogger());
+ return new RedisFactory($systemConfig, $c->get(IEventLogger::class));
});
$this->registerService(\OCP\Activity\IManager::class, function (Server $c) {
@@ -785,8 +767,8 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerDeprecatedAlias('Search', ISearch::class);
$this->registerService(\OC\Security\RateLimiting\Backend\IBackend::class, function ($c) {
- $cacheFactory = $c->get(ICacheFactory::class);
- if ($cacheFactory->isAvailable()) {
+ $config = $c->get(\OCP\IConfig::class);
+ if (ltrim($config->getSystemValueString('memcache.distributed', ''), '\\') === \OC\Memcache\Redis::class) {
$backend = new \OC\Security\RateLimiting\Backend\MemoryCacheBackend(
$c->get(AllConfig::class),
$this->get(ICacheFactory::class),
@@ -829,8 +811,7 @@ class Server extends ServerContainer implements IServerContainer {
if (!$factory->isValidType($type)) {
throw new \OC\DatabaseException('Invalid database type');
}
- $connectionParams = $factory->createConnectionParams();
- $connection = $factory->getConnection($type, $connectionParams);
+ $connection = $factory->getConnection($type, []);
return $connection;
});
/** @deprecated 19.0.0 */
@@ -870,11 +851,10 @@ class Server extends ServerContainer implements IServerContainer {
return new \OC\App\AppManager(
$c->get(IUserSession::class),
$c->get(\OCP\IConfig::class),
- $c->get(\OC\AppConfig::class),
$c->get(IGroupManager::class),
$c->get(ICacheFactory::class),
$c->get(IEventDispatcher::class),
- $c->get(LoggerInterface::class)
+ $c->get(LoggerInterface::class),
);
});
/** @deprecated 19.0.0 */
@@ -962,15 +942,16 @@ class Server extends ServerContainer implements IServerContainer {
return $backend;
});
- $this->registerService('IntegrityCodeChecker', function (ContainerInterface $c) {
+ $this->registerDeprecatedAlias('IntegrityCodeChecker', Checker::class);
+ $this->registerService(Checker::class, function (ContainerInterface $c) {
// IConfig and IAppManager requires a working database. This code
// might however be called when ownCloud is not yet setup.
if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
$config = $c->get(\OCP\IConfig::class);
+ $appConfig = $c->get(\OCP\IAppConfig::class);
$appManager = $c->get(IAppManager::class);
} else {
- $config = null;
- $appManager = null;
+ $config = $appConfig = $appManager = null;
}
return new Checker(
@@ -978,6 +959,7 @@ class Server extends ServerContainer implements IServerContainer {
new FileAccessHelper(),
new AppLocator(),
$config,
+ $appConfig,
$c->get(ICacheFactory::class),
$appManager,
$c->get(IMimeTypeDetector::class)
@@ -1066,7 +1048,8 @@ class Server extends ServerContainer implements IServerContainer {
$memcacheFactory = $c->get(ICacheFactory::class);
$memcache = $memcacheFactory->createLocking('lock');
if (!($memcache instanceof \OC\Memcache\NullCache)) {
- return new MemcacheLockingProvider($memcache, $ttl);
+ $timeFactory = $c->get(ITimeFactory::class);
+ return new MemcacheLockingProvider($memcache, $timeFactory, $ttl);
}
return new DBLockingProvider(
$c->get(IDBConnection::class),
@@ -1122,9 +1105,6 @@ class Server extends ServerContainer implements IServerContainer {
$manager->registerCapability(function () use ($c) {
return $c->get(\OC\Security\Bruteforce\Capabilities::class);
});
- $manager->registerCapability(function () use ($c) {
- return $c->get(MetadataCapabilities::class);
- });
return $manager;
});
/** @deprecated 19.0.0 */
@@ -1142,7 +1122,7 @@ class Server extends ServerContainer implements IServerContainer {
$userDisplayName = $manager->getDisplayName($id);
if ($userDisplayName === null) {
$l = $c->get(IFactory::class)->get('core');
- return $l->t('Unknown user');
+ return $l->t('Unknown account');
}
return $userDisplayName;
});
@@ -1161,14 +1141,21 @@ class Server extends ServerContainer implements IServerContainer {
$classExists = false;
}
- if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isInstalled('theming') && $c->getTrustedDomainHelper()->isTrustedDomain($c->getRequest()->getInsecureServerHost())) {
+ if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isInstalled('theming') && $c->get(TrustedDomainHelper::class)->isTrustedDomain($c->getRequest()->getInsecureServerHost())) {
+ $backgroundService = new BackgroundService(
+ $c->get(IRootFolder::class),
+ $c->getAppDataDir('theming'),
+ $c->get(\OCP\IConfig::class),
+ $c->get(ISession::class)->get('user_id'),
+ );
$imageManager = new ImageManager(
$c->get(\OCP\IConfig::class),
$c->getAppDataDir('theming'),
$c->get(IURLGenerator::class),
- $this->get(ICacheFactory::class),
- $this->get(ILogger::class),
- $this->get(ITempManager::class)
+ $c->get(ICacheFactory::class),
+ $c->get(LoggerInterface::class),
+ $c->get(ITempManager::class),
+ $backgroundService,
);
return new ThemingDefaults(
$c->get(\OCP\IConfig::class),
@@ -1179,7 +1166,8 @@ class Server extends ServerContainer implements IServerContainer {
new Util($c->get(\OCP\IConfig::class), $this->get(IAppManager::class), $c->getAppDataDir('theming'), $imageManager),
$imageManager,
$c->get(IAppManager::class),
- $c->get(INavigationManager::class)
+ $c->get(INavigationManager::class),
+ $backgroundService,
);
}
return new \OC_Defaults();
@@ -1229,34 +1217,14 @@ class Server extends ServerContainer implements IServerContainer {
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('ContentSecurityPolicyManager', ContentSecurityPolicyManager::class);
- $this->registerService(\OCP\Share\IManager::class, function (IServerContainer $c) {
+ $this->registerService(IProviderFactory::class, function (ContainerInterface $c) {
$config = $c->get(\OCP\IConfig::class);
$factoryClass = $config->getSystemValue('sharing.managerFactory', ProviderFactory::class);
/** @var \OCP\Share\IProviderFactory $factory */
- $factory = new $factoryClass($this);
-
- $manager = new \OC\Share20\Manager(
- $c->get(LoggerInterface::class),
- $c->get(\OCP\IConfig::class),
- $c->get(ISecureRandom::class),
- $c->get(IHasher::class),
- $c->get(IMountManager::class),
- $c->get(IGroupManager::class),
- $c->getL10N('lib'),
- $c->get(IFactory::class),
- $factory,
- $c->get(IUserManager::class),
- $c->get(IRootFolder::class),
- $c->get(IMailer::class),
- $c->get(IURLGenerator::class),
- $c->get('ThemingDefaults'),
- $c->get(IEventDispatcher::class),
- $c->get(IUserSession::class),
- $c->get(KnownUserService::class)
- );
-
- return $manager;
+ return new $factoryClass($this);
});
+
+ $this->registerAlias(\OCP\Share\IManager::class, \OC\Share20\Manager::class);
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('ShareManager', \OCP\Share\IManager::class);
@@ -1282,6 +1250,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\Collaboration\Resources\IManager::class, \OC\Collaboration\Resources\Manager::class);
$this->registerAlias(IReferenceManager::class, ReferenceManager::class);
+ $this->registerAlias(ITeamManager::class, TeamManager::class);
$this->registerDeprecatedAlias('SettingsManager', \OC\Settings\Manager::class);
$this->registerAlias(\OCP\Settings\IManager::class, \OC\Settings\Manager::class);
@@ -1304,6 +1273,7 @@ class Server extends ServerContainer implements IServerContainer {
$c->get(IClientService::class)
);
});
+ $this->registerAlias(IOCMDiscoveryService::class, OCMDiscoveryService::class);
$this->registerService(ICloudIdManager::class, function (ContainerInterface $c) {
return new CloudIdManager(
@@ -1319,9 +1289,11 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(ICloudFederationProviderManager::class, function (ContainerInterface $c) {
return new CloudFederationProviderManager(
+ $c->get(\OCP\IConfig::class),
$c->get(IAppManager::class),
$c->get(IClientService::class),
$c->get(ICloudIdManager::class),
+ $c->get(IOCMDiscoveryService::class),
$c->get(LoggerInterface::class)
);
});
@@ -1341,7 +1313,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(Defaults::class, function (Server $c) {
return new Defaults(
- $c->getThemingDefaults()
+ $c->get('ThemingDefaults')
);
});
/** @deprecated 19.0.0 */
@@ -1385,6 +1357,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\Dashboard\IManager::class, \OC\Dashboard\Manager::class);
$this->registerAlias(IFullTextSearchManager::class, FullTextSearchManager::class);
+ $this->registerAlias(IFilesMetadataManager::class, FilesMetadataManager::class);
$this->registerAlias(ISubAdmin::class, SubAdmin::class);
@@ -1396,8 +1369,6 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(IBroker::class, Broker::class);
- $this->registerAlias(IMetadataManager::class, MetadataManager::class);
-
$this->registerAlias(\OCP\Files\AppData\IAppDataFactory::class, \OC\Files\AppData\Factory::class);
$this->registerAlias(IBinaryFinder::class, BinaryFinder::class);
@@ -1412,6 +1383,24 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\TextProcessing\IManager::class, \OC\TextProcessing\Manager::class);
+ $this->registerAlias(\OCP\TextToImage\IManager::class, \OC\TextToImage\Manager::class);
+
+ $this->registerAlias(ILimiter::class, Limiter::class);
+
+ $this->registerAlias(IPhoneNumberUtil::class, PhoneNumberUtil::class);
+
+ $this->registerAlias(IOCMProvider::class, OCMProvider::class);
+
+ $this->registerAlias(ISetupCheckManager::class, SetupCheckManager::class);
+
+ $this->registerAlias(IProfileManager::class, ProfileManager::class);
+
+ $this->registerAlias(IAvailabilityCoordinator::class, AvailabilityCoordinator::class);
+
+ $this->registerAlias(IDeclarativeManager::class, DeclarativeManager::class);
+
+ $this->registerAlias(\OCP\TaskProcessing\IManager::class, \OC\TaskProcessing\Manager::class);
+
$this->connectDispatcher();
}
@@ -1452,6 +1441,9 @@ class Server extends ServerContainer implements IServerContainer {
$eventDispatcher->addServiceListener(PostLoginEvent::class, UserLoggedInListener::class);
$eventDispatcher->addServiceListener(UserChangedEvent::class, UserChangedListener::class);
$eventDispatcher->addServiceListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class);
+
+ FilesMetadataManager::loadListeners($eventDispatcher);
+ GenerateBlurhashMetadata::loadListeners($eventDispatcher);
}
/**
@@ -1628,6 +1620,7 @@ class Server extends ServerContainer implements IServerContainer {
/**
* @param \OCP\ISession $session
+ * @return void
*/
public function setSession(\OCP\ISession $session) {
$this->get(SessionStorage::class)->setSession($session);
@@ -1691,7 +1684,7 @@ class Server extends ServerContainer implements IServerContainer {
* @param string $app appid
* @param string $lang
* @return IL10N
- * @deprecated 20.0.0
+ * @deprecated 20.0.0 use DI of {@see IL10N} or {@see IFactory} instead, or {@see \OCP\Util::getL10N()} as a last resort
*/
public function getL10N($app, $lang = null) {
return $this->get(IFactory::class)->get($app, $lang);
diff --git a/lib/private/ServerContainer.php b/lib/private/ServerContainer.php
index daa480a75d1..9f887b2d48a 100644
--- a/lib/private/ServerContainer.php
+++ b/lib/private/ServerContainer.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/ServerNotAvailableException.php b/lib/private/ServerNotAvailableException.php
index 89a9300e50e..d24f16f30a0 100644
--- a/lib/private/ServerNotAvailableException.php
+++ b/lib/private/ServerNotAvailableException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/ServiceUnavailableException.php b/lib/private/ServiceUnavailableException.php
index 8c52dd9b74c..f0fe3b48dbe 100644
--- a/lib/private/ServiceUnavailableException.php
+++ b/lib/private/ServiceUnavailableException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Session/CryptoSessionData.php b/lib/private/Session/CryptoSessionData.php
index 1eb6987fc18..323253af534 100644
--- a/lib/private/Session/CryptoSessionData.php
+++ b/lib/private/Session/CryptoSessionData.php
@@ -1,42 +1,24 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Session;
use OCP\ISession;
use OCP\Security\ICrypto;
use OCP\Session\Exceptions\SessionNotAvailableException;
+use function json_decode;
+use function OCP\Log\logger;
/**
* Class CryptoSessionData
*
* @package OC\Session
+ * @template-implements \ArrayAccess<string,mixed>
*/
class CryptoSessionData implements \ArrayAccess, ISession {
/** @var ISession */
@@ -57,8 +39,8 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $passphrase
*/
public function __construct(ISession $session,
- ICrypto $crypto,
- string $passphrase) {
+ ICrypto $crypto,
+ string $passphrase) {
$this->crypto = $crypto;
$this->session = $session;
$this->passphrase = $passphrase;
@@ -79,14 +61,24 @@ class CryptoSessionData implements \ArrayAccess, ISession {
protected function initializeSession() {
$encryptedSessionData = $this->session->get(self::encryptedSessionName) ?: '';
- try {
- $this->sessionValues = json_decode(
- $this->crypto->decrypt($encryptedSessionData, $this->passphrase),
- true
- );
- } catch (\Exception $e) {
+ if ($encryptedSessionData === '') {
+ // Nothing to decrypt
$this->sessionValues = [];
- $this->regenerateId(true, false);
+ } else {
+ try {
+ $this->sessionValues = json_decode(
+ $this->crypto->decrypt($encryptedSessionData, $this->passphrase),
+ true,
+ 512,
+ JSON_THROW_ON_ERROR,
+ );
+ } catch (\Exception $e) {
+ logger('core')->critical('Could not decrypt or decode encrypted session data', [
+ 'exception' => $e,
+ ]);
+ $this->sessionValues = [];
+ $this->regenerateId(true, false);
+ }
}
}
diff --git a/lib/private/Session/CryptoWrapper.php b/lib/private/Session/CryptoWrapper.php
index e98aac3b8bf..aceb387ea74 100644
--- a/lib/private/Session/CryptoWrapper.php
+++ b/lib/private/Session/CryptoWrapper.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Phil Davis <phil.davis@inf.org>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Session;
@@ -68,9 +50,9 @@ class CryptoWrapper {
* @param IRequest $request
*/
public function __construct(IConfig $config,
- ICrypto $crypto,
- ISecureRandom $random,
- IRequest $request) {
+ ICrypto $crypto,
+ ISecureRandom $random,
+ IRequest $request) {
$this->crypto = $crypto;
$this->config = $config;
$this->random = $random;
diff --git a/lib/private/Session/Internal.php b/lib/private/Session/Internal.php
index e8e2a4f2d8e..4384b0ab5c0 100644
--- a/lib/private/Session/Internal.php
+++ b/lib/private/Session/Internal.php
@@ -3,38 +3,14 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author cetra3 <peter@parashift.com.au>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author MartB <mart.b@outlook.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Session;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\IProvider;
+use OCP\Authentication\Exceptions\InvalidTokenException;
use OCP\Session\Exceptions\SessionNotAvailableException;
/**
@@ -121,7 +97,7 @@ class Internal extends Session {
* Wrapper around session_regenerate_id
*
* @param bool $deleteOldSession Whether to delete the old associated session file or not.
- * @param bool $updateToken Wheater to update the associated auth token
+ * @param bool $updateToken Whether to update the associated auth token
* @return void
*/
public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {
diff --git a/lib/private/Session/Memory.php b/lib/private/Session/Memory.php
index fe71ec77692..eb10ebe05b4 100644
--- a/lib/private/Session/Memory.php
+++ b/lib/private/Session/Memory.php
@@ -1,32 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Session;
diff --git a/lib/private/Session/Session.php b/lib/private/Session/Session.php
index b434461a335..3006eceecba 100644
--- a/lib/private/Session/Session.php
+++ b/lib/private/Session/Session.php
@@ -1,34 +1,18 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Session;
use OCP\ISession;
+/**
+ * @template-implements \ArrayAccess<string,mixed>
+ */
abstract class Session implements \ArrayAccess, ISession {
/**
* @var bool
diff --git a/lib/private/Settings/AuthorizedGroup.php b/lib/private/Settings/AuthorizedGroup.php
index 21b897b6787..0171e020171 100644
--- a/lib/private/Settings/AuthorizedGroup.php
+++ b/lib/private/Settings/AuthorizedGroup.php
@@ -1,27 +1,9 @@
<?php
/**
- * @copyright Copyright (c) 2021 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Settings;
use OCP\AppFramework\Db\Entity;
diff --git a/lib/private/Settings/AuthorizedGroupMapper.php b/lib/private/Settings/AuthorizedGroupMapper.php
index c7c39cc6758..b622459426b 100644
--- a/lib/private/Settings/AuthorizedGroupMapper.php
+++ b/lib/private/Settings/AuthorizedGroupMapper.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2021 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Settings;
use OCP\AppFramework\Db\Entity;
diff --git a/lib/private/Settings/DeclarativeManager.php b/lib/private/Settings/DeclarativeManager.php
new file mode 100644
index 00000000000..5c2b868f417
--- /dev/null
+++ b/lib/private/Settings/DeclarativeManager.php
@@ -0,0 +1,386 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Settings;
+
+use Exception;
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IAppConfig;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\Server;
+use OCP\Settings\DeclarativeSettingsTypes;
+use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
+use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;
+use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
+use OCP\Settings\IDeclarativeManager;
+use OCP\Settings\IDeclarativeSettingsForm;
+use Psr\Log\LoggerInterface;
+
+/**
+ * @psalm-import-type DeclarativeSettingsValueTypes from IDeclarativeSettingsForm
+ * @psalm-import-type DeclarativeSettingsStorageType from IDeclarativeSettingsForm
+ * @psalm-import-type DeclarativeSettingsSectionType from IDeclarativeSettingsForm
+ * @psalm-import-type DeclarativeSettingsFormSchemaWithValues from IDeclarativeSettingsForm
+ * @psalm-import-type DeclarativeSettingsFormSchemaWithoutValues from IDeclarativeSettingsForm
+ */
+class DeclarativeManager implements IDeclarativeManager {
+ public function __construct(
+ private IEventDispatcher $eventDispatcher,
+ private IGroupManager $groupManager,
+ private Coordinator $coordinator,
+ private IConfig $config,
+ private IAppConfig $appConfig,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ /**
+ * @var array<string, list<DeclarativeSettingsFormSchemaWithoutValues>>
+ */
+ private array $appSchemas = [];
+
+ /**
+ * @inheritdoc
+ */
+ public function registerSchema(string $app, array $schema): void {
+ $this->appSchemas[$app] ??= [];
+
+ if (!$this->validateSchema($app, $schema)) {
+ throw new Exception('Invalid schema. Please check the logs for more details.');
+ }
+
+ foreach ($this->appSchemas[$app] as $otherSchema) {
+ if ($otherSchema['id'] === $schema['id']) {
+ throw new Exception('Duplicate form IDs detected: ' . $schema['id']);
+ }
+ }
+
+ $fieldIDs = array_map(fn ($field) => $field['id'], $schema['fields']);
+ $otherFieldIDs = array_merge(...array_map(fn ($schema) => array_map(fn ($field) => $field['id'], $schema['fields']), $this->appSchemas[$app]));
+ $intersectionFieldIDs = array_intersect($fieldIDs, $otherFieldIDs);
+ if (count($intersectionFieldIDs) > 0) {
+ throw new Exception('Non unique field IDs detected: ' . join(', ', $intersectionFieldIDs));
+ }
+
+ $this->appSchemas[$app][] = $schema;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function loadSchemas(): void {
+ $declarativeSettings = $this->coordinator->getRegistrationContext()->getDeclarativeSettings();
+ foreach ($declarativeSettings as $declarativeSetting) {
+ /** @var IDeclarativeSettingsForm $declarativeSettingObject */
+ $declarativeSettingObject = Server::get($declarativeSetting->getService());
+ $this->registerSchema($declarativeSetting->getAppId(), $declarativeSettingObject->getSchema());
+ }
+
+ $this->eventDispatcher->dispatchTyped(new DeclarativeSettingsRegisterFormEvent($this));
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getFormIDs(IUser $user, string $type, string $section): array {
+ $isAdmin = $this->groupManager->isAdmin($user->getUID());
+ /** @var array<string, list<string>> $formIds */
+ $formIds = [];
+
+ foreach ($this->appSchemas as $app => $schemas) {
+ $ids = [];
+ usort($schemas, [$this, 'sortSchemasByPriorityCallback']);
+ foreach ($schemas as $schema) {
+ if ($schema['section_type'] === DeclarativeSettingsTypes::SECTION_TYPE_ADMIN && !$isAdmin) {
+ continue;
+ }
+ if ($schema['section_type'] === $type && $schema['section_id'] === $section) {
+ $ids[] = $schema['id'];
+ }
+ }
+
+ if (!empty($ids)) {
+ $formIds[$app] = array_merge($formIds[$app] ?? [], $ids);
+ }
+ }
+
+ return $formIds;
+ }
+
+ /**
+ * @inheritdoc
+ * @throws Exception
+ */
+ public function getFormsWithValues(IUser $user, ?string $type, ?string $section): array {
+ $isAdmin = $this->groupManager->isAdmin($user->getUID());
+ $forms = [];
+
+ foreach ($this->appSchemas as $app => $schemas) {
+ foreach ($schemas as $schema) {
+ if ($type !== null && $schema['section_type'] !== $type) {
+ continue;
+ }
+ if ($section !== null && $schema['section_id'] !== $section) {
+ continue;
+ }
+ // If listing all fields skip the admin fields which a non-admin user has no access to
+ if ($type === null && $schema['section_type'] === 'admin' && !$isAdmin) {
+ continue;
+ }
+
+ $s = $schema;
+ $s['app'] = $app;
+
+ foreach ($s['fields'] as &$field) {
+ $field['value'] = $this->getValue($user, $app, $schema['id'], $field['id']);
+ }
+ unset($field);
+
+ /** @var DeclarativeSettingsFormSchemaWithValues $s */
+ $forms[] = $s;
+ }
+ }
+
+ usort($forms, [$this, 'sortSchemasByPriorityCallback']);
+
+ return $forms;
+ }
+
+ private function sortSchemasByPriorityCallback(mixed $a, mixed $b): int {
+ if ($a['priority'] === $b['priority']) {
+ return 0;
+ }
+ return $a['priority'] > $b['priority'] ? -1 : 1;
+ }
+
+ /**
+ * @return DeclarativeSettingsStorageType
+ */
+ private function getStorageType(string $app, string $fieldId): string {
+ if (array_key_exists($app, $this->appSchemas)) {
+ foreach ($this->appSchemas[$app] as $schema) {
+ foreach ($schema['fields'] as $field) {
+ if ($field['id'] == $fieldId) {
+ if (array_key_exists('storage_type', $field)) {
+ return $field['storage_type'];
+ }
+ }
+ }
+
+ if (array_key_exists('storage_type', $schema)) {
+ return $schema['storage_type'];
+ }
+ }
+ }
+
+ return DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL;
+ }
+
+ /**
+ * @return DeclarativeSettingsSectionType
+ * @throws Exception
+ */
+ private function getSectionType(string $app, string $fieldId): string {
+ if (array_key_exists($app, $this->appSchemas)) {
+ foreach ($this->appSchemas[$app] as $schema) {
+ foreach ($schema['fields'] as $field) {
+ if ($field['id'] == $fieldId) {
+ return $schema['section_type'];
+ }
+ }
+ }
+ }
+
+ throw new Exception('Unknown fieldId "' . $fieldId . '"');
+ }
+
+ /**
+ * @psalm-param DeclarativeSettingsSectionType $sectionType
+ * @throws NotAdminException
+ */
+ private function assertAuthorized(IUser $user, string $sectionType): void {
+ if ($sectionType === 'admin' && !$this->groupManager->isAdmin($user->getUID())) {
+ throw new NotAdminException('Logged in user does not have permission to access these settings.');
+ }
+ }
+
+ /**
+ * @return DeclarativeSettingsValueTypes
+ * @throws Exception
+ * @throws NotAdminException
+ */
+ private function getValue(IUser $user, string $app, string $formId, string $fieldId): mixed {
+ $sectionType = $this->getSectionType($app, $fieldId);
+ $this->assertAuthorized($user, $sectionType);
+
+ $storageType = $this->getStorageType($app, $fieldId);
+ switch ($storageType) {
+ case DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL:
+ $event = new DeclarativeSettingsGetValueEvent($user, $app, $formId, $fieldId);
+ $this->eventDispatcher->dispatchTyped($event);
+ return $event->getValue();
+ case DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL:
+ return $this->getInternalValue($user, $app, $formId, $fieldId);
+ default:
+ throw new Exception('Unknown storage type "' . $storageType . '"');
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setValue(IUser $user, string $app, string $formId, string $fieldId, mixed $value): void {
+ $sectionType = $this->getSectionType($app, $fieldId);
+ $this->assertAuthorized($user, $sectionType);
+
+ $storageType = $this->getStorageType($app, $fieldId);
+ switch ($storageType) {
+ case DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL:
+ $this->eventDispatcher->dispatchTyped(new DeclarativeSettingsSetValueEvent($user, $app, $formId, $fieldId, $value));
+ break;
+ case DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL:
+ $this->saveInternalValue($user, $app, $fieldId, $value);
+ break;
+ default:
+ throw new Exception('Unknown storage type "' . $storageType . '"');
+ }
+ }
+
+ private function getInternalValue(IUser $user, string $app, string $formId, string $fieldId): mixed {
+ $sectionType = $this->getSectionType($app, $fieldId);
+ $defaultValue = $this->getDefaultValue($app, $formId, $fieldId);
+ switch ($sectionType) {
+ case DeclarativeSettingsTypes::SECTION_TYPE_ADMIN:
+ return $this->config->getAppValue($app, $fieldId, $defaultValue);
+ case DeclarativeSettingsTypes::SECTION_TYPE_PERSONAL:
+ return $this->config->getUserValue($user->getUID(), $app, $fieldId, $defaultValue);
+ default:
+ throw new Exception('Unknown section type "' . $sectionType . '"');
+ }
+ }
+
+ private function saveInternalValue(IUser $user, string $app, string $fieldId, mixed $value): void {
+ $sectionType = $this->getSectionType($app, $fieldId);
+ switch ($sectionType) {
+ case DeclarativeSettingsTypes::SECTION_TYPE_ADMIN:
+ $this->appConfig->setValueString($app, $fieldId, $value);
+ break;
+ case DeclarativeSettingsTypes::SECTION_TYPE_PERSONAL:
+ $this->config->setUserValue($user->getUID(), $app, $fieldId, $value);
+ break;
+ default:
+ throw new Exception('Unknown section type "' . $sectionType . '"');
+ }
+ }
+
+ private function getDefaultValue(string $app, string $formId, string $fieldId): mixed {
+ foreach ($this->appSchemas[$app] as $schema) {
+ if ($schema['id'] === $formId) {
+ foreach ($schema['fields'] as $field) {
+ if ($field['id'] === $fieldId) {
+ if (isset($field['default'])) {
+ if (is_array($field['default'])) {
+ return json_encode($field['default']);
+ }
+ return $field['default'];
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private function validateSchema(string $appId, array $schema): bool {
+ if (!isset($schema['id'])) {
+ $this->logger->warning('Attempt to register a declarative settings schema with no id', ['app' => $appId]);
+ return false;
+ }
+ $formId = $schema['id'];
+ if (!isset($schema['section_type'])) {
+ $this->logger->warning('Declarative settings: missing section_type', ['app' => $appId, 'form_id' => $formId]);
+ return false;
+ }
+ if (!in_array($schema['section_type'], [DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, DeclarativeSettingsTypes::SECTION_TYPE_PERSONAL])) {
+ $this->logger->warning('Declarative settings: invalid section_type', ['app' => $appId, 'form_id' => $formId, 'section_type' => $schema['section_type']]);
+ return false;
+ }
+ if (!isset($schema['section_id'])) {
+ $this->logger->warning('Declarative settings: missing section_id', ['app' => $appId, 'form_id' => $formId]);
+ return false;
+ }
+ if (!isset($schema['storage_type'])) {
+ $this->logger->warning('Declarative settings: missing storage_type', ['app' => $appId, 'form_id' => $formId]);
+ return false;
+ }
+ if (!in_array($schema['storage_type'], [DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL, DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL])) {
+ $this->logger->warning('Declarative settings: invalid storage_type', ['app' => $appId, 'form_id' => $formId, 'storage_type' => $schema['storage_type']]);
+ return false;
+ }
+ if (!isset($schema['title'])) {
+ $this->logger->warning('Declarative settings: missing title', ['app' => $appId, 'form_id' => $formId]);
+ return false;
+ }
+ if (!isset($schema['fields']) || !is_array($schema['fields'])) {
+ $this->logger->warning('Declarative settings: missing or invalid fields', ['app' => $appId, 'form_id' => $formId]);
+ return false;
+ }
+ foreach ($schema['fields'] as $field) {
+ if (!isset($field['id'])) {
+ $this->logger->warning('Declarative settings: missing field id', ['app' => $appId, 'form_id' => $formId, 'field' => $field]);
+ return false;
+ }
+ $fieldId = $field['id'];
+ if (!isset($field['title'])) {
+ $this->logger->warning('Declarative settings: missing field title', ['app' => $appId, 'form_id' => $formId, 'field_id' => $fieldId]);
+ return false;
+ }
+ if (!isset($field['type'])) {
+ $this->logger->warning('Declarative settings: missing field type', ['app' => $appId, 'form_id' => $formId, 'field_id' => $fieldId]);
+ return false;
+ }
+ if (!in_array($field['type'], [
+ DeclarativeSettingsTypes::MULTI_SELECT, DeclarativeSettingsTypes::MULTI_CHECKBOX, DeclarativeSettingsTypes::RADIO,
+ DeclarativeSettingsTypes::SELECT, DeclarativeSettingsTypes::CHECKBOX,
+ DeclarativeSettingsTypes::URL, DeclarativeSettingsTypes::EMAIL, DeclarativeSettingsTypes::NUMBER,
+ DeclarativeSettingsTypes::TEL, DeclarativeSettingsTypes::TEXT, DeclarativeSettingsTypes::PASSWORD,
+ ])) {
+ $this->logger->warning('Declarative settings: invalid field type', [
+ 'app' => $appId, 'form_id' => $formId, 'field_id' => $fieldId, 'type' => $field['type'],
+ ]);
+ return false;
+ }
+ if (!$this->validateField($appId, $formId, $field)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private function validateField(string $appId, string $formId, array $field): bool {
+ $fieldId = $field['id'];
+ if (in_array($field['type'], [
+ DeclarativeSettingsTypes::MULTI_SELECT, DeclarativeSettingsTypes::MULTI_CHECKBOX, DeclarativeSettingsTypes::RADIO,
+ DeclarativeSettingsTypes::SELECT
+ ])) {
+ if (!isset($field['options'])) {
+ $this->logger->warning('Declarative settings: missing field options', ['app' => $appId, 'form_id' => $formId, 'field_id' => $fieldId]);
+ return false;
+ }
+ if (!is_array($field['options'])) {
+ $this->logger->warning('Declarative settings: field options should be an array', ['app' => $appId, 'form_id' => $formId, 'field_id' => $fieldId]);
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php
index 2d44ac7d3df..c96b73474fa 100644
--- a/lib/private/Settings/Manager.php
+++ b/lib/private/Settings/Manager.php
@@ -1,33 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author sualko <klaus@jsxc.org>
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Settings;
@@ -90,17 +64,14 @@ class Manager implements IManager {
$this->subAdmin = $subAdmin;
}
- /** @var array */
+ /** @var array<self::SETTINGS_*, list<class-string<IIconSection>>> */
protected $sectionClasses = [];
- /** @var array */
+ /** @var array<self::SETTINGS_*, array<string, IIconSection>> */
protected $sections = [];
/**
- * @param string $type 'admin' or 'personal'
- * @param string $section Class must implement OCP\Settings\IIconSection
- *
- * @return void
+ * @inheritdoc
*/
public function registerSection(string $type, string $section) {
if (!isset($this->sectionClasses[$type])) {
@@ -111,7 +82,7 @@ class Manager implements IManager {
}
/**
- * @param string $type 'admin' or 'personal'
+ * @psalm-param self::SETTINGS_* $type
*
* @return IIconSection[]
*/
@@ -149,6 +120,9 @@ class Manager implements IManager {
return $this->sections[$type];
}
+ /**
+ * @inheritdoc
+ */
public function getSection(string $type, string $sectionId): ?IIconSection {
if (isset($this->sections[$type]) && isset($this->sections[$type][$sectionId])) {
return $this->sections[$type][$sectionId];
@@ -163,31 +137,27 @@ class Manager implements IManager {
], true);
}
- /** @var array */
+ /** @var array<class-string<ISettings>, self::SETTINGS_*> */
protected $settingClasses = [];
- /** @var array */
+ /** @var array<self::SETTINGS_*, array<string, list<ISettings>>> */
protected $settings = [];
/**
- * @psam-param 'admin'|'personal' $type The type of the setting.
- * @param string $setting Class must implement OCP\Settings\ISettings
- * @param bool $allowedDelegation
- *
- * @return void
+ * @inheritdoc
*/
public function registerSetting(string $type, string $setting) {
$this->settingClasses[$setting] = $type;
}
/**
- * @param string $type 'admin' or 'personal'
+ * @psalm-param self::SETTINGS_* $type The type of the setting.
* @param string $section
- * @param Closure $filter optional filter to apply on all loaded ISettings
+ * @param ?Closure $filter optional filter to apply on all loaded ISettings
*
* @return ISettings[]
*/
- protected function getSettings(string $type, string $section, Closure $filter = null): array {
+ protected function getSettings(string $type, string $section, ?Closure $filter = null): array {
if (!isset($this->settings[$type])) {
$this->settings[$type] = [];
}
@@ -258,7 +228,7 @@ class Manager implements IManager {
/**
* @inheritdoc
*/
- public function getAdminSettings($section, bool $subAdminOnly = false): array {
+ public function getAdminSettings(string $section, bool $subAdminOnly = false): array {
if ($subAdminOnly) {
$subAdminSettingsFilter = function (ISettings $settings) {
return $settings instanceof ISubAdminSettings;
@@ -329,7 +299,7 @@ class Manager implements IManager {
/**
* @inheritdoc
*/
- public function getPersonalSettings($section): array {
+ public function getPersonalSettings(string $section): array {
$settings = [];
$appSettings = $this->getSettings('personal', $section);
@@ -344,6 +314,9 @@ class Manager implements IManager {
return $settings;
}
+ /**
+ * @inheritdoc
+ */
public function getAllowedAdminSettings(string $section, IUser $user): array {
$isAdmin = $this->groupManager->isAdmin($user->getUID());
if ($isAdmin) {
@@ -375,6 +348,9 @@ class Manager implements IManager {
return $settings;
}
+ /**
+ * @inheritdoc
+ */
public function getAllAllowedAdminSettings(IUser $user): array {
$this->getSettings('admin', ''); // Make sure all the settings are loaded
$settings = [];
diff --git a/lib/private/Settings/Section.php b/lib/private/Settings/Section.php
index ba94a38e874..4f8234254b1 100644
--- a/lib/private/Settings/Section.php
+++ b/lib/private/Settings/Section.php
@@ -1,26 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Settings;
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index 0993fe54f47..a5683655447 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -1,50 +1,11 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Administrator "Administrator@WINDOWS-2012"
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Dan Callahan <dan.callahan@gmail.com>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author François Kubler <francois@kubler.org>
- * @author Frank Isemann <frank@isemann.name>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author KB7777 <k.burkowski@gmail.com>
- * @author Kevin Lanni <therealklanni@gmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author MichaIng <28480705+MichaIng@users.noreply.github.com>
- * @author MichaIng <micha@dietpi.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sean Comeau <sean@ftlnetworks.ca>
- * @author Serge Martin <edb@sigluy.net>
- * @author Simounet <contact@simounet.net>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Valdnet <47037905+Valdnet@users.noreply.github.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -53,51 +14,42 @@ use Exception;
use InvalidArgumentException;
use OC\Authentication\Token\PublicKeyTokenProvider;
use OC\Authentication\Token\TokenCleanupJob;
-use OC\TextProcessing\RemoveOldTasksBackgroundJob;
use OC\Log\Rotate;
use OC\Preview\BackgroundCleanupJob;
+use OC\TextProcessing\RemoveOldTasksBackgroundJob;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\IJobList;
use OCP\Defaults;
+use OCP\IAppConfig;
+use OCP\IConfig;
use OCP\IGroup;
+use OCP\IGroupManager;
use OCP\IL10N;
+use OCP\IRequest;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\L10N\IFactory as IL10NFactory;
+use OCP\Migration\IOutput;
use OCP\Security\ISecureRandom;
+use OCP\Server;
use Psr\Log\LoggerInterface;
class Setup {
- /** @var SystemConfig */
- protected $config;
- /** @var IniGetWrapper */
- protected $iniWrapper;
- /** @var IL10N */
- protected $l10n;
- /** @var Defaults */
- protected $defaults;
- /** @var LoggerInterface */
- protected $logger;
- /** @var ISecureRandom */
- protected $random;
- /** @var Installer */
- protected $installer;
+ protected IL10N $l10n;
public function __construct(
- SystemConfig $config,
- IniGetWrapper $iniWrapper,
- IL10N $l10n,
- Defaults $defaults,
- LoggerInterface $logger,
- ISecureRandom $random,
- Installer $installer
+ protected SystemConfig $config,
+ protected IniGetWrapper $iniWrapper,
+ IL10NFactory $l10nFactory,
+ protected Defaults $defaults,
+ protected LoggerInterface $logger,
+ protected ISecureRandom $random,
+ protected Installer $installer
) {
- $this->config = $config;
- $this->iniWrapper = $iniWrapper;
- $this->l10n = $l10n;
- $this->defaults = $defaults;
- $this->logger = $logger;
- $this->random = $random;
- $this->installer = $installer;
+ $this->l10n = $l10nFactory->get('lib');
}
- protected static $dbSetupClasses = [
+ protected static array $dbSetupClasses = [
'mysql' => \OC\Setup\MySQL::class,
'pgsql' => \OC\Setup\PostgreSQL::class,
'oci' => \OC\Setup\OCI::class,
@@ -107,30 +59,22 @@ class Setup {
/**
* Wrapper around the "class_exists" PHP function to be able to mock it
- *
- * @param string $name
- * @return bool
*/
- protected function class_exists($name) {
+ protected function class_exists(string $name): bool {
return class_exists($name);
}
/**
* Wrapper around the "is_callable" PHP function to be able to mock it
- *
- * @param string $name
- * @return bool
*/
- protected function is_callable($name) {
+ protected function is_callable(string $name): bool {
return is_callable($name);
}
/**
* Wrapper around \PDO::getAvailableDrivers
- *
- * @return array
*/
- protected function getAvailableDbDriversForPdo() {
+ protected function getAvailableDbDriversForPdo(): array {
if (class_exists(\PDO::class)) {
return \PDO::getAvailableDrivers();
}
@@ -140,11 +84,10 @@ class Setup {
/**
* Get the available and supported databases of this instance
*
- * @param bool $allowAllDatabases
* @return array
* @throws Exception
*/
- public function getSupportedDatabases($allowAllDatabases = false) {
+ public function getSupportedDatabases(bool $allowAllDatabases = false): array {
$availableDatabases = [
'sqlite' => [
'type' => 'pdo',
@@ -206,7 +149,7 @@ class Setup {
* @return array of system info, including an "errors" value
* in case of errors/warnings
*/
- public function getSystemInfo($allowAllDatabases = false) {
+ public function getSystemInfo(bool $allowAllDatabases = false): array {
$databases = $this->getSupportedDatabases($allowAllDatabases);
$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
@@ -226,7 +169,7 @@ class Setup {
try {
$util = new \OC_Util();
- $htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
+ $htAccessWorking = $util->isHtaccessWorking(Server::get(IConfig::class));
} catch (\OCP\HintException $e) {
$errors[] = [
'error' => $e->getMessage(),
@@ -272,17 +215,16 @@ class Setup {
}
/**
- * @param $options
- * @return array
+ * @return array<string|array> errors
*/
- public function install($options) {
+ public function install(array $options, ?IOutput $output = null): array {
$l = $this->l10n;
$error = [];
$dbType = $options['dbtype'];
if (empty($options['adminlogin'])) {
- $error[] = $l->t('Set an admin username.');
+ $error[] = $l->t('Set an admin Login.');
}
if (empty($options['adminpass'])) {
$error[] = $l->t('Set an admin password.');
@@ -313,7 +255,7 @@ class Setup {
return $error;
}
- $request = \OC::$server->getRequest();
+ $request = Server::get(IRequest::class);
//no errors, good
if (isset($options['trusted_domains'])
@@ -328,7 +270,7 @@ class Setup {
$dbType = 'sqlite3';
}
- //generate a random salt that is used to salt the local user passwords
+ //generate a random salt that is used to salt the local passwords
$salt = $this->random->generate(30);
// generate a secret
$secret = $this->random->generate(48);
@@ -349,6 +291,7 @@ class Setup {
$this->config->setValues($newConfigValues);
+ $this->outputDebug($output, 'Configuring database');
$dbSetup->initialize($options);
try {
$dbSetup->setupDatabase($username);
@@ -361,15 +304,17 @@ class Setup {
return $error;
} catch (Exception $e) {
$error[] = [
- 'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
+ 'error' => 'Error while trying to create admin account: ' . $e->getMessage(),
'exception' => $e,
'hint' => '',
];
return $error;
}
+
+ $this->outputDebug($output, 'Run server migrations');
try {
// apply necessary migrations
- $dbSetup->runMigrations();
+ $dbSetup->runMigrations($output);
} catch (Exception $e) {
$error[] = [
'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
@@ -379,78 +324,89 @@ class Setup {
return $error;
}
- //create the user and group
+ $this->outputDebug($output, 'Create admin account');
+
+ // create the admin account and group
$user = null;
try {
- $user = \OC::$server->getUserManager()->createUser($username, $password);
+ $user = Server::get(IUserManager::class)->createUser($username, $password);
if (!$user) {
- $error[] = "User <$username> could not be created.";
+ $error[] = "Account <$username> could not be created.";
+ return $error;
}
} catch (Exception $exception) {
$error[] = $exception->getMessage();
+ return $error;
}
- if (empty($error)) {
- $config = \OC::$server->getConfig();
- $config->setAppValue('core', 'installedat', (string)microtime(true));
- $config->setAppValue('core', 'lastupdatedat', (string)microtime(true));
+ $config = Server::get(IConfig::class);
+ $config->setAppValue('core', 'installedat', (string)microtime(true));
+ $appConfig = Server::get(IAppConfig::class);
+ $appConfig->setValueInt('core', 'lastupdatedat', time());
- $vendorData = $this->getVendorData();
- $config->setAppValue('core', 'vendor', $vendorData['vendor']);
- if ($vendorData['channel'] !== 'stable') {
- $config->setSystemValue('updater.release.channel', $vendorData['channel']);
- }
+ $vendorData = $this->getVendorData();
+ $config->setAppValue('core', 'vendor', $vendorData['vendor']);
+ if ($vendorData['channel'] !== 'stable') {
+ $config->setSystemValue('updater.release.channel', $vendorData['channel']);
+ }
- $group = \OC::$server->getGroupManager()->createGroup('admin');
- if ($group instanceof IGroup) {
- $group->addUser($user);
- }
+ $group = Server::get(IGroupManager::class)->createGroup('admin');
+ if ($group instanceof IGroup) {
+ $group->addUser($user);
+ }
- // Install shipped apps and specified app bundles
- Installer::installShippedApps();
+ // Install shipped apps and specified app bundles
+ $this->outputDebug($output, 'Install default apps');
+ Installer::installShippedApps(false, $output);
- // create empty file in data dir, so we can later find
- // out that this is indeed an ownCloud data directory
- file_put_contents($config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
+ // create empty file in data dir, so we can later find
+ // out that this is indeed an ownCloud data directory
+ $this->outputDebug($output, 'Setup data directory');
+ file_put_contents($config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
- // Update .htaccess files
- self::updateHtaccess();
- self::protectDataDirectory();
+ // Update .htaccess files
+ self::updateHtaccess();
+ self::protectDataDirectory();
- self::installBackgroundJobs();
+ $this->outputDebug($output, 'Install background jobs');
+ self::installBackgroundJobs();
- //and we are done
- $config->setSystemValue('installed', true);
- if (self::shouldRemoveCanInstallFile()) {
- unlink(\OC::$configDir.'/CAN_INSTALL');
- }
-
- $bootstrapCoordinator = \OCP\Server::get(\OC\AppFramework\Bootstrap\Coordinator::class);
- $bootstrapCoordinator->runInitialRegistration();
+ //and we are done
+ $config->setSystemValue('installed', true);
+ if (self::shouldRemoveCanInstallFile()) {
+ unlink(\OC::$configDir.'/CAN_INSTALL');
+ }
- // Create a session token for the newly created user
- // The token provider requires a working db, so it's not injected on setup
- /* @var $userSession User\Session */
- $userSession = \OC::$server->getUserSession();
- $provider = \OCP\Server::get(PublicKeyTokenProvider::class);
- $userSession->setTokenProvider($provider);
- $userSession->login($username, $password);
- $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
+ $bootstrapCoordinator = \OCP\Server::get(\OC\AppFramework\Bootstrap\Coordinator::class);
+ $bootstrapCoordinator->runInitialRegistration();
+
+ // Create a session token for the newly created user
+ // The token provider requires a working db, so it's not injected on setup
+ /** @var \OC\User\Session $userSession */
+ $userSession = Server::get(IUserSession::class);
+ $provider = Server::get(PublicKeyTokenProvider::class);
+ $userSession->setTokenProvider($provider);
+ $userSession->login($username, $password);
+ $user = $userSession->getUser();
+ if (!$user) {
+ $error[] = "No account found in session.";
+ return $error;
+ }
+ $userSession->createSessionToken($request, $user->getUID(), $username, $password);
- $session = $userSession->getSession();
- $session->set('last-password-confirm', \OCP\Server::get(ITimeFactory::class)->getTime());
+ $session = $userSession->getSession();
+ $session->set('last-password-confirm', Server::get(ITimeFactory::class)->getTime());
- // Set email for admin
- if (!empty($options['adminemail'])) {
- $user->setSystemEMailAddress($options['adminemail']);
- }
+ // Set email for admin
+ if (!empty($options['adminemail'])) {
+ $user->setSystemEMailAddress($options['adminemail']);
}
return $error;
}
- public static function installBackgroundJobs() {
- $jobList = \OC::$server->getJobList();
+ public static function installBackgroundJobs(): void {
+ $jobList = Server::get(IJobList::class);
$jobList->add(TokenCleanupJob::class);
$jobList->add(Rotate::class);
$jobList->add(BackgroundCleanupJob::class);
@@ -460,15 +416,13 @@ class Setup {
/**
* @return string Absolute path to htaccess
*/
- private function pathToHtaccess() {
+ private function pathToHtaccess(): string {
return \OC::$SERVERROOT . '/.htaccess';
}
/**
* Find webroot from config
*
- * @param SystemConfig $config
- * @return string
* @throws InvalidArgumentException when invalid value for overwrite.cli.url
*/
private static function findWebRoot(SystemConfig $config): string {
@@ -495,8 +449,8 @@ class Setup {
* @return bool True when success, False otherwise
* @throws \OCP\AppFramework\QueryException
*/
- public static function updateHtaccess() {
- $config = \OC::$server->getSystemConfig();
+ public static function updateHtaccess(): bool {
+ $config = Server::get(SystemConfig::class);
try {
$webRoot = self::findWebRoot($config);
@@ -504,15 +458,11 @@ class Setup {
return false;
}
- $setupHelper = new \OC\Setup(
- $config,
- \OC::$server->get(IniGetWrapper::class),
- \OC::$server->getL10N('lib'),
- \OCP\Server::get(Defaults::class),
- \OC::$server->get(LoggerInterface::class),
- \OC::$server->getSecureRandom(),
- \OCP\Server::get(Installer::class)
- );
+ $setupHelper = Server::get(\OC\Setup::class);
+
+ if (!is_writable($setupHelper->pathToHtaccess())) {
+ return false;
+ }
$htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
@@ -531,13 +481,13 @@ class Setup {
$content .= "\n Options -MultiViews";
$content .= "\n RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
$content .= "\n RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
- $content .= "\n RewriteCond %{REQUEST_FILENAME} !\\.(css|js|mjs|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav|wasm|tflite)$";
+ $content .= "\n RewriteCond %{REQUEST_FILENAME} !\\.(css|js|mjs|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav|flac|wasm|tflite)$";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/core/ajax/update\\.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/core/img/(favicon\\.ico|manifest\\.json)$";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/(cron|public|remote|status)\\.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs/v(1|2)\\.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/robots\\.txt";
- $content .= "\n RewriteCond %{REQUEST_FILENAME} !/(ocm-provider|ocs-provider|updater)/";
+ $content .= "\n RewriteCond %{REQUEST_FILENAME} !/(ocs-provider|updater)/";
$content .= "\n RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
$content .= "\n RewriteRule . index.php [PT,E=PATH_INFO:$1]";
@@ -551,15 +501,19 @@ class Setup {
$content .= "\n</IfModule>";
}
- if ($content !== '') {
- //suppress errors in case we don't have permissions for it
- return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
+ // Never write file back if disk space should be too low
+ if (function_exists('disk_free_space')) {
+ $df = disk_free_space(\OC::$SERVERROOT);
+ $size = strlen($content) + 10240;
+ if ($df !== false && $df < (float)$size) {
+ throw new \Exception(\OC::$SERVERROOT . " does not have enough space for writing the htaccess file! Not writing it back!");
+ }
}
-
- return false;
+ //suppress errors in case we don't have permissions for it
+ return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
}
- public static function protectDataDirectory() {
+ public static function protectDataDirectory(): void {
//Require all denied
$now = date('Y-m-d H:i:s');
$content = "# Generated by Nextcloud on $now\n";
@@ -587,7 +541,7 @@ class Setup {
$content .= " IndexIgnore *\n";
$content .= "</IfModule>";
- $baseDir = \OC::$server->getConfig()->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data');
+ $baseDir = Server::get(IConfig::class)->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data');
file_put_contents($baseDir . '/.htaccess', $content);
file_put_contents($baseDir . '/index.html', '');
}
@@ -603,17 +557,17 @@ class Setup {
];
}
- /**
- * @return bool
- */
- public function shouldRemoveCanInstallFile() {
+ public function shouldRemoveCanInstallFile(): bool {
return \OC_Util::getChannel() !== 'git' && is_file(\OC::$configDir.'/CAN_INSTALL');
}
- /**
- * @return bool
- */
- public function canInstallFileExists() {
+ public function canInstallFileExists(): bool {
return is_file(\OC::$configDir.'/CAN_INSTALL');
}
+
+ protected function outputDebug(?IOutput $output, string $message): void {
+ if ($output instanceof IOutput) {
+ $output->debug($message);
+ }
+ }
}
diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php
index 9ec4137cdef..e96ca8a2f3e 100644
--- a/lib/private/Setup/AbstractDatabase.php
+++ b/lib/private/Setup/AbstractDatabase.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Pulzer <t.pulzer@kniel.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Setup;
@@ -33,6 +12,7 @@ use OC\DB\ConnectionFactory;
use OC\DB\MigrationService;
use OC\SystemConfig;
use OCP\IL10N;
+use OCP\Migration\IOutput;
use OCP\Security\ISecureRandom;
use Psr\Log\LoggerInterface;
@@ -70,9 +50,9 @@ abstract class AbstractDatabase {
public function validate($config) {
$errors = [];
if (empty($config['dbuser']) && empty($config['dbname'])) {
- $errors[] = $this->trans->t("Enter the database username and name for %s", [$this->dbprettyname]);
+ $errors[] = $this->trans->t("Enter the database Login and name for %s", [$this->dbprettyname]);
} elseif (empty($config['dbuser'])) {
- $errors[] = $this->trans->t("Enter the database username for %s", [$this->dbprettyname]);
+ $errors[] = $this->trans->t("Enter the database Login for %s", [$this->dbprettyname]);
} elseif (empty($config['dbname'])) {
$errors[] = $this->trans->t("Enter the database name for %s", [$this->dbprettyname]);
}
@@ -88,7 +68,7 @@ abstract class AbstractDatabase {
$dbName = $config['dbname'];
$dbHost = !empty($config['dbhost']) ? $config['dbhost'] : 'localhost';
$dbPort = !empty($config['dbport']) ? $config['dbport'] : '';
- $dbTablePrefix = isset($config['dbtableprefix']) ? $config['dbtableprefix'] : 'oc_';
+ $dbTablePrefix = $config['dbtableprefix'] ?? 'oc_';
$createUserConfig = $this->config->getValue("setup_create_db_user", true);
// accept `false` both as bool and string, since setting config values from env will result in a string
@@ -139,10 +119,12 @@ abstract class AbstractDatabase {
}
$connectionParams['host'] = $host;
}
-
$connectionParams = array_merge($connectionParams, $configOverwrite);
+ $connectionParams = array_merge($connectionParams, ['primary' => $connectionParams, 'replica' => [$connectionParams]]);
$cf = new ConnectionFactory($this->config);
- return $cf->getConnection($this->config->getValue('dbtype', 'sqlite'), $connectionParams);
+ $connection = $cf->getConnection($this->config->getValue('dbtype', 'sqlite'), $connectionParams);
+ $connection->ensureConnectedToPrimary();
+ return $connection;
}
/**
@@ -150,11 +132,11 @@ abstract class AbstractDatabase {
*/
abstract public function setupDatabase($username);
- public function runMigrations() {
+ public function runMigrations(?IOutput $output = null) {
if (!is_dir(\OC::$SERVERROOT."/core/Migrations")) {
return;
}
- $ms = new MigrationService('core', \OC::$server->get(Connection::class));
+ $ms = new MigrationService('core', \OC::$server->get(Connection::class), $output);
$ms->migrate('latest', true);
}
}
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
index 50f566728a9..93aee667d18 100644
--- a/lib/private/Setup/MySQL.php
+++ b/lib/private/Setup/MySQL.php
@@ -1,38 +1,16 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Hemanth Kumar Veeranki <hems.india1997@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Michael Göhler <somebody.here@gmx.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Setup;
+use Doctrine\DBAL\Platforms\MySQL80Platform;
use OC\DB\ConnectionAdapter;
use OC\DB\MySqlTools;
use OCP\IDBConnection;
-use Doctrine\DBAL\Platforms\MySQL80Platform;
use OCP\Security\ISecureRandom;
class MySQL extends AbstractDatabase {
@@ -73,7 +51,7 @@ class MySQL extends AbstractDatabase {
$this->logger->error($e->getMessage(), [
'exception' => $e,
]);
- throw new \OC\DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'),
+ throw new \OC\DatabaseSetupException($this->trans->t('MySQL Login and/or password not valid'),
$this->trans->t('You need to enter details of an existing account.'), 0, $e);
}
}
diff --git a/lib/private/Setup/OCI.php b/lib/private/Setup/OCI.php
index 477561bbe2a..3a0fa34d8d1 100644
--- a/lib/private/Setup/OCI.php
+++ b/lib/private/Setup/OCI.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Setup;
@@ -53,9 +31,9 @@ class OCI extends AbstractDatabase {
public function validate($config) {
$errors = [];
if (empty($config['dbuser']) && empty($config['dbname'])) {
- $errors[] = $this->trans->t("Enter the database username and name for %s", [$this->dbprettyname]);
+ $errors[] = $this->trans->t("Enter the database Login and name for %s", [$this->dbprettyname]);
} elseif (empty($config['dbuser'])) {
- $errors[] = $this->trans->t("Enter the database username for %s", [$this->dbprettyname]);
+ $errors[] = $this->trans->t("Enter the database Login for %s", [$this->dbprettyname]);
} elseif (empty($config['dbname'])) {
$errors[] = $this->trans->t("Enter the database name for %s", [$this->dbprettyname]);
}
@@ -75,7 +53,7 @@ class OCI extends AbstractDatabase {
. ' NLS_LANG=' . getenv('NLS_LANG')
. ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
}
- throw new \OC\DatabaseSetupException($this->trans->t('Oracle username and/or password not valid'),
+ throw new \OC\DatabaseSetupException($this->trans->t('Oracle Login and/or password not valid'),
'Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
. ' ORACLE_SID=' . getenv('ORACLE_SID')
. ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php
index 490cbba69a9..9cee614b7fa 100644
--- a/lib/private/Setup/PostgreSQL.php
+++ b/lib/private/Setup/PostgreSQL.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author eduardo <eduardo@vnexu.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vitor Mattos <vitor@php.rio>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Setup;
@@ -114,7 +93,7 @@ class PostgreSQL extends AbstractDatabase {
$this->logger->error($e->getMessage(), [
'exception' => $e,
]);
- throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'),
+ throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL Login and/or password not valid'),
$this->trans->t('You need to enter details of an existing account.'), 0, $e);
}
}
diff --git a/lib/private/Setup/Sqlite.php b/lib/private/Setup/Sqlite.php
index 8ed432b039a..1b90ebd5a5e 100644
--- a/lib/private/Setup/Sqlite.php
+++ b/lib/private/Setup/Sqlite.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Setup;
diff --git a/lib/private/SetupCheck/SetupCheckManager.php b/lib/private/SetupCheck/SetupCheckManager.php
new file mode 100644
index 00000000000..41f393fef7a
--- /dev/null
+++ b/lib/private/SetupCheck/SetupCheckManager.php
@@ -0,0 +1,46 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+namespace OC\SetupCheck;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OCP\Server;
+use OCP\SetupCheck\ISetupCheck;
+use OCP\SetupCheck\ISetupCheckManager;
+use OCP\SetupCheck\SetupResult;
+use Psr\Log\LoggerInterface;
+
+class SetupCheckManager implements ISetupCheckManager {
+ public function __construct(
+ private Coordinator $coordinator,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ public function runAll(): array {
+ $results = [];
+ $setupChecks = $this->coordinator->getRegistrationContext()->getSetupChecks();
+ foreach ($setupChecks as $setupCheck) {
+ /** @var ISetupCheck $setupCheckObject */
+ $setupCheckObject = Server::get($setupCheck->getService());
+ $this->logger->debug('Running check '.get_class($setupCheckObject));
+ try {
+ $setupResult = $setupCheckObject->run();
+ } catch (\Throwable $t) {
+ $setupResult = SetupResult::error("An exception occured while running the setup check:\n$t");
+ $this->logger->error('Exception running check '.get_class($setupCheckObject).': '.$t->getMessage(), ['exception' => $t]);
+ }
+ $setupResult->setName($setupCheckObject->getName());
+ $category = $setupCheckObject->getCategory();
+ $results[$category] ??= [];
+ $results[$category][$setupCheckObject::class] = $setupResult;
+ }
+ return $results;
+ }
+}
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index 0c8fad17e07..8cfa83f9ea2 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share;
diff --git a/lib/private/Share/Helper.php b/lib/private/Share/Helper.php
index f1b9ae2b9fa..76e7daeb9e5 100644
--- a/lib/private/Share/Helper.php
+++ b/lib/private/Share/Helper.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Miguel Prokop <miguel.prokop@vtu.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share;
diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php
index 8d14f293e5a..0af264fb968 100644
--- a/lib/private/Share/Share.php
+++ b/lib/private/Share/Share.php
@@ -1,45 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Reiter <ockham@raz.or.at>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sebastian Döll <sebastian.doell@libasys.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Volkan Gezer <volkangezer@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Share;
use OCA\Files_Sharing\ShareBackend\File;
-use OCP\DB\Exception;
-use OCP\DB\QueryBuilder\IQueryBuilder;
-use OCP\IDBConnection;
-use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
/**
@@ -94,161 +62,6 @@ class Share extends Constants {
}
/**
- * Get the items of item type shared with the current user
- *
- * @param string $itemType
- * @param int $format (optional) Format type must be defined by the backend
- * @param mixed $parameters (optional)
- * @param int $limit Number of items to return (optional) Returns all by default
- * @param boolean $includeCollections (optional)
- * @return mixed Return depends on format
- * @deprecated TESTS ONLY - this methods is only used by tests
- * called like this:
- * \OC\Share\Share::getItemsSharedWith('folder'); (apps/files_sharing/tests/UpdaterTest.php)
- */
- public static function getItemsSharedWith() {
- return self::getItems('folder', null, self::$shareTypeUserAndGroups, \OC_User::getUser());
- }
-
- /**
- * Get the items of item type shared with a user
- *
- * @param string $itemType
- * @param string $user id for which user we want the shares
- * @param int $format (optional) Format type must be defined by the backend
- * @param mixed $parameters (optional)
- * @param int $limit Number of items to return (optional) Returns all by default
- * @param boolean $includeCollections (optional)
- * @return mixed Return depends on format
- * @deprecated TESTS ONLY - this methods is only used by tests
- * called like this:
- * \OC\Share\Share::getItemsSharedWithUser('test', $shareWith); (tests/lib/Share/Backend.php)
- */
- public static function getItemsSharedWithUser($itemType, $user) {
- return self::getItems('test', null, self::$shareTypeUserAndGroups, $user);
- }
-
- /**
- * Get the item of item type shared with a given user by source
- *
- * @param string $itemType
- * @param string $itemSource
- * @param ?string $user User to whom the item was shared
- * @param ?string $owner Owner of the share
- * @param ?int $shareType only look for a specific share type
- * @return array Return list of items with file_target, permissions and expiration
- * @throws Exception
- */
- public static function getItemSharedWithUser(string $itemType, string $itemSource, ?string $user = null, ?string $owner = null, ?int $shareType = null) {
- $shares = [];
- $fileDependent = $itemType === 'file' || $itemType === 'folder';
- $qb = self::getSelectStatement(self::FORMAT_NONE, $fileDependent);
- $qb->from('share', 's');
- if ($fileDependent) {
- $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('file_source', 'f.fileid'));
- $qb->innerJoin('s', 'storages', 'st', $qb->expr()->eq('numeric_id', 'f.storage'));
- $column = 'file_source';
- } else {
- $column = 'item_source';
- }
-
- $qb->where($qb->expr()->eq($column, $qb->createNamedParameter($itemSource)))
- ->andWhere($qb->expr()->eq('item_type', $qb->createNamedParameter($itemType)));
-
- // for link shares $user === null
- if ($user !== null) {
- $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($user)));
- }
-
- if ($shareType !== null) {
- $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType, IQueryBuilder::PARAM_INT)));
- }
-
- if ($owner !== null) {
- $qb->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($owner)));
- }
-
- $result = $qb->executeQuery();
- while ($row = $result->fetch()) {
- if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
- continue;
- }
- if ($fileDependent && (int)$row['file_parent'] === -1) {
- // if it is a mount point we need to get the path from the mount manager
- $mountManager = \OC\Files\Filesystem::getMountManager();
- $mountPoint = $mountManager->findByStorageId($row['storage_id']);
- if (!empty($mountPoint)) {
- $path = $mountPoint[0]->getMountPoint();
- $path = trim($path, '/');
- $path = substr($path, strlen($owner) + 1); //normalize path to 'files/foo.txt`
- $row['path'] = $path;
- } else {
- \OC::$server->get(LoggerInterface::class)->warning(
- 'Could not resolve mount point for ' . $row['storage_id'],
- ['app' => 'OCP\Share']
- );
- }
- }
- $shares[] = $row;
- }
- $result->closeCursor();
-
- // if we didn't found a result then let's look for a group share.
- if (empty($shares) && $user !== null) {
- $userObject = \OC::$server->getUserManager()->get($user);
- $groups = [];
- if ($userObject) {
- $groups = \OC::$server->getGroupManager()->getUserGroupIds($userObject);
- }
-
- if (!empty($groups)) {
- $qb = self::getSelectStatement(self::FORMAT_NONE, $fileDependent);
- $qb->from('share', 's');
-
- if ($fileDependent) {
- $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('file_source', 'f.fileid'))
- ->innerJoin('s', 'storages', 'st', $qb->expr()->eq('numeric_id', 'f.storage'));
- }
-
- $qb->where($qb->expr()->eq($column, $qb->createNamedParameter($itemSource)))
- ->andWhere($qb->expr()->eq('item_type', $qb->createNamedParameter($itemType, IQueryBuilder::PARAM_STR)))
- ->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY)));
-
- if ($owner !== null) {
- $qb->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($owner)));
- }
- $result = $qb->executeQuery();
-
- while ($row = $result->fetch()) {
- $shares[] = $row;
- }
- $result->closeCursor();
- }
- }
-
- return $shares;
- }
-
- /**
- * Get the shared item of item type owned by the current user
- *
- * @param string $itemType
- * @param string $itemSource
- * @param int $format (optional) Format type must be defined by the backend
- * @param mixed $parameters
- * @param boolean $includeCollections
- * @return mixed Return depends on format
- *
- * Refactoring notes:
- * * defacto $parameters and $format is always the default and therefore is removed in the subsequent call
- */
- public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
- $parameters = null, $includeCollections = false) {
- return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), self::FORMAT_NONE,
- null, -1, $includeCollections);
- }
-
- /**
* Get the backend class for the specified item type
*
* @param string $itemType
@@ -256,8 +69,8 @@ class Share extends Constants {
* @throws \Exception
*/
public static function getBackend($itemType) {
- $l = \OC::$server->getL10N('lib');
- $logger = \OC::$server->get(LoggerInterface::class);
+ $l = \OCP\Util::getL10N('lib');
+ $logger = \OCP\Server::get(LoggerInterface::class);
if (isset(self::$backends[$itemType])) {
return self::$backends[$itemType];
} elseif (isset(self::$backendTypes[$itemType]['class'])) {
@@ -303,421 +116,6 @@ class Share extends Constants {
}
/**
- * Get a list of collection item types for the specified item type
- *
- * @param string $itemType
- * @return array|false
- */
- private static function getCollectionItemTypes(string $itemType) {
- $collectionTypes = [$itemType];
- foreach (self::$backendTypes as $type => $backend) {
- if (in_array($backend['collectionOf'], $collectionTypes)) {
- $collectionTypes[] = $type;
- }
- }
- // TODO Add option for collections to be collection of themselves, only 'folder' does it now...
- if (isset(self::$backendTypes[$itemType]) && (!self::getBackend($itemType) instanceof \OCP\Share_Backend_Collection || $itemType != 'folder')) {
- unset($collectionTypes[0]);
- }
- // Return array if collections were found or the item type is a
- // collection itself - collections can be inside collections
- if (count($collectionTypes) > 0) {
- return $collectionTypes;
- }
- return false;
- }
-
- /**
- * Get shared items from the database
- *
- * @param string $itemType
- * @param string $item Item source or target (optional)
- * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
- * @param string $shareWith User or group the item is being shared with
- * @param string $uidOwner User that is the owner of shared items (optional)
- * @param int $format Format to convert items to with formatItems() (optional)
- * @param mixed $parameters to pass to formatItems() (optional)
- * @param int $limit Number of items to return, -1 to return all matches (optional)
- * @param boolean $includeCollections Include collection item types (optional)
- * @param boolean $itemShareWithBySource (optional)
- * @param boolean $checkExpireDate
- * @return array
- *
- * See public functions getItem(s)... for parameter usage
- *
- * Refactoring notes:
- * * defacto $limit, $itemsShareWithBySource, $checkExpireDate, $parameters and $format is always the default and therefore is removed in the subsequent call
- */
- public static function getItems($itemType, ?string $item = null, ?int $shareType = null, $shareWith = null,
- $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
- $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) {
- if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') != 'yes') {
- return [];
- }
- $fileDependent = $itemType == 'file' || $itemType == 'folder';
- $qb = self::getSelectStatement(self::FORMAT_NONE, $fileDependent, $uidOwner);
- $qb->from('share', 's');
-
- $backend = self::getBackend($itemType);
- $collectionTypes = false;
- // Get filesystem root to add it to the file target and remove from the
- // file source, match file_source with the file cache
- if ($fileDependent) {
- if (!is_null($uidOwner)) {
- $root = \OC\Files\Filesystem::getRoot();
- } else {
- $root = '';
- }
- if (isset($item)) {
- $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('file_source', 'f.fileid'));
- } else {
- $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->andX(
- $qb->expr()->eq('file_source', 'f.fileid'),
- $qb->expr()->isNotNull('file_target')
- ));
- }
- $qb->innerJoin('s', 'storages', 'st', $qb->expr()->eq('numeric_id', 'f.storage'));
- } else {
- $root = '';
- $collectionTypes = self::getCollectionItemTypes($itemType);
- if ($includeCollections && !isset($item) && $collectionTypes) {
- // If includeCollections is true, find collections of this item type, e.g. a music album contains songs
- if (!in_array($itemType, $collectionTypes)) {
- $itemTypes = array_merge([$itemType], $collectionTypes);
- } else {
- $itemTypes = $collectionTypes;
- }
- $qb->where($qb->expr()->in('item_type', $qb->createNamedParameter($itemTypes, IQueryBuilder::PARAM_STR_ARRAY)));
- } else {
- $qb->where($qb->expr()->eq('item_type', $qb->createNamedParameter($itemType)));
- }
- }
- if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
- $qb->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK, IQueryBuilder::PARAM_INT)));
- }
- if (isset($shareType)) {
- // Include all user and group items
- if ($shareType === self::$shareTypeUserAndGroups && isset($shareWith)) {
- $qb->andWhere($qb->expr()->andX(
- $qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_USER, self::$shareTypeGroupUserUnique], IQueryBuilder::PARAM_INT_ARRAY)),
- $qb->expr()->eq('share_with', $qb->createNamedParameter($shareWith))
- ));
-
- $user = \OC::$server->getUserManager()->get($shareWith);
- $groups = [];
- if ($user) {
- $groups = \OC::$server->getGroupManager()->getUserGroupIds($user);
- }
- if (!empty($groups)) {
- $qb->orWhere($qb->expr()->andX(
- $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP, IQueryBuilder::PARAM_INT)),
- $qb->expr()->in('share_with', $qb->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY))
- ));
- }
-
- // Don't include own group shares
- $qb->andWhere($qb->expr()->neq('uid_owner', $qb->createNamedParameter($shareWith)));
- } else {
- $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType, IQueryBuilder::PARAM_INT)));
- if (isset($shareWith)) {
- $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($shareWith, IQueryBuilder::PARAM_STR)));
- }
- }
- }
- if (isset($uidOwner)) {
- $qb->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uidOwner)));
- if (!isset($shareType)) {
- // Prevent unique user targets for group shares from being selected
- $qb->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(self::$shareTypeGroupUserUnique, IQueryBuilder::PARAM_INT)));
- }
- if ($fileDependent) {
- $column = 'file_source';
- } else {
- $column = 'item_source';
- }
- } else {
- if ($fileDependent) {
- $column = 'file_target';
- } else {
- $column = 'item_target';
- }
- }
- if (isset($item)) {
- $collectionTypes = self::getCollectionItemTypes($itemType);
- // If looking for own shared items, check item_source else check item_target
- if (isset($uidOwner)) {
- // If item type is a file, file source needs to be checked in case the item was converted
- if ($fileDependent) {
- $expr = $qb->expr()->eq('file_source', $qb->createNamedParameter($item));
- $column = 'file_source';
- } else {
- $expr = $qb->expr()->eq('item_source', $qb->createNamedParameter($item));
- $column = 'item_source';
- }
- } else {
- if ($fileDependent) {
- $item = \OC\Files\Filesystem::normalizePath($item);
- $expr = $qb->expr()->eq('file_target', $qb->createNamedParameter($item));
- } else {
- $expr = $qb->expr()->eq('item_target', $qb->createNamedParameter($item));
- }
- }
- if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
- $qb->andWhere($qb->expr()->orX(
- $expr,
- $qb->expr()->in('item_type', $qb->createNamedParameter($collectionTypes, IQueryBuilder::PARAM_STR_ARRAY))
- ));
- } else {
- $qb->andWhere($expr);
- }
- }
- $qb->orderBy('s.id', 'ASC');
- try {
- $result = $qb->executeQuery();
- } catch (\Exception $e) {
- \OCP\Server::get(LoggerInterface::class)->error(
- 'Error while selecting shares: ' . $qb->getSQL(),
- [
- 'app' => 'files_sharing',
- 'exception' => $e
- ]);
- throw new \RuntimeException('Wrong SQL query', 500, $e);
- }
-
- $root = strlen($root);
- $items = [];
- $targets = [];
- $switchedItems = [];
- $mounts = [];
- while ($row = $result->fetch()) {
- //var_dump($row);
- self::transformDBResults($row);
- // Filter out duplicate group shares for users with unique targets
- if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
- continue;
- }
- if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
- $row['share_type'] = IShare::TYPE_GROUP;
- $row['unique_name'] = true; // remember that we use a unique name for this user
- $row['share_with'] = $items[$row['parent']]['share_with'];
- // if the group share was unshared from the user we keep the permission, otherwise
- // we take the permission from the parent because this is always the up-to-date
- // permission for the group share
- if ($row['permissions'] > 0) {
- $row['permissions'] = $items[$row['parent']]['permissions'];
- }
- // Remove the parent group share
- unset($items[$row['parent']]);
- if ($row['permissions'] == 0) {
- continue;
- }
- } elseif (!isset($uidOwner)) {
- // Check if the same target already exists
- if (isset($targets[$row['id']])) {
- // Check if the same owner shared with the user twice
- // through a group and user share - this is allowed
- $id = $targets[$row['id']];
- if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
- // Switch to group share type to ensure resharing conditions aren't bypassed
- if ($items[$id]['share_type'] != IShare::TYPE_GROUP) {
- $items[$id]['share_type'] = IShare::TYPE_GROUP;
- $items[$id]['share_with'] = $row['share_with'];
- }
- // Switch ids if sharing permission is granted on only
- // one share to ensure correct parent is used if resharing
- if (~(int)$items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
- && (int)$row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
- $items[$row['id']] = $items[$id];
- $switchedItems[$id] = $row['id'];
- unset($items[$id]);
- $id = $row['id'];
- }
- $items[$id]['permissions'] |= (int)$row['permissions'];
- }
- continue;
- } elseif (!empty($row['parent'])) {
- $targets[$row['parent']] = $row['id'];
- }
- }
- // Remove root from file source paths if retrieving own shared items
- if (isset($uidOwner) && isset($row['path'])) {
- if (isset($row['parent'])) {
- $query = \OC::$server->getDatabaseConnection()->getQueryBuilder();
- $query->select('file_target')
- ->from('share')
- ->where($query->expr()->eq('id', $query->createNamedParameter($row['parent'])));
-
- $parentRow = false;
- try {
- $parentResult = $query->executeQuery();
- $parentRow = $parentResult->fetchOne();
- $parentResult->closeCursor();
-
- $tmpPath = $parentRow['file_target'];
- // find the right position where the row path continues from the target path
- $pos = strrpos($row['path'], $parentRow['file_target']);
- $subPath = substr($row['path'], $pos);
- $splitPath = explode('/', $subPath);
- foreach (array_slice($splitPath, 2) as $pathPart) {
- $tmpPath = $tmpPath . '/' . $pathPart;
- }
- $row['path'] = $tmpPath;
- } catch (Exception $e) {
- \OCP\Server::get(LoggerInterface::class)
- ->error('Can\'t select parent :' . $e->getMessage() . ' query=' . $query->getSQL(), [
- 'exception' => $e,
- 'app' => 'core'
- ]);
- }
- } else {
- if (!isset($mounts[$row['storage']])) {
- $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
- if (is_array($mountPoints) && !empty($mountPoints)) {
- $mounts[$row['storage']] = current($mountPoints);
- }
- }
- if (!empty($mounts[$row['storage']])) {
- $path = $mounts[$row['storage']]->getMountPoint() . $row['path'];
- $relPath = substr($path, $root); // path relative to data/user
- $row['path'] = rtrim($relPath, '/');
- }
- }
- }
-
- // Check if resharing is allowed, if not remove share permission
- if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) {
- $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE;
- }
- // Add display names to result
- $row['share_with_displayname'] = $row['share_with'];
- if (isset($row['share_with']) && $row['share_with'] != '' &&
- $row['share_type'] === IShare::TYPE_USER) {
- $shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
- $row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
- } elseif (isset($row['share_with']) && $row['share_with'] != '' &&
- $row['share_type'] === IShare::TYPE_REMOTE) {
- $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD'], [
- 'limit' => 1,
- 'enumeration' => false,
- 'fullmatch' => false,
- 'strict_search' => true,
- ]);
- foreach ($addressBookEntries as $entry) {
- foreach ($entry['CLOUD'] as $cloudID) {
- if ($cloudID === $row['share_with']) {
- $row['share_with_displayname'] = $entry['FN'];
- }
- }
- }
- }
- if (isset($row['uid_owner']) && $row['uid_owner'] != '') {
- $ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
- $row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
- }
-
- if ($row['permissions'] > 0) {
- $items[$row['id']] = $row;
- }
- }
- $result->closeCursor();
-
- // group items if we are looking for items shared with the current user
- if (isset($shareWith) && $shareWith === \OC_User::getUser()) {
- $items = self::groupItems($items, $itemType);
- }
-
- if (!empty($items)) {
- $collectionItems = [];
- foreach ($items as &$row) {
- // Check if this is a collection of the requested item type
- if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) {
- if (($collectionBackend = self::getBackend($row['item_type']))
- && $collectionBackend instanceof \OCP\Share_Backend_Collection) {
- // Collections can be inside collections, check if the item is a collection
- if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
- $collectionItems[] = $row;
- } else {
- $collection = [];
- $collection['item_type'] = $row['item_type'];
- if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
- $collection['path'] = basename($row['path']);
- }
- $row['collection'] = $collection;
- // Fetch all the children sources
- $children = $collectionBackend->getChildren($row[$column]);
- foreach ($children as $child) {
- $childItem = $row;
- $childItem['item_type'] = $itemType;
- if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
- $childItem['item_source'] = $child['source'];
- $childItem['item_target'] = $child['target'];
- }
- if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
- if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
- $childItem['file_source'] = $child['source'];
- } else { // TODO is this really needed if we already know that we use the file backend?
- $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
- $childItem['file_source'] = $meta['fileid'];
- }
- $childItem['file_target'] =
- \OC\Files\Filesystem::normalizePath($child['file_path']);
- }
- if (isset($item)) {
- if ($childItem[$column] == $item) {
- $collectionItems[] = $childItem;
- }
- } else {
- $collectionItems[] = $childItem;
- }
- }
- }
- }
- // Remove collection item
- $toRemove = $row['id'];
- if (array_key_exists($toRemove, $switchedItems)) {
- $toRemove = $switchedItems[$toRemove];
- }
- unset($items[$toRemove]);
- } elseif ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
- // FIXME: Thats a dirty hack to improve file sharing performance,
- // see github issue #10588 for more details
- // Need to find a solution which works for all back-ends
- $collectionBackend = self::getBackend($row['item_type']);
- $sharedParents = $collectionBackend->getParents($row['item_source']);
- foreach ($sharedParents as $parent) {
- $collectionItems[] = $parent;
- }
- }
- }
- if (!empty($collectionItems)) {
- $collectionItems = array_unique($collectionItems, SORT_REGULAR);
- $items = array_merge($items, $collectionItems);
- }
-
- // filter out invalid items, these can appear when subshare entries exist
- // for a group in which the requested user isn't a member any more
- $items = array_filter($items, function ($item) {
- return $item['share_type'] !== self::$shareTypeGroupUserUnique;
- });
-
- return self::formatResult($items, $column, $backend);
- } elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) {
- // FIXME: Thats a dirty hack to improve file sharing performance,
- // see github issue #10588 for more details
- // Need to find a solution which works for all back-ends
- $collectionItems = [];
- $collectionBackend = self::getBackend('folder');
- $sharedParents = $collectionBackend->getParents($item, $shareWith, $uidOwner);
- foreach ($sharedParents as $parent) {
- $collectionItems[] = $parent;
- }
- return self::formatResult($collectionItems, $column, $backend);
- }
-
- return [];
- }
-
- /**
* group items with link to the same source
*
* @param array $items
@@ -757,185 +155,6 @@ class Share extends Constants {
}
/**
- * Construct select statement
- *
- * @param bool $fileDependent ist it a file/folder share or a general share
- */
- private static function getSelectStatement(int $format, bool $fileDependent, ?string $uidOwner = null): IQueryBuilder {
- /** @var IDBConnection $connection */
- $connection = \OC::$server->get(IDBConnection::class);
- $qb = $connection->getQueryBuilder();
- if ($format == self::FORMAT_STATUSES) {
- if ($fileDependent) {
- return $qb->select(
- 's.id',
- 's.parent',
- 'share_type',
- 'path',
- 'storage',
- 'share_with',
- 'uid_owner',
- 'file_source',
- 'stime',
- 's.permissions',
- 'uid_initiator'
- )->selectAlias('st.id', 'storage_id')
- ->selectAlias('f.parent', 'file_parent');
- }
- return $qb->select('id', 'parent', 'share_type', 'share_with', 'uid_owner', 'item_source', 'stime', 's.permissions');
- }
-
- if (isset($uidOwner)) {
- if ($fileDependent) {
- return $qb->select(
- 's.id',
- 'item_type',
- 'item_source',
- 's.parent',
- 'share_type',
- 'share_with',
- 'file_source',
- 'file_target',
- 'path',
- 's.permissions',
- 'stime',
- 'expiration',
- 'token',
- 'storage',
- 'mail_send',
- 'uid_owner',
- 'uid_initiator'
- )->selectAlias('st.id', 'storage_id')
- ->selectAlias('f.parent', 'file_parent');
- }
- return $qb->select('id', 'item_type', 'item_source', 'parent', 'share_type',
- 'share_with', 'uid_owner', 'file_source', 'stime', 's.permissions',
- 'expiration', 'token', 'mail_send');
- }
-
- if ($fileDependent) {
- if ($format == File::FORMAT_GET_FOLDER_CONTENTS || $format == File::FORMAT_FILE_APP_ROOT) {
- return $qb->select(
- 's.id',
- 'item_type',
- 'item_source',
- 's.parent',
- 'uid_owner',
- 'share_type',
- 'share_with',
- 'file_source',
- 'path',
- 'file_target',
- 's.permissions',
- 'stime',
- 'expiration',
- 'storage',
- 'name',
- 'mtime',
- 'mimepart',
- 'size',
- 'encrypted',
- 'etag',
- 'mail_send'
- )->selectAlias('f.parent', 'file_parent');
- }
- return $qb->select(
- 's.id',
- 'item_type',
- 'item_source',
- 'item_target',
- 's.parent',
- 'share_type',
- 'share_with',
- 'uid_owner',
- 'file_source',
- 'path',
- 'file_target',
- 's.permissions',
- 'stime',
- 'expiration',
- 'token',
- 'storage',
- 'mail_send',
- )->selectAlias('f.parent', 'file_parent')
- ->selectAlias('st.id', 'storage_id');
- }
- return $qb->select('*');
- }
-
-
- /**
- * transform db results
- *
- * @param array $row result
- */
- private static function transformDBResults(&$row) {
- if (isset($row['id'])) {
- $row['id'] = (int)$row['id'];
- }
- if (isset($row['share_type'])) {
- $row['share_type'] = (int)$row['share_type'];
- }
- if (isset($row['parent'])) {
- $row['parent'] = (int)$row['parent'];
- }
- if (isset($row['file_parent'])) {
- $row['file_parent'] = (int)$row['file_parent'];
- }
- if (isset($row['file_source'])) {
- $row['file_source'] = (int)$row['file_source'];
- }
- if (isset($row['permissions'])) {
- $row['permissions'] = (int)$row['permissions'];
- }
- if (isset($row['storage'])) {
- $row['storage'] = (int)$row['storage'];
- }
- if (isset($row['stime'])) {
- $row['stime'] = (int)$row['stime'];
- }
- if (isset($row['expiration']) && $row['share_type'] !== IShare::TYPE_LINK) {
- // discard expiration date for non-link shares, which might have been
- // set by ancient bugs
- $row['expiration'] = null;
- }
- }
-
- /**
- * format result
- *
- * @param array $items result
- * @param string $column is it a file share or a general share ('file_target' or 'item_target')
- * @param \OCP\Share_Backend $backend sharing backend
- * @param int $format
- * @param array $parameters additional format parameters
- * @return array format result
- */
- private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE, $parameters = null) {
- if ($format === self::FORMAT_NONE) {
- return $items;
- } elseif ($format === self::FORMAT_STATUSES) {
- $statuses = [];
- foreach ($items as $item) {
- if ($item['share_type'] === IShare::TYPE_LINK) {
- if ($item['uid_initiator'] !== \OC::$server->getUserSession()->getUser()->getUID()) {
- continue;
- }
- $statuses[$item[$column]]['link'] = true;
- } elseif (!isset($statuses[$item[$column]])) {
- $statuses[$item[$column]]['link'] = false;
- }
- if (!empty($item['file_target'])) {
- $statuses[$item[$column]]['path'] = $item['path'];
- }
- }
- return $statuses;
- } else {
- return $backend->formatItems($items, $format, $parameters);
- }
- }
-
- /**
* remove protocol from URL
*
* @param string $url
@@ -958,29 +177,4 @@ class Share extends Constants {
public static function getExpireInterval() {
return (int)\OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
}
-
- /**
- * Checks whether the given path is reachable for the given owner
- *
- * @param string $path path relative to files
- * @param string $ownerStorageId storage id of the owner
- *
- * @return boolean true if file is reachable, false otherwise
- */
- private static function isFileReachable($path, $ownerStorageId) {
- // if outside the home storage, file is always considered reachable
- if (!(substr($ownerStorageId, 0, 6) === 'home::' ||
- substr($ownerStorageId, 0, 13) === 'object::user:'
- )) {
- return true;
- }
-
- // if inside the home storage, the file has to be under "/files/"
- $path = ltrim($path, '/');
- if (substr($path, 0, 6) === 'files/') {
- return true;
- }
-
- return false;
- }
}
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index 5201cf074b1..03202f215b2 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -1,36 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Jan-Philipp Litza <jplitza@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Maxence Lange <maxence@artificial-owl.com>
- * @author phisch <git@philippschaffrath.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20;
@@ -38,12 +11,12 @@ use OC\Files\Cache\Cache;
use OC\Share20\Exception\BackendError;
use OC\Share20\Exception\InvalidShare;
use OC\Share20\Exception\ProviderException;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Defaults;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
-use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IURLGenerator;
@@ -55,6 +28,7 @@ use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IAttributes;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
+use Psr\Log\LoggerInterface;
use function str_starts_with;
/**
@@ -90,19 +64,19 @@ class DefaultShareProvider implements IShareProvider {
/** @var IURLGenerator */
private $urlGenerator;
- /** @var IConfig */
- private $config;
+ private ITimeFactory $timeFactory;
public function __construct(
- IDBConnection $connection,
- IUserManager $userManager,
- IGroupManager $groupManager,
- IRootFolder $rootFolder,
- IMailer $mailer,
- Defaults $defaults,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator,
- IConfig $config) {
+ IDBConnection $connection,
+ IUserManager $userManager,
+ IGroupManager $groupManager,
+ IRootFolder $rootFolder,
+ IMailer $mailer,
+ Defaults $defaults,
+ IFactory $l10nFactory,
+ IURLGenerator $urlGenerator,
+ ITimeFactory $timeFactory,
+ ) {
$this->dbConn = $connection;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
@@ -111,7 +85,7 @@ class DefaultShareProvider implements IShareProvider {
$this->defaults = $defaults;
$this->l10nFactory = $l10nFactory;
$this->urlGenerator = $urlGenerator;
- $this->config = $config;
+ $this->timeFactory = $timeFactory;
}
/**
@@ -216,32 +190,22 @@ class DefaultShareProvider implements IShareProvider {
}
// Set the time this share was created
- $qb->setValue('stime', $qb->createNamedParameter(time()));
+ $shareTime = $this->timeFactory->now();
+ $qb->setValue('stime', $qb->createNamedParameter($shareTime->getTimestamp()));
// insert the data and fetch the id of the share
- $this->dbConn->beginTransaction();
- $qb->execute();
- $id = $this->dbConn->lastInsertId('*PREFIX*share');
+ $qb->executeStatement();
- // Now fetch the inserted share and create a complete share object
- $qb = $this->dbConn->getQueryBuilder();
- $qb->select('*')
- ->from('share')
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
-
- $cursor = $qb->execute();
- $data = $cursor->fetch();
- $this->dbConn->commit();
- $cursor->closeCursor();
+ // Update mandatory data
+ $id = $qb->getLastInsertId();
+ $share->setId((string)$id);
+ $share->setProviderId($this->identifier());
- if ($data === false) {
- throw new ShareNotFound('Newly created share could not be found');
- }
+ $share->setShareTime(\DateTime::createFromImmutable($shareTime));
$mailSendValue = $share->getMailSend();
- $data['mail_send'] = ($mailSendValue === null) ? true : $mailSendValue;
+ $share->setMailSend(($mailSendValue === null) ? true : $mailSendValue);
- $share = $this->createShare($data);
return $share;
}
@@ -661,6 +625,10 @@ class DefaultShareProvider implements IShareProvider {
}
public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
+ if (!$shallow) {
+ throw new \Exception("non-shallow getSharesInFolder is no longer supported");
+ }
+
$qb = $this->dbConn->getQueryBuilder();
$qb->select('s.*',
'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
@@ -701,21 +669,12 @@ class DefaultShareProvider implements IShareProvider {
}, $childMountNodes);
$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
- if ($shallow) {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
- $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
- )
- );
- } else {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()) . '/%')),
- $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
- )
- );
- }
+ $qb->andWhere(
+ $qb->expr()->orX(
+ $qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
+ $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
+ )
+ );
$qb->orderBy('id');
@@ -831,7 +790,7 @@ class DefaultShareProvider implements IShareProvider {
// If the recipient is set for a group share resolve to that user
if ($recipientId !== null && $share->getShareType() === IShare::TYPE_GROUP) {
- $share = $this->resolveGroupShares([$share], $recipientId)[0];
+ $share = $this->resolveGroupShares([(int) $share->getId() => $share], $recipientId)[0];
}
return $share;
@@ -1008,7 +967,8 @@ class DefaultShareProvider implements IShareProvider {
}
if ($this->isAccessibleResult($data)) {
- $shares2[] = $this->createShare($data);
+ $share = $this->createShare($data);
+ $shares2[$share->getId()] = $share;
}
}
$cursor->closeCursor();
@@ -1129,61 +1089,40 @@ class DefaultShareProvider implements IShareProvider {
}
/**
- * @param Share[] $shares
+ * Update the data from group shares with any per-user modifications
+ *
+ * @param array<int, Share> $shareMap shares indexed by share id
* @param $userId
* @return Share[] The updates shares if no update is found for a share return the original
*/
- private function resolveGroupShares($shares, $userId) {
- $result = [];
-
- $start = 0;
- while (true) {
- /** @var Share[] $shareSlice */
- $shareSlice = array_slice($shares, $start, 100);
- $start += 100;
-
- if ($shareSlice === []) {
- break;
- }
-
- /** @var int[] $ids */
- $ids = [];
- /** @var Share[] $shareMap */
- $shareMap = [];
-
- foreach ($shareSlice as $share) {
- $ids[] = (int)$share->getId();
- $shareMap[$share->getId()] = $share;
- }
-
- $qb = $this->dbConn->getQueryBuilder();
-
- $query = $qb->select('*')
- ->from('share')
- ->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
- ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
- ->andWhere($qb->expr()->orX(
- $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
- $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
- ));
+ private function resolveGroupShares($shareMap, $userId) {
+ $qb = $this->dbConn->getQueryBuilder();
+ $query = $qb->select('*')
+ ->from('share')
+ ->where($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
+ ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
+ ->andWhere($qb->expr()->in('item_type', [$qb->createNamedParameter('file'), $qb->createNamedParameter('folder')]));
+
+ // this is called with either all group shares or one group share.
+ // for all shares it's easier to just only search by share_with,
+ // for a single share it's efficient to filter by parent
+ if (count($shareMap) === 1) {
+ $share = reset($shareMap);
+ $query->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
+ }
- $stmt = $query->execute();
+ $stmt = $query->execute();
- while ($data = $stmt->fetch()) {
+ while ($data = $stmt->fetch()) {
+ if (array_key_exists($data['parent'], $shareMap)) {
$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
$shareMap[$data['parent']]->setStatus((int)$data['accepted']);
$shareMap[$data['parent']]->setTarget($data['file_target']);
$shareMap[$data['parent']]->setParent($data['parent']);
}
-
- $stmt->closeCursor();
-
- foreach ($shareMap as $share) {
- $result[] = $share;
- }
}
- return $result;
+ return array_values($shareMap);
}
/**
@@ -1247,7 +1186,8 @@ class DefaultShareProvider implements IShareProvider {
)
);
} else {
- \OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
+ $e = new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType);
+ \OCP\Server::get(LoggerInterface::class)->error($e->getMessage(), ['exception' => $e]);
return;
}
@@ -1374,7 +1314,7 @@ class DefaultShareProvider implements IShareProvider {
$type = (int)$row['share_type'];
if ($type === IShare::TYPE_USER) {
$uid = $row['share_with'];
- $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
+ $users[$uid] = $users[$uid] ?? [];
$users[$uid][$row['id']] = $row;
} elseif ($type === IShare::TYPE_GROUP) {
$gid = $row['share_with'];
@@ -1387,14 +1327,14 @@ class DefaultShareProvider implements IShareProvider {
$userList = $group->getUsers();
foreach ($userList as $user) {
$uid = $user->getUID();
- $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
+ $users[$uid] = $users[$uid] ?? [];
$users[$uid][$row['id']] = $row;
}
} elseif ($type === IShare::TYPE_LINK) {
$link = true;
} elseif ($type === IShare::TYPE_USERGROUP && $currentAccess === true) {
$uid = $row['share_with'];
- $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
+ $users[$uid] = $users[$uid] ?? [];
$users[$uid][$row['id']] = $row;
}
}
diff --git a/lib/private/Share20/Exception/BackendError.php b/lib/private/Share20/Exception/BackendError.php
index b3e07495378..60f7dcc1a17 100644
--- a/lib/private/Share20/Exception/BackendError.php
+++ b/lib/private/Share20/Exception/BackendError.php
@@ -1,23 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20\Exception;
diff --git a/lib/private/Share20/Exception/InvalidShare.php b/lib/private/Share20/Exception/InvalidShare.php
index 464dc15a9f1..755efdfd2cc 100644
--- a/lib/private/Share20/Exception/InvalidShare.php
+++ b/lib/private/Share20/Exception/InvalidShare.php
@@ -1,23 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20\Exception;
diff --git a/lib/private/Share20/Exception/ProviderException.php b/lib/private/Share20/Exception/ProviderException.php
index b8e15dd9db8..cb79ab884b4 100644
--- a/lib/private/Share20/Exception/ProviderException.php
+++ b/lib/private/Share20/Exception/ProviderException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20\Exception;
diff --git a/lib/private/Share20/Hooks.php b/lib/private/Share20/Hooks.php
index ae08b20fde6..809b50791e5 100644
--- a/lib/private/Share20/Hooks.php
+++ b/lib/private/Share20/Hooks.php
@@ -1,32 +1,20 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20;
+use OCP\Share\IManager as IShareManager;
+
class Hooks {
public static function post_deleteUser($arguments) {
- \OC::$server->getShareManager()->userDeleted($arguments['uid']);
+ \OC::$server->get(IShareManager::class)->userDeleted($arguments['uid']);
}
public static function post_deleteGroup($arguments) {
- \OC::$server->getShareManager()->groupDeleted($arguments['gid']);
+ \OC::$server->get(IShareManager::class)->groupDeleted($arguments['gid']);
}
}
diff --git a/lib/private/Share20/LegacyHooks.php b/lib/private/Share20/LegacyHooks.php
index 24d07167fbd..99c2b0a9a87 100644
--- a/lib/private/Share20/LegacyHooks.php
+++ b/lib/private/Share20/LegacyHooks.php
@@ -1,28 +1,7 @@
<?php
/**
- * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Pauli Järvinen <pauli.jarvinen@gmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Share20;
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index b03608f9872..e10c34fd0d2 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -1,52 +1,16 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Maxence Lange <maxence@artificial-owl.com>
- * @author Maxence Lange <maxence@nextcloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Pauli Järvinen <pauli.jarvinen@gmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Samuel <faust64@gmail.com>
- * @author szaimen <szaimen@e.mail.de>
- * @author Valdnet <47037905+Valdnet@users.noreply.github.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20;
-use OCP\Cache\CappedMemoryCache;
use OC\Files\Mount\MoveableMount;
use OC\KnownUser\KnownUserService;
use OC\Share20\Exception\ProviderException;
use OCA\Files_Sharing\AppInfo\Application;
-use OCA\Files_Sharing\ISharedStorage;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
use OCP\Files\Folder;
@@ -55,6 +19,7 @@ use OCP\Files\Mount\IMountManager;
use OCP\Files\Node;
use OCP\HintException;
use OCP\IConfig;
+use OCP\IDateTimeZone;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
@@ -85,84 +50,34 @@ use Psr\Log\LoggerInterface;
* This class is the communication hub for all sharing related operations.
*/
class Manager implements IManager {
- /** @var IProviderFactory */
- private $factory;
- private LoggerInterface $logger;
- /** @var IConfig */
- private $config;
- /** @var ISecureRandom */
- private $secureRandom;
- /** @var IHasher */
- private $hasher;
- /** @var IMountManager */
- private $mountManager;
- /** @var IGroupManager */
- private $groupManager;
- /** @var IL10N */
- private $l;
- /** @var IFactory */
- private $l10nFactory;
- /** @var IUserManager */
- private $userManager;
- /** @var IRootFolder */
- private $rootFolder;
- /** @var CappedMemoryCache */
- private $sharingDisabledForUsersCache;
- /** @var LegacyHooks */
- private $legacyHooks;
- /** @var IMailer */
- private $mailer;
- /** @var IURLGenerator */
- private $urlGenerator;
- /** @var \OC_Defaults */
- private $defaults;
- /** @var IEventDispatcher */
- private $dispatcher;
- /** @var IUserSession */
- private $userSession;
- /** @var KnownUserService */
- private $knownUserService;
+
+ private IL10N|null $l;
+ private LegacyHooks $legacyHooks;
public function __construct(
- LoggerInterface $logger,
- IConfig $config,
- ISecureRandom $secureRandom,
- IHasher $hasher,
- IMountManager $mountManager,
- IGroupManager $groupManager,
- IL10N $l,
- IFactory $l10nFactory,
- IProviderFactory $factory,
- IUserManager $userManager,
- IRootFolder $rootFolder,
- IMailer $mailer,
- IURLGenerator $urlGenerator,
- \OC_Defaults $defaults,
- IEventDispatcher $dispatcher,
- IUserSession $userSession,
- KnownUserService $knownUserService
+ private LoggerInterface $logger,
+ private IConfig $config,
+ private ISecureRandom $secureRandom,
+ private IHasher $hasher,
+ private IMountManager $mountManager,
+ private IGroupManager $groupManager,
+ private IFactory $l10nFactory,
+ private IProviderFactory $factory,
+ private IUserManager $userManager,
+ private IRootFolder $rootFolder,
+ private IMailer $mailer,
+ private IURLGenerator $urlGenerator,
+ private \OC_Defaults $defaults,
+ private IEventDispatcher $dispatcher,
+ private IUserSession $userSession,
+ private KnownUserService $knownUserService,
+ private ShareDisableChecker $shareDisableChecker,
+ private IDateTimeZone $dateTimeZone
) {
- $this->logger = $logger;
- $this->config = $config;
- $this->secureRandom = $secureRandom;
- $this->hasher = $hasher;
- $this->mountManager = $mountManager;
- $this->groupManager = $groupManager;
- $this->l = $l;
- $this->l10nFactory = $l10nFactory;
- $this->factory = $factory;
- $this->userManager = $userManager;
- $this->rootFolder = $rootFolder;
- $this->sharingDisabledForUsersCache = new CappedMemoryCache();
+ $this->l = $this->l10nFactory->get('lib');
// The constructor of LegacyHooks registers the listeners of share events
// do not remove if those are not properly migrated
- $this->legacyHooks = new LegacyHooks($dispatcher);
- $this->mailer = $mailer;
- $this->urlGenerator = $urlGenerator;
- $this->defaults = $defaults;
- $this->dispatcher = $dispatcher;
- $this->userSession = $userSession;
- $this->knownUserService = $knownUserService;
+ $this->legacyHooks = new LegacyHooks($this->dispatcher);
}
/**
@@ -208,7 +123,7 @@ class Manager implements IManager {
*
* @suppress PhanUndeclaredClassMethod
*/
- protected function generalCreateChecks(IShare $share) {
+ protected function generalCreateChecks(IShare $share, bool $isUpdate = false) {
if ($share->getShareType() === IShare::TYPE_USER) {
// We expect a valid user as sharedWith for user shares
if (!$this->userManager->userExists($share->getSharedWith())) {
@@ -292,50 +207,15 @@ class Manager implements IManager {
throw new \InvalidArgumentException('A share requires permissions');
}
- $isFederatedShare = $share->getNode()->getStorage()->instanceOfStorage('\OCA\Files_Sharing\External\Storage');
$permissions = 0;
-
- if (!$isFederatedShare && $share->getNode()->getOwner() && $share->getNode()->getOwner()->getUID() !== $share->getSharedBy()) {
- $userMounts = array_filter($userFolder->getById($share->getNode()->getId()), function ($mount) {
- // We need to filter since there might be other mountpoints that contain the file
- // e.g. if the user has access to the same external storage that the file is originating from
- return $mount->getStorage()->instanceOfStorage(ISharedStorage::class);
- });
- $userMount = array_shift($userMounts);
- if ($userMount === null) {
- throw new GenericShareException('Could not get proper share mount for ' . $share->getNode()->getId() . '. Failing since else the next calls are called with null');
- }
- $mount = $userMount->getMountPoint();
- // When it's a reshare use the parent share permissions as maximum
- $userMountPointId = $mount->getStorageRootId();
- $userMountPoints = $userFolder->getById($userMountPointId);
- $userMountPoint = array_shift($userMountPoints);
-
- if ($userMountPoint === null) {
- throw new GenericShareException('Could not get proper user mount for ' . $userMountPointId . '. Failing since else the next calls are called with null');
- }
-
- /* Check if this is an incoming share */
- $incomingShares = $this->getSharedWith($share->getSharedBy(), IShare::TYPE_USER, $userMountPoint, -1, 0);
- $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_GROUP, $userMountPoint, -1, 0));
- $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_CIRCLE, $userMountPoint, -1, 0));
- $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_ROOM, $userMountPoint, -1, 0));
-
- /** @var IShare[] $incomingShares */
- if (!empty($incomingShares)) {
- foreach ($incomingShares as $incomingShare) {
- $permissions |= $incomingShare->getPermissions();
- }
- }
- } else {
- /*
- * Quick fix for #23536
- * Non moveable mount points do not have update and delete permissions
- * while we 'most likely' do have that on the storage.
- */
- $permissions = $share->getNode()->getPermissions();
- if (!($share->getNode()->getMountPoint() instanceof MoveableMount)) {
- $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
+ $nodesForUser = $userFolder->getById($share->getNodeId());
+ foreach ($nodesForUser as $node) {
+ if ($node->getInternalPath() === '' && !$node->getMountPoint() instanceof MoveableMount) {
+ // for the root of non-movable mount, the permissions we see if limited by the mount itself,
+ // so we instead use the "raw" permissions from the storage
+ $permissions |= $node->getStorage()->getPermissions('');
+ } else {
+ $permissions |= $node->getPermissions();
}
}
@@ -382,26 +262,6 @@ class Manager implements IManager {
$expirationDate = $share->getExpirationDate();
- if ($expirationDate !== null) {
- //Make sure the expiration date is a date
- $expirationDate->setTime(0, 0, 0);
-
- $date = new \DateTime();
- $date->setTime(0, 0, 0);
- if ($date >= $expirationDate) {
- $message = $this->l->t('Expiration date is in the past');
- throw new GenericShareException($message, $message, 404);
- }
- }
-
- // If expiredate is empty set a default one if there is a default
- $fullId = null;
- try {
- $fullId = $share->getFullId();
- } catch (\UnexpectedValueException $e) {
- // This is a new share
- }
-
if ($isRemote) {
$defaultExpireDate = $this->shareApiRemoteDefaultExpireDate();
$defaultExpireDays = $this->shareApiRemoteDefaultExpireDays();
@@ -413,29 +273,53 @@ class Manager implements IManager {
$configProp = 'internal_defaultExpDays';
$isEnforced = $this->shareApiInternalDefaultExpireDateEnforced();
}
- if ($fullId === null && $expirationDate === null && $defaultExpireDate) {
- $expirationDate = new \DateTime();
- $expirationDate->setTime(0, 0, 0);
- $days = (int)$this->config->getAppValue('core', $configProp, (string)$defaultExpireDays);
- if ($days > $defaultExpireDays) {
- $days = $defaultExpireDays;
+ // If $expirationDate is falsy, noExpirationDate is true and expiration not enforced
+ // Then skip expiration date validation as null is accepted
+ if(!($share->getNoExpirationDate() && !$isEnforced)) {
+ if ($expirationDate != null) {
+ $expirationDate->setTimezone($this->dateTimeZone->getTimeZone());
+ $expirationDate->setTime(0, 0, 0);
+
+ $date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
+ $date->setTime(0, 0, 0);
+ if ($date >= $expirationDate) {
+ $message = $this->l->t('Expiration date is in the past');
+ throw new GenericShareException($message, $message, 404);
+ }
+ }
+
+ // If expiredate is empty set a default one if there is a default
+ $fullId = null;
+ try {
+ $fullId = $share->getFullId();
+ } catch (\UnexpectedValueException $e) {
+ // This is a new share
}
- $expirationDate->add(new \DateInterval('P' . $days . 'D'));
- }
- // If we enforce the expiration date check that is does not exceed
- if ($isEnforced) {
- if ($expirationDate === null) {
- throw new \InvalidArgumentException('Expiration date is enforced');
+ if ($fullId === null && $expirationDate === null && $defaultExpireDate) {
+ $expirationDate = new \DateTime('now', $this->dateTimeZone->getTimeZone());
+ $expirationDate->setTime(0, 0, 0);
+ $days = (int)$this->config->getAppValue('core', $configProp, (string)$defaultExpireDays);
+ if ($days > $defaultExpireDays) {
+ $days = $defaultExpireDays;
+ }
+ $expirationDate->add(new \DateInterval('P' . $days . 'D'));
}
- $date = new \DateTime();
- $date->setTime(0, 0, 0);
- $date->add(new \DateInterval('P' . $defaultExpireDays . 'D'));
- if ($date < $expirationDate) {
- $message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $defaultExpireDays);
- throw new GenericShareException($message, $message, 404);
+ // If we enforce the expiration date check that is does not exceed
+ if ($isEnforced) {
+ if (empty($expirationDate)) {
+ throw new \InvalidArgumentException('Expiration date is enforced');
+ }
+
+ $date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
+ $date->setTime(0, 0, 0);
+ $date->add(new \DateInterval('P' . $defaultExpireDays . 'D'));
+ if ($date < $expirationDate) {
+ $message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $defaultExpireDays);
+ throw new GenericShareException($message, $message, 404);
+ }
}
}
@@ -468,51 +352,57 @@ class Manager implements IManager {
*/
protected function validateExpirationDateLink(IShare $share) {
$expirationDate = $share->getExpirationDate();
-
- if ($expirationDate !== null) {
- //Make sure the expiration date is a date
- $expirationDate->setTime(0, 0, 0);
-
- $date = new \DateTime();
- $date->setTime(0, 0, 0);
- if ($date >= $expirationDate) {
- $message = $this->l->t('Expiration date is in the past');
- throw new GenericShareException($message, $message, 404);
+ $isEnforced = $this->shareApiLinkDefaultExpireDateEnforced();
+
+ // If $expirationDate is falsy, noExpirationDate is true and expiration not enforced
+ // Then skip expiration date validation as null is accepted
+ if(!($share->getNoExpirationDate() && !$isEnforced)) {
+ if ($expirationDate !== null) {
+ $expirationDate->setTimezone($this->dateTimeZone->getTimeZone());
+ $expirationDate->setTime(0, 0, 0);
+
+ $date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
+ $date->setTime(0, 0, 0);
+ if ($date >= $expirationDate) {
+ $message = $this->l->t('Expiration date is in the past');
+ throw new GenericShareException($message, $message, 404);
+ }
}
- }
-
- // If expiredate is empty set a default one if there is a default
- $fullId = null;
- try {
- $fullId = $share->getFullId();
- } catch (\UnexpectedValueException $e) {
- // This is a new share
- }
-
- if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
- $expirationDate = new \DateTime();
- $expirationDate->setTime(0, 0, 0);
- $days = (int)$this->config->getAppValue('core', 'link_defaultExpDays', (string)$this->shareApiLinkDefaultExpireDays());
- if ($days > $this->shareApiLinkDefaultExpireDays()) {
- $days = $this->shareApiLinkDefaultExpireDays();
+ // If expiredate is empty set a default one if there is a default
+ $fullId = null;
+ try {
+ $fullId = $share->getFullId();
+ } catch (\UnexpectedValueException $e) {
+ // This is a new share
+ }
+
+ if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
+ $expirationDate = new \DateTime('now', $this->dateTimeZone->getTimeZone());
+ $expirationDate->setTime(0, 0, 0);
+
+ $days = (int)$this->config->getAppValue('core', 'link_defaultExpDays', (string)$this->shareApiLinkDefaultExpireDays());
+ if ($days > $this->shareApiLinkDefaultExpireDays()) {
+ $days = $this->shareApiLinkDefaultExpireDays();
+ }
+ $expirationDate->add(new \DateInterval('P' . $days . 'D'));
}
- $expirationDate->add(new \DateInterval('P' . $days . 'D'));
- }
-
- // If we enforce the expiration date check that is does not exceed
- if ($this->shareApiLinkDefaultExpireDateEnforced()) {
- if ($expirationDate === null) {
- throw new \InvalidArgumentException('Expiration date is enforced');
+
+ // If we enforce the expiration date check that is does not exceed
+ if ($isEnforced) {
+ if (empty($expirationDate)) {
+ throw new \InvalidArgumentException('Expiration date is enforced');
+ }
+
+ $date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
+ $date->setTime(0, 0, 0);
+ $date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
+ if ($date < $expirationDate) {
+ $message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $this->shareApiLinkDefaultExpireDays());
+ throw new GenericShareException($message, $message, 404);
+ }
}
- $date = new \DateTime();
- $date->setTime(0, 0, 0);
- $date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
- if ($date < $expirationDate) {
- $message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $this->shareApiLinkDefaultExpireDays());
- throw new GenericShareException($message, $message, 404);
- }
}
$accepted = true;
@@ -528,6 +418,9 @@ class Manager implements IManager {
throw new \Exception($message);
}
+ if ($expirationDate instanceof \DateTime) {
+ $expirationDate->setTimezone(new \DateTimeZone(date_default_timezone_get()));
+ }
$share->setExpirationDate($expirationDate);
return $share;
@@ -549,6 +442,11 @@ class Manager implements IManager {
$this->groupManager->getUserGroupIds($sharedBy),
$this->groupManager->getUserGroupIds($sharedWith)
);
+
+ // optional excluded groups
+ $excludedGroups = $this->shareWithGroupMembersOnlyExcludeGroupsList();
+ $groups = array_diff($groups, $excludedGroups);
+
if (empty($groups)) {
$message_t = $this->l->t('Sharing is only allowed with group members');
throw new \Exception($message_t);
@@ -574,7 +472,7 @@ class Manager implements IManager {
// Identical share already exists
if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
- $message = $this->l->t('Sharing %s failed, because this item is already shared with user %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
+ $message = $this->l->t('Sharing %s failed, because this item is already shared with the account %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
throw new AlreadySharedException($message, $existingShare);
}
@@ -585,7 +483,7 @@ class Manager implements IManager {
$user = $this->userManager->get($share->getSharedWith());
if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
- $message = $this->l->t('Sharing %s failed, because this item is already shared with user %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
+ $message = $this->l->t('Sharing %s failed, because this item is already shared with the account %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
throw new AlreadySharedException($message, $existingShare);
}
}
@@ -609,7 +507,10 @@ class Manager implements IManager {
if ($this->shareWithGroupMembersOnly()) {
$sharedBy = $this->userManager->get($share->getSharedBy());
$sharedWith = $this->groupManager->get($share->getSharedWith());
- if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
+
+ // optional excluded groups
+ $excludedGroups = $this->shareWithGroupMembersOnlyExcludeGroupsList();
+ if (is_null($sharedWith) || in_array($share->getSharedWith(), $excludedGroups) || !$sharedWith->inGroup($sharedBy)) {
throw new \Exception('Sharing is only allowed within your own groups');
}
}
@@ -881,12 +782,12 @@ class Manager implements IManager {
* @param \DateTime|null $expiration
*/
protected function sendMailNotification(IL10N $l,
- $filename,
- $link,
- $initiator,
- $shareWith,
- \DateTime $expiration = null,
- $note = '') {
+ $filename,
+ $link,
+ $initiator,
+ $shareWith,
+ ?\DateTime $expiration = null,
+ $note = '') {
$initiatorUser = $this->userManager->get($initiator);
$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
@@ -988,7 +889,7 @@ class Manager implements IManager {
throw new \InvalidArgumentException('Cannot share with the share owner');
}
- $this->generalCreateChecks($share);
+ $this->generalCreateChecks($share, true);
if ($share->getShareType() === IShare::TYPE_USER) {
$this->userCreateChecks($share);
@@ -1300,9 +1201,12 @@ class Manager implements IManager {
public function getSharesInFolder($userId, Folder $node, $reshares = false, $shallow = true) {
$providers = $this->factory->getAllProviders();
+ if (!$shallow) {
+ throw new \Exception("non-shallow getSharesInFolder is no longer supported");
+ }
return array_reduce($providers, function ($shares, IShareProvider $provider) use ($userId, $node, $reshares, $shallow) {
- $newShares = $provider->getSharesInFolder($userId, $node, $reshares, $shallow);
+ $newShares = $provider->getSharesInFolder($userId, $node, $reshares);
foreach ($newShares as $fid => $data) {
if (!isset($shares[$fid])) {
$shares[$fid] = [];
@@ -1574,14 +1478,8 @@ class Manager implements IManager {
* @return bool
*/
public function checkPassword(IShare $share, $password) {
- $passwordProtected = $share->getShareType() !== IShare::TYPE_LINK
- || $share->getShareType() !== IShare::TYPE_EMAIL
- || $share->getShareType() !== IShare::TYPE_CIRCLE;
- if (!$passwordProtected) {
- //TODO maybe exception?
- return false;
- }
+ // if there is no password on the share object / passsword is null, there is nothing to check
if ($password === null || $share->getPassword() === null) {
return false;
}
@@ -1661,9 +1559,10 @@ class Manager implements IManager {
* |-folder2 (32)
* |-fileA (42)
*
- * fileA is shared with user1 and user1@server1
+ * fileA is shared with user1 and user1@server1 and email1@maildomain1
* folder2 is shared with group2 (user4 is a member of group2)
* folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
+ * and email2@maildomain2
*
* Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
* [
@@ -1677,7 +1576,10 @@ class Manager implements IManager {
* 'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
* ],
* public => bool
- * mail => bool
+ * mail => [
+ * 'email1@maildomain1' => ['node_id' => 42, 'token' => 'aBcDeFg'],
+ * 'email2@maildomain2' => ['node_id' => 23, 'token' => 'hIjKlMn'],
+ * ]
* ]
*
* The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
@@ -1685,7 +1587,7 @@ class Manager implements IManager {
* users => ['user1', 'user2', 'user4'],
* remote => bool,
* public => bool
- * mail => bool
+ * mail => ['email1@maildomain1', 'email2@maildomain2']
* ]
*
* This is required for encryption/activity
@@ -1705,9 +1607,9 @@ class Manager implements IManager {
$owner = $owner->getUID();
if ($currentAccess) {
- $al = ['users' => [], 'remote' => [], 'public' => false];
+ $al = ['users' => [], 'remote' => [], 'public' => false, 'mail' => []];
} else {
- $al = ['users' => [], 'remote' => false, 'public' => false];
+ $al = ['users' => [], 'remote' => false, 'public' => false, 'mail' => []];
}
if (!$this->userManager->userExists($owner)) {
return $al;
@@ -1716,8 +1618,7 @@ class Manager implements IManager {
//Get node for the owner and correct the owner in case of external storage
$userFolder = $this->rootFolder->getUserFolder($owner);
if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
- $nodes = $userFolder->getById($path->getId());
- $path = array_shift($nodes);
+ $path = $userFolder->getFirstNodeById($path->getId());
if ($path === null || $path->getOwner() === null) {
return [];
}
@@ -1946,6 +1847,21 @@ class Manager implements IManager {
}
/**
+ * If shareWithGroupMembersOnly is enabled, return an optional
+ * list of groups that must be excluded from the principle of
+ * belonging to the same group.
+ *
+ * @return array
+ */
+ public function shareWithGroupMembersOnlyExcludeGroupsList() {
+ if (!$this->shareWithGroupMembersOnly()) {
+ return [];
+ }
+ $excludeGroups = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
+ return json_decode($excludeGroups, true) ?? [];
+ }
+
+ /**
* Check if users can share with groups
*
* @return bool
@@ -2025,37 +1941,7 @@ class Manager implements IManager {
* @return bool
*/
public function sharingDisabledForUser($userId) {
- if ($userId === null) {
- return false;
- }
-
- if (isset($this->sharingDisabledForUsersCache[$userId])) {
- return $this->sharingDisabledForUsersCache[$userId];
- }
-
- if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
- $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
- $excludedGroups = json_decode($groupsList);
- if (is_null($excludedGroups)) {
- $excludedGroups = explode(',', $groupsList);
- $newValue = json_encode($excludedGroups);
- $this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
- }
- $user = $this->userManager->get($userId);
- $usersGroups = $this->groupManager->getUserGroupIds($user);
- if (!empty($usersGroups)) {
- $remainingGroups = array_diff($usersGroups, $excludedGroups);
- // if the user is only in groups which are disabled for sharing then
- // sharing is also disabled for the user
- if (empty($remainingGroups)) {
- $this->sharingDisabledForUsersCache[$userId] = true;
- return true;
- }
- }
- }
-
- $this->sharingDisabledForUsersCache[$userId] = false;
- return false;
+ return $this->shareDisableChecker->sharingDisabledForUser($userId);
}
/**
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index ff6d9b0eacd..2800db8177a 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -1,35 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Maxence Lange <maxence@nextcloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Samuel <faust64@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20;
@@ -41,10 +15,14 @@ use OCA\FederatedFileSharing\TokenHandler;
use OCA\ShareByMail\Settings\SettingsManager;
use OCA\ShareByMail\ShareByMailProvider;
use OCA\Talk\Share\RoomShareProvider;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Defaults;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Federation\ICloudFederationFactory;
+use OCP\Files\IRootFolder;
use OCP\IServerContainer;
use OCP\Mail\IMailer;
+use OCP\Security\IHasher;
use OCP\Share\IManager;
use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
@@ -100,12 +78,12 @@ class ProviderFactory implements IProviderFactory {
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getUserManager(),
$this->serverContainer->getGroupManager(),
- $this->serverContainer->getLazyRootFolder(),
+ $this->serverContainer->get(IRootFolder::class),
$this->serverContainer->get(IMailer::class),
$this->serverContainer->query(Defaults::class),
$this->serverContainer->getL10NFactory(),
$this->serverContainer->getURLGenerator(),
- $this->serverContainer->getConfig()
+ $this->serverContainer->query(ITimeFactory::class),
);
}
@@ -142,7 +120,7 @@ class ProviderFactory implements IProviderFactory {
$this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
$this->serverContainer->getJobList(),
\OC::$server->getCloudFederationProviderManager(),
- \OC::$server->getCloudFederationFactory(),
+ \OC::$server->get(ICloudFederationFactory::class),
$this->serverContainer->query(IEventDispatcher::class),
$this->serverContainer->get(LoggerInterface::class),
);
@@ -156,7 +134,7 @@ class ProviderFactory implements IProviderFactory {
$notifications,
$tokenHandler,
$l,
- $this->serverContainer->getLazyRootFolder(),
+ $this->serverContainer->get(IRootFolder::class),
$this->serverContainer->getConfig(),
$this->serverContainer->getUserManager(),
$this->serverContainer->getCloudIdManager(),
@@ -191,15 +169,15 @@ class ProviderFactory implements IProviderFactory {
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getSecureRandom(),
$this->serverContainer->getUserManager(),
- $this->serverContainer->getLazyRootFolder(),
+ $this->serverContainer->get(IRootFolder::class),
$this->serverContainer->getL10N('sharebymail'),
- $this->serverContainer->getLogger(),
+ $this->serverContainer->get(LoggerInterface::class),
$this->serverContainer->get(IMailer::class),
$this->serverContainer->getURLGenerator(),
$this->serverContainer->getActivityManager(),
$settingsManager,
$this->serverContainer->query(Defaults::class),
- $this->serverContainer->getHasher(),
+ $this->serverContainer->get(IHasher::class),
$this->serverContainer->get(IEventDispatcher::class),
$this->serverContainer->get(IManager::class)
);
@@ -233,7 +211,7 @@ class ProviderFactory implements IProviderFactory {
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getSecureRandom(),
$this->serverContainer->getUserManager(),
- $this->serverContainer->getLazyRootFolder(),
+ $this->serverContainer->get(IRootFolder::class),
$this->serverContainer->getL10N('circles'),
$this->serverContainer->getLogger(),
$this->serverContainer->getURLGenerator()
diff --git a/lib/private/Share20/PublicShareTemplateFactory.php b/lib/private/Share20/PublicShareTemplateFactory.php
index 222f327496a..34dd9b13b61 100644
--- a/lib/private/Share20/PublicShareTemplateFactory.php
+++ b/lib/private/Share20/PublicShareTemplateFactory.php
@@ -2,34 +2,18 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Louis Chemineau <louis@chmn.me>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Share20;
use Exception;
use OC\AppFramework\Bootstrap\Coordinator;
use OCA\Files_Sharing\DefaultPublicShareTemplateProvider;
use OCP\Server;
-use OCP\Share\IShare;
use OCP\Share\IPublicShareTemplateFactory;
use OCP\Share\IPublicShareTemplateProvider;
+use OCP\Share\IShare;
class PublicShareTemplateFactory implements IPublicShareTemplateFactory {
public function __construct(
diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php
index 0a50fa0ccfb..ac95e3ac0d4 100644
--- a/lib/private/Share20/Share.php
+++ b/lib/private/Share20/Share.php
@@ -1,36 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Maxence Lange <maxence@nextcloud.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20;
-use OCP\Files\File;
use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
@@ -90,28 +68,24 @@ class Share implements IShare {
private $mailSend;
/** @var string */
private $label = '';
-
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IUserManager */
- private $userManager;
-
/** @var ICacheEntry|null */
private $nodeCacheEntry;
-
/** @var bool */
private $hideDownload = false;
- public function __construct(IRootFolder $rootFolder, IUserManager $userManager) {
- $this->rootFolder = $rootFolder;
- $this->userManager = $userManager;
+ private bool $noExpirationDate = false;
+
+ public function __construct(
+ private IRootFolder $rootFolder,
+ private IUserManager $userManager,
+ ) {
}
/**
* @inheritdoc
*/
public function setId($id) {
+ /** @var mixed $id Let's be safe until strong typing */
if (is_int($id)) {
$id = (string)$id;
}
@@ -188,12 +162,12 @@ class Share implements IShare {
$userFolder = $this->rootFolder->getUserFolder($this->sharedBy);
}
- $nodes = $userFolder->getById($this->fileId);
- if (empty($nodes)) {
+ $node = $userFolder->getFirstNodeById($this->fileId);
+ if (!$node) {
throw new NotFoundException('Node for share not found, fileid: ' . $this->fileId);
}
- $this->node = $nodes[0];
+ $this->node = $node;
}
return $this->node;
@@ -211,12 +185,16 @@ class Share implements IShare {
/**
* @inheritdoc
*/
- public function getNodeId() {
+ public function getNodeId(): int {
if ($this->fileId === null) {
$this->fileId = $this->getNode()->getId();
}
- return $this->fileId;
+ if ($this->fileId === null) {
+ throw new NotFoundException("Share source not found");
+ } else {
+ return $this->fileId;
+ }
}
/**
@@ -424,6 +402,21 @@ class Share implements IShare {
/**
* @inheritdoc
*/
+ public function setNoExpirationDate(bool $noExpirationDate) {
+ $this->noExpirationDate = $noExpirationDate;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getNoExpirationDate(): bool {
+ return $this->noExpirationDate;
+ }
+
+ /**
+ * @inheritdoc
+ */
public function isExpired() {
return $this->getExpirationDate() !== null &&
$this->getExpirationDate() <= new \DateTime();
@@ -534,7 +527,7 @@ class Share implements IShare {
/**
* Set the parent of this share
*
- * @param int parent
+ * @param int $parent
* @return IShare
* @deprecated The new shares do not have parents. This is just here for legacy reasons.
*/
diff --git a/lib/private/Share20/ShareAttributes.php b/lib/private/Share20/ShareAttributes.php
index 9b97c94275d..abbbd36759b 100644
--- a/lib/private/Share20/ShareAttributes.php
+++ b/lib/private/Share20/ShareAttributes.php
@@ -1,22 +1,9 @@
<?php
+
/**
- * @author Piotr Mrowczynski <piotr@owncloud.com>
- *
- * @copyright Copyright (c) 2019, ownCloud GmbH
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2019-2022 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Share20;
diff --git a/lib/private/Share20/ShareDisableChecker.php b/lib/private/Share20/ShareDisableChecker.php
new file mode 100644
index 00000000000..9b8bc01558c
--- /dev/null
+++ b/lib/private/Share20/ShareDisableChecker.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Share20;
+
+use OCP\Cache\CappedMemoryCache;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IUserManager;
+
+/**
+ * split of from the share manager to allow using it with minimal DI
+ */
+class ShareDisableChecker {
+ private CappedMemoryCache $sharingDisabledForUsersCache;
+
+ public function __construct(
+ private IConfig $config,
+ private IUserManager $userManager,
+ private IGroupManager $groupManager,
+ ) {
+ $this->sharingDisabledForUsersCache = new CappedMemoryCache();
+ }
+
+
+ /**
+ * @param ?string $userId
+ * @return bool
+ */
+ public function sharingDisabledForUser(?string $userId) {
+ if ($userId === null) {
+ return false;
+ }
+
+ if (isset($this->sharingDisabledForUsersCache[$userId])) {
+ return $this->sharingDisabledForUsersCache[$userId];
+ }
+
+ $excludeGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no');
+
+ if ($excludeGroups && $excludeGroups !== 'no') {
+ $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
+ $excludedGroups = json_decode($groupsList);
+ if (is_null($excludedGroups)) {
+ $excludedGroups = explode(',', $groupsList);
+ $newValue = json_encode($excludedGroups);
+ $this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
+ }
+ $user = $this->userManager->get($userId);
+ if (!$user) {
+ return false;
+ }
+ $usersGroups = $this->groupManager->getUserGroupIds($user);
+ if ($excludeGroups !== 'allow') {
+ if (!empty($usersGroups)) {
+ $remainingGroups = array_diff($usersGroups, $excludedGroups);
+ // if the user is only in groups which are disabled for sharing then
+ // sharing is also disabled for the user
+ if (empty($remainingGroups)) {
+ $this->sharingDisabledForUsersCache[$userId] = true;
+ return true;
+ }
+ }
+ } else {
+ if (!empty($usersGroups)) {
+ $remainingGroups = array_intersect($usersGroups, $excludedGroups);
+ // if the user is in any group which is allowed for sharing then
+ // sharing is also allowed for the user
+ if (!empty($remainingGroups)) {
+ $this->sharingDisabledForUsersCache[$userId] = false;
+ return false;
+ }
+ }
+ $this->sharingDisabledForUsersCache[$userId] = true;
+ return true;
+ }
+ }
+
+ $this->sharingDisabledForUsersCache[$userId] = false;
+ return false;
+ }
+}
diff --git a/lib/private/Share20/ShareHelper.php b/lib/private/Share20/ShareHelper.php
index 3debfe185e0..d4a54f1d687 100644
--- a/lib/private/Share20/ShareHelper.php
+++ b/lib/private/Share20/ShareHelper.php
@@ -1,25 +1,7 @@
<?php
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Share20;
diff --git a/lib/private/Share20/UserRemovedListener.php b/lib/private/Share20/UserRemovedListener.php
index 3af7b5a3650..f06c945b591 100644
--- a/lib/private/Share20/UserRemovedListener.php
+++ b/lib/private/Share20/UserRemovedListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Share20;
diff --git a/lib/private/SpeechToText/SpeechToTextManager.php b/lib/private/SpeechToText/SpeechToTextManager.php
index bdd04ad3651..d6cda473875 100644
--- a/lib/private/SpeechToText/SpeechToTextManager.php
+++ b/lib/private/SpeechToText/SpeechToTextManager.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Julius Härtl <jus@bitgrid.net>
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -36,9 +18,12 @@ use OCP\Files\InvalidPathException;
use OCP\Files\NotFoundException;
use OCP\IConfig;
use OCP\IServerContainer;
+use OCP\IUserSession;
use OCP\PreConditionNotMetException;
use OCP\SpeechToText\ISpeechToTextManager;
use OCP\SpeechToText\ISpeechToTextProvider;
+use OCP\SpeechToText\ISpeechToTextProviderWithId;
+use OCP\SpeechToText\ISpeechToTextProviderWithUserId;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
@@ -55,6 +40,7 @@ class SpeechToTextManager implements ISpeechToTextManager {
private LoggerInterface $logger,
private IJobList $jobList,
private IConfig $config,
+ private IUserSession $userSession,
) {
}
@@ -108,6 +94,24 @@ class SpeechToTextManager implements ISpeechToTextManager {
}
}
+ public function cancelScheduledFileTranscription(File $file, ?string $userId, string $appId): void {
+ try {
+ $jobArguments = [
+ 'fileId' => $file->getId(),
+ 'owner' => $file->getOwner()->getUID(),
+ 'userId' => $userId,
+ 'appId' => $appId,
+ ];
+ if (!$this->jobList->has(TranscriptionJob::class, $jobArguments)) {
+ $this->logger->debug('Failed to cancel a Speech-to-text job for file ' . $file->getId() . '. No related job was found.');
+ return;
+ }
+ $this->jobList->remove(TranscriptionJob::class, $jobArguments);
+ } catch (NotFoundException|InvalidPathException $e) {
+ throw new InvalidArgumentException('Invalid file provided to cancel file transcription: ' . $e->getMessage());
+ }
+ }
+
public function transcribeFile(File $file): string {
if (!$this->hasProviders()) {
throw new PreConditionNotMetException('No SpeechToText providers have been registered');
@@ -117,8 +121,13 @@ class SpeechToTextManager implements ISpeechToTextManager {
$json = $this->config->getAppValue('core', 'ai.stt_provider', '');
if ($json !== '') {
- $className = json_decode($json, true);
- $provider = current(array_filter($providers, fn ($provider) => $provider::class === $className));
+ $classNameOrId = json_decode($json, true);
+ $provider = current(array_filter($providers, function ($provider) use ($classNameOrId) {
+ if ($provider instanceof ISpeechToTextProviderWithId) {
+ return $provider->getId() === $classNameOrId;
+ }
+ return $provider::class === $classNameOrId;
+ }));
if ($provider !== false) {
$providers = [$provider];
}
@@ -126,9 +135,13 @@ class SpeechToTextManager implements ISpeechToTextManager {
foreach ($providers as $provider) {
try {
+ if ($provider instanceof ISpeechToTextProviderWithUserId) {
+ $provider->setUserId($this->userSession->getUser()?->getUID());
+ }
return $provider->transcribeFile($file);
} catch (\Throwable $e) {
$this->logger->info('SpeechToText transcription using provider ' . $provider->getName() . ' failed', ['exception' => $e]);
+ throw new RuntimeException('SpeechToText transcription using provider "' . $provider->getName() . '" failed: ' . $e->getMessage());
}
}
diff --git a/lib/private/SpeechToText/TranscriptionJob.php b/lib/private/SpeechToText/TranscriptionJob.php
index 8921d52ecd1..a46fd737865 100644
--- a/lib/private/SpeechToText/TranscriptionJob.php
+++ b/lib/private/SpeechToText/TranscriptionJob.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -65,7 +49,7 @@ class TranscriptionJob extends QueuedJob {
try {
\OC_Util::setupFS($owner);
$userFolder = $this->rootFolder->getUserFolder($owner);
- $file = current($userFolder->getById($fileId));
+ $file = $userFolder->getFirstNodeById($fileId);
if (!($file instanceof File)) {
$this->logger->warning('Transcription of file ' . $fileId . ' failed. The file could not be found');
$this->eventDispatcher->dispatchTyped(
diff --git a/lib/private/StreamImage.php b/lib/private/StreamImage.php
index 33078310d27..9290bf38b0f 100644
--- a/lib/private/StreamImage.php
+++ b/lib/private/StreamImage.php
@@ -1,30 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2021 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC;
-use OCP\IStreamImage;
use OCP\IImage;
+use OCP\IStreamImage;
/**
* Only useful when dealing with transferring streamed previews from an external
diff --git a/lib/private/Streamer.php b/lib/private/Streamer.php
index aafd3d95dfb..4eca1105002 100644
--- a/lib/private/Streamer.php
+++ b/lib/private/Streamer.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author szaimen <szaimen@e.mail.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -32,6 +11,7 @@ use OC\Files\Filesystem;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\InvalidPathException;
+use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IRequest;
@@ -118,7 +98,7 @@ class Streamer {
// prevent absolute dirs
$internalDir = ltrim($internalDir, '/');
- $userFolder = \OC::$server->getRootFolder()->get(Filesystem::getRoot());
+ $userFolder = \OC::$server->get(IRootFolder::class)->get(Filesystem::getRoot());
/** @var Folder $dirNode */
$dirNode = $userFolder->get($dir);
$files = $dirNode->getDirectoryListing();
diff --git a/lib/private/SubAdmin.php b/lib/private/SubAdmin.php
index 54f14b8ab88..9ffa0ab03a3 100644
--- a/lib/private/SubAdmin.php
+++ b/lib/private/SubAdmin.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Mikael Hammarin <mikael@try2.se>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -60,9 +37,9 @@ class SubAdmin extends PublicEmitter implements ISubAdmin {
* @param IDBConnection $dbConn
*/
public function __construct(IUserManager $userManager,
- IGroupManager $groupManager,
- IDBConnection $dbConn,
- IEventDispatcher $eventDispatcher) {
+ IGroupManager $groupManager,
+ IDBConnection $dbConn,
+ IEventDispatcher $eventDispatcher) {
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->dbConn = $dbConn;
diff --git a/lib/private/Support/CrashReport/Registry.php b/lib/private/Support/CrashReport/Registry.php
index f2a35069288..93969a81265 100644
--- a/lib/private/Support/CrashReport/Registry.php
+++ b/lib/private/Support/CrashReport/Registry.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Support\CrashReport;
diff --git a/lib/private/Support/Subscription/Assertion.php b/lib/private/Support/Subscription/Assertion.php
index 451afe83bd3..04a0dde739f 100644
--- a/lib/private/Support/Subscription/Assertion.php
+++ b/lib/private/Support/Subscription/Assertion.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2022 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Support\Subscription;
use OCP\HintException;
diff --git a/lib/private/Support/Subscription/Registry.php b/lib/private/Support/Subscription/Registry.php
index eba76ca103e..3d3daa97abb 100644
--- a/lib/private/Support/Subscription/Registry.php
+++ b/lib/private/Support/Subscription/Registry.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Support\Subscription;
@@ -62,10 +43,10 @@ class Registry implements IRegistry {
private $logger;
public function __construct(IConfig $config,
- IServerContainer $container,
- IUserManager $userManager,
- IGroupManager $groupManager,
- LoggerInterface $logger) {
+ IServerContainer $container,
+ IUserManager $userManager,
+ IGroupManager $groupManager,
+ LoggerInterface $logger) {
$this->config = $config;
$this->container = $container;
$this->userManager = $userManager;
@@ -239,7 +220,7 @@ class Registry implements IRegistry {
$notificationManager->notify($notification);
}
- $this->logger->warning('The user limit was reached and the new user was not created', ['app' => 'lib']);
+ $this->logger->warning('The account limit was reached and the new account was not created', ['app' => 'lib']);
}
protected function reIssue(): bool {
diff --git a/lib/private/SystemConfig.php b/lib/private/SystemConfig.php
index a18c4c2a138..310433474ec 100644
--- a/lib/private/SystemConfig.php
+++ b/lib/private/SystemConfig.php
@@ -1,28 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Schlichenmaier <johannes@schlichenmaier.info>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -42,6 +23,7 @@ class SystemConfig {
'dbhost' => true,
'dbpassword' => true,
'dbuser' => true,
+ 'dbreplica' => true,
'activity_dbname' => true,
'activity_dbhost' => true,
'activity_dbpassword' => true,
@@ -54,7 +36,10 @@ class SystemConfig {
'passwordsalt' => true,
'secret' => true,
'updater.secret' => true,
+ 'updater.server.url' => true,
'trusted_proxies' => true,
+ 'preview_imaginary_url' => true,
+ 'preview_imaginary_key' => true,
'proxyuserpwd' => true,
'sentry.dsn' => true,
'sentry.public-dsn' => true,
@@ -118,13 +103,14 @@ class SystemConfig {
],
],
],
+ 'onlyoffice' => [
+ 'jwt_secret' => true,
+ ],
];
- /** @var Config */
- private $config;
-
- public function __construct(Config $config) {
- $this->config = $config;
+ public function __construct(
+ private Config $config,
+ ) {
}
/**
diff --git a/lib/private/SystemTag/ManagerFactory.php b/lib/private/SystemTag/ManagerFactory.php
index 6670922407e..0fd2ca5fd36 100644
--- a/lib/private/SystemTag/ManagerFactory.php
+++ b/lib/private/SystemTag/ManagerFactory.php
@@ -1,28 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\SystemTag;
@@ -40,25 +22,16 @@ use OCP\SystemTag\ISystemTagObjectMapper;
*/
class ManagerFactory implements ISystemTagManagerFactory {
/**
- * Server container
- *
- * @var IServerContainer
- */
- private $serverContainer;
-
- /**
* Constructor for the system tag manager factory
- *
- * @param IServerContainer $serverContainer server container
*/
- public function __construct(IServerContainer $serverContainer) {
- $this->serverContainer = $serverContainer;
+ public function __construct(
+ private IServerContainer $serverContainer,
+ ) {
}
/**
* Creates and returns an instance of the system tag manager
*
- * @return ISystemTagManager
* @since 9.0.0
*/
public function getManager(): ISystemTagManager {
@@ -73,7 +46,6 @@ class ManagerFactory implements ISystemTagManagerFactory {
* Creates and returns an instance of the system tag object
* mapper
*
- * @return ISystemTagObjectMapper
* @since 9.0.0
*/
public function getObjectMapper(): ISystemTagObjectMapper {
diff --git a/lib/private/SystemTag/SystemTag.php b/lib/private/SystemTag/SystemTag.php
index da6d4bd4b11..83fb6bc7f93 100644
--- a/lib/private/SystemTag/SystemTag.php
+++ b/lib/private/SystemTag/SystemTag.php
@@ -1,68 +1,22 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Leuker <j.leuker@hosting.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\SystemTag;
use OCP\SystemTag\ISystemTag;
class SystemTag implements ISystemTag {
- /**
- * @var string
- */
- private $id;
-
- /**
- * @var string
- */
- private $name;
-
- /**
- * @var bool
- */
- private $userVisible;
-
- /**
- * @var bool
- */
- private $userAssignable;
-
- /**
- * Constructor.
- *
- * @param string $id tag id
- * @param string $name tag name
- * @param bool $userVisible whether the tag is user visible
- * @param bool $userAssignable whether the tag is user assignable
- */
- public function __construct(string $id, string $name, bool $userVisible, bool $userAssignable) {
- $this->id = $id;
- $this->name = $name;
- $this->userVisible = $userVisible;
- $this->userAssignable = $userAssignable;
+ public function __construct(
+ private string $id,
+ private string $name,
+ private bool $userVisible,
+ private bool $userAssignable,
+ ) {
}
/**
@@ -97,14 +51,14 @@ class SystemTag implements ISystemTag {
* {@inheritdoc}
*/
public function getAccessLevel(): int {
- if ($this->userVisible) {
- if ($this->userAssignable) {
- return self::ACCESS_LEVEL_PUBLIC;
- } else {
- return self::ACCESS_LEVEL_RESTRICTED;
- }
- } else {
+ if (!$this->userVisible) {
return self::ACCESS_LEVEL_INVISIBLE;
}
+
+ if (!$this->userAssignable) {
+ return self::ACCESS_LEVEL_RESTRICTED;
+ }
+
+ return self::ACCESS_LEVEL_PUBLIC;
}
}
diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php
index c52c350b6f8..e99213b618b 100644
--- a/lib/private/SystemTag/SystemTagManager.php
+++ b/lib/private/SystemTag/SystemTagManager.php
@@ -1,31 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\SystemTag;
@@ -50,10 +29,8 @@ class SystemTagManager implements ISystemTagManager {
/**
* Prepared query for selecting tags directly
- *
- * @var \OCP\DB\QueryBuilder\IQueryBuilder
*/
- private $selectTagQuery;
+ private IQueryBuilder $selectTagQuery;
public function __construct(
protected IDBConnection $connection,
@@ -219,7 +196,12 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function updateTag(string $tagId, string $newName, bool $userVisible, bool $userAssignable) {
+ public function updateTag(
+ string $tagId,
+ string $newName,
+ bool $userVisible,
+ bool $userAssignable,
+ ): void {
try {
$tags = $this->getTagsByIds($tagId);
} catch (TagNotFoundException $e) {
@@ -271,7 +253,7 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function deleteTags($tagIds) {
+ public function deleteTags($tagIds): void {
if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -363,14 +345,14 @@ class SystemTagManager implements ISystemTagManager {
return false;
}
- private function createSystemTagFromRow($row) {
+ private function createSystemTagFromRow($row): SystemTag {
return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']);
}
/**
* {@inheritdoc}
*/
- public function setTagGroups(ISystemTag $tag, array $groupIds) {
+ public function setTagGroups(ISystemTag $tag, array $groupIds): void {
// delete relationships first
$this->connection->beginTransaction();
try {
diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php
index 66a21e58609..58a9e6a23da 100644
--- a/lib/private/SystemTag/SystemTagObjectMapper.php
+++ b/lib/private/SystemTag/SystemTagObjectMapper.php
@@ -3,27 +3,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\SystemTag;
@@ -81,7 +63,6 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
$result->closeCursor();
}
-
return $mapping;
}
@@ -128,7 +109,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function assignTags(string $objId, string $objectType, $tagIds) {
+ public function assignTags(string $objId, string $objectType, $tagIds): void {
if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -169,7 +150,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function unassignTags(string $objId, string $objectType, $tagIds) {
+ public function unassignTags(string $objId, string $objectType, $tagIds): void {
if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -241,7 +222,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
*
* @throws \OCP\SystemTag\TagNotFoundException if at least one tag did not exist
*/
- private function assertTagsExist($tagIds) {
+ private function assertTagsExist(array $tagIds): void {
$tags = $this->tagManager->getTagsByIds($tagIds);
if (\count($tags) !== \count($tagIds)) {
// at least one tag missing, bail out
diff --git a/lib/private/SystemTag/SystemTagsInFilesDetector.php b/lib/private/SystemTag/SystemTagsInFilesDetector.php
index c9f26c58c02..a8dfec264a0 100644
--- a/lib/private/SystemTag/SystemTagsInFilesDetector.php
+++ b/lib/private/SystemTag/SystemTagsInFilesDetector.php
@@ -1,29 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2023 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\SystemTag;
use OC\Files\Cache\QuerySearchHelper;
@@ -36,7 +17,9 @@ use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
class SystemTagsInFilesDetector {
- public function __construct(protected QuerySearchHelper $searchHelper) {
+ public function __construct(
+ protected QuerySearchHelper $searchHelper,
+ ) {
}
public function detectAssignedSystemTagsIn(
diff --git a/lib/private/TagManager.php b/lib/private/TagManager.php
index 82c4dd2188d..3258ce50bc5 100644
--- a/lib/private/TagManager.php
+++ b/lib/private/TagManager.php
@@ -1,32 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Reiter <ockham@raz.or.at>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
use OC\Tagging\TagMapper;
+use OCP\Db\Exception as DBException;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
@@ -35,7 +17,6 @@ use OCP\ITagManager;
use OCP\ITags;
use OCP\IUserSession;
use OCP\User\Events\UserDeletedEvent;
-use OCP\Db\Exception as DBException;
use Psr\Log\LoggerInterface;
/**
diff --git a/lib/private/Tagging/Tag.php b/lib/private/Tagging/Tag.php
index 17af385418d..ae770beb62f 100644
--- a/lib/private/Tagging/Tag.php
+++ b/lib/private/Tagging/Tag.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Reiter <ockham@raz.or.at>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Tagging;
diff --git a/lib/private/Tagging/TagMapper.php b/lib/private/Tagging/TagMapper.php
index 1ee9c33acf7..efac45a2e3a 100644
--- a/lib/private/Tagging/TagMapper.php
+++ b/lib/private/Tagging/TagMapper.php
@@ -1,34 +1,16 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bernhard Reiter <ockham@raz.or.at>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Tagging;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
-use OCP\IDBConnection;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
/**
* Mapper for Tag entity
diff --git a/lib/private/Tags.php b/lib/private/Tags.php
index 8da1e7edc3b..420cabc36b9 100644
--- a/lib/private/Tags.php
+++ b/lib/private/Tags.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bernhard Reiter <ockham@raz.or.at>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -35,7 +12,6 @@ use OC\Tagging\TagMapper;
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
-use OCP\ILogger;
use OCP\ITags;
use OCP\Share_Backend;
use Psr\Log\LoggerInterface;
@@ -235,7 +211,7 @@ class Tags implements ITags {
}
if ($tagId === false) {
- $l10n = \OC::$server->getL10N('core');
+ $l10n = \OCP\Util::getL10N('core');
throw new \Exception(
$l10n->t('Could not find category "%s"', [$tag])
);
@@ -486,11 +462,13 @@ class Tags implements ITags {
try {
return $this->getIdsForTag(ITags::TAG_FAVORITE);
} catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, [
- 'message' => __METHOD__,
- 'level' => ILogger::ERROR,
- 'app' => 'core',
- ]);
+ \OCP\Server::get(LoggerInterface::class)->error(
+ $e->getMessage(),
+ [
+ 'app' => 'core',
+ 'exception' => $e,
+ ]
+ );
return [];
}
}
@@ -529,7 +507,7 @@ class Tags implements ITags {
if (is_string($tag) && !is_numeric($tag)) {
$tag = trim($tag);
if ($tag === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
+ $this->logger->debug(__METHOD__.', Cannot add an empty tag');
return false;
}
if (!$this->hasTag($tag)) {
@@ -549,7 +527,7 @@ class Tags implements ITags {
try {
$qb->executeStatement();
} catch (\Exception $e) {
- \OC::$server->getLogger()->error($e->getMessage(), [
+ \OCP\Server::get(LoggerInterface::class)->error($e->getMessage(), [
'app' => 'core',
'exception' => $e,
]);
@@ -569,7 +547,7 @@ class Tags implements ITags {
if (is_string($tag) && !is_numeric($tag)) {
$tag = trim($tag);
if ($tag === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
+ $this->logger->debug(__METHOD__.', Tag name is empty');
return false;
}
$tagId = $this->getTagId($tag);
@@ -609,8 +587,7 @@ class Tags implements ITags {
$names = array_map('trim', $names);
array_filter($names);
- \OCP\Util::writeLog('core', __METHOD__ . ', before: '
- . print_r($this->tags, true), ILogger::DEBUG);
+ $this->logger->debug(__METHOD__ . ', before: ' . print_r($this->tags, true));
foreach ($names as $name) {
$id = null;
@@ -625,8 +602,7 @@ class Tags implements ITags {
unset($this->tags[$key]);
$this->mapper->delete($tag);
} else {
- \OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
- . ': not found.', ILogger::ERROR);
+ $this->logger->error(__METHOD__ . 'Cannot delete tag ' . $name . ': not found.');
}
if (!is_null($id) && $id !== false) {
try {
diff --git a/lib/private/Talk/Broker.php b/lib/private/Talk/Broker.php
index 12e6c5fb34b..fc8e0280043 100644
--- a/lib/private/Talk/Broker.php
+++ b/lib/private/Talk/Broker.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Talk;
@@ -48,8 +32,8 @@ class Broker implements IBroker {
private ?ITalkBackend $backend = null;
public function __construct(Coordinator $coordinator,
- IServerContainer $container,
- LoggerInterface $logger) {
+ IServerContainer $container,
+ LoggerInterface $logger) {
$this->coordinator = $coordinator;
$this->container = $container;
$this->logger = $logger;
@@ -94,8 +78,8 @@ class Broker implements IBroker {
}
public function createConversation(string $name,
- array $moderators,
- IConversationOptions $options = null): IConversation {
+ array $moderators,
+ ?IConversationOptions $options = null): IConversation {
if (!$this->hasBackend()) {
throw new NoBackendException("The Talk broker has no registered backend");
}
diff --git a/lib/private/Talk/ConversationOptions.php b/lib/private/Talk/ConversationOptions.php
index f86c8d037d3..f167fa6d164 100644
--- a/lib/private/Talk/ConversationOptions.php
+++ b/lib/private/Talk/ConversationOptions.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
-/*
- * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Talk;
diff --git a/lib/private/TaskProcessing/Db/Task.php b/lib/private/TaskProcessing/Db/Task.php
new file mode 100644
index 00000000000..1ac40327899
--- /dev/null
+++ b/lib/private/TaskProcessing/Db/Task.php
@@ -0,0 +1,119 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\TaskProcessing\Db;
+
+use OCP\AppFramework\Db\Entity;
+use OCP\TaskProcessing\Task as OCPTask;
+
+/**
+ * @method setType(string $type)
+ * @method string getType()
+ * @method setLastUpdated(int $lastUpdated)
+ * @method int getLastUpdated()
+ * @method setStatus(int $status)
+ * @method int getStatus()
+ * @method setOutput(string $output)
+ * @method string getOutput()
+ * @method setInput(string $input)
+ * @method string getInput()
+ * @method setUserId(?string $userId)
+ * @method string|null getUserId()
+ * @method setAppId(string $type)
+ * @method string getAppId()
+ * @method setCustomId(string $customId)
+ * @method string getCustomId()
+ * @method setCompletionExpectedAt(null|\DateTime $completionExpectedAt)
+ * @method null|\DateTime getCompletionExpectedAt()
+ * @method setErrorMessage(null|string $error)
+ * @method null|string getErrorMessage()
+ * @method setProgress(null|float $progress)
+ * @method null|float getProgress()
+ */
+class Task extends Entity {
+ protected $lastUpdated;
+ protected $type;
+ protected $input;
+ protected $output;
+ protected $status;
+ protected $userId;
+ protected $appId;
+ protected $customId;
+ protected $completionExpectedAt;
+ protected $errorMessage;
+ protected $progress;
+
+ /**
+ * @var string[]
+ */
+ public static array $columns = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'custom_id', 'completion_expected_at', 'error_message', 'progress'];
+
+ /**
+ * @var string[]
+ */
+ public static array $fields = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'customId', 'completionExpectedAt', 'errorMessage', 'progress'];
+
+
+ public function __construct() {
+ // add types in constructor
+ $this->addType('id', 'integer');
+ $this->addType('lastUpdated', 'integer');
+ $this->addType('type', 'string');
+ $this->addType('input', 'string');
+ $this->addType('output', 'string');
+ $this->addType('status', 'integer');
+ $this->addType('userId', 'string');
+ $this->addType('appId', 'string');
+ $this->addType('customId', 'string');
+ $this->addType('completionExpectedAt', 'datetime');
+ $this->addType('errorMessage', 'string');
+ $this->addType('progress', 'float');
+ }
+
+ public function toRow(): array {
+ return array_combine(self::$columns, array_map(function ($field) {
+ return $this->{'get'.ucfirst($field)}();
+ }, self::$fields));
+ }
+
+ public static function fromPublicTask(OCPTask $task): self {
+ /** @var Task $taskEntity */
+ $taskEntity = self::fromParams([
+ 'id' => $task->getId(),
+ 'type' => $task->getTaskTypeId(),
+ 'lastUpdated' => time(),
+ 'status' => $task->getStatus(),
+ 'input' => json_encode($task->getInput(), JSON_THROW_ON_ERROR),
+ 'output' => json_encode($task->getOutput(), JSON_THROW_ON_ERROR),
+ 'errorMessage' => $task->getErrorMessage(),
+ 'userId' => $task->getUserId(),
+ 'appId' => $task->getAppId(),
+ 'customId' => $task->getCustomId(),
+ 'completionExpectedAt' => $task->getCompletionExpectedAt(),
+ 'progress' => $task->getProgress(),
+ ]);
+ return $taskEntity;
+ }
+
+ /**
+ * @return OCPTask
+ * @throws \JsonException
+ */
+ public function toPublicTask(): OCPTask {
+ $task = new OCPTask($this->getType(), json_decode($this->getInput(), true, 512, JSON_THROW_ON_ERROR), $this->getAppId(), $this->getuserId(), $this->getCustomId());
+ $task->setId($this->getId());
+ $task->setStatus($this->getStatus());
+ $task->setLastUpdated($this->getLastUpdated());
+ $task->setOutput(json_decode($this->getOutput(), true, 512, JSON_THROW_ON_ERROR));
+ $task->setCompletionExpectedAt($this->getCompletionExpectedAt());
+ $task->setErrorMessage($this->getErrorMessage());
+ $task->setProgress($this->getProgress());
+ return $task;
+ }
+}
diff --git a/lib/private/TaskProcessing/Db/TaskMapper.php b/lib/private/TaskProcessing/Db/TaskMapper.php
new file mode 100644
index 00000000000..e66c62007cc
--- /dev/null
+++ b/lib/private/TaskProcessing/Db/TaskMapper.php
@@ -0,0 +1,143 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\TaskProcessing\Db;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\Entity;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\DB\Exception;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+/**
+ * @extends QBMapper<Task>
+ */
+class TaskMapper extends QBMapper {
+ public function __construct(
+ IDBConnection $db,
+ private ITimeFactory $timeFactory,
+ ) {
+ parent::__construct($db, 'taskprocessing_tasks', Task::class);
+ }
+
+ /**
+ * @param int $id
+ * @return Task
+ * @throws Exception
+ * @throws DoesNotExistException
+ * @throws MultipleObjectsReturnedException
+ */
+ public function find(int $id): Task {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @param string|null $taskType
+ * @return Task
+ * @throws DoesNotExistException
+ * @throws Exception
+ */
+ public function findOldestScheduledByType(?string $taskType): Task {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('status', $qb->createPositionalParameter(\OCP\TaskProcessing\Task::STATUS_SCHEDULED, IQueryBuilder::PARAM_INT)))
+ ->setMaxResults(1)
+ ->orderBy('last_updated', 'ASC');
+ if ($taskType !== null) {
+ $qb->andWhere($qb->expr()->eq('type', $qb->createPositionalParameter($taskType)));
+ }
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @param int $id
+ * @param string|null $userId
+ * @return Task
+ * @throws DoesNotExistException
+ * @throws Exception
+ * @throws MultipleObjectsReturnedException
+ */
+ public function findByIdAndUser(int $id, ?string $userId): Task {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
+ if ($userId === null) {
+ $qb->andWhere($qb->expr()->isNull('user_id'));
+ } else {
+ $qb->andWhere($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)));
+ }
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @param string|null $userId
+ * @param string|null $taskType
+ * @param string|null $customId
+ * @return list<Task>
+ * @throws Exception
+ */
+ public function findByUserAndTaskType(?string $userId, ?string $taskType = null, ?string $customId = null): array {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)));
+ if ($taskType !== null) {
+ $qb->andWhere($qb->expr()->eq('type', $qb->createPositionalParameter($taskType)));
+ }
+ if ($customId !== null) {
+ $qb->andWhere($qb->expr()->eq('custom_id', $qb->createPositionalParameter($customId)));
+ }
+ return array_values($this->findEntities($qb));
+ }
+
+ /**
+ * @param string $userId
+ * @param string $appId
+ * @param string|null $customId
+ * @return list<Task>
+ * @throws Exception
+ */
+ public function findUserTasksByApp(?string $userId, string $appId, ?string $customId = null): array {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)))
+ ->andWhere($qb->expr()->eq('app_id', $qb->createPositionalParameter($appId)));
+ if ($customId !== null) {
+ $qb->andWhere($qb->expr()->eq('custom_id', $qb->createPositionalParameter($customId)));
+ }
+ return array_values($this->findEntities($qb));
+ }
+
+ /**
+ * @param int $timeout
+ * @return int the number of deleted tasks
+ * @throws Exception
+ */
+ public function deleteOlderThan(int $timeout): int {
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete($this->tableName)
+ ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($this->timeFactory->getDateTime()->getTimestamp() - $timeout)));
+ return $qb->executeStatement();
+ }
+
+ public function update(Entity $entity): Entity {
+ $entity->setLastUpdated($this->timeFactory->now()->getTimestamp());
+ return parent::update($entity);
+ }
+}
diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php
new file mode 100644
index 00000000000..7dfdafe0d14
--- /dev/null
+++ b/lib/private/TaskProcessing/Manager.php
@@ -0,0 +1,866 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\TaskProcessing;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\Files\SimpleFS\SimpleFile;
+use OC\TaskProcessing\Db\TaskMapper;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\BackgroundJob\IJobList;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\File;
+use OCP\Files\GenericFileException;
+use OCP\Files\IAppData;
+use OCP\Files\IRootFolder;
+use OCP\Files\NotPermittedException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\IL10N;
+use OCP\IServerContainer;
+use OCP\L10N\IFactory;
+use OCP\Lock\LockedException;
+use OCP\SpeechToText\ISpeechToTextProvider;
+use OCP\SpeechToText\ISpeechToTextProviderWithId;
+use OCP\TaskProcessing\EShapeType;
+use OCP\TaskProcessing\Events\TaskFailedEvent;
+use OCP\TaskProcessing\Events\TaskSuccessfulEvent;
+use OCP\TaskProcessing\Exception\NotFoundException;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\Exception\UnauthorizedException;
+use OCP\TaskProcessing\Exception\ValidationException;
+use OCP\TaskProcessing\IManager;
+use OCP\TaskProcessing\IProvider;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\ITaskType;
+use OCP\TaskProcessing\ShapeDescriptor;
+use OCP\TaskProcessing\Task;
+use OCP\TaskProcessing\TaskTypes\AudioToText;
+use OCP\TaskProcessing\TaskTypes\TextToImage;
+use OCP\TaskProcessing\TaskTypes\TextToText;
+use OCP\TaskProcessing\TaskTypes\TextToTextHeadline;
+use OCP\TaskProcessing\TaskTypes\TextToTextSummary;
+use OCP\TaskProcessing\TaskTypes\TextToTextTopics;
+use Psr\Log\LoggerInterface;
+
+class Manager implements IManager {
+
+ public const LEGACY_PREFIX_TEXTPROCESSING = 'legacy:TextProcessing:';
+ public const LEGACY_PREFIX_TEXTTOIMAGE = 'legacy:TextToImage:';
+ public const LEGACY_PREFIX_SPEECHTOTEXT = 'legacy:SpeechToText:';
+
+ /** @var list<IProvider>|null */
+ private ?array $providers = null;
+
+ /** @var array<string,array{name: string, description: string, inputShape: array<string, ShapeDescriptor>, optionalInputShape: array<string, ShapeDescriptor>, outputShape: array<string, ShapeDescriptor>, optionalOutputShape: array<string, ShapeDescriptor>}>|null */
+ private ?array $availableTaskTypes = null;
+
+ private IAppData $appData;
+
+ public function __construct(
+ private Coordinator $coordinator,
+ private IServerContainer $serverContainer,
+ private LoggerInterface $logger,
+ private TaskMapper $taskMapper,
+ private IJobList $jobList,
+ private IEventDispatcher $dispatcher,
+ IAppDataFactory $appDataFactory,
+ private IRootFolder $rootFolder,
+ private \OCP\TextProcessing\IManager $textProcessingManager,
+ private \OCP\TextToImage\IManager $textToImageManager,
+ private \OCP\SpeechToText\ISpeechToTextManager $speechToTextManager,
+ private \OCP\Share\IManager $shareManager,
+ ) {
+ $this->appData = $appDataFactory->get('core');
+ }
+
+ /**
+ * @return IProvider[]
+ */
+ private function _getTextProcessingProviders(): array {
+ $oldProviders = $this->textProcessingManager->getProviders();
+ $newProviders = [];
+ foreach ($oldProviders as $oldProvider) {
+ $provider = new class($oldProvider) implements IProvider, ISynchronousProvider {
+ private \OCP\TextProcessing\IProvider $provider;
+
+ public function __construct(\OCP\TextProcessing\IProvider $provider) {
+ $this->provider = $provider;
+ }
+
+ public function getId(): string {
+ if ($this->provider instanceof \OCP\TextProcessing\IProviderWithId) {
+ return $this->provider->getId();
+ }
+ return Manager::LEGACY_PREFIX_TEXTPROCESSING . $this->provider::class;
+ }
+
+ public function getName(): string {
+ return $this->provider->getName();
+ }
+
+ public function getTaskTypeId(): string {
+ return match ($this->provider->getTaskType()) {
+ \OCP\TextProcessing\FreePromptTaskType::class => TextToText::ID,
+ \OCP\TextProcessing\HeadlineTaskType::class => TextToTextHeadline::ID,
+ \OCP\TextProcessing\TopicsTaskType::class => TextToTextTopics::ID,
+ \OCP\TextProcessing\SummaryTaskType::class => TextToTextSummary::ID,
+ default => Manager::LEGACY_PREFIX_TEXTPROCESSING . $this->provider->getTaskType(),
+ };
+ }
+
+ public function getExpectedRuntime(): int {
+ if ($this->provider instanceof \OCP\TextProcessing\IProviderWithExpectedRuntime) {
+ return $this->provider->getExpectedRuntime();
+ }
+ return 60;
+ }
+
+ public function getOptionalInputShape(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if ($this->provider instanceof \OCP\TextProcessing\IProviderWithUserId) {
+ $this->provider->setUserId($userId);
+ }
+ try {
+ return ['output' => $this->provider->process($input['input'])];
+ } catch(\RuntimeException $e) {
+ throw new ProcessingException($e->getMessage(), 0, $e);
+ }
+ }
+ };
+ $newProviders[$provider->getId()] = $provider;
+ }
+
+ return $newProviders;
+ }
+
+ /**
+ * @return ITaskType[]
+ */
+ private function _getTextProcessingTaskTypes(): array {
+ $oldProviders = $this->textProcessingManager->getProviders();
+ $newTaskTypes = [];
+ foreach ($oldProviders as $oldProvider) {
+ // These are already implemented in the TaskProcessing realm
+ if (in_array($oldProvider->getTaskType(), [
+ \OCP\TextProcessing\FreePromptTaskType::class,
+ \OCP\TextProcessing\HeadlineTaskType::class,
+ \OCP\TextProcessing\TopicsTaskType::class,
+ \OCP\TextProcessing\SummaryTaskType::class
+ ], true)) {
+ continue;
+ }
+ $taskType = new class($oldProvider->getTaskType()) implements ITaskType {
+ private string $oldTaskTypeClass;
+ private \OCP\TextProcessing\ITaskType $oldTaskType;
+ private IL10N $l;
+
+ public function __construct(string $oldTaskTypeClass) {
+ $this->oldTaskTypeClass = $oldTaskTypeClass;
+ $this->oldTaskType = \OCP\Server::get($oldTaskTypeClass);
+ $this->l = \OCP\Server::get(IFactory::class)->get('core');
+ }
+
+ public function getId(): string {
+ return Manager::LEGACY_PREFIX_TEXTPROCESSING . $this->oldTaskTypeClass;
+ }
+
+ public function getName(): string {
+ return $this->oldTaskType->getName();
+ }
+
+ public function getDescription(): string {
+ return $this->oldTaskType->getDescription();
+ }
+
+ public function getInputShape(): array {
+ return ['input' => new ShapeDescriptor($this->l->t('Input text'), $this->l->t('The input text'), EShapeType::Text)];
+ }
+
+ public function getOutputShape(): array {
+ return ['output' => new ShapeDescriptor($this->l->t('Input text'), $this->l->t('The input text'), EShapeType::Text)];
+ }
+ };
+ $newTaskTypes[$taskType->getId()] = $taskType;
+ }
+
+ return $newTaskTypes;
+ }
+
+ /**
+ * @return IProvider[]
+ */
+ private function _getTextToImageProviders(): array {
+ $oldProviders = $this->textToImageManager->getProviders();
+ $newProviders = [];
+ foreach ($oldProviders as $oldProvider) {
+ $newProvider = new class($oldProvider, $this->appData) implements IProvider, ISynchronousProvider {
+ private \OCP\TextToImage\IProvider $provider;
+ private IAppData $appData;
+
+ public function __construct(\OCP\TextToImage\IProvider $provider, IAppData $appData) {
+ $this->provider = $provider;
+ $this->appData = $appData;
+ }
+
+ public function getId(): string {
+ return Manager::LEGACY_PREFIX_TEXTTOIMAGE . $this->provider->getId();
+ }
+
+ public function getName(): string {
+ return $this->provider->getName();
+ }
+
+ public function getTaskTypeId(): string {
+ return TextToImage::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return $this->provider->getExpectedRuntime();
+ }
+
+ public function getOptionalInputShape(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ try {
+ $folder = $this->appData->getFolder('text2image');
+ } catch(\OCP\Files\NotFoundException) {
+ $folder = $this->appData->newFolder('text2image');
+ }
+ $resources = [];
+ $files = [];
+ for ($i = 0; $i < $input['numberOfImages']; $i++) {
+ $file = $folder->newFile(time() . '-' . rand(1, 100000) . '-' . $i);
+ $files[] = $file;
+ $resource = $file->write();
+ if ($resource !== false && $resource !== true && is_resource($resource)) {
+ $resources[] = $resource;
+ } else {
+ throw new ProcessingException('Text2Image generation using provider "' . $this->getName() . '" failed: Couldn\'t open file to write.');
+ }
+ }
+ if ($this->provider instanceof \OCP\TextToImage\IProviderWithUserId) {
+ $this->provider->setUserId($userId);
+ }
+ try {
+ $this->provider->generate($input['input'], $resources);
+ } catch (\RuntimeException $e) {
+ throw new ProcessingException($e->getMessage(), 0, $e);
+ }
+ for ($i = 0; $i < $input['numberOfImages']; $i++) {
+ if (is_resource($resources[$i])) {
+ // If $resource hasn't been closed yet, we'll do that here
+ fclose($resources[$i]);
+ }
+ }
+ return ['images' => array_map(fn (ISimpleFile $file) => $file->getContent(), $files)];
+ }
+ };
+ $newProviders[$newProvider->getId()] = $newProvider;
+ }
+
+ return $newProviders;
+ }
+
+
+ /**
+ * @return IProvider[]
+ */
+ private function _getSpeechToTextProviders(): array {
+ $oldProviders = $this->speechToTextManager->getProviders();
+ $newProviders = [];
+ foreach ($oldProviders as $oldProvider) {
+ $newProvider = new class($oldProvider, $this->rootFolder, $this->appData) implements IProvider, ISynchronousProvider {
+ private ISpeechToTextProvider $provider;
+ private IAppData $appData;
+
+ private IRootFolder $rootFolder;
+
+ public function __construct(ISpeechToTextProvider $provider, IRootFolder $rootFolder, IAppData $appData) {
+ $this->provider = $provider;
+ $this->rootFolder = $rootFolder;
+ $this->appData = $appData;
+ }
+
+ public function getId(): string {
+ if ($this->provider instanceof ISpeechToTextProviderWithId) {
+ return Manager::LEGACY_PREFIX_SPEECHTOTEXT . $this->provider->getId();
+ }
+ return Manager::LEGACY_PREFIX_SPEECHTOTEXT . $this->provider::class;
+ }
+
+ public function getName(): string {
+ return $this->provider->getName();
+ }
+
+ public function getTaskTypeId(): string {
+ return AudioToText::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 60;
+ }
+
+ public function getOptionalInputShape(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ try {
+ $result = $this->provider->transcribeFile($input['input']);
+ } catch (\RuntimeException $e) {
+ throw new ProcessingException($e->getMessage(), 0, $e);
+ }
+ return ['output' => $result];
+ }
+ };
+ $newProviders[$newProvider->getId()] = $newProvider;
+ }
+
+ return $newProviders;
+ }
+
+ /**
+ * @return IProvider[]
+ */
+ private function _getProviders(): array {
+ $context = $this->coordinator->getRegistrationContext();
+
+ if ($context === null) {
+ return [];
+ }
+
+ $providers = [];
+
+ foreach ($context->getTaskProcessingProviders() as $providerServiceRegistration) {
+ $class = $providerServiceRegistration->getService();
+ try {
+ /** @var IProvider $provider */
+ $provider = $this->serverContainer->get($class);
+ if (isset($providers[$provider->getId()])) {
+ $this->logger->warning('Task processing provider ' . $class . ' is using ID ' . $provider->getId() . ' which is already used by ' . $providers[$provider->getId()]::class);
+ }
+ $providers[$provider->getId()] = $provider;
+ } catch (\Throwable $e) {
+ $this->logger->error('Failed to load task processing provider ' . $class, [
+ 'exception' => $e,
+ ]);
+ }
+ }
+
+ $providers += $this->_getTextProcessingProviders() + $this->_getTextToImageProviders() + $this->_getSpeechToTextProviders();
+
+ return $providers;
+ }
+
+ /**
+ * @return ITaskType[]
+ */
+ private function _getTaskTypes(): array {
+ $context = $this->coordinator->getRegistrationContext();
+
+ if ($context === null) {
+ return [];
+ }
+
+ // Default task types
+ $taskTypes = [
+ \OCP\TaskProcessing\TaskTypes\TextToText::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToText::class),
+ \OCP\TaskProcessing\TaskTypes\TextToTextTopics::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToTextTopics::class),
+ \OCP\TaskProcessing\TaskTypes\TextToTextHeadline::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToTextHeadline::class),
+ \OCP\TaskProcessing\TaskTypes\TextToTextSummary::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToTextSummary::class),
+ \OCP\TaskProcessing\TaskTypes\TextToImage::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToImage::class),
+ \OCP\TaskProcessing\TaskTypes\AudioToText::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\AudioToText::class),
+ ];
+
+ foreach ($context->getTaskProcessingTaskTypes() as $providerServiceRegistration) {
+ $class = $providerServiceRegistration->getService();
+ try {
+ /** @var ITaskType $provider */
+ $taskType = $this->serverContainer->get($class);
+ if (isset($taskTypes[$taskType->getId()])) {
+ $this->logger->warning('Task processing task type ' . $class . ' is using ID ' . $taskType->getId() . ' which is already used by ' . $taskTypes[$taskType->getId()]::class);
+ }
+ $taskTypes[$taskType->getId()] = $taskType;
+ } catch (\Throwable $e) {
+ $this->logger->error('Failed to load task processing task type ' . $class, [
+ 'exception' => $e,
+ ]);
+ }
+ }
+
+ $taskTypes += $this->_getTextProcessingTaskTypes();
+
+ return $taskTypes;
+ }
+
+ /**
+ * @param string $taskType
+ * @return IProvider
+ * @throws \OCP\TaskProcessing\Exception\Exception
+ */
+ private function _getPreferredProvider(string $taskType) {
+ $providers = $this->getProviders();
+ foreach ($providers as $provider) {
+ if ($provider->getTaskTypeId() === $taskType) {
+ return $provider;
+ }
+ }
+ throw new \OCP\TaskProcessing\Exception\Exception('No matching provider found');
+ }
+
+ /**
+ * @param ShapeDescriptor[] $spec
+ * @param array $io
+ * @return void
+ * @throws ValidationException
+ */
+ private function validateInput(array $spec, array $io, bool $optional = false): void {
+ foreach ($spec as $key => $descriptor) {
+ $type = $descriptor->getShapeType();
+ if (!isset($io[$key])) {
+ if ($optional) {
+ continue;
+ }
+ throw new ValidationException('Missing key: "' . $key . '"');
+ }
+ try {
+ $type->validateInput($io[$key]);
+ } catch (ValidationException $e) {
+ throw new ValidationException('Failed to validate input key "' . $key . '": ' . $e->getMessage());
+ }
+ }
+ }
+
+ /**
+ * @param ShapeDescriptor[] $spec
+ * @param array $io
+ * @param bool $optional
+ * @return void
+ * @throws ValidationException
+ */
+ private function validateOutput(array $spec, array $io, bool $optional = false): void {
+ foreach ($spec as $key => $descriptor) {
+ $type = $descriptor->getShapeType();
+ if (!isset($io[$key])) {
+ if ($optional) {
+ continue;
+ }
+ throw new ValidationException('Missing key: "' . $key . '"');
+ }
+ try {
+ $type->validateOutput($io[$key]);
+ } catch (ValidationException $e) {
+ throw new ValidationException('Failed to validate output key "' . $key . '": ' . $e->getMessage());
+ }
+ }
+ }
+
+ /**
+ * @param array<array-key, T> $array The array to filter
+ * @param ShapeDescriptor[] ...$specs the specs that define which keys to keep
+ * @return array<array-key, T>
+ * @psalm-template T
+ */
+ private function removeSuperfluousArrayKeys(array $array, ...$specs): array {
+ $keys = array_unique(array_reduce($specs, fn ($carry, $spec) => $carry + array_keys($spec), []));
+ $values = array_map(fn (string $key) => $array[$key], $keys);
+ return array_combine($keys, $values);
+ }
+
+ public function hasProviders(): bool {
+ return count($this->getProviders()) !== 0;
+ }
+
+ public function getProviders(): array {
+ if ($this->providers === null) {
+ $this->providers = $this->_getProviders();
+ }
+
+ return $this->providers;
+ }
+
+ public function getAvailableTaskTypes(): array {
+ if ($this->availableTaskTypes === null) {
+ $taskTypes = $this->_getTaskTypes();
+ $providers = $this->getProviders();
+
+ $availableTaskTypes = [];
+ foreach ($providers as $provider) {
+ if (!isset($taskTypes[$provider->getTaskTypeId()])) {
+ continue;
+ }
+ $taskType = $taskTypes[$provider->getTaskTypeId()];
+ $availableTaskTypes[$provider->getTaskTypeId()] = [
+ 'name' => $taskType->getName(),
+ 'description' => $taskType->getDescription(),
+ 'inputShape' => $taskType->getInputShape(),
+ 'optionalInputShape' => $provider->getOptionalInputShape(),
+ 'outputShape' => $taskType->getOutputShape(),
+ 'optionalOutputShape' => $provider->getOptionalOutputShape(),
+ ];
+ }
+
+ $this->availableTaskTypes = $availableTaskTypes;
+ }
+
+ return $this->availableTaskTypes;
+ }
+
+ public function canHandleTask(Task $task): bool {
+ return isset($this->getAvailableTaskTypes()[$task->getTaskTypeId()]);
+ }
+
+ public function scheduleTask(Task $task): void {
+ if (!$this->canHandleTask($task)) {
+ throw new \OCP\TaskProcessing\Exception\PreConditionNotMetException('No task processing provider is installed that can handle this task type: ' . $task->getTaskTypeId());
+ }
+ $taskTypes = $this->getAvailableTaskTypes();
+ $inputShape = $taskTypes[$task->getTaskTypeId()]['inputShape'];
+ $optionalInputShape = $taskTypes[$task->getTaskTypeId()]['optionalInputShape'];
+ // validate input
+ $this->validateInput($inputShape, $task->getInput());
+ $this->validateInput($optionalInputShape, $task->getInput(), true);
+ // authenticate access to mentioned files
+ $ids = [];
+ foreach ($inputShape + $optionalInputShape as $key => $descriptor) {
+ if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) {
+ /** @var list<int>|int $inputSlot */
+ $inputSlot = $task->getInput()[$key];
+ if (is_array($inputSlot)) {
+ $ids += $inputSlot;
+ } else {
+ $ids[] = $inputSlot;
+ }
+ }
+ }
+ foreach ($ids as $fileId) {
+ $node = $this->rootFolder->getFirstNodeById($fileId);
+ if ($node === null) {
+ $node = $this->rootFolder->getFirstNodeByIdInPath($fileId, '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
+ if ($node === null) {
+ throw new ValidationException('Could not find file ' . $fileId);
+ }
+ }
+ /** @var array{users:array<string,array{node_id:int, node_path: string}>, remote: array<string,array{node_id:int, node_path: string}>, mail: array<string,array{node_id:int, node_path: string}>} $accessList */
+ $accessList = $this->shareManager->getAccessList($node, true, true);
+ $userIds = array_map(fn ($id) => strval($id), array_keys($accessList['users']));
+ if (!in_array($task->getUserId(), $userIds)) {
+ throw new UnauthorizedException('User ' . $task->getUserId() . ' does not have access to file ' . $fileId);
+ }
+ }
+ // remove superfluous keys and set input
+ $task->setInput($this->removeSuperfluousArrayKeys($task->getInput(), $inputShape, $optionalInputShape));
+ $task->setStatus(Task::STATUS_SCHEDULED);
+ $provider = $this->_getPreferredProvider($task->getTaskTypeId());
+ // calculate expected completion time
+ $completionExpectedAt = new \DateTime('now');
+ $completionExpectedAt->add(new \DateInterval('PT'.$provider->getExpectedRuntime().'S'));
+ $task->setCompletionExpectedAt($completionExpectedAt);
+ // create a db entity and insert into db table
+ $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task);
+ $this->taskMapper->insert($taskEntity);
+ // make sure the scheduler knows the id
+ $task->setId($taskEntity->getId());
+ // schedule synchronous job if the provider is synchronous
+ if ($provider instanceof ISynchronousProvider) {
+ $this->jobList->add(SynchronousBackgroundJob::class, null);
+ }
+ }
+
+ public function deleteTask(Task $task): void {
+ $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task);
+ $this->taskMapper->delete($taskEntity);
+ }
+
+ public function getTask(int $id): Task {
+ try {
+ $taskEntity = $this->taskMapper->find($id);
+ return $taskEntity->toPublicTask();
+ } catch (DoesNotExistException $e) {
+ throw new NotFoundException('Couldn\'t find task with id ' . $id, 0, $e);
+ } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
+ } catch (\JsonException $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding the task', 0, $e);
+ }
+ }
+
+ public function cancelTask(int $id): void {
+ $task = $this->getTask($id);
+ if ($task->getStatus() !== Task::STATUS_SCHEDULED && $task->getStatus() !== Task::STATUS_RUNNING) {
+ return;
+ }
+ $task->setStatus(Task::STATUS_CANCELLED);
+ $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task);
+ try {
+ $this->taskMapper->update($taskEntity);
+ } catch (\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
+ }
+ }
+
+ public function setTaskProgress(int $id, float $progress): bool {
+ // TODO: Not sure if we should rather catch the exceptions of getTask here and fail silently
+ $task = $this->getTask($id);
+ if ($task->getStatus() === Task::STATUS_CANCELLED) {
+ return false;
+ }
+ $task->setStatus(Task::STATUS_RUNNING);
+ $task->setProgress($progress);
+ $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task);
+ try {
+ $this->taskMapper->update($taskEntity);
+ } catch (\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
+ }
+ return true;
+ }
+
+ public function setTaskResult(int $id, ?string $error, ?array $result): void {
+ // TODO: Not sure if we should rather catch the exceptions of getTask here and fail silently
+ $task = $this->getTask($id);
+ if ($task->getStatus() === Task::STATUS_CANCELLED) {
+ $this->logger->info('A TaskProcessing ' . $task->getTaskTypeId() . ' task with id ' . $id . ' finished but was cancelled in the mean time. Moving on without storing result.');
+ return;
+ }
+ if ($error !== null) {
+ $task->setStatus(Task::STATUS_FAILED);
+ $task->setErrorMessage($error);
+ $this->logger->warning('A TaskProcessing ' . $task->getTaskTypeId() . ' task with id ' . $id . ' failed with the following message: ' . $error);
+ } elseif ($result !== null) {
+ $taskTypes = $this->getAvailableTaskTypes();
+ $outputShape = $taskTypes[$task->getTaskTypeId()]['outputShape'];
+ $optionalOutputShape = $taskTypes[$task->getTaskTypeId()]['optionalOutputShape'];
+ try {
+ // validate output
+ $this->validateOutput($outputShape, $result);
+ $this->validateOutput($optionalOutputShape, $result, true);
+ $output = $this->removeSuperfluousArrayKeys($result, $outputShape, $optionalOutputShape);
+ // extract raw data and put it in files, replace it with file ids
+ $output = $this->encapsulateOutputFileData($output, $outputShape, $optionalOutputShape);
+ $task->setOutput($output);
+ $task->setProgress(1);
+ $task->setStatus(Task::STATUS_SUCCESSFUL);
+ } catch (ValidationException $e) {
+ $task->setProgress(1);
+ $task->setStatus(Task::STATUS_FAILED);
+ $error = 'The task was processed successfully but the provider\'s output doesn\'t pass validation against the task type\'s outputShape spec and/or the provider\'s own optionalOutputShape spec';
+ $task->setErrorMessage($error);
+ $this->logger->error($error, ['exception' => $e]);
+ } catch (NotPermittedException $e) {
+ $task->setProgress(1);
+ $task->setStatus(Task::STATUS_FAILED);
+ $error = 'The task was processed successfully but storing the output in a file failed';
+ $task->setErrorMessage($error);
+ $this->logger->error($error, ['exception' => $e]);
+
+ }
+ }
+ $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task);
+ try {
+ $this->taskMapper->update($taskEntity);
+ } catch (\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
+ }
+ if ($task->getStatus() === Task::STATUS_SUCCESSFUL) {
+ $event = new TaskSuccessfulEvent($task);
+ } else {
+ $event = new TaskFailedEvent($task, $error);
+ }
+ $this->dispatcher->dispatchTyped($event);
+ }
+
+ public function getNextScheduledTask(?string $taskTypeId = null): Task {
+ try {
+ $taskEntity = $this->taskMapper->findOldestScheduledByType($taskTypeId);
+ return $taskEntity->toPublicTask();
+ } catch (DoesNotExistException $e) {
+ throw new \OCP\TaskProcessing\Exception\NotFoundException('Could not find the task', 0, $e);
+ } catch (\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
+ } catch (\JsonException $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding the task', 0, $e);
+ }
+ }
+
+ /**
+ * Takes task input or output data and replaces fileIds with base64 data
+ *
+ * @param string|null $userId
+ * @param array<array-key, list<numeric|string>|numeric|string> $input
+ * @param ShapeDescriptor[] ...$specs the specs
+ * @return array<array-key, list<File|numeric|string>|numeric|string|File>
+ * @throws GenericFileException
+ * @throws LockedException
+ * @throws NotPermittedException
+ * @throws ValidationException
+ */
+ public function fillInputFileData(?string $userId, array $input, ...$specs): array {
+ if ($userId !== null) {
+ \OC_Util::setupFS($userId);
+ }
+ $newInputOutput = [];
+ $spec = array_reduce($specs, fn ($carry, $spec) => $carry + $spec, []);
+ foreach($spec as $key => $descriptor) {
+ $type = $descriptor->getShapeType();
+ if (!isset($input[$key])) {
+ continue;
+ }
+ if (!in_array(EShapeType::getScalarType($type), [EShapeType::Image, EShapeType::Audio, EShapeType::Video, EShapeType::File], true)) {
+ $newInputOutput[$key] = $input[$key];
+ continue;
+ }
+ if ($type->value < 10) {
+ $node = $this->rootFolder->getFirstNodeById((int)$input[$key]);
+ if ($node === null) {
+ $node = $this->rootFolder->getFirstNodeByIdInPath((int)$input[$key], '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
+ if (!$node instanceof File) {
+ throw new ValidationException('File id given for key "' . $key . '" is not a file');
+ }
+ } elseif (!$node instanceof File) {
+ throw new ValidationException('File id given for key "' . $key . '" is not a file');
+ }
+ // TODO: Validate if userId has access to this file
+ $newInputOutput[$key] = $node;
+ } else {
+ $newInputOutput[$key] = [];
+ foreach ($input[$key] as $item) {
+ $node = $this->rootFolder->getFirstNodeById((int)$item);
+ if ($node === null) {
+ $node = $this->rootFolder->getFirstNodeByIdInPath((int)$item, '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
+ if (!$node instanceof File) {
+ throw new ValidationException('File id given for key "' . $key . '" is not a file');
+ }
+ } elseif (!$node instanceof File) {
+ throw new ValidationException('File id given for key "' . $key . '" is not a file');
+ }
+ // TODO: Validate if userId has access to this file
+ $newInputOutput[$key][] = $node;
+ }
+ }
+ }
+ return $newInputOutput;
+ }
+
+ public function getUserTask(int $id, ?string $userId): Task {
+ try {
+ $taskEntity = $this->taskMapper->findByIdAndUser($id, $userId);
+ return $taskEntity->toPublicTask();
+ } catch (DoesNotExistException $e) {
+ throw new \OCP\TaskProcessing\Exception\NotFoundException('Could not find the task', 0, $e);
+ } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
+ } catch (\JsonException $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding the task', 0, $e);
+ }
+ }
+
+ public function getUserTasks(?string $userId, ?string $taskTypeId = null, ?string $customId = null): array {
+ try {
+ $taskEntities = $this->taskMapper->findByUserAndTaskType($userId, $taskTypeId, $customId);
+ return array_map(fn ($taskEntity): Task => $taskEntity->toPublicTask(), $taskEntities);
+ } catch (\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the tasks', 0, $e);
+ } catch (\JsonException $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding the tasks', 0, $e);
+ }
+ }
+
+ public function getUserTasksByApp(?string $userId, string $appId, ?string $customId = null): array {
+ try {
+ $taskEntities = $this->taskMapper->findUserTasksByApp($userId, $appId, $customId);
+ return array_map(fn ($taskEntity): Task => $taskEntity->toPublicTask(), $taskEntities);
+ } catch (\OCP\DB\Exception $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding a task', 0, $e);
+ } catch (\JsonException $e) {
+ throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding a task', 0, $e);
+ }
+ }
+
+ /**
+ *Takes task input or output and replaces base64 data with file ids
+ *
+ * @param array $output
+ * @param ShapeDescriptor[] ...$specs the specs that define which keys to keep
+ * @return array
+ * @throws NotPermittedException
+ */
+ public function encapsulateOutputFileData(array $output, ...$specs): array {
+ $newOutput = [];
+ try {
+ $folder = $this->appData->getFolder('TaskProcessing');
+ } catch (\OCP\Files\NotFoundException) {
+ $folder = $this->appData->newFolder('TaskProcessing');
+ }
+ $spec = array_reduce($specs, fn ($carry, $spec) => $carry + $spec, []);
+ foreach($spec as $key => $descriptor) {
+ $type = $descriptor->getShapeType();
+ if (!isset($output[$key])) {
+ continue;
+ }
+ if (!in_array(EShapeType::getScalarType($type), [EShapeType::Image, EShapeType::Audio, EShapeType::Video, EShapeType::File], true)) {
+ $newOutput[$key] = $output[$key];
+ continue;
+ }
+ if ($type->value < 10) {
+ /** @var SimpleFile $file */
+ $file = $folder->newFile((string) rand(0, 10000000), $output[$key]);
+ $newOutput[$key] = $file->getId(); // polymorphic call to SimpleFile
+ } else {
+ $newOutput = [];
+ foreach ($output[$key] as $item) {
+ /** @var SimpleFile $file */
+ $file = $folder->newFile((string) rand(0, 10000000), $item);
+ $newOutput[$key][] = $file->getId();
+ }
+ }
+ }
+ return $newOutput;
+ }
+
+ /**
+ * @param Task $task
+ * @return array<array-key, list<numeric|string|File>|numeric|string|File>
+ * @throws GenericFileException
+ * @throws LockedException
+ * @throws NotPermittedException
+ * @throws ValidationException
+ */
+ public function prepareInputData(Task $task): array {
+ $taskTypes = $this->getAvailableTaskTypes();
+ $inputShape = $taskTypes[$task->getTaskTypeId()]['inputShape'];
+ $optionalInputShape = $taskTypes[$task->getTaskTypeId()]['optionalInputShape'];
+ $input = $task->getInput();
+ // validate input, again for good measure (should have been validated in scheduleTask)
+ $this->validateInput($inputShape, $input);
+ $this->validateInput($optionalInputShape, $input, true);
+ $input = $this->removeSuperfluousArrayKeys($input, $inputShape, $optionalInputShape);
+ $input = $this->fillInputFileData($task->getUserId(), $input, $inputShape, $optionalInputShape);
+ return $input;
+ }
+}
diff --git a/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php b/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php
new file mode 100644
index 00000000000..823ea09a622
--- /dev/null
+++ b/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\TaskProcessing;
+
+use OC\TaskProcessing\Db\TaskMapper;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\TimedJob;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use Psr\Log\LoggerInterface;
+
+class RemoveOldTasksBackgroundJob extends TimedJob {
+ public const MAX_TASK_AGE_SECONDS = 60 * 50 * 24 * 7 * 4; // 4 weeks
+ private \OCP\Files\IAppData $appData;
+
+ public function __construct(
+ ITimeFactory $timeFactory,
+ private TaskMapper $taskMapper,
+ private LoggerInterface $logger,
+ IAppDataFactory $appDataFactory,
+ ) {
+ parent::__construct($timeFactory);
+ $this->setInterval(60 * 60 * 24);
+ // can be deferred to maintenance window
+ $this->setTimeSensitivity(TimedJob::TIME_INSENSITIVE);
+ $this->appData = $appDataFactory->get('core');
+ }
+
+
+ /**
+ * @inheritDoc
+ */
+ protected function run($argument): void {
+ try {
+ $this->taskMapper->deleteOlderThan(self::MAX_TASK_AGE_SECONDS);
+ } catch (\OCP\DB\Exception $e) {
+ $this->logger->warning('Failed to delete stale task processing tasks', ['exception' => $e]);
+ }
+ try {
+ $this->clearFilesOlderThan($this->appData->getFolder('text2image'), self::MAX_TASK_AGE_SECONDS);
+ } catch (NotFoundException $e) {
+ // noop
+ }
+ try {
+ $this->clearFilesOlderThan($this->appData->getFolder('audio2text'), self::MAX_TASK_AGE_SECONDS);
+ } catch (NotFoundException $e) {
+ // noop
+ }
+ try {
+ $this->clearFilesOlderThan($this->appData->getFolder('TaskProcessing'), self::MAX_TASK_AGE_SECONDS);
+ } catch (NotFoundException $e) {
+ // noop
+ }
+ }
+
+ /**
+ * @param ISimpleFolder $folder
+ * @param int $ageInSeconds
+ * @return void
+ */
+ private function clearFilesOlderThan(ISimpleFolder $folder, int $ageInSeconds): void {
+ foreach($folder->getDirectoryListing() as $file) {
+ if ($file->getMTime() < time() - $ageInSeconds) {
+ try {
+ $file->delete();
+ } catch (NotPermittedException $e) {
+ $this->logger->warning('Failed to delete a stale task processing file', ['exception' => $e]);
+ }
+ }
+ }
+ }
+
+}
diff --git a/lib/private/TaskProcessing/SynchronousBackgroundJob.php b/lib/private/TaskProcessing/SynchronousBackgroundJob.php
new file mode 100644
index 00000000000..47c3c83a618
--- /dev/null
+++ b/lib/private/TaskProcessing/SynchronousBackgroundJob.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\TaskProcessing;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\IJobList;
+use OCP\BackgroundJob\QueuedJob;
+use OCP\Files\GenericFileException;
+use OCP\Files\NotPermittedException;
+use OCP\Lock\LockedException;
+use OCP\TaskProcessing\Exception\Exception;
+use OCP\TaskProcessing\Exception\NotFoundException;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\Exception\ValidationException;
+use OCP\TaskProcessing\IManager;
+use OCP\TaskProcessing\ISynchronousProvider;
+use Psr\Log\LoggerInterface;
+
+class SynchronousBackgroundJob extends QueuedJob {
+ public function __construct(
+ ITimeFactory $timeFactory,
+ private readonly IManager $taskProcessingManager,
+ private readonly IJobList $jobList,
+ private readonly LoggerInterface $logger,
+ ) {
+ parent::__construct($timeFactory);
+ }
+
+
+ /**
+ * @inheritDoc
+ */
+ protected function run($argument) {
+ $providers = $this->taskProcessingManager->getProviders();
+
+ foreach ($providers as $provider) {
+ if (!$provider instanceof ISynchronousProvider) {
+ continue;
+ }
+ $taskType = $provider->getTaskTypeId();
+ try {
+ $task = $this->taskProcessingManager->getNextScheduledTask($taskType);
+ } catch (NotFoundException $e) {
+ continue;
+ } catch (Exception $e) {
+ $this->logger->error('Unknown error while retrieving scheduled TaskProcessing tasks', ['exception' => $e]);
+ continue;
+ }
+ try {
+ try {
+ $input = $this->taskProcessingManager->prepareInputData($task);
+ } catch (GenericFileException|NotPermittedException|LockedException|ValidationException $e) {
+ $this->logger->warning('Failed to prepare input data for a TaskProcessing task with synchronous provider ' . $provider->getId(), ['exception' => $e]);
+ $this->taskProcessingManager->setTaskResult($task->getId(), $e->getMessage(), null);
+ // Schedule again
+ $this->jobList->add(self::class, $argument);
+ return;
+ }
+ try {
+ $output = $provider->process($task->getUserId(), $input, fn (float $progress) => $this->taskProcessingManager->setTaskProgress($task->getId(), $progress));
+ } catch (ProcessingException $e) {
+ $this->logger->warning('Failed to process a TaskProcessing task with synchronous provider ' . $provider->getId(), ['exception' => $e]);
+ $this->taskProcessingManager->setTaskResult($task->getId(), $e->getMessage(), null);
+ // Schedule again
+ $this->jobList->add(self::class, $argument);
+ return;
+ } catch (\Throwable $e) {
+ $this->logger->error('Unknown error while processing TaskProcessing task', ['exception' => $e]);
+ $this->taskProcessingManager->setTaskResult($task->getId(), $e->getMessage(), null);
+ // Schedule again
+ $this->jobList->add(self::class, $argument);
+ return;
+ }
+ $this->taskProcessingManager->setTaskResult($task->getId(), null, $output);
+ } catch (NotFoundException $e) {
+ $this->logger->info('Could not find task anymore after execution. Moving on.', ['exception' => $e]);
+ } catch (Exception $e) {
+ $this->logger->error('Failed to report result of TaskProcessing task', ['exception' => $e]);
+ }
+ }
+
+ $synchronousProviders = array_filter($providers, fn ($provider) =>
+ $provider instanceof ISynchronousProvider);
+ $taskTypes = array_values(array_map(fn ($provider) =>
+ $provider->getTaskTypeId(),
+ $synchronousProviders
+ ));
+ $taskTypesWithTasks = array_filter($taskTypes, function ($taskType) {
+ try {
+ $this->taskProcessingManager->getNextScheduledTask($taskType);
+ return true;
+ } catch (NotFoundException|Exception $e) {
+ return false;
+ }
+ });
+
+ if (count($taskTypesWithTasks) > 0) {
+ // Schedule again
+ $this->jobList->add(self::class, $argument);
+ }
+ }
+}
diff --git a/lib/private/Teams/TeamManager.php b/lib/private/Teams/TeamManager.php
new file mode 100644
index 00000000000..4fe0e60b7d1
--- /dev/null
+++ b/lib/private/Teams/TeamManager.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Teams;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OCA\Circles\CirclesManager;
+use OCA\Circles\Exceptions\CircleNotFoundException;
+use OCA\Circles\Model\Circle;
+use OCA\Circles\Model\Member;
+use OCP\IURLGenerator;
+use OCP\Server;
+use OCP\Teams\ITeamManager;
+use OCP\Teams\ITeamResourceProvider;
+use OCP\Teams\Team;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+
+class TeamManager implements ITeamManager {
+
+ /** @var ?ITeamResourceProvider[] */
+ private ?array $providers = null;
+
+ public function __construct(
+ private Coordinator $bootContext,
+ private IURLGenerator $urlGenerator,
+ private ?CirclesManager $circlesManager,
+ ) {
+ }
+
+ public function hasTeamSupport(): bool {
+ return $this->circlesManager !== null;
+ }
+
+ public function getProviders(): array {
+ if ($this->providers !== null) {
+ return $this->providers;
+ }
+
+ $this->providers = [];
+ foreach ($this->bootContext->getRegistrationContext()->getTeamResourceProviders() as $providerRegistration) {
+ try {
+ /** @var ITeamResourceProvider $provider */
+ $provider = Server::get($providerRegistration->getService());
+ $this->providers[$provider->getId()] = $provider;
+ } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
+ }
+ }
+ return $this->providers;
+ }
+
+ public function getProvider(string $providerId): ITeamResourceProvider {
+ $providers = $this->getProviders();
+ if (isset($providers[$providerId])) {
+ return $providers[$providerId];
+ }
+
+ throw new \RuntimeException('No provider found for id ' .$providerId);
+ }
+
+ public function getSharedWith(string $teamId, string $userId): array {
+ if ($this->getTeam($teamId, $userId) === null) {
+ return [];
+ }
+
+ $resources = [];
+
+ foreach ($this->getProviders() as $provider) {
+ array_push($resources, ...$provider->getSharedWith($teamId));
+ }
+
+ return $resources;
+ }
+
+ public function getTeamsForResource(string $providerId, string $resourceId, string $userId): array {
+ $provider = $this->getProvider($providerId);
+ return array_values(array_filter(array_map(function ($teamId) use ($userId) {
+ $team = $this->getTeam($teamId, $userId);
+ if ($team === null) {
+ return null;
+ }
+
+ return new Team(
+ $teamId,
+ $team->getDisplayName(),
+ $this->urlGenerator->linkToRouteAbsolute('contacts.contacts.directcircle', ['singleId' => $teamId]),
+ );
+ }, $provider->getTeamsForResource($resourceId))));
+ }
+
+ private function getTeam(string $teamId, string $userId): ?Circle {
+ try {
+ $federatedUser = $this->circlesManager->getFederatedUser($userId, Member::TYPE_USER);
+ $this->circlesManager->startSession($federatedUser);
+ return $this->circlesManager->getCircle($teamId);
+ } catch (CircleNotFoundException) {
+ return null;
+ }
+ }
+}
diff --git a/lib/private/TempManager.php b/lib/private/TempManager.php
index 0df31dce3ff..68a53f493db 100644
--- a/lib/private/TempManager.php
+++ b/lib/private/TempManager.php
@@ -1,33 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lars <winnetou+github@catolic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Martin Mattel <martin.mattel@diemattels.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php
index 71ce2ed9d86..2adf9172f6b 100644
--- a/lib/private/Template/Base.php
+++ b/lib/private/Template/Base.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Template;
diff --git a/lib/private/Template/CSSResourceLocator.php b/lib/private/Template/CSSResourceLocator.php
index 4ebe054ca7b..e9aa38ef2cc 100644
--- a/lib/private/Template/CSSResourceLocator.php
+++ b/lib/private/Template/CSSResourceLocator.php
@@ -1,33 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Axel Helmert <axel.helmert@luka.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Kyle Fazzari <kyrofa@ubuntu.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author tux-rampage <tux-rampage@users.noreply.github.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Template;
diff --git a/lib/private/Template/JSCombiner.php b/lib/private/Template/JSCombiner.php
index b87829360d5..5fce3effb3f 100644
--- a/lib/private/Template/JSCombiner.php
+++ b/lib/private/Template/JSCombiner.php
@@ -1,28 +1,7 @@
<?php
/**
- * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Template;
@@ -55,10 +34,10 @@ class JSCombiner {
private $cacheFactory;
public function __construct(IAppData $appData,
- IURLGenerator $urlGenerator,
- ICacheFactory $cacheFactory,
- SystemConfig $config,
- LoggerInterface $logger) {
+ IURLGenerator $urlGenerator,
+ ICacheFactory $cacheFactory,
+ SystemConfig $config,
+ LoggerInterface $logger) {
$this->appData = $appData;
$this->urlGenerator = $urlGenerator;
$this->cacheFactory = $cacheFactory;
diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php
index 7b6d0a6a346..2f2ff9d64e3 100644
--- a/lib/private/Template/JSConfigHelper.php
+++ b/lib/private/Template/JSConfigHelper.php
@@ -2,34 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Abijeet <abijeetpatro@gmail.com>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Template;
@@ -45,10 +19,11 @@ use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IInitialStateService;
use OCP\IL10N;
+use OCP\ILogger;
use OCP\ISession;
use OCP\IURLGenerator;
-use OCP\ILogger;
use OCP\IUser;
+use OCP\Share\IManager as IShareManager;
use OCP\User\Backend\IPasswordConfirmationBackend;
use OCP\Util;
@@ -69,16 +44,16 @@ class JSConfigHelper {
private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true];
public function __construct(IL10N $l,
- Defaults $defaults,
- IAppManager $appManager,
- ISession $session,
- ?IUser $currentUser,
- IConfig $config,
- IGroupManager $groupManager,
- IniGetWrapper $iniWrapper,
- IURLGenerator $urlGenerator,
- CapabilitiesManager $capabilitiesManager,
- IInitialStateService $initialStateService) {
+ Defaults $defaults,
+ IAppManager $appManager,
+ ISession $session,
+ ?IUser $currentUser,
+ IConfig $config,
+ IGroupManager $groupManager,
+ IniGetWrapper $iniWrapper,
+ IURLGenerator $urlGenerator,
+ CapabilitiesManager $capabilitiesManager,
+ IInitialStateService $initialStateService) {
$this->l = $l;
$this->defaults = $defaults;
$this->appManager = $appManager;
@@ -168,6 +143,7 @@ class JSConfigHelper {
$config = [
'auto_logout' => $this->config->getSystemValue('auto_logout', false),
'blacklist_files_regex' => FileInfo::BLACKLIST_FILES_REGEX,
+ 'forbidden_filename_characters' => Util::getForbiddenFileNameChars(),
'loglevel' => $this->config->getSystemValue('loglevel_frontend',
$this->config->getSystemValue('loglevel', ILogger::WARN)
),
@@ -179,7 +155,8 @@ class JSConfigHelper {
'sharing.maxAutocompleteResults' => max(0, $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)),
'sharing.minSearchStringLength' => $this->config->getSystemValueInt('sharing.minSearchStringLength', 0),
'version' => implode('.', Util::getVersion()),
- 'versionstring' => \OC_Util::getVersionString()
+ 'versionstring' => \OC_Util::getVersionString(),
+ 'enable_non-accessible_features' => $this->config->getSystemValueBool('enable_non-accessible_features', true),
];
$array = [
@@ -260,7 +237,7 @@ class JSConfigHelper {
'resharingAllowed' => Share::isResharingAllowed(),
'remoteShareAllowed' => $outgoingServer2serverShareEnabled,
'federatedCloudShareDoc' => $this->urlGenerator->linkToDocs('user-sharing-federated'),
- 'allowGroupSharing' => \OC::$server->getShareManager()->allowGroupSharing(),
+ 'allowGroupSharing' => \OC::$server->get(IShareManager::class)->allowGroupSharing(),
'defaultInternalExpireDateEnabled' => $defaultInternalExpireDateEnabled,
'defaultInternalExpireDate' => $defaultInternalExpireDate,
'defaultInternalExpireDateEnforced' => $defaultInternalExpireDateEnforced,
diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php
index b283f0b610f..b9a2fce6cd5 100644
--- a/lib/private/Template/JSResourceLocator.php
+++ b/lib/private/Template/JSResourceLocator.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Kyle Fazzari <kyrofa@ubuntu.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Template;
@@ -51,6 +31,22 @@ class JSResourceLocator extends ResourceLocator {
// Extracting the appId and the script file name
$app = substr($script, 0, strpos($script, '/'));
$scriptName = basename($script);
+ // Get the app root path
+ $appRoot = $this->serverroot . '/apps/';
+ $appWebRoot = null;
+ try {
+ // We need the dir name as getAppPath appends the appid
+ $appRoot = dirname($this->appManager->getAppPath($app));
+ // Only do this if $app_path is set, because an empty argument to realpath gets turned into cwd.
+ if ($appRoot) {
+ // Handle symlinks
+ $appRoot = realpath($appRoot);
+ }
+ // Get the app webroot
+ $appWebRoot = dirname($this->appManager->getAppWebPath($app));
+ } catch (AppPathNotFoundException $e) {
+ // ignore
+ }
if (str_contains($script, '/l10n/')) {
// For language files we try to load them all, so themes can overwrite
@@ -60,7 +56,7 @@ class JSResourceLocator extends ResourceLocator {
$found += $this->appendScriptIfExist($this->serverroot, $theme_dir.'core/'.$script);
$found += $this->appendScriptIfExist($this->serverroot, $script);
$found += $this->appendScriptIfExist($this->serverroot, $theme_dir.$script);
- $found += $this->appendScriptIfExist($this->serverroot, 'apps/'.$script);
+ $found += $this->appendScriptIfExist($appRoot, $script, $appWebRoot);
$found += $this->appendScriptIfExist($this->serverroot, $theme_dir.'apps/'.$script);
if ($found) {
@@ -71,8 +67,9 @@ class JSResourceLocator extends ResourceLocator {
|| $this->appendScriptIfExist($this->serverroot, $script)
|| $this->appendScriptIfExist($this->serverroot, $theme_dir."dist/$app-$scriptName")
|| $this->appendScriptIfExist($this->serverroot, "dist/$app-$scriptName")
- || $this->appendScriptIfExist($this->serverroot, 'apps/'.$script)
+ || $this->appendScriptIfExist($appRoot, $script, $appWebRoot)
|| $this->cacheAndAppendCombineJsonIfExist($this->serverroot, $script.'.json')
+ || $this->cacheAndAppendCombineJsonIfExist($appRoot, $script.'.json', $appWebRoot)
|| $this->appendScriptIfExist($this->serverroot, $theme_dir.'core/'.$script)
|| $this->appendScriptIfExist($this->serverroot, 'core/'.$script)
|| (strpos($scriptName, '/') === -1 && ($this->appendScriptIfExist($this->serverroot, $theme_dir."dist/core-$scriptName")
@@ -82,43 +79,13 @@ class JSResourceLocator extends ResourceLocator {
return;
}
- $script = substr($script, strpos($script, '/') + 1);
- $app_url = null;
-
- try {
- $app_url = $this->appManager->getAppWebPath($app);
- } catch (AppPathNotFoundException) {
- // pass
- }
-
- try {
- $app_path = $this->appManager->getAppPath($app);
-
- // Account for the possibility of having symlinks in app path. Only
- // do this if $app_path is set, because an empty argument to realpath
- // gets turned into cwd.
- $app_path = realpath($app_path);
-
- // check combined files
- if (!str_starts_with($script, 'l10n/') && $this->cacheAndAppendCombineJsonIfExist($app_path, $script.'.json', $app)) {
- return;
- }
-
- // fallback to plain file location
- if ($this->appendScriptIfExist($app_path, $script, $app_url)) {
- return;
- }
- } catch (AppPathNotFoundException) {
- // pass (general error handling happens below)
- }
-
// missing translations files will be ignored
- if (str_starts_with($script, 'l10n/')) {
+ if (str_contains($script, '/l10n/')) {
return;
}
$this->logger->error('Could not find resource {resource} to load', [
- 'resource' => $app . '/' . $script . '.js',
+ 'resource' => $script . '.js',
'app' => 'jsresourceloader',
]);
}
@@ -133,7 +100,7 @@ class JSResourceLocator extends ResourceLocator {
* Try to find ES6 script file (`.mjs`) with fallback to plain javascript (`.js`)
* @see appendIfExist()
*/
- protected function appendScriptIfExist(string $root, string $file, string $webRoot = null) {
+ protected function appendScriptIfExist(string $root, string $file, ?string $webRoot = null) {
if (!$this->appendIfExist($root, $file . '.mjs', $webRoot)) {
return $this->appendIfExist($root, $file . '.js', $webRoot);
}
diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php
index 9e6e2056e6b..377f0e0b6a8 100755
--- a/lib/private/Template/ResourceLocator.php
+++ b/lib/private/Template/ResourceLocator.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author tux-rampage <tux-rampage@users.noreply.github.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Template;
diff --git a/lib/private/Template/ResourceNotFoundException.php b/lib/private/Template/ResourceNotFoundException.php
index c8ed33f569c..e51dfb5cb89 100644
--- a/lib/private/Template/ResourceNotFoundException.php
+++ b/lib/private/Template/ResourceNotFoundException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Template;
diff --git a/lib/private/Template/TemplateFileLocator.php b/lib/private/Template/TemplateFileLocator.php
index 027144e2f43..164fcd503c1 100644
--- a/lib/private/Template/TemplateFileLocator.php
+++ b/lib/private/Template/TemplateFileLocator.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Template;
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 658a85152bf..0ff56ece635 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -1,44 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Guillaume COMPAGNON <gcompagnon@outlook.com>
- * @author Hendrik Leppelsack <hendrik@leppelsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Haertl <jus@bitgrid.net>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Nils <git@to.nilsschnabel.de>
- * @author Remco Brenninkmeijer <requist1@starmail.nl>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -47,11 +12,13 @@ use OC\Search\SearchQuery;
use OC\Template\CSSResourceLocator;
use OC\Template\JSConfigHelper;
use OC\Template\JSResourceLocator;
+use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Defaults;
use OCP\IConfig;
use OCP\IInitialStateService;
use OCP\INavigationManager;
+use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\Support\Subscription\IRegistry;
use OCP\Util;
@@ -106,11 +73,15 @@ class TemplateLayout extends \OC_Template {
$this->initialState->provideInitialState('core', 'active-app', $this->navigationManager->getActiveEntry());
$this->initialState->provideInitialState('core', 'apps', $this->navigationManager->getAll());
- $this->initialState->provideInitialState('unified-search', 'limit-default', (int)$this->config->getAppValue('core', 'unified-search.limit-default', (string)SearchQuery::LIMIT_DEFAULT));
- $this->initialState->provideInitialState('unified-search', 'min-search-length', (int)$this->config->getAppValue('core', 'unified-search.min-search-length', (string)1));
- $this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes');
- Util::addScript('core', 'unified-search', 'core');
+ if ($this->config->getSystemValueBool('unified_search.enabled', false) || !$this->config->getSystemValueBool('enable_non-accessible_features', true)) {
+ $this->initialState->provideInitialState('unified-search', 'limit-default', (int)$this->config->getAppValue('core', 'unified-search.limit-default', (string)SearchQuery::LIMIT_DEFAULT));
+ $this->initialState->provideInitialState('unified-search', 'min-search-length', (int)$this->config->getAppValue('core', 'unified-search.min-search-length', (string)1));
+ $this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes');
+ Util::addScript('core', 'legacy-unified-search', 'core');
+ } else {
+ Util::addScript('core', 'unified-search', 'core');
+ }
// Set body data-theme
$this->assign('enabledThemes', []);
if (\OC::$server->getAppManager()->isEnabledForUser('theming') && class_exists('\OCA\Theming\Service\ThemesService')) {
@@ -189,13 +160,31 @@ class TemplateLayout extends \OC_Template {
$this->assign('appid', $appId);
$this->assign('bodyid', 'body-public');
+ // Set logo link target
+ $logoUrl = $this->config->getSystemValueString('logo_url', '');
+ $this->assign('logoUrl', $logoUrl);
+
/** @var IRegistry $subscription */
$subscription = \OCP\Server::get(IRegistry::class);
$showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true);
if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) {
$showSimpleSignup = false;
}
+
+ $defaultSignUpLink = 'https://nextcloud.com/signup/';
+ $signUpLink = $this->config->getSystemValueString('registration_link', $defaultSignUpLink);
+ if ($signUpLink !== $defaultSignUpLink) {
+ $showSimpleSignup = true;
+ }
+
+ $appManager = \OCP\Server::get(IAppManager::class);
+ if ($appManager->isEnabledForUser('registration')) {
+ $urlGenerator = \OCP\Server::get(IURLGenerator::class);
+ $signUpLink = $urlGenerator->getAbsoluteURL('/index.php/apps/registration/');
+ }
+
$this->assign('showSimpleSignUpLink', $showSimpleSignup);
+ $this->assign('signUpLink', $signUpLink);
} else {
parent::__construct('core', 'layout.base');
}
@@ -225,7 +214,7 @@ class TemplateLayout extends \OC_Template {
// this is on purpose outside of the if statement below so that the initial state is prefilled (done in the getConfig() call)
// see https://github.com/nextcloud/server/pull/22636 for details
$jsConfigHelper = new JSConfigHelper(
- \OC::$server->getL10N('lib'),
+ \OCP\Util::getL10N('lib'),
\OCP\Server::get(Defaults::class),
\OC::$server->getAppManager(),
\OC::$server->getSession(),
@@ -234,7 +223,7 @@ class TemplateLayout extends \OC_Template {
\OC::$server->getGroupManager(),
\OC::$server->get(IniGetWrapper::class),
\OC::$server->getURLGenerator(),
- \OC::$server->getCapabilitiesManager(),
+ \OC::$server->get(CapabilitiesManager::class),
\OCP\Server::get(IInitialStateService::class)
);
$config = $jsConfigHelper->getConfig();
@@ -279,7 +268,7 @@ class TemplateLayout extends \OC_Template {
$web = $info[1];
$file = $info[2];
- if (substr($file, -strlen('print.css')) === 'print.css') {
+ if (str_ends_with($file, 'print.css')) {
$this->append('printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix());
} else {
$suffix = $this->getVersionHashSuffix($web, $file);
diff --git a/lib/private/TextProcessing/Db/Task.php b/lib/private/TextProcessing/Db/Task.php
index 9c6f16d11ae..31c9aab345b 100644
--- a/lib/private/TextProcessing/Db/Task.php
+++ b/lib/private/TextProcessing/Db/Task.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\TextProcessing\Db;
@@ -45,6 +29,8 @@ use OCP\TextProcessing\Task as OCPTask;
* @method string getAppId()
* @method setIdentifier(string $identifier)
* @method string getIdentifier()
+ * @method setCompletionExpectedAt(null|\DateTime $completionExpectedAt)
+ * @method null|\DateTime getCompletionExpectedAt()
*/
class Task extends Entity {
protected $lastUpdated;
@@ -55,16 +41,17 @@ class Task extends Entity {
protected $userId;
protected $appId;
protected $identifier;
+ protected $completionExpectedAt;
/**
* @var string[]
*/
- public static array $columns = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'identifier'];
+ public static array $columns = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'identifier', 'completion_expected_at'];
/**
* @var string[]
*/
- public static array $fields = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'identifier'];
+ public static array $fields = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'identifier', 'completionExpectedAt'];
public function __construct() {
@@ -78,6 +65,7 @@ class Task extends Entity {
$this->addType('userId', 'string');
$this->addType('appId', 'string');
$this->addType('identifier', 'string');
+ $this->addType('completionExpectedAt', 'datetime');
}
public function toRow(): array {
@@ -98,6 +86,7 @@ class Task extends Entity {
'userId' => $task->getUserId(),
'appId' => $task->getAppId(),
'identifier' => $task->getIdentifier(),
+ 'completionExpectedAt' => $task->getCompletionExpectedAt(),
]);
return $task;
}
@@ -107,6 +96,7 @@ class Task extends Entity {
$task->setId($this->getId());
$task->setStatus($this->getStatus());
$task->setOutput($this->getOutput());
+ $task->setCompletionExpectedAt($this->getCompletionExpectedAt());
return $task;
}
}
diff --git a/lib/private/TextProcessing/Db/TaskMapper.php b/lib/private/TextProcessing/Db/TaskMapper.php
index 62dabea544f..b03e5833958 100644
--- a/lib/private/TextProcessing/Db/TaskMapper.php
+++ b/lib/private/TextProcessing/Db/TaskMapper.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\TextProcessing\Db;
diff --git a/lib/private/TextProcessing/Manager.php b/lib/private/TextProcessing/Manager.php
index b9cb06c298e..44387662937 100644
--- a/lib/private/TextProcessing/Manager.php
+++ b/lib/private/TextProcessing/Manager.php
@@ -3,43 +3,30 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\TextProcessing;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\TextProcessing\Db\Task as DbTask;
-use OCP\IConfig;
-use OCP\TextProcessing\Task;
-use OCP\TextProcessing\Task as OCPTask;
use OC\TextProcessing\Db\TaskMapper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\BackgroundJob\IJobList;
use OCP\Common\Exception\NotFoundException;
use OCP\DB\Exception;
+use OCP\IConfig;
use OCP\IServerContainer;
+use OCP\PreConditionNotMetException;
+use OCP\TextProcessing\Exception\TaskFailureException;
use OCP\TextProcessing\IManager;
use OCP\TextProcessing\IProvider;
-use OCP\PreConditionNotMetException;
+use OCP\TextProcessing\IProviderWithExpectedRuntime;
+use OCP\TextProcessing\IProviderWithId;
+use OCP\TextProcessing\Task;
+use OCP\TextProcessing\Task as OCPTask;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Throwable;
@@ -114,26 +101,16 @@ class Manager implements IManager {
if (!$this->canHandleTask($task)) {
throw new PreConditionNotMetException('No text processing provider is installed that can handle this task');
}
- $providers = $this->getProviders();
- $json = $this->config->getAppValue('core', 'ai.textprocessing_provider_preferences', '');
- if ($json !== '') {
- $preferences = json_decode($json, true);
- if (isset($preferences[$task->getType()])) {
- // If a preference for this task type is set, move the preferred provider to the start
- $provider = current(array_filter($providers, fn ($provider) => $provider::class === $preferences[$task->getType()]));
- if ($provider !== false) {
- $providers = array_filter($providers, fn ($p) => $p !== $provider);
- array_unshift($providers, $provider);
- }
- }
- }
+ $providers = $this->getPreferredProviders($task);
foreach ($providers as $provider) {
- if (!$task->canUseProvider($provider)) {
- continue;
- }
try {
$task->setStatus(OCPTask::STATUS_RUNNING);
+ if ($provider instanceof IProviderWithExpectedRuntime) {
+ $completionExpectedAt = new \DateTime('now');
+ $completionExpectedAt->add(new \DateInterval('PT'.$provider->getExpectedRuntime().'S'));
+ $task->setCompletionExpectedAt($completionExpectedAt);
+ }
if ($task->getId() === null) {
$taskEntity = $this->taskMapper->insert(DbTask::fromPublicTask($task));
$task->setId($taskEntity->getId());
@@ -145,31 +122,37 @@ class Manager implements IManager {
$task->setStatus(OCPTask::STATUS_SUCCESSFUL);
$this->taskMapper->update(DbTask::fromPublicTask($task));
return $output;
- } catch (\RuntimeException $e) {
- $this->logger->info('LanguageModel call using provider ' . $provider->getName() . ' failed', ['exception' => $e]);
- $task->setStatus(OCPTask::STATUS_FAILED);
- $this->taskMapper->update(DbTask::fromPublicTask($task));
- throw $e;
} catch (\Throwable $e) {
$this->logger->info('LanguageModel call using provider ' . $provider->getName() . ' failed', ['exception' => $e]);
$task->setStatus(OCPTask::STATUS_FAILED);
$this->taskMapper->update(DbTask::fromPublicTask($task));
- throw new RuntimeException('LanguageModel call using provider ' . $provider->getName() . ' failed: ' . $e->getMessage(), 0, $e);
+ throw new TaskFailureException('LanguageModel call using provider ' . $provider->getName() . ' failed: ' . $e->getMessage(), 0, $e);
}
}
- throw new RuntimeException('Could not run task');
+ $task->setStatus(OCPTask::STATUS_FAILED);
+ $this->taskMapper->update(DbTask::fromPublicTask($task));
+ throw new TaskFailureException('Could not run task');
}
/**
* @inheritDoc
- * @throws Exception
*/
public function scheduleTask(OCPTask $task): void {
if (!$this->canHandleTask($task)) {
throw new PreConditionNotMetException('No LanguageModel provider is installed that can handle this task');
}
$task->setStatus(OCPTask::STATUS_SCHEDULED);
+ $providers = $this->getPreferredProviders($task);
+ if (count($providers) === 0) {
+ throw new PreConditionNotMetException('No LanguageModel provider is installed that can handle this task');
+ }
+ [$provider,] = $providers;
+ if ($provider instanceof IProviderWithExpectedRuntime) {
+ $completionExpectedAt = new \DateTime('now');
+ $completionExpectedAt->add(new \DateInterval('PT'.$provider->getExpectedRuntime().'S'));
+ $task->setCompletionExpectedAt($completionExpectedAt);
+ }
$taskEntity = DbTask::fromPublicTask($task);
$this->taskMapper->insert($taskEntity);
$task->setId($taskEntity->getId());
@@ -181,6 +164,25 @@ class Manager implements IManager {
/**
* @inheritDoc
*/
+ public function runOrScheduleTask(OCPTask $task): bool {
+ if (!$this->canHandleTask($task)) {
+ throw new PreConditionNotMetException('No LanguageModel provider is installed that can handle this task');
+ }
+ [$provider,] = $this->getPreferredProviders($task);
+ $maxExecutionTime = (int) ini_get('max_execution_time');
+ // Offload the task to a background job if the expected runtime of the likely provider is longer than 80% of our max execution time
+ // or if the provider doesn't provide a getExpectedRuntime() method
+ if (!$provider instanceof IProviderWithExpectedRuntime || $provider->getExpectedRuntime() > $maxExecutionTime * 0.8) {
+ $this->scheduleTask($task);
+ return false;
+ }
+ $this->runTask($task);
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
public function deleteTask(Task $task): void {
$taskEntity = DbTask::fromPublicTask($task);
$this->taskMapper->delete($taskEntity);
@@ -253,4 +255,30 @@ class Manager implements IManager {
throw new RuntimeException('Failure while trying to find tasks by appId and identifier: ' . $e->getMessage(), 0, $e);
}
}
+
+ /**
+ * @param OCPTask $task
+ * @return IProvider[]
+ */
+ public function getPreferredProviders(OCPTask $task): array {
+ $providers = $this->getProviders();
+ $json = $this->config->getAppValue('core', 'ai.textprocessing_provider_preferences', '');
+ if ($json !== '') {
+ $preferences = json_decode($json, true);
+ if (isset($preferences[$task->getType()])) {
+ // If a preference for this task type is set, move the preferred provider to the start
+ $provider = current(array_values(array_filter($providers, function ($provider) use ($preferences, $task) {
+ if ($provider instanceof IProviderWithId) {
+ return $provider->getId() === $preferences[$task->getType()];
+ }
+ return $provider::class === $preferences[$task->getType()];
+ })));
+ if ($provider !== false) {
+ $providers = array_filter($providers, fn ($p) => $p !== $provider);
+ array_unshift($providers, $provider);
+ }
+ }
+ }
+ return array_values(array_filter($providers, fn (IProvider $provider) => $task->canUseProvider($provider)));
+ }
}
diff --git a/lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php b/lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php
index 89d329acfbb..2a71256c492 100644
--- a/lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php
+++ b/lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
diff --git a/lib/private/TextProcessing/TaskBackgroundJob.php b/lib/private/TextProcessing/TaskBackgroundJob.php
index 4c24b3e531f..781d8207934 100644
--- a/lib/private/TextProcessing/TaskBackgroundJob.php
+++ b/lib/private/TextProcessing/TaskBackgroundJob.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net>
- *
- * @author Marcel Klehr <mklehr@gmx.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
diff --git a/lib/private/TextToImage/Db/Task.php b/lib/private/TextToImage/Db/Task.php
new file mode 100644
index 00000000000..d7eb0a22014
--- /dev/null
+++ b/lib/private/TextToImage/Db/Task.php
@@ -0,0 +1,101 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\TextToImage\Db;
+
+use DateTime;
+use OCP\AppFramework\Db\Entity;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\TextToImage\Task as OCPTask;
+
+/**
+ * @method setLastUpdated(DateTime $lastUpdated)
+ * @method DateTime getLastUpdated()
+ * @method setInput(string $type)
+ * @method string getInput()
+ * @method setResultPath(string $resultPath)
+ * @method string getResultPath()
+ * @method setStatus(int $type)
+ * @method int getStatus()
+ * @method setUserId(?string $userId)
+ * @method string|null getUserId()
+ * @method setAppId(string $type)
+ * @method string getAppId()
+ * @method setIdentifier(string $identifier)
+ * @method string|null getIdentifier()
+ * @method setNumberOfImages(int $numberOfImages)
+ * @method int getNumberOfImages()
+ * @method setCompletionExpectedAt(DateTime $at)
+ * @method DateTime getCompletionExpectedAt()
+ */
+class Task extends Entity {
+ protected $lastUpdated;
+ protected $type;
+ protected $input;
+ protected $status;
+ protected $userId;
+ protected $appId;
+ protected $identifier;
+ protected $numberOfImages;
+ protected $completionExpectedAt;
+
+ /**
+ * @var string[]
+ */
+ public static array $columns = ['id', 'last_updated', 'input', 'status', 'user_id', 'app_id', 'identifier', 'number_of_images', 'completion_expected_at'];
+
+ /**
+ * @var string[]
+ */
+ public static array $fields = ['id', 'lastUpdated', 'input', 'status', 'userId', 'appId', 'identifier', 'numberOfImages', 'completionExpectedAt'];
+
+
+ public function __construct() {
+ // add types in constructor
+ $this->addType('id', 'integer');
+ $this->addType('lastUpdated', 'datetime');
+ $this->addType('input', 'string');
+ $this->addType('status', 'integer');
+ $this->addType('userId', 'string');
+ $this->addType('appId', 'string');
+ $this->addType('identifier', 'string');
+ $this->addType('numberOfImages', 'integer');
+ $this->addType('completionExpectedAt', 'datetime');
+ }
+
+ public function toRow(): array {
+ return array_combine(self::$columns, array_map(function ($field) {
+ return $this->{'get'.ucfirst($field)}();
+ }, self::$fields));
+ }
+
+ public static function fromPublicTask(OCPTask $task): Task {
+ /** @var Task $dbTask */
+ $dbTask = Task::fromParams([
+ 'id' => $task->getId(),
+ 'lastUpdated' => \OCP\Server::get(ITimeFactory::class)->getDateTime(),
+ 'status' => $task->getStatus(),
+ 'numberOfImages' => $task->getNumberOfImages(),
+ 'input' => $task->getInput(),
+ 'userId' => $task->getUserId(),
+ 'appId' => $task->getAppId(),
+ 'identifier' => $task->getIdentifier(),
+ 'completionExpectedAt' => $task->getCompletionExpectedAt(),
+ ]);
+ return $dbTask;
+ }
+
+ public function toPublicTask(): OCPTask {
+ $task = new OCPTask($this->getInput(), $this->getAppId(), $this->getNumberOfImages(), $this->getuserId(), $this->getIdentifier());
+ $task->setId($this->getId());
+ $task->setStatus($this->getStatus());
+ $task->setCompletionExpectedAt($this->getCompletionExpectedAt());
+ return $task;
+ }
+}
diff --git a/lib/private/TextToImage/Db/TaskMapper.php b/lib/private/TextToImage/Db/TaskMapper.php
new file mode 100644
index 00000000000..4c0357884e3
--- /dev/null
+++ b/lib/private/TextToImage/Db/TaskMapper.php
@@ -0,0 +1,111 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\TextToImage\Db;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\Entity;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\DB\Exception;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+/**
+ * @extends QBMapper<Task>
+ */
+class TaskMapper extends QBMapper {
+ public function __construct(
+ IDBConnection $db,
+ private ITimeFactory $timeFactory,
+ ) {
+ parent::__construct($db, 'text2image_tasks', Task::class);
+ }
+
+ /**
+ * @param int $id
+ * @return Task
+ * @throws Exception
+ * @throws DoesNotExistException
+ * @throws MultipleObjectsReturnedException
+ */
+ public function find(int $id): Task {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @param int $id
+ * @param string|null $userId
+ * @return Task
+ * @throws DoesNotExistException
+ * @throws Exception
+ * @throws MultipleObjectsReturnedException
+ */
+ public function findByIdAndUser(int $id, ?string $userId): Task {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
+ if ($userId === null) {
+ $qb->andWhere($qb->expr()->isNull('user_id'));
+ } else {
+ $qb->andWhere($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)));
+ }
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @param string $userId
+ * @param string $appId
+ * @param string|null $identifier
+ * @return array
+ * @throws Exception
+ */
+ public function findUserTasksByApp(?string $userId, string $appId, ?string $identifier = null): array {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select(Task::$columns)
+ ->from($this->tableName)
+ ->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)))
+ ->andWhere($qb->expr()->eq('app_id', $qb->createPositionalParameter($appId)));
+ if ($identifier !== null) {
+ $qb->andWhere($qb->expr()->eq('identifier', $qb->createPositionalParameter($identifier)));
+ }
+ return $this->findEntities($qb);
+ }
+
+ /**
+ * @param int $timeout
+ * @return Task[] the deleted tasks
+ * @throws Exception
+ */
+ public function deleteOlderThan(int $timeout): array {
+ $datetime = $this->timeFactory->getDateTime();
+ $datetime->sub(new \DateInterval('PT'.$timeout.'S'));
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->tableName)
+ ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($datetime, IQueryBuilder::PARAM_DATE)));
+ $deletedTasks = $this->findEntities($qb);
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete($this->tableName)
+ ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($datetime, IQueryBuilder::PARAM_DATE)));
+ $qb->executeStatement();
+ return $deletedTasks;
+ }
+
+ public function update(Entity $entity): Entity {
+ $entity->setLastUpdated($this->timeFactory->getDateTime());
+ return parent::update($entity);
+ }
+}
diff --git a/lib/private/TextToImage/Manager.php b/lib/private/TextToImage/Manager.php
new file mode 100644
index 00000000000..6ad3592a1b7
--- /dev/null
+++ b/lib/private/TextToImage/Manager.php
@@ -0,0 +1,325 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\TextToImage;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\TextToImage\Db\Task as DbTask;
+use OC\TextToImage\Db\TaskMapper;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\BackgroundJob\IJobList;
+use OCP\DB\Exception;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\IConfig;
+use OCP\IServerContainer;
+use OCP\PreConditionNotMetException;
+use OCP\TextToImage\Exception\TaskFailureException;
+use OCP\TextToImage\Exception\TaskNotFoundException;
+use OCP\TextToImage\IManager;
+use OCP\TextToImage\IProvider;
+use OCP\TextToImage\IProviderWithUserId;
+use OCP\TextToImage\Task;
+use Psr\Log\LoggerInterface;
+use RuntimeException;
+use Throwable;
+
+class Manager implements IManager {
+ /** @var ?list<IProvider> */
+ private ?array $providers = null;
+ private IAppData $appData;
+
+ public function __construct(
+ private IServerContainer $serverContainer,
+ private Coordinator $coordinator,
+ private LoggerInterface $logger,
+ private IJobList $jobList,
+ private TaskMapper $taskMapper,
+ private IConfig $config,
+ IAppDataFactory $appDataFactory,
+ ) {
+ $this->appData = $appDataFactory->get('core');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getProviders(): array {
+ $context = $this->coordinator->getRegistrationContext();
+ if ($context === null) {
+ return [];
+ }
+
+ if ($this->providers !== null) {
+ return $this->providers;
+ }
+
+ $this->providers = [];
+
+ foreach ($context->getTextToImageProviders() as $providerServiceRegistration) {
+ $class = $providerServiceRegistration->getService();
+ try {
+ /** @var IProvider $provider */
+ $provider = $this->serverContainer->get($class);
+ $this->providers[] = $provider;
+ } catch (Throwable $e) {
+ $this->logger->error('Failed to load Text to image provider ' . $class, [
+ 'exception' => $e,
+ ]);
+ }
+ }
+
+ return $this->providers;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasProviders(): bool {
+ $context = $this->coordinator->getRegistrationContext();
+ if ($context === null) {
+ return false;
+ }
+ return count($context->getTextToImageProviders()) > 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function runTask(Task $task): void {
+ $this->logger->debug('Running TextToImage Task');
+ if (!$this->hasProviders()) {
+ throw new PreConditionNotMetException('No text to image provider is installed that can handle this task');
+ }
+ $providers = $this->getPreferredProviders();
+
+ foreach ($providers as $provider) {
+ $this->logger->debug('Trying to run Text2Image provider '.$provider::class);
+ try {
+ $task->setStatus(Task::STATUS_RUNNING);
+ $completionExpectedAt = new \DateTime('now');
+ $completionExpectedAt->add(new \DateInterval('PT'.$provider->getExpectedRuntime().'S'));
+ $task->setCompletionExpectedAt($completionExpectedAt);
+ if ($task->getId() === null) {
+ $this->logger->debug('Inserting Text2Image task into DB');
+ $taskEntity = $this->taskMapper->insert(DbTask::fromPublicTask($task));
+ $task->setId($taskEntity->getId());
+ } else {
+ $this->logger->debug('Updating Text2Image task in DB');
+ $this->taskMapper->update(DbTask::fromPublicTask($task));
+ }
+ try {
+ $folder = $this->appData->getFolder('text2image');
+ } catch(NotFoundException) {
+ $this->logger->debug('Creating folder in appdata for Text2Image results');
+ $folder = $this->appData->newFolder('text2image');
+ }
+ try {
+ $folder = $folder->getFolder((string) $task->getId());
+ } catch(NotFoundException) {
+ $this->logger->debug('Creating new folder in appdata Text2Image results folder');
+ $folder = $folder->newFolder((string) $task->getId());
+ }
+ $this->logger->debug('Creating result files for Text2Image task');
+ $resources = [];
+ $files = [];
+ for ($i = 0; $i < $task->getNumberOfImages(); $i++) {
+ $file = $folder->newFile((string) $i);
+ $files[] = $file;
+ $resource = $file->write();
+ if ($resource !== false && $resource !== true && is_resource($resource)) {
+ $resources[] = $resource;
+ } else {
+ throw new RuntimeException('Text2Image generation using provider "' . $provider->getName() . '" failed: Couldn\'t open file to write.');
+ }
+ }
+ $this->logger->debug('Calling Text2Image provider\'s generate method');
+ if ($provider instanceof IProviderWithUserId) {
+ $provider->setUserId($task->getUserId());
+ }
+ $provider->generate($task->getInput(), $resources);
+ for ($i = 0; $i < $task->getNumberOfImages(); $i++) {
+ if (is_resource($resources[$i])) {
+ // If $resource hasn't been closed yet, we'll do that here
+ fclose($resources[$i]);
+ }
+ }
+ $task->setStatus(Task::STATUS_SUCCESSFUL);
+ $this->logger->debug('Updating Text2Image task in DB');
+ $this->taskMapper->update(DbTask::fromPublicTask($task));
+ return;
+ } catch (\RuntimeException|\Throwable $e) {
+ for ($i = 0; $i < $task->getNumberOfImages(); $i++) {
+ if (isset($files, $files[$i])) {
+ try {
+ $files[$i]->delete();
+ } catch(NotPermittedException $e) {
+ $this->logger->warning('Failed to clean up Text2Image result file after error', ['exception' => $e]);
+ }
+ }
+ }
+
+ $this->logger->info('Text2Image generation using provider "' . $provider->getName() . '" failed', ['exception' => $e]);
+ $task->setStatus(Task::STATUS_FAILED);
+ try {
+ $this->taskMapper->update(DbTask::fromPublicTask($task));
+ } catch (Exception $e) {
+ $this->logger->warning('Failed to update database after Text2Image error', ['exception' => $e]);
+ }
+ throw new TaskFailureException('Text2Image generation using provider "' . $provider->getName() . '" failed: ' . $e->getMessage(), 0, $e);
+ }
+ }
+
+ $task->setStatus(Task::STATUS_FAILED);
+ try {
+ $this->taskMapper->update(DbTask::fromPublicTask($task));
+ } catch (Exception $e) {
+ $this->logger->warning('Failed to update database after Text2Image error', ['exception' => $e]);
+ }
+ throw new TaskFailureException('Could not run task');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function scheduleTask(Task $task): void {
+ if (!$this->hasProviders()) {
+ throw new PreConditionNotMetException('No text to image provider is installed that can handle this task');
+ }
+ $this->logger->debug('Scheduling Text2Image Task');
+ $task->setStatus(Task::STATUS_SCHEDULED);
+ $completionExpectedAt = new \DateTime('now');
+ $completionExpectedAt->add(new \DateInterval('PT'.$this->getPreferredProviders()[0]->getExpectedRuntime().'S'));
+ $task->setCompletionExpectedAt($completionExpectedAt);
+ $taskEntity = DbTask::fromPublicTask($task);
+ $this->taskMapper->insert($taskEntity);
+ $task->setId($taskEntity->getId());
+ $this->jobList->add(TaskBackgroundJob::class, [
+ 'taskId' => $task->getId()
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function runOrScheduleTask(Task $task) : void {
+ if (!$this->hasProviders()) {
+ throw new PreConditionNotMetException('No text to image provider is installed that can handle this task');
+ }
+ $providers = $this->getPreferredProviders();
+ $maxExecutionTime = (int) ini_get('max_execution_time');
+ // Offload the task to a background job if the expected runtime of the likely provider is longer than 80% of our max execution time
+ if ($providers[0]->getExpectedRuntime() > $maxExecutionTime * 0.8) {
+ $this->scheduleTask($task);
+ return;
+ }
+ $this->runTask($task);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function deleteTask(Task $task): void {
+ $taskEntity = DbTask::fromPublicTask($task);
+ $this->taskMapper->delete($taskEntity);
+ $this->jobList->remove(TaskBackgroundJob::class, [
+ 'taskId' => $task->getId()
+ ]);
+ }
+
+ /**
+ * Get a task from its id
+ *
+ * @param int $id The id of the task
+ * @return Task
+ * @throws RuntimeException If the query failed
+ * @throws TaskNotFoundException If the task could not be found
+ */
+ public function getTask(int $id): Task {
+ try {
+ $taskEntity = $this->taskMapper->find($id);
+ return $taskEntity->toPublicTask();
+ } catch (DoesNotExistException $e) {
+ throw new TaskNotFoundException('Could not find task with the provided id');
+ } catch (MultipleObjectsReturnedException $e) {
+ throw new RuntimeException('Could not uniquely identify task with given id', 0, $e);
+ } catch (Exception $e) {
+ throw new RuntimeException('Failure while trying to find task by id: ' . $e->getMessage(), 0, $e);
+ }
+ }
+
+ /**
+ * Get a task from its user id and task id
+ * If userId is null, this can only get a task that was scheduled anonymously
+ *
+ * @param int $id The id of the task
+ * @param string|null $userId The user id that scheduled the task
+ * @return Task
+ * @throws RuntimeException If the query failed
+ * @throws TaskNotFoundException If the task could not be found
+ */
+ public function getUserTask(int $id, ?string $userId): Task {
+ try {
+ $taskEntity = $this->taskMapper->findByIdAndUser($id, $userId);
+ return $taskEntity->toPublicTask();
+ } catch (DoesNotExistException $e) {
+ throw new TaskNotFoundException('Could not find task with the provided id and user id');
+ } catch (MultipleObjectsReturnedException $e) {
+ throw new RuntimeException('Could not uniquely identify task with given id and user id', 0, $e);
+ } catch (Exception $e) {
+ throw new RuntimeException('Failure while trying to find task by id and user id: ' . $e->getMessage(), 0, $e);
+ }
+ }
+
+ /**
+ * Get a list of tasks scheduled by a specific user for a specific app
+ * and optionally with a specific identifier.
+ * This cannot be used to get anonymously scheduled tasks
+ *
+ * @param string $userId
+ * @param string $appId
+ * @param string|null $identifier
+ * @return Task[]
+ * @throws RuntimeException
+ */
+ public function getUserTasksByApp(?string $userId, string $appId, ?string $identifier = null): array {
+ try {
+ $taskEntities = $this->taskMapper->findUserTasksByApp($userId, $appId, $identifier);
+ return array_map(static function (DbTask $taskEntity) {
+ return $taskEntity->toPublicTask();
+ }, $taskEntities);
+ } catch (Exception $e) {
+ throw new RuntimeException('Failure while trying to find tasks by appId and identifier: ' . $e->getMessage(), 0, $e);
+ }
+ }
+
+ /**
+ * @return list<IProvider>
+ */
+ private function getPreferredProviders() {
+ $providers = $this->getProviders();
+ $json = $this->config->getAppValue('core', 'ai.text2image_provider', '');
+ if ($json !== '') {
+ try {
+ $id = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
+ $provider = current(array_filter($providers, fn ($provider) => $provider->getId() === $id));
+ if ($provider !== false && $provider !== null) {
+ $providers = [$provider];
+ }
+ } catch (\JsonException $e) {
+ $this->logger->warning('Failed to decode Text2Image setting `ai.text2image_provider`', ['exception' => $e]);
+ }
+ }
+
+ return $providers;
+ }
+}
diff --git a/lib/private/TextToImage/RemoveOldTasksBackgroundJob.php b/lib/private/TextToImage/RemoveOldTasksBackgroundJob.php
new file mode 100644
index 00000000000..525d68df22b
--- /dev/null
+++ b/lib/private/TextToImage/RemoveOldTasksBackgroundJob.php
@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+
+namespace OC\TextToImage;
+
+use OC\TextToImage\Db\TaskMapper;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\TimedJob;
+use OCP\DB\Exception;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use Psr\Log\LoggerInterface;
+
+class RemoveOldTasksBackgroundJob extends TimedJob {
+ public const MAX_TASK_AGE_SECONDS = 60 * 50 * 24 * 7; // 1 week
+
+ private IAppData $appData;
+
+ public function __construct(
+ ITimeFactory $timeFactory,
+ private TaskMapper $taskMapper,
+ private LoggerInterface $logger,
+ IAppDataFactory $appDataFactory,
+ ) {
+ parent::__construct($timeFactory);
+ $this->appData = $appDataFactory->get('core');
+ $this->setInterval(60 * 60 * 24);
+ }
+
+ /**
+ * @param mixed $argument
+ * @inheritDoc
+ */
+ protected function run($argument) {
+ try {
+ $deletedTasks = $this->taskMapper->deleteOlderThan(self::MAX_TASK_AGE_SECONDS);
+ $folder = $this->appData->getFolder('text2image');
+ foreach ($deletedTasks as $deletedTask) {
+ try {
+ $folder->getFolder((string)$deletedTask->getId())->delete();
+ } catch (NotFoundException) {
+ // noop
+ } catch (NotPermittedException $e) {
+ $this->logger->warning('Failed to delete stale text to image task files', ['exception' => $e]);
+ }
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('Failed to delete stale text to image tasks', ['exception' => $e]);
+ } catch(NotFoundException) {
+ // noop
+ }
+ }
+}
diff --git a/lib/private/TextToImage/TaskBackgroundJob.php b/lib/private/TextToImage/TaskBackgroundJob.php
new file mode 100644
index 00000000000..16990005530
--- /dev/null
+++ b/lib/private/TextToImage/TaskBackgroundJob.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+
+namespace OC\TextToImage;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\QueuedJob;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\TextToImage\Events\TaskFailedEvent;
+use OCP\TextToImage\Events\TaskSuccessfulEvent;
+use OCP\TextToImage\IManager;
+
+class TaskBackgroundJob extends QueuedJob {
+ public function __construct(
+ ITimeFactory $timeFactory,
+ private IManager $text2imageManager,
+ private IEventDispatcher $eventDispatcher,
+ ) {
+ parent::__construct($timeFactory);
+ // We want to avoid overloading the machine with these jobs
+ // so we only allow running one job at a time
+ $this->setAllowParallelRuns(false);
+ }
+
+ /**
+ * @param array{taskId: int} $argument
+ * @inheritDoc
+ */
+ protected function run($argument) {
+ $taskId = $argument['taskId'];
+ $task = $this->text2imageManager->getTask($taskId);
+ try {
+ $this->text2imageManager->runTask($task);
+ $event = new TaskSuccessfulEvent($task);
+ } catch (\Throwable $e) {
+ $event = new TaskFailedEvent($task, $e->getMessage());
+ }
+ $this->eventDispatcher->dispatchTyped($event);
+ }
+}
diff --git a/lib/private/Translation/TranslationManager.php b/lib/private/Translation/TranslationManager.php
index 48a0e2cdebd..08f9f36678a 100644
--- a/lib/private/Translation/TranslationManager.php
+++ b/lib/private/Translation/TranslationManager.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Julius Härtl <jus@bitgrid.net>
- *
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -30,11 +14,14 @@ use InvalidArgumentException;
use OC\AppFramework\Bootstrap\Coordinator;
use OCP\IConfig;
use OCP\IServerContainer;
+use OCP\IUserSession;
use OCP\PreConditionNotMetException;
use OCP\Translation\CouldNotTranslateException;
use OCP\Translation\IDetectLanguageProvider;
use OCP\Translation\ITranslationManager;
use OCP\Translation\ITranslationProvider;
+use OCP\Translation\ITranslationProviderWithId;
+use OCP\Translation\ITranslationProviderWithUserId;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
@@ -50,6 +37,7 @@ class TranslationManager implements ITranslationManager {
private Coordinator $coordinator,
private LoggerInterface $logger,
private IConfig $config,
+ private IUserSession $userSession,
) {
}
@@ -73,19 +61,26 @@ class TranslationManager implements ITranslationManager {
$precedence = json_decode($json, true);
$newProviders = [];
foreach ($precedence as $className) {
- $provider = current(array_filter($providers, fn ($provider) => $provider::class === $className));
+ $provider = current(array_filter($providers, function ($provider) use ($className) {
+ return $provider instanceof ITranslationProviderWithId ? $provider->getId() === $className : $provider::class === $className;
+ }));
if ($provider !== false) {
$newProviders[] = $provider;
}
}
// Add all providers that haven't been added so far
- $newProviders += array_udiff($providers, $newProviders, fn ($a, $b) => $a::class > $b::class ? 1 : ($a::class < $b::class ? -1 : 0));
+ $newProviders += array_udiff($providers, $newProviders, function ($a, $b) {
+ return ($a instanceof ITranslationProviderWithId ? $a->getId() : $a::class) <=> ($b instanceof ITranslationProviderWithId ? $b->getId() : $b::class);
+ });
$providers = $newProviders;
}
if ($fromLanguage === null) {
foreach ($providers as $provider) {
if ($provider instanceof IDetectLanguageProvider) {
+ if ($provider instanceof ITranslationProviderWithUserId) {
+ $provider->setUserId($this->userSession->getUser()?->getUID());
+ }
$fromLanguage = $provider->detectLanguage($text);
}
@@ -105,6 +100,9 @@ class TranslationManager implements ITranslationManager {
foreach ($providers as $provider) {
try {
+ if ($provider instanceof ITranslationProviderWithUserId) {
+ $provider->setUserId($this->userSession->getUser()?->getUID());
+ }
return $provider->translate($fromLanguage, $toLanguage, $text);
} catch (RuntimeException $e) {
$this->logger->warning("Failed to translate from {$fromLanguage} to {$toLanguage} using provider {$provider->getName()}", ['exception' => $e]);
diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php
index 3a52b99889c..ab568a3296d 100644
--- a/lib/private/URLGenerator.php
+++ b/lib/private/URLGenerator.php
@@ -1,42 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Rudolf <github.com@daniel-rudolf.de>
- * @author Felix Epp <work@felixepp.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Haertl <jus@bitgrid.net>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author mmccarn <mmccarn-github@mmsionline.us>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
@@ -70,10 +38,10 @@ class URLGenerator implements IURLGenerator {
private ?IAppManager $appManager = null;
public function __construct(IConfig $config,
- IUserSession $userSession,
- ICacheFactory $cacheFactory,
- IRequest $request,
- Router $router
+ IUserSession $userSession,
+ ICacheFactory $cacheFactory,
+ IRequest $request,
+ Router $router
) {
$this->config = $config;
$this->userSession = $userSession;
@@ -116,16 +84,25 @@ class URLGenerator implements IURLGenerator {
}
public function linkToOCSRouteAbsolute(string $routeName, array $arguments = []): string {
+ // Returns `/subfolder/index.php/ocsapp/…` with `'htaccess.IgnoreFrontController' => false` in config.php
+ // And `/subfolder/ocsapp/…` with `'htaccess.IgnoreFrontController' => true` in config.php
$route = $this->router->generate('ocs.'.$routeName, $arguments, false);
- $indexPhpPos = strpos($route, '/index.php/');
- if ($indexPhpPos !== false) {
- $route = substr($route, $indexPhpPos + 10);
+ // Cut off `/subfolder`
+ if (\OC::$WEBROOT !== '' && str_starts_with($route, \OC::$WEBROOT)) {
+ $route = substr($route, \strlen(\OC::$WEBROOT));
+ }
+
+ if (str_starts_with($route, '/index.php/')) {
+ $route = substr($route, 10);
}
+ // Remove `ocsapp/` bit
$route = substr($route, 7);
+ // Prefix with ocs/v2.php endpoint
$route = '/ocs/v2.php' . $route;
+ // Turn into an absolute URL
return $this->getAbsoluteURL($route);
}
@@ -147,7 +124,7 @@ class URLGenerator implements IURLGenerator {
$app_path = $this->getAppManager()->getAppPath($appName);
// Check if the app is in the app folder
if (file_exists($app_path . '/' . $file)) {
- if (substr($file, -3) === 'php') {
+ if (str_ends_with($file, 'php')) {
$urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $appName;
if ($frontControllerActive) {
$urlLinkTo = \OC::$WEBROOT . '/apps/' . $appName;
@@ -217,7 +194,7 @@ class URLGenerator implements IURLGenerator {
$themingEnabled = $this->config->getSystemValueBool('installed', false) && $this->getAppManager()->isEnabledForUser('theming');
$themingImagePath = false;
if ($themingEnabled) {
- $themingDefaults = \OC::$server->getThemingDefaults();
+ $themingDefaults = \OC::$server->get('ThemingDefaults');
if ($themingDefaults instanceof ThemingDefaults) {
$themingImagePath = $themingDefaults->replaceImagePath($appName, $file);
}
@@ -290,7 +267,7 @@ class URLGenerator implements IURLGenerator {
* @return string url to the online documentation
*/
public function linkToDocs(string $key): string {
- $theme = \OC::$server->getThemingDefaults();
+ $theme = \OC::$server->get('ThemingDefaults');
return $theme->buildDocLinkToKey($key);
}
diff --git a/lib/private/Updater.php b/lib/private/Updater.php
index 5a14bb17507..6d23e81aa63 100644
--- a/lib/private/Updater.php
+++ b/lib/private/Updater.php
@@ -3,51 +3,14 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Steffen Lindner <mail@steffen-lindner.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC;
-use OCP\App\IAppManager;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventDispatcher;
-use OCP\HintException;
-use OCP\IConfig;
-use OCP\ILogger;
-use OCP\Util;
use OC\App\AppManager;
+use OC\App\AppStore\Fetcher\AppFetcher;
use OC\DB\Connection;
use OC\DB\MigrationService;
use OC\DB\MigratorExecuteSqlEvent;
@@ -61,6 +24,14 @@ use OC\Repair\Events\RepairStartEvent;
use OC\Repair\Events\RepairStepEvent;
use OC\Repair\Events\RepairWarningEvent;
use OC_App;
+use OCP\App\IAppManager;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\HintException;
+use OCP\IAppConfig;
+use OCP\IConfig;
+use OCP\ILogger;
+use OCP\Util;
use Psr\Log\LoggerInterface;
/**
@@ -73,19 +44,7 @@ use Psr\Log\LoggerInterface;
* - failure(string $message)
*/
class Updater extends BasicEmitter {
- /** @var LoggerInterface */
- private $log;
-
- /** @var IConfig */
- private $config;
-
- /** @var Checker */
- private $checker;
-
- /** @var Installer */
- private $installer;
-
- private $logLevelNames = [
+ private array $logLevelNames = [
0 => 'Debug',
1 => 'Info',
2 => 'Warning',
@@ -93,14 +52,13 @@ class Updater extends BasicEmitter {
4 => 'Fatal',
];
- public function __construct(IConfig $config,
- Checker $checker,
- ?LoggerInterface $log,
- Installer $installer) {
- $this->log = $log;
- $this->config = $config;
- $this->checker = $checker;
- $this->installer = $installer;
+ public function __construct(
+ private IConfig $config,
+ private IAppConfig $appConfig,
+ private Checker $checker,
+ private ?LoggerInterface $log,
+ private Installer $installer
+ ) {
}
/**
@@ -255,7 +213,8 @@ class Updater extends BasicEmitter {
file_put_contents($this->config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
// pre-upgrade repairs
- $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->get(LoggerInterface::class));
+ $repair = \OCP\Server::get(Repair::class);
+ $repair->setRepairSteps(Repair::getBeforeUpgradeRepairSteps());
$repair->run();
$this->doCoreUpgrade();
@@ -272,7 +231,7 @@ class Updater extends BasicEmitter {
$this->doAppUpgrade();
// Update the appfetchers version so it downloads the correct list from the appstore
- \OC::$server->getAppFetcher()->setVersion($currentVersion);
+ \OC::$server->get(AppFetcher::class)->setVersion($currentVersion);
/** @var AppManager $appManager */
$appManager = \OC::$server->getAppManager();
@@ -296,11 +255,12 @@ class Updater extends BasicEmitter {
}
// post-upgrade repairs
- $repair = new Repair(Repair::getRepairSteps(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->get(LoggerInterface::class));
+ $repair = \OCP\Server::get(Repair::class);
+ $repair->setRepairSteps(Repair::getRepairSteps());
$repair->run();
//Invalidate update feed
- $this->config->setAppValue('core', 'lastupdatedat', '0');
+ $this->appConfig->setValueInt('core', 'lastupdatedat', 0);
// Check for code integrity if not disabled
if (\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
diff --git a/lib/private/Updater/Changes.php b/lib/private/Updater/Changes.php
index 81a57c0c871..bdf799a0100 100644
--- a/lib/private/Updater/Changes.php
+++ b/lib/private/Updater/Changes.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Updater;
diff --git a/lib/private/Updater/ChangesCheck.php b/lib/private/Updater/ChangesCheck.php
index ee4d1f1fcee..df017b09040 100644
--- a/lib/private/Updater/ChangesCheck.php
+++ b/lib/private/Updater/ChangesCheck.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Updater;
diff --git a/lib/private/Updater/ChangesMapper.php b/lib/private/Updater/ChangesMapper.php
index 33d50f5844f..5583cf5a1a6 100644
--- a/lib/private/Updater/ChangesMapper.php
+++ b/lib/private/Updater/ChangesMapper.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Updater;
diff --git a/lib/private/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php
index 2aab260716a..9ad129db1a4 100644
--- a/lib/private/Updater/VersionCheck.php
+++ b/lib/private/Updater/VersionCheck.php
@@ -1,43 +1,28 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Updater;
use OCP\Http\Client\IClientService;
+use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IUserManager;
use OCP\Support\Subscription\IRegistry;
use OCP\Util;
+use Psr\Log\LoggerInterface;
class VersionCheck {
public function __construct(
private IClientService $clientService,
private IConfig $config,
+ private IAppConfig $appConfig,
private IUserManager $userManager,
private IRegistry $registry,
+ private LoggerInterface $logger,
) {
}
@@ -54,13 +39,13 @@ class VersionCheck {
}
// Look up the cache - it is invalidated all 30 minutes
- if (((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) {
+ if (($this->appConfig->getValueInt('core', 'lastupdatedat') + 1800) > time()) {
return json_decode($this->config->getAppValue('core', 'lastupdateResult'), true);
}
$updaterUrl = $this->config->getSystemValueString('updater.server.url', 'https://updates.nextcloud.com/updater_server/');
- $this->config->setAppValue('core', 'lastupdatedat', (string)time());
+ $this->appConfig->setValueInt('core', 'lastupdatedat', time());
if ($this->config->getAppValue('core', 'installedat', '') === '') {
$this->config->setAppValue('core', 'installedat', (string)microtime(true));
@@ -68,7 +53,7 @@ class VersionCheck {
$version = Util::getVersion();
$version['installed'] = $this->config->getAppValue('core', 'installedat');
- $version['updated'] = $this->config->getAppValue('core', 'lastupdatedat');
+ $version['updated'] = $this->appConfig->getValueInt('core', 'lastupdatedat');
$version['updatechannel'] = \OC_Util::getChannel();
$version['edition'] = '';
$version['build'] = \OC_Util::getBuild();
@@ -86,6 +71,8 @@ class VersionCheck {
try {
$xml = $this->getUrlContent($url);
} catch (\Exception $e) {
+ $this->logger->info('Version could not be fetched from updater server: ' . $url, ['exception' => $e]);
+
return false;
}
@@ -123,7 +110,9 @@ class VersionCheck {
*/
protected function getUrlContent($url) {
$client = $this->clientService->newClient();
- $response = $client->get($url);
+ $response = $client->get($url, [
+ 'timeout' => 5,
+ ]);
return $response->getBody();
}
diff --git a/lib/private/User/AvailabilityCoordinator.php b/lib/private/User/AvailabilityCoordinator.php
new file mode 100644
index 00000000000..5017a85c28b
--- /dev/null
+++ b/lib/private/User/AvailabilityCoordinator.php
@@ -0,0 +1,122 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\User;
+
+use JsonException;
+use OCA\DAV\AppInfo\Application;
+use OCA\DAV\CalDAV\TimezoneService;
+use OCA\DAV\Service\AbsenceService;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+use OCP\IUser;
+use OCP\User\IAvailabilityCoordinator;
+use OCP\User\IOutOfOfficeData;
+use Psr\Log\LoggerInterface;
+
+class AvailabilityCoordinator implements IAvailabilityCoordinator {
+ private ICache $cache;
+
+ public function __construct(
+ ICacheFactory $cacheFactory,
+ private IConfig $config,
+ private AbsenceService $absenceService,
+ private LoggerInterface $logger,
+ private TimezoneService $timezoneService,
+ ) {
+ $this->cache = $cacheFactory->createLocal('OutOfOfficeData');
+ }
+
+ public function isEnabled(): bool {
+ return $this->config->getAppValue(Application::APP_ID, 'hide_absence_settings', 'no') === 'no';
+ }
+
+ private function getCachedOutOfOfficeData(IUser $user): ?OutOfOfficeData {
+ $cachedString = $this->cache->get($user->getUID());
+ if ($cachedString === null) {
+ return null;
+ }
+
+ try {
+ $cachedData = json_decode($cachedString, true, 10, JSON_THROW_ON_ERROR);
+ } catch (JsonException $e) {
+ $this->logger->error('Failed to deserialize cached out-of-office data: ' . $e->getMessage(), [
+ 'exception' => $e,
+ 'json' => $cachedString,
+ ]);
+ return null;
+ }
+
+ return new OutOfOfficeData(
+ $cachedData['id'],
+ $user,
+ $cachedData['startDate'],
+ $cachedData['endDate'],
+ $cachedData['shortMessage'],
+ $cachedData['message'],
+ );
+ }
+
+ private function setCachedOutOfOfficeData(IOutOfOfficeData $data): void {
+ try {
+ $cachedString = json_encode([
+ 'id' => $data->getId(),
+ 'startDate' => $data->getStartDate(),
+ 'endDate' => $data->getEndDate(),
+ 'shortMessage' => $data->getShortMessage(),
+ 'message' => $data->getMessage(),
+ ], JSON_THROW_ON_ERROR);
+ } catch (JsonException $e) {
+ $this->logger->error('Failed to serialize out-of-office data: ' . $e->getMessage(), [
+ 'exception' => $e,
+ ]);
+ return;
+ }
+
+ $this->cache->set($data->getUser()->getUID(), $cachedString, 300);
+ }
+
+ public function getCurrentOutOfOfficeData(IUser $user): ?IOutOfOfficeData {
+ $timezone = $this->getCachedTimezone($user->getUID());
+ if ($timezone === null) {
+ $timezone = $this->timezoneService->getUserTimezone($user->getUID()) ?? $this->timezoneService->getDefaultTimezone();
+ $this->setCachedTimezone($user->getUID(), $timezone);
+ }
+
+ $data = $this->getCachedOutOfOfficeData($user);
+ if ($data === null) {
+ $absenceData = $this->absenceService->getAbsence($user->getUID());
+ if ($absenceData === null) {
+ return null;
+ }
+ $data = $absenceData->toOutOufOfficeData($user, $timezone);
+ }
+
+ $this->setCachedOutOfOfficeData($data);
+ return $data;
+ }
+
+ private function getCachedTimezone(string $userId): ?string {
+ return $this->cache->get($userId . '_timezone') ?? null;
+ }
+
+ private function setCachedTimezone(string $userId, string $timezone): void {
+ $this->cache->set($userId . '_timezone', $timezone, 3600);
+ }
+
+ public function clearCache(string $userId): void {
+ $this->cache->set($userId, null, 300);
+ $this->cache->set($userId . '_timezone', null, 3600);
+ }
+
+ public function isInEffect(IOutOfOfficeData $data): bool {
+ return $this->absenceService->isInEffect($data);
+ }
+}
diff --git a/lib/private/User/Backend.php b/lib/private/User/Backend.php
index b68e4c2e541..98b291e5dee 100644
--- a/lib/private/User/Backend.php
+++ b/lib/private/User/Backend.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index 9ef1bc67a58..cc7050f2da8 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -1,47 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author adrien <adrien.waksberg@believedigital.com>
- * @author Aldo "xoen" Giambelluca <xoen@xoen.org>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author fabian <fabian@web2.0-apps.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Loki3000 <github@labcms.ru>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author nishiki <nishiki@yaegashi.fr>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
@@ -50,6 +13,7 @@ use OCP\Cache\CappedMemoryCache;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IDBConnection;
use OCP\Security\Events\ValidatePasswordPolicyEvent;
+use OCP\Security\IHasher;
use OCP\User\Backend\ABackend;
use OCP\User\Backend\ICheckPasswordBackend;
use OCP\User\Backend\ICountUsersBackend;
@@ -130,7 +94,7 @@ class Database extends ABackend implements
$qb->insert($this->table)
->values([
'uid' => $qb->createNamedParameter($uid),
- 'password' => $qb->createNamedParameter(\OC::$server->getHasher()->hash($password)),
+ 'password' => $qb->createNamedParameter(\OC::$server->get(IHasher::class)->hash($password)),
'uid_lower' => $qb->createNamedParameter(mb_strtolower($uid)),
]);
@@ -197,7 +161,7 @@ class Database extends ABackend implements
if ($this->userExists($uid)) {
$this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password));
- $hasher = \OC::$server->getHasher();
+ $hasher = \OC::$server->get(IHasher::class);
$hashedPassword = $hasher->hash($password);
$return = $this->updatePassword($uid, $hashedPassword);
@@ -353,7 +317,7 @@ class Database extends ABackend implements
if ($found && is_array($this->cache[$loginName])) {
$storedHash = $this->cache[$loginName]['password'];
$newHash = '';
- if (\OC::$server->getHasher()->verify($password, $storedHash, $newHash)) {
+ if (\OC::$server->get(IHasher::class)->verify($password, $storedHash, $newHash)) {
if (!empty($newHash)) {
$this->updatePassword($loginName, $newHash);
}
diff --git a/lib/private/User/DisplayNameCache.php b/lib/private/User/DisplayNameCache.php
index 6ee74cc9f6c..34db783de68 100644
--- a/lib/private/User/DisplayNameCache.php
+++ b/lib/private/User/DisplayNameCache.php
@@ -1,26 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license AGPL-3.0-or-later
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
-
namespace OC\User;
use OCP\EventDispatcher\Event;
@@ -37,6 +21,7 @@ use OCP\User\Events\UserDeletedEvent;
* This saves fetching the user from a user backend and later on fetching
* their preferences. It's generally not an issue if this data is slightly
* outdated.
+ * @template-implements IEventListener<UserChangedEvent|UserDeletedEvent>
*/
class DisplayNameCache implements IEventListener {
private array $cache = [];
diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php
index 396d3c252f1..80b2bfe510f 100644
--- a/lib/private/User/LazyUser.php
+++ b/lib/private/User/LazyUser.php
@@ -2,23 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\User;
diff --git a/lib/private/User/Listeners/BeforeUserDeletedListener.php b/lib/private/User/Listeners/BeforeUserDeletedListener.php
index ec1f80c5413..50dc9835400 100644
--- a/lib/private/User/Listeners/BeforeUserDeletedListener.php
+++ b/lib/private/User/Listeners/BeforeUserDeletedListener.php
@@ -3,31 +3,17 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\User\Listeners;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
-use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\Files\NotFoundException;
use OCP\IAvatarManager;
+use OCP\Security\ICredentialsManager;
+use OCP\User\Events\BeforeUserDeletedEvent;
use Psr\Log\LoggerInterface;
/**
@@ -35,10 +21,12 @@ use Psr\Log\LoggerInterface;
*/
class BeforeUserDeletedListener implements IEventListener {
private IAvatarManager $avatarManager;
+ private ICredentialsManager $credentialsManager;
private LoggerInterface $logger;
- public function __construct(LoggerInterface $logger, IAvatarManager $avatarManager) {
+ public function __construct(LoggerInterface $logger, IAvatarManager $avatarManager, ICredentialsManager $credentialsManager) {
$this->avatarManager = $avatarManager;
+ $this->credentialsManager = $credentialsManager;
$this->logger = $logger;
}
@@ -61,5 +49,7 @@ class BeforeUserDeletedListener implements IEventListener {
'exception' => $e,
]);
}
+ // Delete storages credentials on user deletion
+ $this->credentialsManager->erase($user->getUID());
}
}
diff --git a/lib/private/User/Listeners/UserChangedListener.php b/lib/private/User/Listeners/UserChangedListener.php
index a561db2423d..983a4e81233 100644
--- a/lib/private/User/Listeners/UserChangedListener.php
+++ b/lib/private/User/Listeners/UserChangedListener.php
@@ -3,31 +3,16 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Carl Schwan <carl@carlschwan.eu>
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\User\Listeners;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
-use OCP\User\Events\UserChangedEvent;
use OCP\Files\NotFoundException;
use OCP\IAvatarManager;
+use OCP\User\Events\UserChangedEvent;
/**
* @template-implements IEventListener<UserChangedEvent>
diff --git a/lib/private/User/LoginException.php b/lib/private/User/LoginException.php
index 7133b7b76dc..6f0e98513dd 100644
--- a/lib/private/User/LoginException.php
+++ b/lib/private/User/LoginException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index fb1afb65825..d93431a2699 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -1,35 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Chan <plus.vincchan@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
@@ -48,13 +22,15 @@ use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Server;
use OCP\Support\Subscription\IAssertion;
-use OCP\User\Backend\IGetRealUIDBackend;
-use OCP\User\Backend\ISearchKnownUsersBackend;
use OCP\User\Backend\ICheckPasswordBackend;
use OCP\User\Backend\ICountUsersBackend;
+use OCP\User\Backend\IGetRealUIDBackend;
+use OCP\User\Backend\IProvideEnabledStateBackend;
+use OCP\User\Backend\ISearchKnownUsersBackend;
use OCP\User\Events\BeforeUserCreatedEvent;
use OCP\User\Events\UserCreatedEvent;
use OCP\UserInterface;
+use Psr\Log\LoggerInterface;
/**
* Class Manager
@@ -77,35 +53,26 @@ class Manager extends PublicEmitter implements IUserManager {
/**
* @var \OCP\UserInterface[] $backends
*/
- private $backends = [];
+ private array $backends = [];
/**
- * @var \OC\User\User[] $cachedUsers
+ * @var array<string,\OC\User\User> $cachedUsers
*/
- private $cachedUsers = [];
-
- /** @var IConfig */
- private $config;
+ private array $cachedUsers = [];
- /** @var ICache */
- private $cache;
-
- /** @var IEventDispatcher */
- private $eventDispatcher;
+ private ICache $cache;
private DisplayNameCache $displayNameCache;
- public function __construct(IConfig $config,
- ICacheFactory $cacheFactory,
- IEventDispatcher $eventDispatcher) {
- $this->config = $config;
+ public function __construct(
+ private IConfig $config,
+ ICacheFactory $cacheFactory,
+ private IEventDispatcher $eventDispatcher,
+ ) {
$this->cache = new WithLocalCache($cacheFactory->createDistributed('user_backend_map'));
- $cachedUsers = &$this->cachedUsers;
- $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) {
- /** @var \OC\User\User $user */
- unset($cachedUsers[$user->getUID()]);
+ $this->listen('\OC\User', 'postDelete', function (IUser $user): void {
+ unset($this->cachedUsers[$user->getUID()]);
});
- $this->eventDispatcher = $eventDispatcher;
$this->displayNameCache = new DisplayNameCache($cacheFactory, $this);
}
@@ -234,7 +201,7 @@ class Manager extends PublicEmitter implements IUserManager {
$result = $this->checkPasswordNoLogging($loginName, $password);
if ($result === false) {
- \OC::$server->getLogger()->warning('Login failed: \''. $loginName .'\' (Remote IP: \''. \OC::$server->getRequest()->getRemoteAddress(). '\')', ['app' => 'core']);
+ \OCP\Server::get(LoggerInterface::class)->warning('Login failed: \''. $loginName .'\' (Remote IP: \''. \OC::$server->getRequest()->getRemoteAddress(). '\')', ['app' => 'core']);
}
return $result;
@@ -338,6 +305,44 @@ class Manager extends PublicEmitter implements IUserManager {
}
/**
+ * @return IUser[]
+ */
+ public function getDisabledUsers(?int $limit = null, int $offset = 0, string $search = ''): array {
+ $users = $this->config->getUsersForUserValue('core', 'enabled', 'false');
+ $users = array_combine(
+ $users,
+ array_map(
+ fn (string $uid): IUser => new LazyUser($uid, $this),
+ $users
+ )
+ );
+ if ($search !== '') {
+ $users = array_filter(
+ $users,
+ fn (IUser $user): bool =>
+ mb_stripos($user->getUID(), $search) !== false ||
+ mb_stripos($user->getDisplayName(), $search) !== false ||
+ mb_stripos($user->getEMailAddress() ?? '', $search) !== false,
+ );
+ }
+
+ $tempLimit = ($limit === null ? null : $limit + $offset);
+ foreach ($this->backends as $backend) {
+ if (($tempLimit !== null) && (count($users) >= $tempLimit)) {
+ break;
+ }
+ if ($backend instanceof IProvideEnabledStateBackend) {
+ $backendUsers = $backend->getDisabledUserList(($tempLimit === null ? null : $tempLimit - count($users)), 0, $search);
+ foreach ($backendUsers as $uid) {
+ $users[$uid] = new LazyUser($uid, $this, null, $backend);
+ }
+ }
+ }
+
+ return array_slice($users, $offset, $limit);
+ }
+
+ /**
* Search known users (from phonebook sync) by displayName
*
* @param string $searcher
@@ -415,7 +420,7 @@ class Manager extends PublicEmitter implements IUserManager {
* @throws \InvalidArgumentException
*/
public function createUserFromBackend($uid, $password, UserInterface $backend) {
- $l = \OC::$server->getL10N('lib');
+ $l = \OCP\Util::getL10N('lib');
$this->validateUserId($uid, true);
@@ -426,7 +431,7 @@ class Manager extends PublicEmitter implements IUserManager {
// Check if user already exists
if ($this->userExists($uid)) {
- throw new \InvalidArgumentException($l->t('The username is already being used'));
+ throw new \InvalidArgumentException($l->t('The Login is already being used'));
}
/** @deprecated 21.0.0 use BeforeUserCreatedEvent event with the IEventDispatcher instead */
@@ -434,7 +439,7 @@ class Manager extends PublicEmitter implements IUserManager {
$this->eventDispatcher->dispatchTyped(new BeforeUserCreatedEvent($uid, $password));
$state = $backend->createUser($uid, $password);
if ($state === false) {
- throw new \InvalidArgumentException($l->t('Could not create user'));
+ throw new \InvalidArgumentException($l->t('Could not create account'));
}
$user = $this->getUserObject($uid, $backend);
if ($user instanceof IUser) {
@@ -704,27 +709,27 @@ class Manager extends PublicEmitter implements IUserManager {
// Check the name for bad characters
// Allowed are: "a-z", "A-Z", "0-9", spaces and "_.@-'"
if (preg_match('/[^a-zA-Z0-9 _.@\-\']/', $uid)) {
- throw new \InvalidArgumentException($l->t('Only the following characters are allowed in a username:'
+ throw new \InvalidArgumentException($l->t('Only the following characters are allowed in an Login:'
. ' "a-z", "A-Z", "0-9", spaces and "_.@-\'"'));
}
// No empty username
if (trim($uid) === '') {
- throw new \InvalidArgumentException($l->t('A valid username must be provided'));
+ throw new \InvalidArgumentException($l->t('A valid Login must be provided'));
}
// No whitespace at the beginning or at the end
if (trim($uid) !== $uid) {
- throw new \InvalidArgumentException($l->t('Username contains whitespace at the beginning or at the end'));
+ throw new \InvalidArgumentException($l->t('Login contains whitespace at the beginning or at the end'));
}
// Username only consists of 1 or 2 dots (directory traversal)
if ($uid === '.' || $uid === '..') {
- throw new \InvalidArgumentException($l->t('Username must not consist of dots only'));
+ throw new \InvalidArgumentException($l->t('Login must not consist of dots only'));
}
if (!$this->verifyUid($uid, $checkDataDirectory)) {
- throw new \InvalidArgumentException($l->t('Username is invalid because files already exist for this user'));
+ throw new \InvalidArgumentException($l->t('Login is invalid because files already exist for this user'));
}
}
@@ -738,6 +743,8 @@ class Manager extends PublicEmitter implements IUserManager {
'.ocdata',
'owncloud.log',
'nextcloud.log',
+ 'updater.log',
+ 'audit.log',
$appdata], true)) {
return false;
}
diff --git a/lib/private/User/NoUserException.php b/lib/private/User/NoUserException.php
index d9149318467..c0a5c51b08d 100644
--- a/lib/private/User/NoUserException.php
+++ b/lib/private/User/NoUserException.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
diff --git a/lib/private/User/OutOfOfficeData.php b/lib/private/User/OutOfOfficeData.php
new file mode 100644
index 00000000000..65d7c9c24cb
--- /dev/null
+++ b/lib/private/User/OutOfOfficeData.php
@@ -0,0 +1,58 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\User;
+
+use OCP\IUser;
+use OCP\User\IOutOfOfficeData;
+
+class OutOfOfficeData implements IOutOfOfficeData {
+ public function __construct(private string $id,
+ private IUser $user,
+ private int $startDate,
+ private int $endDate,
+ private string $shortMessage,
+ private string $message) {
+ }
+
+ public function getId(): string {
+ return $this->id;
+ }
+
+ public function getUser(): IUser {
+ return $this->user;
+ }
+
+ public function getStartDate(): int {
+ return $this->startDate;
+ }
+
+ public function getEndDate(): int {
+ return $this->endDate;
+ }
+
+ public function getShortMessage(): string {
+ return $this->shortMessage;
+ }
+
+ public function getMessage(): string {
+ return $this->message;
+ }
+
+ public function jsonSerialize(): array {
+ return [
+ 'id' => $this->getId(),
+ 'userId' => $this->getUser()->getUID(),
+ 'startDate' => $this->getStartDate(),
+ 'endDate' => $this->getEndDate(),
+ 'shortMessage' => $this->getShortMessage(),
+ 'message' => $this->getMessage(),
+ ];
+ }
+}
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 82887f8d029..9d77a90c541 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -1,56 +1,26 @@
<?php
/**
- * @copyright Copyright (c) 2017, Sandro Lutz <sandro.lutz@temparus.ch>
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Felix Rupp <github@felixrupp.com>
- * @author Greta Doci <gretadoci@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lionel Elie Mamane <lionel@mamane.lu>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sandro Lutz <sandro.lutz@temparus.ch>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
use OC;
-use OC\Authentication\Exceptions\ExpiredTokenException;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
+use OC\Authentication\Token\PublicKeyToken;
+use OC\Authentication\TwoFactorAuth\Manager as TwoFactorAuthManager;
use OC\Hooks\Emitter;
use OC\Hooks\PublicEmitter;
use OC_User;
use OC_Util;
use OCA\DAV\Connector\Sabre\Auth;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Exceptions\ExpiredTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
use OCP\EventDispatcher\GenericEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\NotPermittedException;
@@ -120,14 +90,14 @@ class Session implements IUserSession, Emitter {
private $dispatcher;
public function __construct(Manager $manager,
- ISession $session,
- ITimeFactory $timeFactory,
- ?IProvider $tokenProvider,
- IConfig $config,
- ISecureRandom $random,
- ILockdownManager $lockdownManager,
- LoggerInterface $logger,
- IEventDispatcher $dispatcher
+ ISession $session,
+ ITimeFactory $timeFactory,
+ ?IProvider $tokenProvider,
+ IConfig $config,
+ ISecureRandom $random,
+ ILockdownManager $lockdownManager,
+ LoggerInterface $logger,
+ IEventDispatcher $dispatcher
) {
$this->manager = $manager;
$this->session = $session;
@@ -161,7 +131,7 @@ class Session implements IUserSession, Emitter {
* @param string $method optional
* @param callable $callback optional
*/
- public function removeListener($scope = null, $method = null, callable $callback = null) {
+ public function removeListener($scope = null, $method = null, ?callable $callback = null) {
$this->manager->removeListener($scope, $method, $callback);
}
@@ -211,6 +181,15 @@ class Session implements IUserSession, Emitter {
}
/**
+ * Temporarily set the currently active user without persisting in the session
+ *
+ * @param IUser|null $user
+ */
+ public function setVolatileActiveUser(?IUser $user): void {
+ $this->activeUser = $user;
+ }
+
+ /**
* get the current active user
*
* @return IUser|null Current user, otherwise null
@@ -367,7 +346,7 @@ class Session implements IUserSession, Emitter {
if (!$user->isEnabled()) {
// disabled users can not log in
// injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
- $message = \OC::$server->getL10N('lib')->t('User disabled');
+ $message = \OCP\Util::getL10N('lib')->t('Account disabled');
throw new LoginException($message);
}
@@ -406,7 +385,7 @@ class Session implements IUserSession, Emitter {
return true;
}
- $message = \OC::$server->getL10N('lib')->t('Login canceled by app');
+ $message = \OCP\Util::getL10N('lib')->t('Login canceled by app');
throw new LoginException($message);
}
@@ -425,9 +404,9 @@ class Session implements IUserSession, Emitter {
* @return boolean
*/
public function logClientIn($user,
- $password,
- IRequest $request,
- IThrottler $throttler) {
+ $password,
+ IRequest $request,
+ IThrottler $throttler) {
$remoteAddress = $request->getRemoteAddress();
$currentDelay = $throttler->sleepDelayOrThrowOnMax($remoteAddress, 'login');
@@ -456,8 +435,18 @@ class Session implements IUserSession, Emitter {
$this->handleLoginFailed($throttler, $currentDelay, $remoteAddress, $user, $password);
return false;
}
- $users = $this->manager->getByEmail($user);
- if (!(\count($users) === 1 && $this->login($users[0]->getUID(), $password))) {
+
+ if ($isTokenPassword) {
+ $dbToken = $this->tokenProvider->getToken($password);
+ $userFromToken = $this->manager->get($dbToken->getUID());
+ $isValidEmailLogin = $userFromToken->getEMailAddress() === $user
+ && $this->validateTokenLoginName($userFromToken->getEMailAddress(), $dbToken);
+ } else {
+ $users = $this->manager->getByEmail($user);
+ $isValidEmailLogin = (\count($users) === 1 && $this->login($users[0]->getUID(), $password));
+ }
+
+ if (!$isValidEmailLogin) {
$this->handleLoginFailed($throttler, $currentDelay, $remoteAddress, $user, $password);
return false;
}
@@ -514,7 +503,7 @@ class Session implements IUserSession, Emitter {
$user = $users[0];
}
// DI not possible due to cyclic dependencies :'-/
- return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
+ return OC::$server->get(TwoFactorAuthManager::class)->isTwoFactorAuthenticated($user);
}
/**
@@ -576,7 +565,7 @@ class Session implements IUserSession, Emitter {
* @return boolean if the login was successful
*/
public function tryBasicAuthLogin(IRequest $request,
- IThrottler $throttler) {
+ IThrottler $throttler) {
if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
try {
if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request, $throttler)) {
@@ -747,8 +736,6 @@ class Session implements IUserSession, Emitter {
return false;
}
- $dbToken->setLastCheck($now);
- $this->tokenProvider->updateToken($dbToken);
return true;
}
@@ -766,6 +753,9 @@ class Session implements IUserSession, Emitter {
}
$dbToken->setLastCheck($now);
+ if ($dbToken instanceof PublicKeyToken) {
+ $dbToken->setLastActivity($now);
+ }
$this->tokenProvider->updateToken($dbToken);
return true;
}
@@ -783,23 +773,23 @@ class Session implements IUserSession, Emitter {
try {
$dbToken = $this->tokenProvider->getToken($token);
} catch (InvalidTokenException $ex) {
+ $this->logger->debug('Session token is invalid because it does not exist', [
+ 'app' => 'core',
+ 'user' => $user,
+ 'exception' => $ex,
+ ]);
return false;
}
- // Check if login names match
- if (!is_null($user) && $dbToken->getLoginName() !== $user) {
- // TODO: this makes it impossible to use different login names on browser and client
- // e.g. login by e-mail 'user@example.com' on browser for generating the token will not
- // allow to use the client token with the login name 'user'.
- $this->logger->error('App token login name does not match', [
- 'tokenLoginName' => $dbToken->getLoginName(),
- 'sessionLoginName' => $user,
- ]);
-
+ if (!is_null($user) && !$this->validateTokenLoginName($user, $dbToken)) {
return false;
}
if (!$this->checkTokenCredentials($dbToken, $token)) {
+ $this->logger->warning('Session token credentials are invalid', [
+ 'app' => 'core',
+ 'user' => $user,
+ ]);
return false;
}
@@ -812,6 +802,27 @@ class Session implements IUserSession, Emitter {
}
/**
+ * Check if login names match
+ */
+ private function validateTokenLoginName(?string $loginName, IToken $token): bool {
+ if ($token->getLoginName() !== $loginName) {
+ // TODO: this makes it impossible to use different login names on browser and client
+ // e.g. login by e-mail 'user@example.com' on browser for generating the token will not
+ // allow to use the client token with the login name 'user'.
+ $this->logger->error('App token login name does not match', [
+ 'tokenLoginName' => $token->getLoginName(),
+ 'sessionLoginName' => $loginName,
+ 'app' => 'core',
+ 'user' => $token->getUID(),
+ ]);
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* Tries to login the user with auth token header
*
* @param IRequest $request
@@ -822,13 +833,16 @@ class Session implements IUserSession, Emitter {
$authHeader = $request->getHeader('Authorization');
if (str_starts_with($authHeader, 'Bearer ')) {
$token = substr($authHeader, 7);
- } else {
- // No auth header, let's try session id
+ } elseif ($request->getCookie($this->config->getSystemValueString('instanceid')) !== null) {
+ // No auth header, let's try session id, but only if this is an existing
+ // session and the request has a session cookie
try {
$token = $this->session->getId();
} catch (SessionNotAvailableException $ex) {
return false;
}
+ } else {
+ return false;
}
if (!$this->loginWithToken($token)) {
@@ -875,9 +889,9 @@ class Session implements IUserSession, Emitter {
$tokens = $this->config->getUserKeys($uid, 'login_token');
// test cookies token against stored tokens
if (!in_array($currentToken, $tokens, true)) {
- $this->logger->info('Tried to log in {uid} but could not verify token', [
+ $this->logger->info('Tried to log in but could not verify token', [
'app' => 'core',
- 'uid' => $uid,
+ 'user' => $uid,
]);
return false;
}
@@ -885,18 +899,31 @@ class Session implements IUserSession, Emitter {
$this->config->deleteUserValue($uid, 'login_token', $currentToken);
$newToken = $this->random->generate(32);
$this->config->setUserValue($uid, 'login_token', $newToken, (string)$this->timeFactory->getTime());
+ $this->logger->debug('Remember-me token replaced', [
+ 'app' => 'core',
+ 'user' => $uid,
+ ]);
try {
$sessionId = $this->session->getId();
$token = $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
+ $this->logger->debug('Session token replaced', [
+ 'app' => 'core',
+ 'user' => $uid,
+ ]);
} catch (SessionNotAvailableException $ex) {
- $this->logger->warning('Could not renew session token for {uid} because the session is unavailable', [
+ $this->logger->critical('Could not renew session token for {uid} because the session is unavailable', [
'app' => 'core',
'uid' => $uid,
+ 'user' => $uid,
]);
return false;
} catch (InvalidTokenException $ex) {
- $this->logger->warning('Renewing session token failed', ['app' => 'core']);
+ $this->logger->error('Renewing session token failed: ' . $ex->getMessage(), [
+ 'app' => 'core',
+ 'user' => $uid,
+ 'exception' => $ex,
+ ]);
return false;
}
@@ -935,10 +962,17 @@ class Session implements IUserSession, Emitter {
$this->manager->emit('\OC\User', 'logout', [$user]);
if ($user !== null) {
try {
- $this->tokenProvider->invalidateToken($this->session->getId());
+ $token = $this->session->getId();
+ $this->tokenProvider->invalidateToken($token);
+ $this->logger->debug('Session token invalidated before logout', [
+ 'user' => $user->getUID(),
+ ]);
} catch (SessionNotAvailableException $ex) {
}
}
+ $this->logger->debug('Logging out', [
+ 'user' => $user === null ? null : $user->getUID(),
+ ]);
$this->setUser(null);
$this->setLoginName(null);
$this->setToken(null);
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index d1185e17aef..06ec6db6066 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -1,36 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Leon Klingele <leon@struktur.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\User;
@@ -40,6 +13,7 @@ use OC\Avatar\AvatarManager;
use OC\Hooks\Emitter;
use OC_Helper;
use OCP\Accounts\IAccountManager;
+use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Group\Events\BeforeUserRemovedEvent;
use OCP\Group\Events\UserRemovedEvent;
@@ -49,17 +23,17 @@ use OCP\IImage;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserBackend;
+use OCP\User\Backend\IGetHomeBackend;
+use OCP\User\Backend\IProvideAvatarBackend;
+use OCP\User\Backend\IProvideEnabledStateBackend;
+use OCP\User\Backend\ISetDisplayNameBackend;
+use OCP\User\Backend\ISetPasswordBackend;
use OCP\User\Events\BeforePasswordUpdatedEvent;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\PasswordUpdatedEvent;
use OCP\User\Events\UserChangedEvent;
use OCP\User\Events\UserDeletedEvent;
use OCP\User\GetQuotaEvent;
-use OCP\User\Backend\ISetDisplayNameBackend;
-use OCP\User\Backend\ISetPasswordBackend;
-use OCP\User\Backend\IProvideAvatarBackend;
-use OCP\User\Backend\IProvideEnabledStateBackend;
-use OCP\User\Backend\IGetHomeBackend;
use OCP\UserInterface;
use function json_decode;
use function json_encode;
@@ -102,7 +76,7 @@ class User implements IUser {
/** @var IURLGenerator */
private $urlGenerator;
- public function __construct(string $uid, ?UserInterface $backend, IEventDispatcher $dispatcher, $emitter = null, IConfig $config = null, $urlGenerator = null) {
+ public function __construct(string $uid, ?UserInterface $backend, IEventDispatcher $dispatcher, $emitter = null, ?IConfig $config = null, $urlGenerator = null) {
$this->uid = $uid;
$this->backend = $backend;
$this->emitter = $emitter;
@@ -290,8 +264,8 @@ class User implements IUser {
// Delete the user's keys in preferences
\OC::$server->getConfig()->deleteAllUserValues($this->uid);
- \OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
- \OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
+ \OC::$server->get(ICommentsManager::class)->deleteReferencesOfActor('users', $this->uid);
+ \OC::$server->get(ICommentsManager::class)->deleteReadMarksFromUser($this);
/** @var AvatarManager $avatarManager */
$avatarManager = \OCP\Server::get(AvatarManager::class);
@@ -576,7 +550,7 @@ class User implements IUser {
public function getAvatarImage($size) {
// delay the initialization
if (is_null($this->avatarManager)) {
- $this->avatarManager = \OC::$server->getAvatarManager();
+ $this->avatarManager = \OC::$server->get(IAvatarManager::class);
}
$avatar = $this->avatarManager->getAvatar($this->uid);
@@ -597,7 +571,7 @@ class User implements IUser {
public function getCloudId() {
$uid = $this->getUID();
$server = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
- if (substr($server, -10) === '/index.php') {
+ if (str_ends_with($server, '/index.php')) {
$server = substr($server, 0, -10);
}
$server = $this->removeProtocolFromUrl($server);
diff --git a/lib/private/UserStatus/ISettableProvider.php b/lib/private/UserStatus/ISettableProvider.php
index 88a107d1f86..1a2e7cfe7cf 100644
--- a/lib/private/UserStatus/ISettableProvider.php
+++ b/lib/private/UserStatus/ISettableProvider.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Carl Schwan <carl@carlschwan.eu>
- *
- * @author Carl Schwan <carl@carlschwan.eu>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\UserStatus;
@@ -39,8 +22,9 @@ interface ISettableProvider extends IProvider {
* @param string $messageId The new message id.
* @param string $status The new status.
* @param bool $createBackup If true, this will store the old status so that it is possible to revert it later (e.g. after a call).
+ * @param string|null $customMessage
*/
- public function setUserStatus(string $userId, string $messageId, string $status, bool $createBackup): void;
+ public function setUserStatus(string $userId, string $messageId, string $status, bool $createBackup, ?string $customMessage = null): void;
/**
* Revert an automatically set user status. For example after leaving a call,
diff --git a/lib/private/UserStatus/Manager.php b/lib/private/UserStatus/Manager.php
index 89a1bb455c7..4658f61df82 100644
--- a/lib/private/UserStatus/Manager.php
+++ b/lib/private/UserStatus/Manager.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Georg Ehrke
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\UserStatus;
@@ -51,7 +34,7 @@ class Manager implements IManager {
* @param LoggerInterface $logger
*/
public function __construct(IServerContainer $container,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->container = $container;
$this->logger = $logger;
}
@@ -104,13 +87,13 @@ class Manager implements IManager {
$this->provider = $provider;
}
- public function setUserStatus(string $userId, string $messageId, string $status, bool $createBackup = false): void {
+ public function setUserStatus(string $userId, string $messageId, string $status, bool $createBackup = false, ?string $customMessage = null): void {
$this->setupProvider();
if (!$this->provider || !($this->provider instanceof ISettableProvider)) {
return;
}
- $this->provider->setUserStatus($userId, $messageId, $status, $createBackup);
+ $this->provider->setUserStatus($userId, $messageId, $status, $createBackup, $customMessage);
}
public function revertUserStatus(string $userId, string $messageId, string $status): void {
diff --git a/lib/private/legacy/OC_API.php b/lib/private/legacy/OC_API.php
index 275e02986c4..bb2376d4ea0 100644
--- a/lib/private/legacy/OC_API.php
+++ b/lib/private/legacy/OC_API.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tom Needham <tom@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
use OCP\API;
use OCP\AppFramework\Http;
@@ -130,7 +107,7 @@ class OC_API {
protected static function isV2(\OCP\IRequest $request) {
$script = $request->getScriptName();
- return substr($script, -11) === '/ocs/v2.php';
+ return str_ends_with($script, '/ocs/v2.php');
}
/**
@@ -171,7 +148,7 @@ class OC_API {
],
];
if ($format == 'json') {
- return OC_JSON::encode($response);
+ return json_encode($response, JSON_HEX_TAG);
}
$writer = new XMLWriter();
diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php
index ac449a62a4f..c9d1f86cb0e 100644
--- a/lib/private/legacy/OC_App.php
+++ b/lib/private/legacy/OC_App.php
@@ -1,69 +1,24 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Borjan Tchakaloff <borjan@tchakaloff.fr>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Rudolf <github.com@daniel-rudolf.de>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Haertl <jus@bitgrid.net>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Kamil Domanski <kdomanski@kdemail.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Markus Goetz <markus@woboq.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author RealRancor <Fisch.666@gmx.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sam Tuke <mail@samtuke.com>
- * @author Sebastian Wessalowski <sebastian@wessalowski.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
-use OCP\App\Events\AppUpdateEvent;
-use OCP\App\IAppManager;
-use OCP\App\ManagerEvent;
-use OCP\Authentication\IAlternativeLogin;
-use OCP\EventDispatcher\IEventDispatcher;
-use OCP\ILogger;
-use OC\AppFramework\Bootstrap\Coordinator;
use OC\App\DependencyAnalyzer;
use OC\App\Platform;
+use OC\AppFramework\Bootstrap\Coordinator;
use OC\DB\MigrationService;
use OC\Installer;
use OC\Repair;
use OC\Repair\Events\RepairErrorEvent;
+use OCP\App\Events\AppUpdateEvent;
+use OCP\App\IAppManager;
+use OCP\App\ManagerEvent;
+use OCP\Authentication\IAlternativeLogin;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IAppConfig;
use Psr\Container\ContainerExceptionInterface;
use Psr\Log\LoggerInterface;
@@ -117,6 +72,8 @@ class OC_App {
* exists.
*
* if $types is set to non-empty array, only apps of those types will be loaded
+ *
+ * @deprecated 29.0.0 use IAppManager::loadApps instead
*/
public static function loadApps(array $types = []): bool {
if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
@@ -252,7 +209,7 @@ class OC_App {
* This function set an app as enabled in appconfig.
*/
public function enable(string $appId,
- array $groups = []) {
+ array $groups = []) {
// Check if app is already downloaded
/** @var Installer $installer */
$installer = \OCP\Server::get(Installer::class);
@@ -282,17 +239,15 @@ class OC_App {
/**
* Get the path where to install apps
- *
- * @return string|false
*/
- public static function getInstallPath() {
+ public static function getInstallPath(): string|null {
foreach (OC::$APPSROOTS as $dir) {
if (isset($dir['writable']) && $dir['writable'] === true) {
return $dir['path'];
}
}
- \OCP\Util::writeLog('core', 'No application directories are marked as writable.', ILogger::ERROR);
+ \OCP\Server::get(LoggerInterface::class)->error('No application directories are marked as writable.', ['app' => 'core']);
return null;
}
@@ -354,7 +309,7 @@ class OC_App {
* @param string $appId
* @param bool $refreshAppPath should be set to true only during install/upgrade
* @return string|false
- * @deprecated 11.0.0 use \OC::$server->getAppManager()->getAppPath()
+ * @deprecated 11.0.0 use \OCP\Server::get(IAppManager)->getAppPath()
*/
public static function getAppPath(string $appId, bool $refreshAppPath = false) {
if ($appId === null || trim($appId) === '') {
@@ -391,7 +346,7 @@ class OC_App {
public static function getAppVersionByPath(string $path): string {
$infoFile = $path . '/appinfo/info.xml';
$appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true);
- return isset($appData['version']) ? $appData['version'] : '';
+ return $appData['version'] ?? '';
}
/**
@@ -517,7 +472,7 @@ class OC_App {
foreach (OC::$APPSROOTS as $apps_dir) {
if (!is_readable($apps_dir['path'])) {
- \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], ILogger::WARN);
+ \OCP\Server::get(LoggerInterface::class)->warning('unable to read app folder : ' . $apps_dir['path'], ['app' => 'core']);
continue;
}
$dh = opendir($apps_dir['path']);
@@ -565,15 +520,15 @@ class OC_App {
$supportedApps = $this->getSupportedApps();
foreach ($installedApps as $app) {
- if (array_search($app, $blacklist) === false) {
+ if (!in_array($app, $blacklist)) {
$info = $appManager->getAppInfo($app, false, $langCode);
if (!is_array($info)) {
- \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', ILogger::ERROR);
+ \OCP\Server::get(LoggerInterface::class)->error('Could not read app info file for app "' . $app . '"', ['app' => 'core']);
continue;
}
if (!isset($info['name'])) {
- \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', ILogger::ERROR);
+ \OCP\Server::get(LoggerInterface::class)->error('App id "' . $app . '" has no name in appinfo', ['app' => 'core']);
continue;
}
@@ -731,8 +686,9 @@ class OC_App {
static $versions;
if (!$versions) {
- $appConfig = \OC::$server->getAppConfig();
- $versions = $appConfig->getValues(false, 'installed_version');
+ /** @var IAppConfig $appConfig */
+ $appConfig = \OCP\Server::get(IAppConfig::class);
+ $versions = $appConfig->searchValues('installed_version');
}
return $versions;
}
@@ -824,7 +780,7 @@ class OC_App {
$dispatcher = \OC::$server->get(IEventDispatcher::class);
// load the steps
- $r = new Repair([], $dispatcher, \OC::$server->get(LoggerInterface::class));
+ $r = \OCP\Server::get(Repair::class);
foreach ($steps as $step) {
try {
$r->addStep($step);
@@ -870,11 +826,11 @@ class OC_App {
}
return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
} else {
- \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', ILogger::ERROR);
+ \OCP\Server::get(LoggerInterface::class)->error('Can\'t get app storage, app ' . $appId . ', user not logged in', ['app' => 'core']);
return false;
}
} else {
- \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', ILogger::ERROR);
+ \OCP\Server::get(LoggerInterface::class)->error('Can\'t get app storage, app ' . $appId . ' not enabled', ['app' => 'core']);
return false;
}
}
diff --git a/lib/private/legacy/OC_Defaults.php b/lib/private/legacy/OC_Defaults.php
index ce89a642741..54640a892c9 100644
--- a/lib/private/legacy/OC_Defaults.php
+++ b/lib/private/legacy/OC_Defaults.php
@@ -1,40 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Haertl <jus@bitgrid.net>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Markus Staab <markus.staab@redaxo.de>
- * @author Michael Weimann <mail@michael-weimann.eu>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Pascal de Bruijn <pmjdebruijn@pcode.nl>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author scolebrook <scolebrook@mac.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Volkan Gezer <volkangezer@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
class OC_Defaults {
@@ -52,6 +21,7 @@ class OC_Defaults {
private $defaultDocBaseUrl;
private $defaultDocVersion;
private $defaultSlogan;
+ private $defaultColorBackground;
private $defaultColorPrimary;
private $defaultTextColorPrimary;
private $defaultProductName;
@@ -70,7 +40,8 @@ class OC_Defaults {
$this->defaultFDroidClientUrl = $config->getSystemValue('customclient_fdroid', 'https://f-droid.org/packages/com.nextcloud.client/');
$this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
$this->defaultDocVersion = \OC_Util::getVersion()[0]; // used to generate doc links
- $this->defaultColorPrimary = '#0082c9';
+ $this->defaultColorBackground = '#00679e';
+ $this->defaultColorPrimary = '#00679e';
$this->defaultTextColorPrimary = '#ffffff';
$this->defaultProductName = 'Nextcloud';
@@ -300,6 +271,17 @@ class OC_Defaults {
}
/**
+ * Returns primary color
+ * @return string
+ */
+ public function getColorBackground() {
+ if ($this->themeExist('getColorBackground')) {
+ return $this->theme->getColorBackground();
+ }
+ return $this->defaultColorBackground;
+ }
+
+ /**
* @return array scss variables to overwrite
*/
public function getScssVariables() {
diff --git a/lib/private/legacy/OC_FileChunking.php b/lib/private/legacy/OC_FileChunking.php
index 58bdd0af3d0..7600d810657 100644
--- a/lib/private/legacy/OC_FileChunking.php
+++ b/lib/private/legacy/OC_FileChunking.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
class OC_FileChunking {
protected $info;
diff --git a/lib/private/legacy/OC_Files.php b/lib/private/legacy/OC_Files.php
index 7bc1fab94b6..76d61a98558 100644
--- a/lib/private/legacy/OC_Files.php
+++ b/lib/private/legacy/OC_Files.php
@@ -1,52 +1,18 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Ko- <k.stoffelen@cs.ru.nl>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Nicolai Ehemann <en@enlightened.de>
- * @author Piotr Filiciak <piotr@filiciak.pl>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thibaut GRIDEL <tgridel@free.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Valdnet <47037905+Valdnet@users.noreply.github.com>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
use bantu\IniGetWrapper\IniGetWrapper;
use OC\Files\View;
use OC\Streamer;
-use OCP\Lock\ILockingProvider;
-use OCP\Files\Events\BeforeZipCreatedEvent;
-use OCP\Files\Events\BeforeDirectFileDownloadEvent;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\BeforeDirectFileDownloadEvent;
+use OCP\Files\Events\BeforeZipCreatedEvent;
+use OCP\Files\IRootFolder;
+use OCP\Lock\ILockingProvider;
/**
* Class for file server access
@@ -76,7 +42,6 @@ class OC_Files {
private static function sendHeaders($filename, $name, array $rangeArray): void {
OC_Response::setContentDispositionHeader($name, 'attachment');
header('Content-Transfer-Encoding: binary', true);
- header('Pragma: public');// enable caching in IE
header('Expires: 0');
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
$fileSize = \OC\Files\Filesystem::filesize($filename);
@@ -87,7 +52,7 @@ class OC_Files {
header('Accept-Ranges: bytes', true);
if (count($rangeArray) > 1) {
$type = 'multipart/byteranges; boundary='.self::getBoundary();
- // no Content-Length header here
+ // no Content-Length header here
} else {
header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true);
OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1);
@@ -104,7 +69,7 @@ class OC_Files {
* return the content of a file or return a zip file containing multiple files
*
* @param string $dir
- * @param string $files ; separated list of files to download
+ * @param string|array $files ; separated list of files to download
* @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
*/
public static function get($dir, $files, $params = null) {
@@ -188,7 +153,7 @@ class OC_Files {
foreach ($files as $file) {
$file = $dir . '/' . $file;
if (\OC\Files\Filesystem::is_file($file)) {
- $userFolder = \OC::$server->getRootFolder()->get(\OC\Files\Filesystem::getRoot());
+ $userFolder = \OC::$server->get(IRootFolder::class)->get(\OC\Files\Filesystem::getRoot());
$file = $userFolder->get($file);
if ($file instanceof \OC\Files\Node\File) {
try {
@@ -230,6 +195,10 @@ class OC_Files {
OC::$server->getLogger()->logException($ex);
$l = \OC::$server->getL10N('lib');
\OC_Template::printErrorPage($l->t('Cannot download file'), $ex->getMessage(), 200);
+ } catch (\OCP\Files\ConnectionLostException $ex) {
+ self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
+ OC::$server->getLogger()->logException($ex, ['level' => \OCP\ILogger::DEBUG]);
+ \OC_Template::printErrorPage('Connection lost', $ex->getMessage(), 200);
} catch (\Exception $ex) {
self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
OC::$server->getLogger()->logException($ex);
@@ -304,7 +273,7 @@ class OC_Files {
$file = null;
try {
- $userFolder = \OC::$server->getRootFolder()->get(\OC\Files\Filesystem::getRoot());
+ $userFolder = \OC::$server->get(IRootFolder::class)->get(\OC\Files\Filesystem::getRoot());
$file = $userFolder->get($filename);
if (!$file instanceof \OC\Files\Node\File || !$file->isReadable()) {
http_response_code(403);
diff --git a/lib/private/legacy/OC_Helper.php b/lib/private/legacy/OC_Helper.php
index cf39d045ae9..0c913709111 100644
--- a/lib/private/legacy/OC_Helper.php
+++ b/lib/private/legacy/OC_Helper.php
@@ -1,53 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Ardinis <Ardinis@users.noreply.github.com>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Pellaeon Lin <nfsmwlin@gmail.com>
- * @author RealRancor <fisch.666@gmx.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Simon Könnecke <simonkoennecke@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
use bantu\IniGetWrapper\IniGetWrapper;
use OC\Files\Filesystem;
use OCP\Files\Mount\IMountPoint;
-use OCP\ICacheFactory;
use OCP\IBinaryFinder;
+use OCP\ICacheFactory;
use OCP\IUser;
use OCP\Util;
use Psr\Log\LoggerInterface;
@@ -138,7 +100,7 @@ class OC_Helper {
$bytes = (float)$str;
- if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) {
+ if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && isset($bytes_array[$matches[1]])) {
$bytes *= $bytes_array[$matches[1]];
} else {
return false;
@@ -596,6 +558,11 @@ class OC_Helper {
'mountPoint' => trim($mountPoint, '/'),
];
+ if ($ownerId && $path === '/') {
+ // If path is root, store this as last known quota usage for this user
+ \OCP\Server::get(\OCP\IConfig::class)->setUserValue($ownerId, 'files', 'lastSeenQuotaUsage', (string)$relative);
+ }
+
$memcache->set($cacheKey, $info, 5 * 60);
return $info;
diff --git a/lib/private/legacy/OC_Hook.php b/lib/private/legacy/OC_Hook.php
index a7a0f755673..2f6686f9126 100644
--- a/lib/private/legacy/OC_Hook.php
+++ b/lib/private/legacy/OC_Hook.php
@@ -1,32 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Sam Tuke <mail@samtuke.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
class OC_Hook {
public static $thrownExceptions = [];
diff --git a/lib/private/legacy/OC_Image.php b/lib/private/legacy/OC_Image.php
index aac0c496734..cc6968839d4 100644
--- a/lib/private/legacy/OC_Image.php
+++ b/lib/private/legacy/OC_Image.php
@@ -1,47 +1,10 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bartek Przybylski <bart.p.pl@gmail.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Byron Marohn <combustible@live.com>
- * @author Côme Chilliet <come.chilliet@nextcloud.com>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author j-ed <juergen@eisfair.org>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Johannes Willnecker <johannes@willnecker.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Samuel CHEMLA <chemla.samuel@gmail.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
use OCP\IImage;
@@ -55,7 +18,10 @@ class OC_Image implements \OCP\IImage {
// Default quality for jpeg images
protected const DEFAULT_JPEG_QUALITY = 80;
- /** @var false|resource|\GdImage */
+ // Default quality for webp images
+ protected const DEFAULT_WEBP_QUALITY = 80;
+
+ /** @var false|\GdImage */
protected $resource = false; // tmp resource.
/** @var int */
protected $imageType = IMAGETYPE_PNG; // Default to png if file type isn't evident.
@@ -63,25 +29,25 @@ class OC_Image implements \OCP\IImage {
protected $mimeType = 'image/png'; // Default to png
/** @var null|string */
protected $filePath = null;
- /** @var finfo */
- private $fileInfo;
+ /** @var ?finfo */
+ private $fileInfo = null;
/** @var \OCP\ILogger */
private $logger;
/** @var \OCP\IConfig */
private $config;
- /** @var array */
- private $exif;
+ /** @var ?array */
+ private $exif = null;
/**
* Constructor.
*
- * @param resource|string|\GdImage $imageRef The path to a local file, a base64 encoded string or a resource created by
- * an imagecreate* function.
+ * @param mixed $imageRef Deprecated, should be null
+ * @psalm-assert null $imageRef
* @param \OCP\ILogger $logger
* @param \OCP\IConfig $config
* @throws \InvalidArgumentException in case the $imageRef parameter is not null
*/
- public function __construct($imageRef = null, \OCP\ILogger $logger = null, \OCP\IConfig $config = null) {
+ public function __construct($imageRef = null, ?\OCP\ILogger $logger = null, ?\OCP\IConfig $config = null) {
$this->logger = $logger;
if ($logger === null) {
$this->logger = \OC::$server->getLogger();
@@ -103,11 +69,11 @@ class OC_Image implements \OCP\IImage {
/**
* Determine whether the object contains an image resource.
*
+ * @psalm-assert-if-true \GdImage $this->resource
* @return bool
*/
public function valid(): bool {
- if ((is_resource($this->resource) && get_resource_type($this->resource) === 'gd') ||
- (is_object($this->resource) && get_class($this->resource) === \GdImage::class)) {
+ if (is_object($this->resource) && get_class($this->resource) === \GdImage::class) {
return true;
}
@@ -130,10 +96,7 @@ class OC_Image implements \OCP\IImage {
*/
public function width(): int {
if ($this->valid()) {
- $width = imagesx($this->resource);
- if ($width !== false) {
- return $width;
- }
+ return imagesx($this->resource);
}
return -1;
}
@@ -145,10 +108,7 @@ class OC_Image implements \OCP\IImage {
*/
public function height(): int {
if ($this->valid()) {
- $height = imagesy($this->resource);
- if ($height !== false) {
- return $height;
- }
+ return imagesy($this->resource);
}
return -1;
}
@@ -207,7 +167,7 @@ class OC_Image implements \OCP\IImage {
* @param string $mimeType
* @return bool
*/
- public function show(string $mimeType = null): bool {
+ public function show(?string $mimeType = null): bool {
if ($mimeType === null) {
$mimeType = $this->mimeType();
}
@@ -283,6 +243,9 @@ class OC_Image implements \OCP\IImage {
case 'image/x-ms-bmp':
$imageType = IMAGETYPE_BMP;
break;
+ case 'image/webp':
+ $imageType = IMAGETYPE_WEBP;
+ break;
default:
throw new Exception('\OC_Image::_output(): "' . $mimeType . '" is not supported when forcing a specific output format');
}
@@ -293,8 +256,7 @@ class OC_Image implements \OCP\IImage {
$retVal = imagegif($this->resource, $filePath);
break;
case IMAGETYPE_JPEG:
- /** @psalm-suppress InvalidScalarArgument */
- imageinterlace($this->resource, (PHP_VERSION_ID >= 80000 ? true : 1));
+ imageinterlace($this->resource, true);
$retVal = imagejpeg($this->resource, $filePath, $this->getJpegQuality());
break;
case IMAGETYPE_PNG:
@@ -314,6 +276,9 @@ class OC_Image implements \OCP\IImage {
case IMAGETYPE_BMP:
$retVal = imagebmp($this->resource, $filePath);
break;
+ case IMAGETYPE_WEBP:
+ $retVal = imagewebp($this->resource, null, $this->getWebpQuality());
+ break;
default:
$retVal = imagepng($this->resource, $filePath);
}
@@ -328,25 +293,14 @@ class OC_Image implements \OCP\IImage {
}
/**
- * @param resource|\GdImage $resource
- * @throws \InvalidArgumentException in case the supplied resource does not have the type "gd"
+ * @param \GdImage $resource
*/
- public function setResource($resource) {
- // For PHP<8
- if (is_resource($resource) && get_resource_type($resource) === 'gd') {
- $this->resource = $resource;
- return;
- }
- // PHP 8 has real objects for GD stuff
- if (is_object($resource) && get_class($resource) === \GdImage::class) {
- $this->resource = $resource;
- return;
- }
- throw new \InvalidArgumentException('Supplied resource is not of type "gd".');
+ public function setResource(\GdImage $resource): void {
+ $this->resource = $resource;
}
/**
- * @return false|resource|\GdImage Returns the image resource if any
+ * @return false|\GdImage Returns the image resource if any
*/
public function resource() {
return $this->resource;
@@ -364,6 +318,7 @@ class OC_Image implements \OCP\IImage {
case 'image/png':
case 'image/jpeg':
case 'image/gif':
+ case 'image/webp':
return $this->mimeType;
default:
return 'image/png';
@@ -383,14 +338,16 @@ class OC_Image implements \OCP\IImage {
$res = imagepng($this->resource);
break;
case "image/jpeg":
- /** @psalm-suppress InvalidScalarArgument */
- imageinterlace($this->resource, (PHP_VERSION_ID >= 80000 ? true : 1));
+ imageinterlace($this->resource, true);
$quality = $this->getJpegQuality();
$res = imagejpeg($this->resource, null, $quality);
break;
case "image/gif":
$res = imagegif($this->resource);
break;
+ case "image/webp":
+ $res = imagewebp($this->resource, null, $this->getWebpQuality());
+ break;
default:
$res = imagepng($this->resource);
$this->logger->info('OC_Image->data. Could not guess mime-type, defaulting to png', ['app' => 'core']);
@@ -405,7 +362,7 @@ class OC_Image implements \OCP\IImage {
/**
* @return string - base64 encoded, which is suitable for embedding in a VCard.
*/
- public function __toString() {
+ public function __toString(): string {
return base64_encode($this->data());
}
@@ -422,6 +379,18 @@ class OC_Image implements \OCP\IImage {
}
/**
+ * @return int
+ */
+ protected function getWebpQuality(): int {
+ $quality = $this->config->getAppValue('preview', 'webp_quality', (string) self::DEFAULT_WEBP_QUALITY);
+ // TODO: remove when getAppValue is type safe
+ if ($quality === null) {
+ $quality = self::DEFAULT_WEBP_QUALITY;
+ }
+ return min(100, max(10, (int) $quality));
+ }
+
+ /**
* (I'm open for suggestions on better method name ;)
* Get the orientation based on EXIF data.
*
@@ -558,7 +527,7 @@ class OC_Image implements \OCP\IImage {
* It is the responsibility of the caller to position the pointer at the correct place and to close the handle again.
*
* @param resource $handle
- * @return resource|\GdImage|false An image resource or false on error
+ * @return \GdImage|false An image resource or false on error
*/
public function loadFromFileHandle($handle) {
$contents = stream_get_contents($handle);
@@ -637,7 +606,7 @@ class OC_Image implements \OCP\IImage {
* Loads an image from a local file.
*
* @param bool|string $imagePath The path to a local file.
- * @return bool|resource|\GdImage An image resource or false on error
+ * @return bool|\GdImage An image resource or false on error
*/
public function loadFromFile($imagePath = false) {
// exif_imagetype throws "read error!" if file is less than 12 byte
@@ -775,7 +744,7 @@ class OC_Image implements \OCP\IImage {
* Loads an image from a string of data.
*
* @param string $str A string of image data as read from a file.
- * @return bool|resource|\GdImage An image resource or false on error
+ * @return bool|\GdImage An image resource or false on error
*/
public function loadFromData(string $str) {
if (!$this->checkImageDataSize($str)) {
@@ -801,7 +770,7 @@ class OC_Image implements \OCP\IImage {
* Loads an image from a base64 encoded string.
*
* @param string $str A string base64 encoded string of image data.
- * @return bool|resource|\GdImage An image resource or false on error
+ * @return bool|\GdImage An image resource or false on error
*/
public function loadFromBase64(string $str) {
$data = base64_decode($str);
@@ -842,7 +811,7 @@ class OC_Image implements \OCP\IImage {
/**
* @param $maxSize
- * @return resource|bool|\GdImage
+ * @return bool|\GdImage
*/
private function resizeNew(int $maxSize) {
if (!$this->valid()) {
@@ -883,7 +852,7 @@ class OC_Image implements \OCP\IImage {
/**
* @param int $width
* @param int $height
- * @return resource|bool|\GdImage
+ * @return bool|\GdImage
*/
public function preciseResizeNew(int $width, int $height) {
if (!($width > 0) || !($height > 0)) {
@@ -959,13 +928,13 @@ class OC_Image implements \OCP\IImage {
// preserve transparency
if ($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
- imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
+ imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127) ?: null);
imagealphablending($process, false);
imagesavealpha($process, true);
}
- imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $targetWidth, $targetHeight, $width, $height);
- if ($process === false) {
+ $result = imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $targetWidth, $targetHeight, $width, $height);
+ if ($result === false) {
$this->logger->debug('OC_Image->centerCrop, Error re-sampling process image ' . $width . 'x' . $height, ['app' => 'core']);
return false;
}
@@ -1001,7 +970,7 @@ class OC_Image implements \OCP\IImage {
* @param int $y Vertical position
* @param int $w Width
* @param int $h Height
- * @return resource|\GdImage|false
+ * @return \GdImage|false
*/
public function cropNew(int $x, int $y, int $w, int $h) {
if (!$this->valid()) {
@@ -1016,13 +985,13 @@ class OC_Image implements \OCP\IImage {
// preserve transparency
if ($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
- imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
+ imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127) ?: null);
imagealphablending($process, false);
imagesavealpha($process, true);
}
- imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $w, $h, $w, $h);
- if ($process === false) {
+ $result = imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $w, $h, $w, $h);
+ if ($result === false) {
$this->logger->debug(__METHOD__ . '(): Error re-sampling process image ' . $w . 'x' . $h, ['app' => 'core']);
return false;
}
@@ -1141,7 +1110,7 @@ if (!function_exists('exif_imagetype')) {
*
* @link https://www.php.net/manual/en/function.exif-imagetype.php#80383
* @param string $fileName
- * @return string|boolean
+ * @return int|false
*/
function exif_imagetype(string $fileName) {
if (($info = getimagesize($fileName)) !== false) {
diff --git a/lib/private/legacy/OC_JSON.php b/lib/private/legacy/OC_JSON.php
index b9cfb8210e0..a9682e2cce7 100644
--- a/lib/private/legacy/OC_JSON.php
+++ b/lib/private/legacy/OC_JSON.php
@@ -1,32 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
+
+use OC\Authentication\TwoFactorAuth\Manager as TwoFactorAuthManager;
+
class OC_JSON {
/**
* Check if the app is enabled, send json error msg if not
@@ -48,7 +29,7 @@ class OC_JSON {
* @suppress PhanDeprecatedFunction
*/
public static function checkLoggedIn() {
- $twoFactorAuthManger = \OC::$server->getTwoFactorAuthManager();
+ $twoFactorAuthManger = \OC::$server->get(TwoFactorAuthManager::class);
if (!\OC::$server->getUserSession()->isLoggedIn()
|| $twoFactorAuthManger->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
$l = \OC::$server->getL10N('lib');
@@ -114,22 +95,10 @@ class OC_JSON {
}
/**
- * Convert OC_L10N_String to string, for use in json encodings
- */
- protected static function to_string(&$value) {
- if ($value instanceof \OC\L10N\L10NString) {
- $value = (string)$value;
- }
- }
-
- /**
* Encode JSON
* @deprecated Use a AppFramework JSONResponse instead
*/
- public static function encode($data) {
- if (is_array($data)) {
- array_walk_recursive($data, ['OC_JSON', 'to_string']);
- }
+ private static function encode($data) {
return json_encode($data, JSON_HEX_TAG);
}
}
diff --git a/lib/private/legacy/OC_Response.php b/lib/private/legacy/OC_Response.php
index 9440feae3cd..8c8890c74c4 100644
--- a/lib/private/legacy/OC_Response.php
+++ b/lib/private/legacy/OC_Response.php
@@ -1,31 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
class OC_Response {
/**
diff --git a/lib/private/legacy/OC_Template.php b/lib/private/legacy/OC_Template.php
index 974f26fa381..5caa733b115 100644
--- a/lib/private/legacy/OC_Template.php
+++ b/lib/private/legacy/OC_Template.php
@@ -1,44 +1,14 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Individual IT Services <info@individual-it.net>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Marin Treselj <marin@pixelipo.com>
- * @author Michael Letzgus <www@chronos.michael-letzgus.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
use OC\TemplateLayout;
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\EventDispatcher\IEventDispatcher;
require_once __DIR__.'/template/functions.php';
@@ -249,20 +219,44 @@ class OC_Template extends \OC\Template\Base {
// If the hint is the same as the message there is no need to display it twice.
$hint = '';
}
+ $errors = [['error' => $error_msg, 'hint' => $hint]];
http_response_code($statusCode);
try {
- $content = new \OC_Template('', 'error', 'error', false);
- $errors = [['error' => $error_msg, 'hint' => $hint]];
- $content->assign('errors', $errors);
- $content->printPage();
- } catch (\Exception $e) {
+ // Try rendering themed html error page
+ $response = new TemplateResponse(
+ '',
+ 'error',
+ ['errors' => $errors],
+ TemplateResponse::RENDER_AS_ERROR,
+ $statusCode,
+ );
+ $event = new BeforeTemplateRenderedEvent(false, $response);
+ \OC::$server->get(IEventDispatcher::class)->dispatchTyped($event);
+ print($response->render());
+ } catch (\Throwable $e1) {
$logger = \OC::$server->getLogger();
- $logger->error("$error_msg $hint", ['app' => 'core']);
- $logger->logException($e, ['app' => 'core']);
+ $logger->logException($e1, [
+ 'app' => 'core',
+ 'message' => 'Rendering themed error page failed. Falling back to unthemed error page.'
+ ]);
- header('Content-Type: text/plain; charset=utf-8');
- print("$error_msg $hint");
+ try {
+ // Try rendering unthemed html error page
+ $content = new \OC_Template('', 'error', 'error', false);
+ $content->assign('errors', $errors);
+ $content->printPage();
+ } catch (\Exception $e2) {
+ // If nothing else works, fall back to plain text error page
+ $logger->error("$error_msg $hint", ['app' => 'core']);
+ $logger->logException($e2, [
+ 'app' => 'core',
+ 'message' => 'Rendering unthemed error page failed. Falling back to plain text error page.'
+ ]);
+
+ header('Content-Type: text/plain; charset=utf-8');
+ print("$error_msg $hint");
+ }
}
die();
}
@@ -275,8 +269,11 @@ class OC_Template extends \OC\Template\Base {
* @suppress PhanAccessMethodInternal
*/
public static function printExceptionErrorPage($exception, $statusCode = 503) {
+ $debug = false;
http_response_code($statusCode);
try {
+ $debug = \OC::$server->getSystemConfig()->getValue('debug', false);
+ $serverLogsDocumentation = \OC::$server->getSystemConfig()->getValue('documentation_url.server_logs', '');
$request = \OC::$server->getRequest();
$content = new \OC_Template('', 'exception', 'error', false);
$content->assign('errorClass', get_class($exception));
@@ -285,7 +282,8 @@ class OC_Template extends \OC\Template\Base {
$content->assign('file', $exception->getFile());
$content->assign('line', $exception->getLine());
$content->assign('exception', $exception);
- $content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
+ $content->assign('debugMode', $debug);
+ $content->assign('serverLogsDocumentation', $serverLogsDocumentation);
$content->assign('remoteAddr', $request->getRemoteAddress());
$content->assign('requestID', $request->getId());
$content->printPage();
@@ -296,22 +294,28 @@ class OC_Template extends \OC\Template\Base {
$logger->logException($e, ['app' => 'core']);
} catch (Throwable $e) {
// no way to log it properly - but to avoid a white page of death we send some output
- header('Content-Type: text/plain; charset=utf-8');
- print("Internal Server Error\n\n");
- print("The server encountered an internal error and was unable to complete your request.\n");
- print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
- print("More details can be found in the server log.\n");
+ self::printPlainErrorPage($e, $debug);
// and then throw it again to log it at least to the web server error log
throw $e;
}
- header('Content-Type: text/plain; charset=utf-8');
- print("Internal Server Error\n\n");
- print("The server encountered an internal error and was unable to complete your request.\n");
- print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
- print("More details can be found in the server log.\n");
+ self::printPlainErrorPage($e, $debug);
}
die();
}
+
+ private static function printPlainErrorPage(\Throwable $exception, bool $debug = false) {
+ header('Content-Type: text/plain; charset=utf-8');
+ print("Internal Server Error\n\n");
+ print("The server encountered an internal error and was unable to complete your request.\n");
+ print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
+ print("More details can be found in the server log.\n");
+
+ if ($debug) {
+ print("\n");
+ print($exception->getMessage() . ' ' . $exception->getFile() . ' at ' . $exception->getLine() . "\n");
+ print($exception->getTraceAsString());
+ }
+ }
}
diff --git a/lib/private/legacy/OC_User.php b/lib/private/legacy/OC_User.php
index caa4f5dca65..e7708525c76 100644
--- a/lib/private/legacy/OC_User.php
+++ b/lib/private/legacy/OC_User.php
@@ -1,47 +1,20 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Aldo "xoen" Giambelluca <xoen@xoen.org>
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bartek Przybylski <bart.p.pl@gmail.com>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author shkdee <louis.traynard@m4x.org>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
use OC\User\LoginException;
use OCP\EventDispatcher\IEventDispatcher;
-use OCP\ILogger;
+use OCP\IGroupManager;
+use OCP\ISession;
+use OCP\IUser;
use OCP\IUserManager;
+use OCP\Server;
use OCP\User\Events\BeforeUserLoggedInEvent;
use OCP\User\Events\UserLoggedInEvent;
+use Psr\Log\LoggerInterface;
/**
* This class provides wrapper methods for user management. Multiple backends are
@@ -84,7 +57,7 @@ class OC_User {
\OC::$server->getUserManager()->registerBackend($backend);
} else {
// You'll never know what happens
- if (null === $backend or !is_string($backend)) {
+ if ($backend === null or !is_string($backend)) {
$backend = 'database';
}
@@ -93,7 +66,7 @@ class OC_User {
case 'database':
case 'mysql':
case 'sqlite':
- \OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', ILogger::DEBUG);
+ Server::get(LoggerInterface::class)->debug('Adding user backend ' . $backend . '.', ['app' => 'core']);
self::$_usedBackends[$backend] = new \OC\User\Database();
\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
break;
@@ -102,7 +75,7 @@ class OC_User {
\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
break;
default:
- \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', ILogger::DEBUG);
+ Server::get(LoggerInterface::class)->debug('Adding default user backend ' . $backend . '.', ['app' => 'core']);
$className = 'OC_USER_' . strtoupper($backend);
self::$_usedBackends[$backend] = new $className();
\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
@@ -138,7 +111,7 @@ class OC_User {
$class = $config['class'];
$arguments = $config['arguments'];
if (class_exists($class)) {
- if (array_search($i, self::$_setupedBackends) === false) {
+ if (!in_array($i, self::$_setupedBackends)) {
// make a reflection object
$reflectionObj = new ReflectionClass($class);
@@ -147,10 +120,10 @@ class OC_User {
self::useBackend($backend);
self::$_setupedBackends[] = $i;
} else {
- \OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', ILogger::DEBUG);
+ Server::get(LoggerInterface::class)->debug('User backend ' . $class . ' already initialized.', ['app' => 'core']);
}
} else {
- \OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', ILogger::ERROR);
+ Server::get(LoggerInterface::class)->error('User backend ' . $class . ' not found.', ['app' => 'core']);
}
}
}
@@ -178,7 +151,7 @@ class OC_User {
$dispatcher = \OC::$server->get(IEventDispatcher::class);
if ($userSession->getUser() && !$userSession->getUser()->isEnabled()) {
- $message = \OC::$server->getL10N('lib')->t('User disabled');
+ $message = \OC::$server->getL10N('lib')->t('Account disabled');
throw new LoginException($message);
}
$userSession->setLoginName($uid);
@@ -303,7 +276,7 @@ class OC_User {
}
$user = \OC::$server->getUserSession()->getUser();
- if ($user instanceof \OCP\IUser) {
+ if ($user instanceof IUser) {
$backend = $user->getBackend();
if ($backend instanceof \OCP\User\Backend\ICustomLogout) {
return $backend->getLogoutUrl();
@@ -323,12 +296,9 @@ class OC_User {
* @return bool
*/
public static function isAdminUser($uid) {
- $group = \OC::$server->getGroupManager()->get('admin');
- $user = \OC::$server->getUserManager()->get($uid);
- if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
- return true;
- }
- return false;
+ $user = Server::get(IUserManager::class)->get($uid);
+ $isAdmin = $user && Server::get(IGroupManager::class)->isAdmin($user->getUID());
+ return $isAdmin && self::$incognitoMode === false;
}
@@ -338,7 +308,7 @@ class OC_User {
* @return string|false uid or false
*/
public static function getUser() {
- $uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
+ $uid = Server::get(ISession::class)?->get('user_id');
if (!is_null($uid) && self::$incognitoMode === false) {
return $uid;
} else {
diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php
index 9d62c46137e..8be4c81c2cd 100644
--- a/lib/private/legacy/OC_Util.php
+++ b/lib/private/legacy/OC_Util.php
@@ -1,70 +1,12 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Birk Borkason <daniel.niccoli@gmail.com>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Brice Maron <brice@bmaron.net>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Clark Tomlinson <fallen013@gmail.com>
- * @author cmeh <cmeh@users.noreply.github.com>
- * @author Eric Masseran <rico.masseran@gmail.com>
- * @author Felix Epp <work@felixepp.de>
- * @author Florin Peter <github@florin-peter.de>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author helix84 <helix84@centrum.sk>
- * @author Ilja Neumann <ineumann@owncloud.com>
- * @author Individual IT Services <info@individual-it.net>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Kawohl <john@owncloud.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Markus Goetz <markus@woboq.com>
- * @author Martin Mattel <martin.mattel@diemattels.at>
- * @author Marvin Thomas Rabe <mrabe@marvinrabe.de>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author rakekniven <mark.ziegler@rakekniven.de>
- * @author Robert Dailey <rcdailey@gmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sebastian Wessalowski <sebastian@wessalowski.org>
- * @author Stefan Rado <owncloud@sradonia.net>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Valdnet <47037905+Valdnet@users.noreply.github.com>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- * @author Volkan Gezer <volkangezer@gmail.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
use bantu\IniGetWrapper\IniGetWrapper;
+use OC\Authentication\TwoFactorAuth\Manager as TwoFactorAuthManager;
use OC\Files\SetupManager;
use OCP\Files\Template\ITemplateManager;
use OCP\IConfig;
@@ -325,9 +267,10 @@ class OC_Util {
return;
}
+ $timestamp = filemtime(OC::$SERVERROOT . '/version.php');
require OC::$SERVERROOT . '/version.php';
/** @var int $timestamp */
- self::$versionCache['OC_Version_Timestamp'] = \OC::$VERSION_MTIME;
+ self::$versionCache['OC_Version_Timestamp'] = $timestamp;
/** @var string $OC_Version */
self::$versionCache['OC_Version'] = $OC_Version;
/** @var string $OC_VersionString */
@@ -512,15 +455,7 @@ class OC_Util {
}
$webServerRestart = false;
- $setup = new \OC\Setup(
- $config,
- \OC::$server->get(IniGetWrapper::class),
- \OC::$server->getL10N('lib'),
- \OC::$server->get(\OCP\Defaults::class),
- \OC::$server->get(LoggerInterface::class),
- \OC::$server->getSecureRandom(),
- \OC::$server->get(\OC\Installer::class)
- );
+ $setup = \OCP\Server::get(\OC\Setup::class);
$urlGenerator = \OC::$server->getURLGenerator();
@@ -739,8 +674,8 @@ class OC_Util {
if ($perms[2] !== '0') {
$l = \OC::$server->getL10N('lib');
return [[
- 'error' => $l->t('Your data directory is readable by other users.'),
- 'hint' => $l->t('Please change the permissions to 0770 so that the directory cannot be listed by other users.'),
+ 'error' => $l->t('Your data directory is readable by other people.'),
+ 'hint' => $l->t('Please change the permissions to 0770 so that the directory cannot be listed by other people.'),
]];
}
}
@@ -792,7 +727,7 @@ class OC_Util {
exit();
}
// Redirect to 2FA challenge selection if 2FA challenge was not solved yet
- if (\OC::$server->getTwoFactorAuthManager()->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
+ if (\OC::$server->get(TwoFactorAuthManager::class)->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
exit();
}
@@ -976,11 +911,11 @@ class OC_Util {
*/
private static function isNonUTF8Locale() {
if (function_exists('escapeshellcmd')) {
- return '' === escapeshellcmd('§');
+ return escapeshellcmd('§') === '';
} elseif (function_exists('escapeshellarg')) {
- return '\'\'' === escapeshellarg('§');
+ return escapeshellarg('§') === '\'\'';
} else {
- return 0 === preg_match('/utf-?8/i', setlocale(LC_CTYPE, 0));
+ return preg_match('/utf-?8/i', setlocale(LC_CTYPE, 0)) === 0;
}
}
@@ -1119,8 +1054,8 @@ class OC_Util {
return false;
}
- foreach (str_split($trimmed) as $char) {
- if (str_contains(\OCP\Constants::FILENAME_INVALID_CHARS, $char)) {
+ foreach (\OCP\Util::getForbiddenFileNameChars() as $char) {
+ if (str_contains($trimmed, $char)) {
return false;
}
}
diff --git a/lib/private/legacy/template/functions.php b/lib/private/legacy/template/functions.php
index bcc0906dcdf..84ada2aa6d8 100644
--- a/lib/private/legacy/template/functions.php
+++ b/lib/private/legacy/template/functions.php
@@ -1,39 +1,12 @@
<?php
-use OCP\Util;
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Michael Letzgus <www@chronos.michael-letzgus.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
+use OCP\Util;
+
function p($string) {
print(\OCP\Util::sanitizeHTML($string));
}