aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPawel Boguslawski <pawel.boguslawski@ib.pl>2022-11-04 13:34:21 +0100
committerPawel Boguslawski <pawel.boguslawski@ib.pl>2022-11-04 13:34:21 +0100
commit4a46c747e9ec5e06b26d4ca4c319fcc40d06d504 (patch)
tree15a0f25e5c7701b92a6e91e4a9422bf08fc07fd3 /lib
parenta850424b1bb768a834415f699afef0014a50b505 (diff)
parent2600a00c007683f39e24028d4ad7a912937ef16f (diff)
downloadnextcloud-server-4a46c747e9ec5e06b26d4ca4c319fcc40d06d504.tar.gz
nextcloud-server-4a46c747e9ec5e06b26d4ca4c319fcc40d06d504.zip
Merge master
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php39
-rw-r--r--lib/composer/composer/autoload_classmap.php40
-rw-r--r--lib/composer/composer/autoload_static.php40
-rw-r--r--lib/l10n/bg.js5
-rw-r--r--lib/l10n/bg.json5
-rw-r--r--lib/l10n/cs.js3
-rw-r--r--lib/l10n/cs.json3
-rw-r--r--lib/l10n/da.js1
-rw-r--r--lib/l10n/da.json1
-rw-r--r--lib/l10n/de.js58
-rw-r--r--lib/l10n/de.json58
-rw-r--r--lib/l10n/de_DE.js3
-rw-r--r--lib/l10n/de_DE.json3
-rw-r--r--lib/l10n/el.js2
-rw-r--r--lib/l10n/el.json2
-rw-r--r--lib/l10n/es.js2
-rw-r--r--lib/l10n/es.json2
-rw-r--r--lib/l10n/es_SV.js2
-rw-r--r--lib/l10n/es_SV.json2
-rw-r--r--lib/l10n/eu.js3
-rw-r--r--lib/l10n/eu.json3
-rw-r--r--lib/l10n/fi.js7
-rw-r--r--lib/l10n/fi.json7
-rw-r--r--lib/l10n/fr.js3
-rw-r--r--lib/l10n/fr.json3
-rw-r--r--lib/l10n/hr.js2
-rw-r--r--lib/l10n/hr.json2
-rw-r--r--lib/l10n/hu.js3
-rw-r--r--lib/l10n/hu.json3
-rw-r--r--lib/l10n/id.js1
-rw-r--r--lib/l10n/id.json1
-rw-r--r--lib/l10n/is.js1
-rw-r--r--lib/l10n/is.json1
-rw-r--r--lib/l10n/it.js2
-rw-r--r--lib/l10n/it.json2
-rw-r--r--lib/l10n/ja.js3
-rw-r--r--lib/l10n/ja.json3
-rw-r--r--lib/l10n/ko.js1
-rw-r--r--lib/l10n/ko.json1
-rw-r--r--lib/l10n/mk.js2
-rw-r--r--lib/l10n/mk.json2
-rw-r--r--lib/l10n/nb.js16
-rw-r--r--lib/l10n/nb.json16
-rw-r--r--lib/l10n/nl.js2
-rw-r--r--lib/l10n/nl.json2
-rw-r--r--lib/l10n/nn_NO.js7
-rw-r--r--lib/l10n/nn_NO.json7
-rw-r--r--lib/l10n/pl.js3
-rw-r--r--lib/l10n/pl.json3
-rw-r--r--lib/l10n/pt_BR.js3
-rw-r--r--lib/l10n/pt_BR.json3
-rw-r--r--lib/l10n/pt_PT.js2
-rw-r--r--lib/l10n/pt_PT.json2
-rw-r--r--lib/l10n/ro.js1
-rw-r--r--lib/l10n/ro.json1
-rw-r--r--lib/l10n/ru.js8
-rw-r--r--lib/l10n/ru.json8
-rw-r--r--lib/l10n/sc.js2
-rw-r--r--lib/l10n/sc.json2
-rw-r--r--lib/l10n/sk.js2
-rw-r--r--lib/l10n/sk.json2
-rw-r--r--lib/l10n/sl.js2
-rw-r--r--lib/l10n/sl.json2
-rw-r--r--lib/l10n/sv.js2
-rw-r--r--lib/l10n/sv.json2
-rw-r--r--lib/l10n/th.js2
-rw-r--r--lib/l10n/th.json2
-rw-r--r--lib/l10n/tr.js7
-rw-r--r--lib/l10n/tr.json7
-rw-r--r--lib/l10n/uk.js5
-rw-r--r--lib/l10n/uk.json5
-rw-r--r--lib/l10n/zh_CN.js2
-rw-r--r--lib/l10n/zh_CN.json2
-rw-r--r--lib/l10n/zh_HK.js3
-rw-r--r--lib/l10n/zh_HK.json3
-rw-r--r--lib/l10n/zh_TW.js3
-rw-r--r--lib/l10n/zh_TW.json3
-rw-r--r--lib/private/Accounts/AccountManager.php2
-rw-r--r--lib/private/AllConfig.php6
-rw-r--r--lib/private/App/AppStore/Bundles/HubBundle.php4
-rw-r--r--lib/private/App/CompareVersion.php2
-rw-r--r--lib/private/App/Platform.php38
-rw-r--r--lib/private/App/PlatformRepository.php23
-rw-r--r--lib/private/AppFramework/App.php2
-rw-r--r--lib/private/AppFramework/Bootstrap/RegistrationContext.php45
-rw-r--r--lib/private/AppFramework/Http/Dispatcher.php4
-rw-r--r--lib/private/AppFramework/Http/Request.php35
-rw-r--r--lib/private/AppFramework/Middleware/MiddlewareDispatcher.php2
-rw-r--r--lib/private/AppFramework/Middleware/SessionMiddleware.php4
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php2
-rw-r--r--lib/private/Authentication/Token/IProvider.php2
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php20
-rw-r--r--lib/private/Authentication/Token/TokenCleanupJob.php41
-rw-r--r--lib/private/Avatar/Avatar.php90
-rw-r--r--lib/private/Avatar/GuestAvatar.php27
-rw-r--r--lib/private/Avatar/PlaceholderAvatar.php25
-rw-r--r--lib/private/Avatar/UserAvatar.php50
-rw-r--r--lib/private/BackgroundJob/Job.php4
-rw-r--r--lib/private/BackgroundJob/JobList.php113
-rw-r--r--lib/private/BinaryFinder.php71
-rw-r--r--lib/private/Cache/CappedMemoryCache.php1
-rw-r--r--lib/private/Calendar/Manager.php153
-rw-r--r--lib/private/Collaboration/Reference/File/FileReferenceEventListener.php61
-rw-r--r--lib/private/Collaboration/Reference/File/FileReferenceProvider.php153
-rw-r--r--lib/private/Collaboration/Reference/LinkReferenceProvider.php162
-rw-r--r--lib/private/Collaboration/Reference/Reference.php163
-rw-r--r--lib/private/Collaboration/Reference/ReferenceManager.php169
-rw-r--r--lib/private/Comments/Comment.php8
-rw-r--r--lib/private/Comments/Manager.php17
-rw-r--r--lib/private/Config.php8
-rw-r--r--lib/private/Console/Application.php6
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php4
-rw-r--r--lib/private/DB/Connection.php2
-rw-r--r--lib/private/DB/MigrationService.php35
-rw-r--r--lib/private/DB/Migrator.php37
-rw-r--r--lib/private/DB/MigratorExecuteSqlEvent.php55
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php96
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php4
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php50
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php4
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php11
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php11
-rw-r--r--lib/private/DB/QueryBuilder/QueryBuilder.php14
-rw-r--r--lib/private/Diagnostics/QueryLogger.php2
-rw-r--r--lib/private/Encryption/File.php29
-rw-r--r--lib/private/Encryption/Util.php78
-rw-r--r--lib/private/Files/AppData/AppData.php2
-rw-r--r--lib/private/Files/Cache/Cache.php70
-rw-r--r--lib/private/Files/Cache/CacheQueryBuilder.php12
-rw-r--r--lib/private/Files/Cache/Propagator.php10
-rw-r--r--lib/private/Files/Cache/QuerySearchHelper.php4
-rw-r--r--lib/private/Files/Cache/Scanner.php13
-rw-r--r--lib/private/Files/Cache/SearchBuilder.php2
-rw-r--r--lib/private/Files/Cache/Storage.php4
-rw-r--r--lib/private/Files/Cache/StorageGlobal.php2
-rw-r--r--lib/private/Files/Cache/Updater.php4
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheJail.php22
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheWrapper.php2
-rw-r--r--lib/private/Files/Config/UserMountCache.php11
-rw-r--r--lib/private/Files/FileInfo.php4
-rw-r--r--lib/private/Files/Filesystem.php2
-rw-r--r--lib/private/Files/Mount/Manager.php2
-rw-r--r--lib/private/Files/Node/File.php1
-rw-r--r--lib/private/Files/Node/Folder.php19
-rw-r--r--lib/private/Files/Node/Node.php21
-rw-r--r--lib/private/Files/Node/Root.php4
-rw-r--r--lib/private/Files/ObjectStore/NoopScanner.php2
-rw-r--r--lib/private/Files/ObjectStore/S3ConnectionTrait.php31
-rw-r--r--lib/private/Files/ObjectStore/S3ObjectTrait.php10
-rw-r--r--lib/private/Files/SetupManager.php29
-rw-r--r--lib/private/Files/SimpleFS/NewSimpleFile.php38
-rw-r--r--lib/private/Files/SimpleFS/SimpleFile.php44
-rw-r--r--lib/private/Files/SimpleFS/SimpleFolder.php13
-rw-r--r--lib/private/Files/Storage/Wrapper/Encoding.php2
-rw-r--r--lib/private/Files/View.php11
-rw-r--r--lib/private/HintException.php2
-rw-r--r--lib/private/Http/Client/Client.php2
-rw-r--r--lib/private/Http/Client/LocalAddressChecker.php16
-rwxr-xr-xlib/private/LargeFileHelper.php4
-rw-r--r--lib/private/Log.php39
-rw-r--r--lib/private/Log/ExceptionSerializer.php13
-rw-r--r--lib/private/Log/Rotate.php2
-rw-r--r--lib/private/Mail/Mailer.php21
-rw-r--r--lib/private/MemoryInfo.php2
-rw-r--r--lib/private/Metadata/IMetadataManager.php2
-rw-r--r--lib/private/Metadata/Provider/ExifProvider.php2
-rw-r--r--lib/private/Migration/BackgroundRepair.php45
-rw-r--r--lib/private/NavigationManager.php40
-rw-r--r--lib/private/Notification/Manager.php10
-rw-r--r--lib/private/OCS/DiscoveryService.php2
-rw-r--r--lib/private/Preview/ProviderV1Adapter.php2
-rw-r--r--lib/private/PreviewManager.php113
-rw-r--r--lib/private/Profile/ProfileManager.php13
-rw-r--r--lib/private/Repair.php72
-rw-r--r--lib/private/Repair/Events/RepairAdvanceEvent.php48
-rw-r--r--lib/private/Repair/Events/RepairErrorEvent.php (renamed from lib/public/BackgroundJob.php)38
-rw-r--r--lib/private/Repair/Events/RepairFinishEvent.php30
-rw-r--r--lib/private/Repair/Events/RepairInfoEvent.php (renamed from lib/private/BackgroundJob/Legacy/RegularJob.php)36
-rw-r--r--lib/private/Repair/Events/RepairStartEvent.php (renamed from lib/private/BackgroundJob/Legacy/QueuedJob.php)42
-rw-r--r--lib/private/Repair/Events/RepairStepEvent.php41
-rw-r--r--lib/private/Repair/Events/RepairWarningEvent.php41
-rw-r--r--lib/private/Repair/NC24/AddTokenCleanupJob.php47
-rw-r--r--lib/private/Repair/RemoveLinkShares.php2
-rw-r--r--lib/private/Route/Router.php2
-rw-r--r--lib/private/Security/Bruteforce/Throttler.php16
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php6
-rw-r--r--lib/private/Security/TrustedDomainHelper.php2
-rw-r--r--lib/private/Security/VerificationToken/CleanUpJob.php31
-rw-r--r--lib/private/Server.php89
-rw-r--r--lib/private/Session/CryptoSessionData.php17
-rw-r--r--lib/private/Session/Internal.php25
-rw-r--r--lib/private/Session/Memory.php6
-rw-r--r--lib/private/Setup.php2
-rw-r--r--lib/private/Setup/MySQL.php21
-rw-r--r--lib/private/Share/Constants.php2
-rw-r--r--lib/private/Share/Share.php4
-rw-r--r--lib/private/Share20/DefaultShareProvider.php100
-rw-r--r--lib/private/Share20/Manager.php15
-rw-r--r--lib/private/Share20/Share.php29
-rw-r--r--lib/private/Share20/ShareAttributes.php73
-rw-r--r--lib/private/Template/JSConfigHelper.php2
-rw-r--r--lib/private/Template/JSResourceLocator.php4
-rw-r--r--lib/private/TemplateLayout.php4
-rw-r--r--lib/private/URLGenerator.php39
-rw-r--r--lib/private/Updater.php142
-rw-r--r--lib/private/User/Database.php6
-rw-r--r--lib/private/User/DisplayNameCache.php4
-rw-r--r--lib/private/User/LazyUser.php6
-rw-r--r--lib/private/User/Listeners/UserChangedListener.php62
-rw-r--r--lib/private/User/Listeners/UserDeletedListener.php65
-rw-r--r--lib/private/User/Manager.php11
-rw-r--r--lib/private/User/User.php13
-rw-r--r--lib/private/legacy/OC_App.php38
-rw-r--r--lib/private/legacy/OC_Files.php33
-rw-r--r--lib/private/legacy/OC_Helper.php44
-rw-r--r--lib/private/legacy/OC_User.php8
-rw-r--r--lib/public/App.php104
-rw-r--r--lib/public/App/IAppManager.php3
-rw-r--r--lib/public/AppFramework/Bootstrap/IRegistrationContext.php21
-rw-r--r--lib/public/AppFramework/Db/Entity.php3
-rw-r--r--lib/public/Authentication/IProvideUserSecretBackend.php41
-rw-r--r--lib/public/BackgroundJob/IJob.php21
-rw-r--r--lib/public/BackgroundJob/IJobList.php54
-rw-r--r--lib/public/BackgroundJob/Job.php31
-rw-r--r--lib/public/BackgroundJob/QueuedJob.php15
-rw-r--r--lib/public/BackgroundJob/TimedJob.php20
-rw-r--r--lib/public/Cache/CappedMemoryCache.php160
-rw-r--r--lib/public/Calendar/ICreateFromString.php9
-rw-r--r--lib/public/Calendar/IManager.php14
-rw-r--r--lib/public/Collaboration/Reference/IReference.php130
-rw-r--r--lib/public/Collaboration/Reference/IReferenceManager.php70
-rw-r--r--lib/public/Collaboration/Reference/IReferenceProvider.php63
-rw-r--r--lib/public/Color.php142
-rw-r--r--lib/public/Comments/IComment.php4
-rw-r--r--lib/public/Comments/ICommentsManager.php4
-rw-r--r--lib/public/DB/QueryBuilder/IExpressionBuilder.php64
-rw-r--r--lib/public/DB/QueryBuilder/IFunctionBuilder.php12
-rw-r--r--lib/public/DB/QueryBuilder/IQueryBuilder.php8
-rw-r--r--lib/public/Federation/Events/TrustedServerRemovedEvent.php48
-rw-r--r--lib/public/Files/Cache/ICache.php2
-rw-r--r--lib/public/Files/DavUtil.php89
-rw-r--r--lib/public/Files/Events/BeforeDirectFileDownloadEvent.php84
-rw-r--r--lib/public/Files/Events/BeforeZipCreatedEvent.php91
-rw-r--r--lib/public/Files/Mount/ISystemMountPoint.php34
-rw-r--r--lib/public/Files/SimpleFS/ISimpleFile.php22
-rw-r--r--lib/public/Files/SimpleFS/ISimpleFolder.php17
-rw-r--r--lib/public/Files/SimpleFS/ISimpleRoot.php4
-rw-r--r--lib/public/Files/SimpleFS/InMemoryFile.php24
-rw-r--r--lib/public/IAvatar.php42
-rw-r--r--lib/public/IAvatarManager.php7
-rw-r--r--lib/public/IBinaryFinder.php41
-rw-r--r--lib/public/IEventSource.php2
-rw-r--r--lib/public/ISession.php8
-rw-r--r--lib/public/IURLGenerator.php10
-rw-r--r--lib/public/IUserManager.php9
-rw-r--r--lib/public/Migration/IOutput.php6
-rw-r--r--lib/public/Security/Bruteforce/IThrottler.php126
-rw-r--r--lib/public/Share/IAttributes.php68
-rw-r--r--lib/public/Share/IManager.php3
-rw-r--r--lib/public/Share/IShare.php31
-rw-r--r--lib/public/Share/IShareProvider.php3
-rw-r--r--lib/public/User/Events/UserChangedEvent.php10
-rw-r--r--lib/public/UserStatus/IUserStatus.php12
-rw-r--r--lib/public/Util.php24
264 files changed, 4556 insertions, 1709 deletions
diff --git a/lib/base.php b/lib/base.php
index 814f30b5af3..055cc6786f0 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -295,6 +295,7 @@ class OC {
if (((bool) $systemConfig->getValue('maintenance', false)) && OC::$SUBURI != '/core/ajax/update.php') {
// send http status 503
http_response_code(503);
+ header('X-Nextcloud-Maintenance-Mode: 1');
header('Retry-After: 120');
// render error page
@@ -444,7 +445,9 @@ class OC {
die();
}
+ //try to set the session lifetime
$sessionLifeTime = self::getSessionLifeTime();
+ @ini_set('gc_maxlifetime', (string)$sessionLifeTime);
// session timeout
if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
@@ -454,7 +457,10 @@ class OC {
\OC::$server->getUserSession()->logout();
}
- $session->set('LAST_ACTIVITY', time());
+ if (!self::hasSessionRelaxedExpiry()) {
+ $session->set('LAST_ACTIVITY', time());
+ }
+ $session->close();
}
/**
@@ -465,6 +471,13 @@ class OC {
}
/**
+ * @return bool true if the session expiry should only be done by gc instead of an explicit timeout
+ */
+ public static function hasSessionRelaxedExpiry(): bool {
+ return \OC::$server->getConfig()->getSystemValue('session_relaxed_expiry', false);
+ }
+
+ /**
* Try to set some values to the required Nextcloud default
*/
public static function setRequiredIniValues() {
@@ -706,9 +719,6 @@ class OC {
$config->deleteAppValue('core', 'cronErrors');
}
}
- //try to set the session lifetime
- $sessionLifeTime = self::getSessionLifeTime();
- @ini_set('gc_maxlifetime', (string)$sessionLifeTime);
// User and Groups
if (!$systemConfig->getValue("installed", false)) {
@@ -740,6 +750,7 @@ class OC {
self::registerEncryptionWrapperAndHooks();
self::registerAccountHooks();
self::registerResourceCollectionHooks();
+ self::registerFileReferenceEventListener();
self::registerAppRestrictionsHooks();
// Make sure that the application class is not loaded before the database is setup
@@ -902,6 +913,10 @@ class OC {
\OC\Collaboration\Resources\Listener::register(Server::get(SymfonyAdapter::class), Server::get(IEventDispatcher::class));
}
+ private static function registerFileReferenceEventListener() {
+ \OC\Collaboration\Reference\File\FileReferenceEventListener::register(Server::get(IEventDispatcher::class));
+ }
+
/**
* register hooks for the filesystem
*/
@@ -1048,6 +1063,22 @@ class OC {
return;
}
+ // Handle requests for JSON or XML
+ $acceptHeader = $request->getHeader('Accept');
+ if (in_array($acceptHeader, ['application/json', 'application/xml'], true)) {
+ http_response_code(404);
+ return;
+ }
+
+ // Handle resources that can't be found
+ // This prevents browsers from redirecting to the default page and then
+ // attempting to parse HTML as CSS and similar.
+ $destinationHeader = $request->getHeader('Sec-Fetch-Dest');
+ if (in_array($destinationHeader, ['font', 'script', 'style'])) {
+ http_response_code(404);
+ return;
+ }
+
// Someone is logged in
if (\OC::$server->getUserSession()->isLoggedIn()) {
OC_App::loadApps();
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index eae31d41449..8c485fe53d9 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -21,7 +21,6 @@ return array(
'OCP\\Activity\\IManager' => $baseDir . '/lib/public/Activity/IManager.php',
'OCP\\Activity\\IProvider' => $baseDir . '/lib/public/Activity/IProvider.php',
'OCP\\Activity\\ISetting' => $baseDir . '/lib/public/Activity/ISetting.php',
- 'OCP\\App' => $baseDir . '/lib/public/App.php',
'OCP\\AppFramework\\ApiController' => $baseDir . '/lib/public/AppFramework/ApiController.php',
'OCP\\AppFramework\\App' => $baseDir . '/lib/public/AppFramework/App.php',
'OCP\\AppFramework\\AuthPublicShareController' => $baseDir . '/lib/public/AppFramework/AuthPublicShareController.php',
@@ -90,6 +89,7 @@ return array(
'OCP\\Authentication\\Exceptions\\PasswordUnavailableException' => $baseDir . '/lib/public/Authentication/Exceptions/PasswordUnavailableException.php',
'OCP\\Authentication\\IAlternativeLogin' => $baseDir . '/lib/public/Authentication/IAlternativeLogin.php',
'OCP\\Authentication\\IApacheBackend' => $baseDir . '/lib/public/Authentication/IApacheBackend.php',
+ 'OCP\\Authentication\\IProvideUserSecretBackend' => $baseDir . '/lib/public/Authentication/IProvideUserSecretBackend.php',
'OCP\\Authentication\\LoginCredentials\\ICredentials' => $baseDir . '/lib/public/Authentication/LoginCredentials/ICredentials.php',
'OCP\\Authentication\\LoginCredentials\\IStore' => $baseDir . '/lib/public/Authentication/LoginCredentials/IStore.php',
'OCP\\Authentication\\TwoFactorAuth\\ALoginSetupController' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/ALoginSetupController.php',
@@ -109,13 +109,13 @@ return array(
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorProviderForUserDisabled' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/TwoFactorProviderForUserDisabled.php',
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorProviderForUserEnabled' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/TwoFactorProviderForUserEnabled.php',
'OCP\\AutoloadNotAllowedException' => $baseDir . '/lib/public/AutoloadNotAllowedException.php',
- 'OCP\\BackgroundJob' => $baseDir . '/lib/public/BackgroundJob.php',
'OCP\\BackgroundJob\\IJob' => $baseDir . '/lib/public/BackgroundJob/IJob.php',
'OCP\\BackgroundJob\\IJobList' => $baseDir . '/lib/public/BackgroundJob/IJobList.php',
'OCP\\BackgroundJob\\Job' => $baseDir . '/lib/public/BackgroundJob/Job.php',
'OCP\\BackgroundJob\\QueuedJob' => $baseDir . '/lib/public/BackgroundJob/QueuedJob.php',
'OCP\\BackgroundJob\\TimedJob' => $baseDir . '/lib/public/BackgroundJob/TimedJob.php',
'OCP\\Broadcast\\Events\\IBroadcastEvent' => $baseDir . '/lib/public/Broadcast/Events/IBroadcastEvent.php',
+ 'OCP\\Cache\\CappedMemoryCache' => $baseDir . '/lib/public/Cache/CappedMemoryCache.php',
'OCP\\Calendar\\BackendTemporarilyUnavailableException' => $baseDir . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
'OCP\\Calendar\\Exceptions\\CalendarException' => $baseDir . '/lib/public/Calendar/Exceptions/CalendarException.php',
'OCP\\Calendar\\ICalendar' => $baseDir . '/lib/public/Calendar/ICalendar.php',
@@ -142,6 +142,9 @@ return array(
'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php',
'OCP\\Collaboration\\Collaborators\\ISearchResult' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchResult.php',
'OCP\\Collaboration\\Collaborators\\SearchResultType' => $baseDir . '/lib/public/Collaboration/Collaborators/SearchResultType.php',
+ 'OCP\\Collaboration\\Reference\\IReference' => $baseDir . '/lib/public/Collaboration/Reference/IReference.php',
+ 'OCP\\Collaboration\\Reference\\IReferenceManager' => $baseDir . '/lib/public/Collaboration/Reference/IReferenceManager.php',
+ 'OCP\\Collaboration\\Reference\\IReferenceProvider' => $baseDir . '/lib/public/Collaboration/Reference/IReferenceProvider.php',
'OCP\\Collaboration\\Resources\\CollectionException' => $baseDir . '/lib/public/Collaboration/Resources/CollectionException.php',
'OCP\\Collaboration\\Resources\\ICollection' => $baseDir . '/lib/public/Collaboration/Resources/ICollection.php',
'OCP\\Collaboration\\Resources\\IManager' => $baseDir . '/lib/public/Collaboration/Resources/IManager.php',
@@ -150,6 +153,7 @@ return array(
'OCP\\Collaboration\\Resources\\IResource' => $baseDir . '/lib/public/Collaboration/Resources/IResource.php',
'OCP\\Collaboration\\Resources\\LoadAdditionalScriptsEvent' => $baseDir . '/lib/public/Collaboration/Resources/LoadAdditionalScriptsEvent.php',
'OCP\\Collaboration\\Resources\\ResourceException' => $baseDir . '/lib/public/Collaboration/Resources/ResourceException.php',
+ 'OCP\\Color' => $baseDir . '/lib/public/Color.php',
'OCP\\Command\\IBus' => $baseDir . '/lib/public/Command/IBus.php',
'OCP\\Command\\ICommand' => $baseDir . '/lib/public/Command/ICommand.php',
'OCP\\Comments\\CommentsEntityEvent' => $baseDir . '/lib/public/Comments/CommentsEntityEvent.php',
@@ -224,6 +228,7 @@ return array(
'OCP\\EventDispatcher\\GenericEvent' => $baseDir . '/lib/public/EventDispatcher/GenericEvent.php',
'OCP\\EventDispatcher\\IEventDispatcher' => $baseDir . '/lib/public/EventDispatcher/IEventDispatcher.php',
'OCP\\EventDispatcher\\IEventListener' => $baseDir . '/lib/public/EventDispatcher/IEventListener.php',
+ 'OCP\\Federation\\Events\\TrustedServerRemovedEvent' => $baseDir . '/lib/public/Federation/Events/TrustedServerRemovedEvent.php',
'OCP\\Federation\\Exceptions\\ActionNotSupportedException' => $baseDir . '/lib/public/Federation/Exceptions/ActionNotSupportedException.php',
'OCP\\Federation\\Exceptions\\AuthenticationFailedException' => $baseDir . '/lib/public/Federation/Exceptions/AuthenticationFailedException.php',
'OCP\\Federation\\Exceptions\\BadRequestException' => $baseDir . '/lib/public/Federation/Exceptions/BadRequestException.php',
@@ -260,10 +265,13 @@ return array(
'OCP\\Files\\Config\\IMountProviderCollection' => $baseDir . '/lib/public/Files/Config/IMountProviderCollection.php',
'OCP\\Files\\Config\\IRootMountProvider' => $baseDir . '/lib/public/Files/Config/IRootMountProvider.php',
'OCP\\Files\\Config\\IUserMountCache' => $baseDir . '/lib/public/Files/Config/IUserMountCache.php',
+ 'OCP\\Files\\DavUtil' => $baseDir . '/lib/public/Files/DavUtil.php',
'OCP\\Files\\EmptyFileNameException' => $baseDir . '/lib/public/Files/EmptyFileNameException.php',
'OCP\\Files\\EntityTooLargeException' => $baseDir . '/lib/public/Files/EntityTooLargeException.php',
+ 'OCP\\Files\\Events\\BeforeDirectFileDownloadEvent' => $baseDir . '/lib/public/Files/Events/BeforeDirectFileDownloadEvent.php',
'OCP\\Files\\Events\\BeforeFileScannedEvent' => $baseDir . '/lib/public/Files/Events/BeforeFileScannedEvent.php',
'OCP\\Files\\Events\\BeforeFolderScannedEvent' => $baseDir . '/lib/public/Files/Events/BeforeFolderScannedEvent.php',
+ 'OCP\\Files\\Events\\BeforeZipCreatedEvent' => $baseDir . '/lib/public/Files/Events/BeforeZipCreatedEvent.php',
'OCP\\Files\\Events\\FileCacheUpdated' => $baseDir . '/lib/public/Files/Events/FileCacheUpdated.php',
'OCP\\Files\\Events\\FileScannedEvent' => $baseDir . '/lib/public/Files/Events/FileScannedEvent.php',
'OCP\\Files\\Events\\FolderScannedEvent' => $baseDir . '/lib/public/Files/Events/FolderScannedEvent.php',
@@ -310,6 +318,7 @@ return array(
'OCP\\Files\\Lock\\OwnerLockedException' => $baseDir . '/lib/public/Files/Lock/OwnerLockedException.php',
'OCP\\Files\\Mount\\IMountManager' => $baseDir . '/lib/public/Files/Mount/IMountManager.php',
'OCP\\Files\\Mount\\IMountPoint' => $baseDir . '/lib/public/Files/Mount/IMountPoint.php',
+ 'OCP\\Files\\Mount\\ISystemMountPoint' => $baseDir . '/lib/public/Files/Mount/ISystemMountPoint.php',
'OCP\\Files\\Node' => $baseDir . '/lib/public/Files/Node.php',
'OCP\\Files\\NotEnoughSpaceException' => $baseDir . '/lib/public/Files/NotEnoughSpaceException.php',
'OCP\\Files\\NotFoundException' => $baseDir . '/lib/public/Files/NotFoundException.php',
@@ -406,6 +415,7 @@ return array(
'OCP\\IAppConfig' => $baseDir . '/lib/public/IAppConfig.php',
'OCP\\IAvatar' => $baseDir . '/lib/public/IAvatar.php',
'OCP\\IAvatarManager' => $baseDir . '/lib/public/IAvatarManager.php',
+ 'OCP\\IBinaryFinder' => $baseDir . '/lib/public/IBinaryFinder.php',
'OCP\\ICache' => $baseDir . '/lib/public/ICache.php',
'OCP\\ICacheFactory' => $baseDir . '/lib/public/ICacheFactory.php',
'OCP\\ICertificate' => $baseDir . '/lib/public/ICertificate.php',
@@ -506,6 +516,7 @@ return array(
'OCP\\Search\\Result' => $baseDir . '/lib/public/Search/Result.php',
'OCP\\Search\\SearchResult' => $baseDir . '/lib/public/Search/SearchResult.php',
'OCP\\Search\\SearchResultEntry' => $baseDir . '/lib/public/Search/SearchResultEntry.php',
+ 'OCP\\Security\\Bruteforce\\IThrottler' => $baseDir . '/lib/public/Security/Bruteforce/IThrottler.php',
'OCP\\Security\\Bruteforce\\MaxDelayReached' => $baseDir . '/lib/public/Security/Bruteforce/MaxDelayReached.php',
'OCP\\Security\\CSP\\AddContentSecurityPolicyEvent' => $baseDir . '/lib/public/Security/CSP/AddContentSecurityPolicyEvent.php',
'OCP\\Security\\Events\\GenerateSecurePasswordEvent' => $baseDir . '/lib/public/Security/Events/GenerateSecurePasswordEvent.php',
@@ -534,6 +545,7 @@ return array(
'OCP\\Share\\Exceptions\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php',
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
'OCP\\Share\\Exceptions\\ShareNotFound' => $baseDir . '/lib/public/Share/Exceptions/ShareNotFound.php',
+ 'OCP\\Share\\IAttributes' => $baseDir . '/lib/public/Share/IAttributes.php',
'OCP\\Share\\IManager' => $baseDir . '/lib/public/Share/IManager.php',
'OCP\\Share\\IProviderFactory' => $baseDir . '/lib/public/Share/IProviderFactory.php',
'OCP\\Share\\IShare' => $baseDir . '/lib/public/Share/IShare.php',
@@ -774,6 +786,7 @@ return array(
'OC\\Authentication\\Token\\PublicKeyTokenMapper' => $baseDir . '/lib/private/Authentication/Token/PublicKeyTokenMapper.php',
'OC\\Authentication\\Token\\PublicKeyTokenProvider' => $baseDir . '/lib/private/Authentication/Token/PublicKeyTokenProvider.php',
'OC\\Authentication\\Token\\RemoteWipe' => $baseDir . '/lib/private/Authentication/Token/RemoteWipe.php',
+ 'OC\\Authentication\\Token\\TokenCleanupJob' => $baseDir . '/lib/private/Authentication/Token/TokenCleanupJob.php',
'OC\\Authentication\\TwoFactorAuth\\Db\\ProviderUserAssignmentDao' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php',
'OC\\Authentication\\TwoFactorAuth\\EnforcementState' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/EnforcementState.php',
'OC\\Authentication\\TwoFactorAuth\\Manager' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/Manager.php',
@@ -793,10 +806,9 @@ return array(
'OC\\Avatar\\UserAvatar' => $baseDir . '/lib/private/Avatar/UserAvatar.php',
'OC\\BackgroundJob\\Job' => $baseDir . '/lib/private/BackgroundJob/Job.php',
'OC\\BackgroundJob\\JobList' => $baseDir . '/lib/private/BackgroundJob/JobList.php',
- 'OC\\BackgroundJob\\Legacy\\QueuedJob' => $baseDir . '/lib/private/BackgroundJob/Legacy/QueuedJob.php',
- 'OC\\BackgroundJob\\Legacy\\RegularJob' => $baseDir . '/lib/private/BackgroundJob/Legacy/RegularJob.php',
'OC\\BackgroundJob\\QueuedJob' => $baseDir . '/lib/private/BackgroundJob/QueuedJob.php',
'OC\\BackgroundJob\\TimedJob' => $baseDir . '/lib/private/BackgroundJob/TimedJob.php',
+ 'OC\\BinaryFinder' => $baseDir . '/lib/private/BinaryFinder.php',
'OC\\Broadcast\\Events\\BroadcastEvent' => $baseDir . '/lib/private/Broadcast/Events/BroadcastEvent.php',
'OC\\Cache\\CappedMemoryCache' => $baseDir . '/lib/private/Cache/CappedMemoryCache.php',
'OC\\Cache\\File' => $baseDir . '/lib/private/Cache/File.php',
@@ -814,6 +826,11 @@ return array(
'OC\\Collaboration\\Collaborators\\Search' => $baseDir . '/lib/private/Collaboration/Collaborators/Search.php',
'OC\\Collaboration\\Collaborators\\SearchResult' => $baseDir . '/lib/private/Collaboration/Collaborators/SearchResult.php',
'OC\\Collaboration\\Collaborators\\UserPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/UserPlugin.php',
+ 'OC\\Collaboration\\Reference\\File\\FileReferenceEventListener' => $baseDir . '/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php',
+ 'OC\\Collaboration\\Reference\\File\\FileReferenceProvider' => $baseDir . '/lib/private/Collaboration/Reference/File/FileReferenceProvider.php',
+ 'OC\\Collaboration\\Reference\\LinkReferenceProvider' => $baseDir . '/lib/private/Collaboration/Reference/LinkReferenceProvider.php',
+ 'OC\\Collaboration\\Reference\\Reference' => $baseDir . '/lib/private/Collaboration/Reference/Reference.php',
+ 'OC\\Collaboration\\Reference\\ReferenceManager' => $baseDir . '/lib/private/Collaboration/Reference/ReferenceManager.php',
'OC\\Collaboration\\Resources\\Collection' => $baseDir . '/lib/private/Collaboration/Resources/Collection.php',
'OC\\Collaboration\\Resources\\Listener' => $baseDir . '/lib/private/Collaboration/Resources/Listener.php',
'OC\\Collaboration\\Resources\\Manager' => $baseDir . '/lib/private/Collaboration/Resources/Manager.php',
@@ -858,6 +875,7 @@ return array(
'OC\\Core\\Command\\Background\\Base' => $baseDir . '/core/Command/Background/Base.php',
'OC\\Core\\Command\\Background\\Cron' => $baseDir . '/core/Command/Background/Cron.php',
'OC\\Core\\Command\\Background\\Job' => $baseDir . '/core/Command/Background/Job.php',
+ 'OC\\Core\\Command\\Background\\ListCommand' => $baseDir . '/core/Command/Background/ListCommand.php',
'OC\\Core\\Command\\Background\\WebCron' => $baseDir . '/core/Command/Background/WebCron.php',
'OC\\Core\\Command\\Base' => $baseDir . '/core/Command/Base.php',
'OC\\Core\\Command\\Broadcast\\Test' => $baseDir . '/core/Command/Broadcast/Test.php',
@@ -965,6 +983,8 @@ return array(
'OC\\Core\\Controller\\ProfileApiController' => $baseDir . '/core/Controller/ProfileApiController.php',
'OC\\Core\\Controller\\ProfilePageController' => $baseDir . '/core/Controller/ProfilePageController.php',
'OC\\Core\\Controller\\RecommendedAppsController' => $baseDir . '/core/Controller/RecommendedAppsController.php',
+ 'OC\\Core\\Controller\\ReferenceApiController' => $baseDir . '/core/Controller/ReferenceApiController.php',
+ 'OC\\Core\\Controller\\ReferenceController' => $baseDir . '/core/Controller/ReferenceController.php',
'OC\\Core\\Controller\\SearchController' => $baseDir . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
@@ -1053,6 +1073,7 @@ return array(
'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php',
+ 'OC\\DB\\MigratorExecuteSqlEvent' => $baseDir . '/lib/private/DB/MigratorExecuteSqlEvent.php',
'OC\\DB\\MissingColumnInformation' => $baseDir . '/lib/private/DB/MissingColumnInformation.php',
'OC\\DB\\MissingIndexInformation' => $baseDir . '/lib/private/DB/MissingIndexInformation.php',
'OC\\DB\\MissingPrimaryKeyInformation' => $baseDir . '/lib/private/DB/MissingPrimaryKeyInformation.php',
@@ -1407,6 +1428,13 @@ return array(
'OC\\Repair\\ClearFrontendCaches' => $baseDir . '/lib/private/Repair/ClearFrontendCaches.php',
'OC\\Repair\\ClearGeneratedAvatarCache' => $baseDir . '/lib/private/Repair/ClearGeneratedAvatarCache.php',
'OC\\Repair\\Collation' => $baseDir . '/lib/private/Repair/Collation.php',
+ 'OC\\Repair\\Events\\RepairAdvanceEvent' => $baseDir . '/lib/private/Repair/Events/RepairAdvanceEvent.php',
+ 'OC\\Repair\\Events\\RepairErrorEvent' => $baseDir . '/lib/private/Repair/Events/RepairErrorEvent.php',
+ 'OC\\Repair\\Events\\RepairFinishEvent' => $baseDir . '/lib/private/Repair/Events/RepairFinishEvent.php',
+ 'OC\\Repair\\Events\\RepairInfoEvent' => $baseDir . '/lib/private/Repair/Events/RepairInfoEvent.php',
+ 'OC\\Repair\\Events\\RepairStartEvent' => $baseDir . '/lib/private/Repair/Events/RepairStartEvent.php',
+ 'OC\\Repair\\Events\\RepairStepEvent' => $baseDir . '/lib/private/Repair/Events/RepairStepEvent.php',
+ 'OC\\Repair\\Events\\RepairWarningEvent' => $baseDir . '/lib/private/Repair/Events/RepairWarningEvent.php',
'OC\\Repair\\MoveUpdaterStepFile' => $baseDir . '/lib/private/Repair/MoveUpdaterStepFile.php',
'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php',
'OC\\Repair\\NC13\\AddLogRotateJob' => $baseDir . '/lib/private/Repair/NC13/AddLogRotateJob.php',
@@ -1421,6 +1449,7 @@ return array(
'OC\\Repair\\NC21\\AddCheckForUserCertificatesJob' => $baseDir . '/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php',
'OC\\Repair\\NC21\\ValidatePhoneNumber' => $baseDir . '/lib/private/Repair/NC21/ValidatePhoneNumber.php',
'OC\\Repair\\NC22\\LookupServerSendCheck' => $baseDir . '/lib/private/Repair/NC22/LookupServerSendCheck.php',
+ 'OC\\Repair\\NC24\\AddTokenCleanupJob' => $baseDir . '/lib/private/Repair/NC24/AddTokenCleanupJob.php',
'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php',
'OC\\Repair\\Owncloud\\CleanPreviews' => $baseDir . '/lib/private/Repair/Owncloud/CleanPreviews.php',
'OC\\Repair\\Owncloud\\CleanPreviewsBackgroundJob' => $baseDir . '/lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php',
@@ -1506,6 +1535,7 @@ return array(
'OC\\Share20\\Manager' => $baseDir . '/lib/private/Share20/Manager.php',
'OC\\Share20\\ProviderFactory' => $baseDir . '/lib/private/Share20/ProviderFactory.php',
'OC\\Share20\\Share' => $baseDir . '/lib/private/Share20/Share.php',
+ 'OC\\Share20\\ShareAttributes' => $baseDir . '/lib/private/Share20/ShareAttributes.php',
'OC\\Share20\\ShareHelper' => $baseDir . '/lib/private/Share20/ShareHelper.php',
'OC\\Share20\\UserRemovedListener' => $baseDir . '/lib/private/Share20/UserRemovedListener.php',
'OC\\Share\\Constants' => $baseDir . '/lib/private/Share/Constants.php',
@@ -1549,6 +1579,8 @@ return array(
'OC\\User\\Database' => $baseDir . '/lib/private/User/Database.php',
'OC\\User\\DisplayNameCache' => $baseDir . '/lib/private/User/DisplayNameCache.php',
'OC\\User\\LazyUser' => $baseDir . '/lib/private/User/LazyUser.php',
+ 'OC\\User\\Listeners\\UserChangedListener' => $baseDir . '/lib/private/User/Listeners/UserChangedListener.php',
+ 'OC\\User\\Listeners\\UserDeletedListener' => $baseDir . '/lib/private/User/Listeners/UserDeletedListener.php',
'OC\\User\\LoginException' => $baseDir . '/lib/private/User/LoginException.php',
'OC\\User\\Manager' => $baseDir . '/lib/private/User/Manager.php',
'OC\\User\\NoUserException' => $baseDir . '/lib/private/User/NoUserException.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 8a2a72713ec..0dd18e5ddbf 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -54,7 +54,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Activity\\IManager' => __DIR__ . '/../../..' . '/lib/public/Activity/IManager.php',
'OCP\\Activity\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Activity/IProvider.php',
'OCP\\Activity\\ISetting' => __DIR__ . '/../../..' . '/lib/public/Activity/ISetting.php',
- 'OCP\\App' => __DIR__ . '/../../..' . '/lib/public/App.php',
'OCP\\AppFramework\\ApiController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/ApiController.php',
'OCP\\AppFramework\\App' => __DIR__ . '/../../..' . '/lib/public/AppFramework/App.php',
'OCP\\AppFramework\\AuthPublicShareController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/AuthPublicShareController.php',
@@ -123,6 +122,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Authentication\\Exceptions\\PasswordUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Authentication/Exceptions/PasswordUnavailableException.php',
'OCP\\Authentication\\IAlternativeLogin' => __DIR__ . '/../../..' . '/lib/public/Authentication/IAlternativeLogin.php',
'OCP\\Authentication\\IApacheBackend' => __DIR__ . '/../../..' . '/lib/public/Authentication/IApacheBackend.php',
+ 'OCP\\Authentication\\IProvideUserSecretBackend' => __DIR__ . '/../../..' . '/lib/public/Authentication/IProvideUserSecretBackend.php',
'OCP\\Authentication\\LoginCredentials\\ICredentials' => __DIR__ . '/../../..' . '/lib/public/Authentication/LoginCredentials/ICredentials.php',
'OCP\\Authentication\\LoginCredentials\\IStore' => __DIR__ . '/../../..' . '/lib/public/Authentication/LoginCredentials/IStore.php',
'OCP\\Authentication\\TwoFactorAuth\\ALoginSetupController' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/ALoginSetupController.php',
@@ -142,13 +142,13 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorProviderForUserDisabled' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/TwoFactorProviderForUserDisabled.php',
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorProviderForUserEnabled' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/TwoFactorProviderForUserEnabled.php',
'OCP\\AutoloadNotAllowedException' => __DIR__ . '/../../..' . '/lib/public/AutoloadNotAllowedException.php',
- 'OCP\\BackgroundJob' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob.php',
'OCP\\BackgroundJob\\IJob' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/IJob.php',
'OCP\\BackgroundJob\\IJobList' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/IJobList.php',
'OCP\\BackgroundJob\\Job' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/Job.php',
'OCP\\BackgroundJob\\QueuedJob' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/QueuedJob.php',
'OCP\\BackgroundJob\\TimedJob' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/TimedJob.php',
'OCP\\Broadcast\\Events\\IBroadcastEvent' => __DIR__ . '/../../..' . '/lib/public/Broadcast/Events/IBroadcastEvent.php',
+ 'OCP\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/public/Cache/CappedMemoryCache.php',
'OCP\\Calendar\\BackendTemporarilyUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
'OCP\\Calendar\\Exceptions\\CalendarException' => __DIR__ . '/../../..' . '/lib/public/Calendar/Exceptions/CalendarException.php',
'OCP\\Calendar\\ICalendar' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendar.php',
@@ -175,6 +175,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php',
'OCP\\Collaboration\\Collaborators\\ISearchResult' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchResult.php',
'OCP\\Collaboration\\Collaborators\\SearchResultType' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/SearchResultType.php',
+ 'OCP\\Collaboration\\Reference\\IReference' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReference.php',
+ 'OCP\\Collaboration\\Reference\\IReferenceManager' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReferenceManager.php',
+ 'OCP\\Collaboration\\Reference\\IReferenceProvider' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReferenceProvider.php',
'OCP\\Collaboration\\Resources\\CollectionException' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/CollectionException.php',
'OCP\\Collaboration\\Resources\\ICollection' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/ICollection.php',
'OCP\\Collaboration\\Resources\\IManager' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/IManager.php',
@@ -183,6 +186,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Collaboration\\Resources\\IResource' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/IResource.php',
'OCP\\Collaboration\\Resources\\LoadAdditionalScriptsEvent' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/LoadAdditionalScriptsEvent.php',
'OCP\\Collaboration\\Resources\\ResourceException' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/ResourceException.php',
+ 'OCP\\Color' => __DIR__ . '/../../..' . '/lib/public/Color.php',
'OCP\\Command\\IBus' => __DIR__ . '/../../..' . '/lib/public/Command/IBus.php',
'OCP\\Command\\ICommand' => __DIR__ . '/../../..' . '/lib/public/Command/ICommand.php',
'OCP\\Comments\\CommentsEntityEvent' => __DIR__ . '/../../..' . '/lib/public/Comments/CommentsEntityEvent.php',
@@ -257,6 +261,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\EventDispatcher\\GenericEvent' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/GenericEvent.php',
'OCP\\EventDispatcher\\IEventDispatcher' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventDispatcher.php',
'OCP\\EventDispatcher\\IEventListener' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventListener.php',
+ 'OCP\\Federation\\Events\\TrustedServerRemovedEvent' => __DIR__ . '/../../..' . '/lib/public/Federation/Events/TrustedServerRemovedEvent.php',
'OCP\\Federation\\Exceptions\\ActionNotSupportedException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/ActionNotSupportedException.php',
'OCP\\Federation\\Exceptions\\AuthenticationFailedException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/AuthenticationFailedException.php',
'OCP\\Federation\\Exceptions\\BadRequestException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/BadRequestException.php',
@@ -293,10 +298,13 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Files\\Config\\IMountProviderCollection' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IMountProviderCollection.php',
'OCP\\Files\\Config\\IRootMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IRootMountProvider.php',
'OCP\\Files\\Config\\IUserMountCache' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IUserMountCache.php',
+ 'OCP\\Files\\DavUtil' => __DIR__ . '/../../..' . '/lib/public/Files/DavUtil.php',
'OCP\\Files\\EmptyFileNameException' => __DIR__ . '/../../..' . '/lib/public/Files/EmptyFileNameException.php',
'OCP\\Files\\EntityTooLargeException' => __DIR__ . '/../../..' . '/lib/public/Files/EntityTooLargeException.php',
+ 'OCP\\Files\\Events\\BeforeDirectFileDownloadEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/BeforeDirectFileDownloadEvent.php',
'OCP\\Files\\Events\\BeforeFileScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/BeforeFileScannedEvent.php',
'OCP\\Files\\Events\\BeforeFolderScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/BeforeFolderScannedEvent.php',
+ 'OCP\\Files\\Events\\BeforeZipCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/BeforeZipCreatedEvent.php',
'OCP\\Files\\Events\\FileCacheUpdated' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FileCacheUpdated.php',
'OCP\\Files\\Events\\FileScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FileScannedEvent.php',
'OCP\\Files\\Events\\FolderScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FolderScannedEvent.php',
@@ -343,6 +351,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Files\\Lock\\OwnerLockedException' => __DIR__ . '/../../..' . '/lib/public/Files/Lock/OwnerLockedException.php',
'OCP\\Files\\Mount\\IMountManager' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/IMountManager.php',
'OCP\\Files\\Mount\\IMountPoint' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/IMountPoint.php',
+ 'OCP\\Files\\Mount\\ISystemMountPoint' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/ISystemMountPoint.php',
'OCP\\Files\\Node' => __DIR__ . '/../../..' . '/lib/public/Files/Node.php',
'OCP\\Files\\NotEnoughSpaceException' => __DIR__ . '/../../..' . '/lib/public/Files/NotEnoughSpaceException.php',
'OCP\\Files\\NotFoundException' => __DIR__ . '/../../..' . '/lib/public/Files/NotFoundException.php',
@@ -439,6 +448,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\IAppConfig' => __DIR__ . '/../../..' . '/lib/public/IAppConfig.php',
'OCP\\IAvatar' => __DIR__ . '/../../..' . '/lib/public/IAvatar.php',
'OCP\\IAvatarManager' => __DIR__ . '/../../..' . '/lib/public/IAvatarManager.php',
+ 'OCP\\IBinaryFinder' => __DIR__ . '/../../..' . '/lib/public/IBinaryFinder.php',
'OCP\\ICache' => __DIR__ . '/../../..' . '/lib/public/ICache.php',
'OCP\\ICacheFactory' => __DIR__ . '/../../..' . '/lib/public/ICacheFactory.php',
'OCP\\ICertificate' => __DIR__ . '/../../..' . '/lib/public/ICertificate.php',
@@ -539,6 +549,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Search\\Result' => __DIR__ . '/../../..' . '/lib/public/Search/Result.php',
'OCP\\Search\\SearchResult' => __DIR__ . '/../../..' . '/lib/public/Search/SearchResult.php',
'OCP\\Search\\SearchResultEntry' => __DIR__ . '/../../..' . '/lib/public/Search/SearchResultEntry.php',
+ 'OCP\\Security\\Bruteforce\\IThrottler' => __DIR__ . '/../../..' . '/lib/public/Security/Bruteforce/IThrottler.php',
'OCP\\Security\\Bruteforce\\MaxDelayReached' => __DIR__ . '/../../..' . '/lib/public/Security/Bruteforce/MaxDelayReached.php',
'OCP\\Security\\CSP\\AddContentSecurityPolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/CSP/AddContentSecurityPolicyEvent.php',
'OCP\\Security\\Events\\GenerateSecurePasswordEvent' => __DIR__ . '/../../..' . '/lib/public/Security/Events/GenerateSecurePasswordEvent.php',
@@ -567,6 +578,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Share\\Exceptions\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php',
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
'OCP\\Share\\Exceptions\\ShareNotFound' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareNotFound.php',
+ 'OCP\\Share\\IAttributes' => __DIR__ . '/../../..' . '/lib/public/Share/IAttributes.php',
'OCP\\Share\\IManager' => __DIR__ . '/../../..' . '/lib/public/Share/IManager.php',
'OCP\\Share\\IProviderFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IProviderFactory.php',
'OCP\\Share\\IShare' => __DIR__ . '/../../..' . '/lib/public/Share/IShare.php',
@@ -807,6 +819,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Authentication\\Token\\PublicKeyTokenMapper' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/PublicKeyTokenMapper.php',
'OC\\Authentication\\Token\\PublicKeyTokenProvider' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/PublicKeyTokenProvider.php',
'OC\\Authentication\\Token\\RemoteWipe' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/RemoteWipe.php',
+ 'OC\\Authentication\\Token\\TokenCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/TokenCleanupJob.php',
'OC\\Authentication\\TwoFactorAuth\\Db\\ProviderUserAssignmentDao' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php',
'OC\\Authentication\\TwoFactorAuth\\EnforcementState' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/EnforcementState.php',
'OC\\Authentication\\TwoFactorAuth\\Manager' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/Manager.php',
@@ -826,10 +839,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Avatar\\UserAvatar' => __DIR__ . '/../../..' . '/lib/private/Avatar/UserAvatar.php',
'OC\\BackgroundJob\\Job' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/Job.php',
'OC\\BackgroundJob\\JobList' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/JobList.php',
- 'OC\\BackgroundJob\\Legacy\\QueuedJob' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/Legacy/QueuedJob.php',
- 'OC\\BackgroundJob\\Legacy\\RegularJob' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/Legacy/RegularJob.php',
'OC\\BackgroundJob\\QueuedJob' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/QueuedJob.php',
'OC\\BackgroundJob\\TimedJob' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/TimedJob.php',
+ 'OC\\BinaryFinder' => __DIR__ . '/../../..' . '/lib/private/BinaryFinder.php',
'OC\\Broadcast\\Events\\BroadcastEvent' => __DIR__ . '/../../..' . '/lib/private/Broadcast/Events/BroadcastEvent.php',
'OC\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/private/Cache/CappedMemoryCache.php',
'OC\\Cache\\File' => __DIR__ . '/../../..' . '/lib/private/Cache/File.php',
@@ -847,6 +859,11 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Collaboration\\Collaborators\\Search' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/Search.php',
'OC\\Collaboration\\Collaborators\\SearchResult' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/SearchResult.php',
'OC\\Collaboration\\Collaborators\\UserPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/UserPlugin.php',
+ 'OC\\Collaboration\\Reference\\File\\FileReferenceEventListener' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php',
+ 'OC\\Collaboration\\Reference\\File\\FileReferenceProvider' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/File/FileReferenceProvider.php',
+ 'OC\\Collaboration\\Reference\\LinkReferenceProvider' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/LinkReferenceProvider.php',
+ 'OC\\Collaboration\\Reference\\Reference' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/Reference.php',
+ 'OC\\Collaboration\\Reference\\ReferenceManager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/ReferenceManager.php',
'OC\\Collaboration\\Resources\\Collection' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Collection.php',
'OC\\Collaboration\\Resources\\Listener' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Listener.php',
'OC\\Collaboration\\Resources\\Manager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Manager.php',
@@ -891,6 +908,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Command\\Background\\Base' => __DIR__ . '/../../..' . '/core/Command/Background/Base.php',
'OC\\Core\\Command\\Background\\Cron' => __DIR__ . '/../../..' . '/core/Command/Background/Cron.php',
'OC\\Core\\Command\\Background\\Job' => __DIR__ . '/../../..' . '/core/Command/Background/Job.php',
+ 'OC\\Core\\Command\\Background\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/Background/ListCommand.php',
'OC\\Core\\Command\\Background\\WebCron' => __DIR__ . '/../../..' . '/core/Command/Background/WebCron.php',
'OC\\Core\\Command\\Base' => __DIR__ . '/../../..' . '/core/Command/Base.php',
'OC\\Core\\Command\\Broadcast\\Test' => __DIR__ . '/../../..' . '/core/Command/Broadcast/Test.php',
@@ -998,6 +1016,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Controller\\ProfileApiController' => __DIR__ . '/../../..' . '/core/Controller/ProfileApiController.php',
'OC\\Core\\Controller\\ProfilePageController' => __DIR__ . '/../../..' . '/core/Controller/ProfilePageController.php',
'OC\\Core\\Controller\\RecommendedAppsController' => __DIR__ . '/../../..' . '/core/Controller/RecommendedAppsController.php',
+ 'OC\\Core\\Controller\\ReferenceApiController' => __DIR__ . '/../../..' . '/core/Controller/ReferenceApiController.php',
+ 'OC\\Core\\Controller\\ReferenceController' => __DIR__ . '/../../..' . '/core/Controller/ReferenceController.php',
'OC\\Core\\Controller\\SearchController' => __DIR__ . '/../../..' . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
@@ -1086,6 +1106,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php',
+ 'OC\\DB\\MigratorExecuteSqlEvent' => __DIR__ . '/../../..' . '/lib/private/DB/MigratorExecuteSqlEvent.php',
'OC\\DB\\MissingColumnInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingColumnInformation.php',
'OC\\DB\\MissingIndexInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingIndexInformation.php',
'OC\\DB\\MissingPrimaryKeyInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingPrimaryKeyInformation.php',
@@ -1440,6 +1461,13 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Repair\\ClearFrontendCaches' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearFrontendCaches.php',
'OC\\Repair\\ClearGeneratedAvatarCache' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearGeneratedAvatarCache.php',
'OC\\Repair\\Collation' => __DIR__ . '/../../..' . '/lib/private/Repair/Collation.php',
+ 'OC\\Repair\\Events\\RepairAdvanceEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairAdvanceEvent.php',
+ 'OC\\Repair\\Events\\RepairErrorEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairErrorEvent.php',
+ 'OC\\Repair\\Events\\RepairFinishEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairFinishEvent.php',
+ 'OC\\Repair\\Events\\RepairInfoEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairInfoEvent.php',
+ 'OC\\Repair\\Events\\RepairStartEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairStartEvent.php',
+ 'OC\\Repair\\Events\\RepairStepEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairStepEvent.php',
+ 'OC\\Repair\\Events\\RepairWarningEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairWarningEvent.php',
'OC\\Repair\\MoveUpdaterStepFile' => __DIR__ . '/../../..' . '/lib/private/Repair/MoveUpdaterStepFile.php',
'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php',
'OC\\Repair\\NC13\\AddLogRotateJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC13/AddLogRotateJob.php',
@@ -1454,6 +1482,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Repair\\NC21\\AddCheckForUserCertificatesJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php',
'OC\\Repair\\NC21\\ValidatePhoneNumber' => __DIR__ . '/../../..' . '/lib/private/Repair/NC21/ValidatePhoneNumber.php',
'OC\\Repair\\NC22\\LookupServerSendCheck' => __DIR__ . '/../../..' . '/lib/private/Repair/NC22/LookupServerSendCheck.php',
+ 'OC\\Repair\\NC24\\AddTokenCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC24/AddTokenCleanupJob.php',
'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php',
'OC\\Repair\\Owncloud\\CleanPreviews' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/CleanPreviews.php',
'OC\\Repair\\Owncloud\\CleanPreviewsBackgroundJob' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php',
@@ -1539,6 +1568,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Share20\\Manager' => __DIR__ . '/../../..' . '/lib/private/Share20/Manager.php',
'OC\\Share20\\ProviderFactory' => __DIR__ . '/../../..' . '/lib/private/Share20/ProviderFactory.php',
'OC\\Share20\\Share' => __DIR__ . '/../../..' . '/lib/private/Share20/Share.php',
+ 'OC\\Share20\\ShareAttributes' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareAttributes.php',
'OC\\Share20\\ShareHelper' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareHelper.php',
'OC\\Share20\\UserRemovedListener' => __DIR__ . '/../../..' . '/lib/private/Share20/UserRemovedListener.php',
'OC\\Share\\Constants' => __DIR__ . '/../../..' . '/lib/private/Share/Constants.php',
@@ -1582,6 +1612,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\User\\Database' => __DIR__ . '/../../..' . '/lib/private/User/Database.php',
'OC\\User\\DisplayNameCache' => __DIR__ . '/../../..' . '/lib/private/User/DisplayNameCache.php',
'OC\\User\\LazyUser' => __DIR__ . '/../../..' . '/lib/private/User/LazyUser.php',
+ 'OC\\User\\Listeners\\UserChangedListener' => __DIR__ . '/../../..' . '/lib/private/User/Listeners/UserChangedListener.php',
+ 'OC\\User\\Listeners\\UserDeletedListener' => __DIR__ . '/../../..' . '/lib/private/User/Listeners/UserDeletedListener.php',
'OC\\User\\LoginException' => __DIR__ . '/../../..' . '/lib/private/User/LoginException.php',
'OC\\User\\Manager' => __DIR__ . '/../../..' . '/lib/private/User/Manager.php',
'OC\\User\\NoUserException' => __DIR__ . '/../../..' . '/lib/private/User/NoUserException.php',
diff --git a/lib/l10n/bg.js b/lib/l10n/bg.js
index 84f67dd760a..1f31e9e0504 100644
--- a/lib/l10n/bg.js
+++ b/lib/l10n/bg.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Приложението „%1$s“ не може да бъде инсталирано, защото следните зависимости не са изпълнени: %2$s",
"a safe home for all your data" : "безопасен дом за всички ваши данни",
"File is currently busy, please try again later" : "Файлът в момента е зает, моля, опитайте отново по-късно",
- "Cannot read file" : "Не може да се прочете файл",
+ "Cannot download file" : "Файлът не можа да бъде изтеглен",
"Application is not enabled" : "Приложението не е включено",
"Authentication error" : "Грешка при удостоверяването",
"Token expired. Please reload page." : "Изтекла сесия. Моля, презареди страницата.",
@@ -235,6 +235,8 @@ OC.L10N.register(
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Това може да се дължи на cache/accelerator като Zend OPache или eAccelerator.",
"PHP modules have been installed, but they are still listed as missing?" : "PHP модулите са инсталирани, но все още се обявяват като липсващи?",
"Please ask your server administrator to restart the web server." : "Моля, поискай от своя администратор да рестартира уеб сървъра.",
+ "The required %s config variable is not configured in the config.php file." : "Необходимата %s конфигурационна променлива не е конфигурирана във файла config.php.",
+ "Please ask your server administrator to check the Nextcloud configuration." : "Моля, помолете администратора на вашия сървър да провери конфигурацията на Nextcloud.",
"PostgreSQL >= 9 required." : "Нужно е PostgreSQL >= 9",
"Please upgrade your database version." : "Моля, надстройте версията на вашата база данни.",
"Your data directory is readable by other users." : "Вашата директория с данни може да се чете от други потребители.",
@@ -255,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Временно хранилището не е налично",
"Storage connection timeout. %s" : "Време за изчакване при свързването с хранилище. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Това обикновено може да бъде оправено като, се даде достъп на уеб сървъра да записва в config директорията.",
+ "Cannot read file" : "Не може да се прочете файл",
"Cannot write into \"config\" directory" : "Неуспешен опит за запис в \"config\" папката.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Това обикновено може да бъде оправено като, се даде достъп на уеб сървъра да записва в config директорията. Погледнете %s",
"Cannot write into \"apps\" directory" : "Писането в папка приложения не е възможно",
diff --git a/lib/l10n/bg.json b/lib/l10n/bg.json
index 27b6ca57155..41507e49a44 100644
--- a/lib/l10n/bg.json
+++ b/lib/l10n/bg.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Приложението „%1$s“ не може да бъде инсталирано, защото следните зависимости не са изпълнени: %2$s",
"a safe home for all your data" : "безопасен дом за всички ваши данни",
"File is currently busy, please try again later" : "Файлът в момента е зает, моля, опитайте отново по-късно",
- "Cannot read file" : "Не може да се прочете файл",
+ "Cannot download file" : "Файлът не можа да бъде изтеглен",
"Application is not enabled" : "Приложението не е включено",
"Authentication error" : "Грешка при удостоверяването",
"Token expired. Please reload page." : "Изтекла сесия. Моля, презареди страницата.",
@@ -233,6 +233,8 @@
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Това може да се дължи на cache/accelerator като Zend OPache или eAccelerator.",
"PHP modules have been installed, but they are still listed as missing?" : "PHP модулите са инсталирани, но все още се обявяват като липсващи?",
"Please ask your server administrator to restart the web server." : "Моля, поискай от своя администратор да рестартира уеб сървъра.",
+ "The required %s config variable is not configured in the config.php file." : "Необходимата %s конфигурационна променлива не е конфигурирана във файла config.php.",
+ "Please ask your server administrator to check the Nextcloud configuration." : "Моля, помолете администратора на вашия сървър да провери конфигурацията на Nextcloud.",
"PostgreSQL >= 9 required." : "Нужно е PostgreSQL >= 9",
"Please upgrade your database version." : "Моля, надстройте версията на вашата база данни.",
"Your data directory is readable by other users." : "Вашата директория с данни може да се чете от други потребители.",
@@ -253,6 +255,7 @@
"Storage is temporarily not available" : "Временно хранилището не е налично",
"Storage connection timeout. %s" : "Време за изчакване при свързването с хранилище. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Това обикновено може да бъде оправено като, се даде достъп на уеб сървъра да записва в config директорията.",
+ "Cannot read file" : "Не може да се прочете файл",
"Cannot write into \"config\" directory" : "Неуспешен опит за запис в \"config\" папката.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Това обикновено може да бъде оправено като, се даде достъп на уеб сървъра да записва в config директорията. Погледнете %s",
"Cannot write into \"apps\" directory" : "Писането в папка приложения не е възможно",
diff --git a/lib/l10n/cs.js b/lib/l10n/cs.js
index 9f5de98a9e6..c772b9db74a 100644
--- a/lib/l10n/cs.js
+++ b/lib/l10n/cs.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Aplikaci „%1$s“ nelze nainstalovat, protože nejsou splněny následující závislosti: %2$s",
"a safe home for all your data" : "bezpečný domov pro všechna vaše data",
"File is currently busy, please try again later" : "Soubor je nyní používán, zkuste to později",
- "Cannot read file" : "Nelze přečíst soubor",
+ "Cannot download file" : "Soubor se nedaří stáhnout",
"Application is not enabled" : "Aplikace není povolena",
"Authentication error" : "Chyba při ověřování se",
"Token expired. Please reload page." : "Platnost tokenu skončila. Načtěte stránku znovu.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Úložiště je dočasně nedostupné",
"Storage connection timeout. %s" : "Překročen časový limit připojování k úložišti. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Toto je obvykle možné vyřešit udělením webovému serveru oprávnění k zápisu do adresáře s nastaveními.",
+ "Cannot read file" : "Nelze přečíst soubor",
"Cannot write into \"config\" directory" : "Nelze zapisovat do adresáře „config“",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Toto obvykle lze vyřešit udělením oprávnění k zápisu do kořenové složky webu pro účet, pod kterým je provozován webový server. Viz %s",
"Cannot write into \"apps\" directory" : "Nedaří se zapisovat do adresáře „apps“",
diff --git a/lib/l10n/cs.json b/lib/l10n/cs.json
index 1401735b826..a2e89fae911 100644
--- a/lib/l10n/cs.json
+++ b/lib/l10n/cs.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Aplikaci „%1$s“ nelze nainstalovat, protože nejsou splněny následující závislosti: %2$s",
"a safe home for all your data" : "bezpečný domov pro všechna vaše data",
"File is currently busy, please try again later" : "Soubor je nyní používán, zkuste to později",
- "Cannot read file" : "Nelze přečíst soubor",
+ "Cannot download file" : "Soubor se nedaří stáhnout",
"Application is not enabled" : "Aplikace není povolena",
"Authentication error" : "Chyba při ověřování se",
"Token expired. Please reload page." : "Platnost tokenu skončila. Načtěte stránku znovu.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Úložiště je dočasně nedostupné",
"Storage connection timeout. %s" : "Překročen časový limit připojování k úložišti. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Toto je obvykle možné vyřešit udělením webovému serveru oprávnění k zápisu do adresáře s nastaveními.",
+ "Cannot read file" : "Nelze přečíst soubor",
"Cannot write into \"config\" directory" : "Nelze zapisovat do adresáře „config“",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Toto obvykle lze vyřešit udělením oprávnění k zápisu do kořenové složky webu pro účet, pod kterým je provozován webový server. Viz %s",
"Cannot write into \"apps\" directory" : "Nedaří se zapisovat do adresáře „apps“",
diff --git a/lib/l10n/da.js b/lib/l10n/da.js
index 683b6da5338..c5bd2b5215b 100644
--- a/lib/l10n/da.js
+++ b/lib/l10n/da.js
@@ -5,6 +5,7 @@ OC.L10N.register(
"See %s" : "Se %s",
"Sample configuration detected" : "Eksempel for konfiguration registreret",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Der er registreret at eksempel for konfiguration er blevet kopieret. Dette kan ødelægge din installation og understøttes ikke. Læs venligst dokumentationen før der foretages ændringer i config.php",
+ "Other activities" : "Andre aktiviteter",
"%1$s and %2$s" : "%1$s og %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s",
"%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s",
diff --git a/lib/l10n/da.json b/lib/l10n/da.json
index cadfde89f09..7b1840e39ef 100644
--- a/lib/l10n/da.json
+++ b/lib/l10n/da.json
@@ -3,6 +3,7 @@
"See %s" : "Se %s",
"Sample configuration detected" : "Eksempel for konfiguration registreret",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Der er registreret at eksempel for konfiguration er blevet kopieret. Dette kan ødelægge din installation og understøttes ikke. Læs venligst dokumentationen før der foretages ændringer i config.php",
+ "Other activities" : "Andre aktiviteter",
"%1$s and %2$s" : "%1$s og %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s",
"%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s",
diff --git a/lib/l10n/de.js b/lib/l10n/de.js
index c8c03b8028f..f7f736b8d24 100644
--- a/lib/l10n/de.js
+++ b/lib/l10n/de.js
@@ -3,16 +3,16 @@ OC.L10N.register(
{
"Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!",
"This can usually be fixed by giving the web server write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.",
- "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn Du jedoch möchtest dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true.",
+ "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn du jedoch möchtest dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true.",
"See %s" : "Siehe %s",
"The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %1$swurden nicht korrekt ersetzt. Stelle sicher, dass es sich um eine mit dem Server kompatible Version handelt.",
"Sample configuration detected" : "Beispielkonfiguration gefunden",
- "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
"%s email verification" : "%s E-Mail-Überprüfung",
"Email verification" : "E-Mail-Überprüfung",
- "Click the following button to confirm your email." : "Klicke die folgende Schaltfläche, um Deine E-Mail-Adresse zu bestätigen.",
- "Click the following link to confirm your email." : "Klicke den nachfolgenden Link, um Deine E-Mail-Adresse zu bestätigen",
- "Confirm your email" : "Bestätige Deine E-Mail-Adresse",
+ "Click the following button to confirm your email." : "Klicke die folgende Schaltfläche, um deine E-Mail-Adresse zu bestätigen.",
+ "Click the following link to confirm your email." : "Klicke den nachfolgenden Link, um deine E-Mail-Adresse zu bestätigen",
+ "Confirm your email" : "Bestätige deine E-Mail-Adresse",
"Other activities" : "Andere Aktivitäten",
"%1$s and %2$s" : "%1$s und %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s und %3$s",
@@ -123,19 +123,19 @@ OC.L10N.register(
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X wird nicht unterstützt und %s wird auf dieser Plattform nicht richtig funktionieren. Die Benutzung erfolgt auf eigene Gefahr!",
"For the best results, please consider using a GNU/Linux server instead." : "Zur Gewährleistung eines optimalen Betriebs sollte stattdessen ein GNU/Linux-Server verwendet werden.",
"It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Es scheint, dass diese %s-Instanz unter einer 32-Bit-PHP-Umgebung läuft und open_basedir in der Datei php.ini konfiguriert worden ist. Von einem solchen Betrieb wird dringend abgeraten, weil es dabei zu Problemen mit Dateien kommt, deren Größe 4 GB übersteigt.",
- "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entferne die open_basedir-Einstellung in Deiner php.ini oder wechsele zu 64-Bit-PHP.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entferne die open_basedir-Einstellung in deiner php.ini oder wechsele zu 64-Bit-PHP.",
"Set an admin username." : "Einen Administrator-Benutzernamen setzen.",
"Set an admin password." : "Ein Administrator-Passwort setzen.",
"Cannot create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.",
"Sharing backend %s must implement the interface OCP\\Share_Backend" : "Freigabe-Backend %s muss in der OCP\\Share_Backend - Schnittstelle implementiert werden",
"Sharing backend %s not found" : "Freigabe-Backend %s nicht gefunden",
"Sharing backend for %s not found" : "Freigabe-Backend für %s nicht gefunden",
- "%1$s shared »%2$s« with you and wants to add:" : "%1$shat » %2$s«  mit Dir geteilt und möchte folgendes hinzufügen:",
- "%1$s shared »%2$s« with you and wants to add" : "%1$shat »%2$s« mit Dir geteilt und möchte folgendes hinzufügen",
- "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit Dir geteilten Datei hinzugefügt",
+ "%1$s shared »%2$s« with you and wants to add:" : "%1$shat » %2$s«  mit dir geteilt und möchte folgendes hinzufügen:",
+ "%1$s shared »%2$s« with you and wants to add" : "%1$shat »%2$s« mit dir geteilt und möchte folgendes hinzufügen",
+ "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit dir geteilten Datei hinzugefügt",
"Open »%s«" : "»%s« öffnen",
"%1$s via %2$s" : "%1$s über %2$s",
- "You are not allowed to share %s" : "Die Freigabe von %s ist Dir nicht erlaubt",
+ "You are not allowed to share %s" : "Die Freigabe von %s ist dir nicht erlaubt",
"Cannot increase permissions of %s" : "Kann die Berechtigungen von %s nicht erhöhen",
"Files cannot be shared with delete permissions" : "Dateien mit Lösch-Berechtigungen können nicht geteilt werden",
"Files cannot be shared with create permissions" : "Dateien mit Erstell-Berechtigungen können nicht geteilt werden",
@@ -143,8 +143,8 @@ OC.L10N.register(
"_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Das Ablaufdatum kann nicht mehr als %n Tag in der Zukunft liegen","Das Ablaufdatum kann nicht mehr als %n Tage in der Zukunft liegen"],
"Sharing is only allowed with group members" : "Teilen ist nur mit Gruppenmitgliedern erlaubt",
"Sharing %s failed, because this item is already shared with user %s" : "Freigabe von %s fehlgeschlagen, da dieses Element schon mit dem Benutzer %s geteilt wird",
- "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit Dir geteilt",
- "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit Dir geteilt.",
+ "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit dir geteilt",
+ "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit dir geteilt.",
"Click the button below to open it." : "Klicke zum Öffnen auf die untere Schaltfläche.",
"The requested share does not exist anymore" : "Die angeforderte Freigabe existiert nicht mehr",
"Could not find category \"%s\"" : "Die Kategorie \"%s“ konnte nicht gefunden werden",
@@ -205,16 +205,15 @@ OC.L10N.register(
"User disabled" : "Benutzer deaktiviert",
"Login canceled by app" : "Anmeldung durch die App abgebrochen",
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s",
- "a safe home for all your data" : "ein sicherer Ort für all Deine Daten",
+ "a safe home for all your data" : "ein sicherer Ort für all deine Daten",
"File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte versuche es später noch einmal",
- "Cannot read file" : "Datei kann nicht gelesen werden",
"Application is not enabled" : "Die Anwendung ist nicht aktiviert",
"Authentication error" : "Authentifizierungsfehler",
"Token expired. Please reload page." : "Token abgelaufen. Bitte lade die Seite neu.",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Keine Datenbanktreiber (SQLite, MySQL oder PostgreSQL) installiert.",
"Cannot write into \"config\" directory." : "Schreiben in das „config“-Verzeichnis ist nicht möglich.",
"This can usually be fixed by giving the web server write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
- "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn Du lieber möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true. Siehe %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn du lieber möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true. Siehe %s",
"Cannot write into \"apps\" directory." : "Schreiben in das „apps“-Verzeichnis ist nicht möglich.",
"This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird oder der App-Store in der Konfigurationsdatei deaktiviert wird.",
"Cannot create \"data\" directory." : "Kann das \"Daten\"-Verzeichnis nicht erstellen.",
@@ -222,27 +221,27 @@ OC.L10N.register(
"Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Berechtigungen können zumeist korrigiert werden, indem dem Webserver Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s. ",
"Your data directory is not writable." : "Dein Datenverzeichnis ist schreibgeschützt.",
"Setting locale to %s failed." : "Das Setzen der Spracheeinstellung auf %s ist fehlgeschlagen.",
- "Please install one of these locales on your system and restart your web server." : "Bitte installiere eine dieser Sprachen auf Deinem System und starte den Webserver neu.",
+ "Please install one of these locales on your system and restart your web server." : "Bitte installiere eine dieser Sprachen auf deinem System und starte den Webserver neu.",
"PHP module %s not installed." : "PHP-Modul %s nicht installiert.",
- "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls Deinen Server-Administrator kontaktieren.",
+ "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls deinen Server-Administrator kontaktieren.",
"PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung „%s“ ist nicht auf „%s“ gesetzt.",
- "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann Deine Nextcloud wieder lauffähig machen.",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann deine Nextcloud wieder lauffähig machen.",
"<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> ist auf <code>%s</code> gesetzt und nicht auf den erwarteten Wert <code>0</code>.",
- "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in Deiner php.ini auf <code>0</code>.",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in deiner php.ini auf <code>0</code>.",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 2.7.0 ist mindestestens erforderlich. Im Moment ist %s installiert.",
- "To fix this issue update your libxml2 version and restart your web server." : "Um den Fehler zu beheben, musst Du die libxml2 Version aktualisieren und den Webserver neustarten.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Um den Fehler zu beheben, musst du die libxml2 Version aktualisieren und den Webserver neustarten.",
"PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ist offenbar so konfiguriert, dass PHPDoc-Blöcke in der Anweisung entfernt werden. Dadurch sind mehrere Kern-Apps nicht erreichbar.",
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dies wird wahrscheinlich durch Zwischenspeicher/Beschleuniger wie etwa Zend OPcache oder eAccelerator verursacht.",
"PHP modules have been installed, but they are still listed as missing?" : "PHP-Module wurden installiert, werden aber als noch fehlend gelistet?",
- "Please ask your server administrator to restart the web server." : "Bitte kontaktiere Deinen Server-Administrator und bitte um den Neustart des Webservers.",
+ "Please ask your server administrator to restart the web server." : "Bitte kontaktiere deinen Server-Administrator und bitte um den Neustart des Webservers.",
"The required %s config variable is not configured in the config.php file." : "Die erforderliche %s Konfigurationsvariable ist in der config.php nicht konfiguriert.",
- "Please ask your server administrator to check the Nextcloud configuration." : "Bitte Deinen Server-Administrator, die Nextcloud-Konfiguration zu überprüfen.",
+ "Please ask your server administrator to check the Nextcloud configuration." : "Bitte deinen Server-Administrator, die Nextcloud-Konfiguration zu überprüfen.",
"PostgreSQL >= 9 required." : "PostgreSQL >= 9 benötigt",
- "Please upgrade your database version." : "Bitte aktualisiere Deine Datenbankversion",
+ "Please upgrade your database version." : "Bitte aktualisiere deine Datenbankversion",
"Your data directory is readable by other users." : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden",
"Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bitte ändere die Berechtigungen auf 0770, sodass das Verzeichnis nicht von anderen Benutzern angezeigt werden kann.",
"Your data directory must be an absolute path." : "Dein Datenverzeichnis muss einen eindeutigen Pfad haben",
- "Check the value of \"datadirectory\" in your configuration." : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
+ "Check the value of \"datadirectory\" in your configuration." : "Überprüfe bitte die Angabe unter „datadirectory“ in deiner Konfiguration",
"Your data directory is invalid." : "Dein Datenverzeichnis ist ungültig",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
"Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
@@ -257,22 +256,23 @@ OC.L10N.register(
"Storage is temporarily not available" : "Speicher ist vorübergehend nicht verfügbar",
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.",
+ "Cannot read file" : "Datei kann nicht gelesen werden",
"Cannot write into \"config\" directory" : "Schreiben in das „config“-Verzeichnis ist nicht möglich",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
"Cannot write into \"apps\" directory" : "Schreiben in das „apps“-Verzeichnis ist nicht möglich",
"This can usually be fixed by giving the webserver write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird oder der App-Store in der Konfigurationsdatei deaktiviert wird.",
- "Cannot create \"data\" directory" : "Kann das \"Daten\"-Verzeichnis nicht erstellen",
+ "Cannot create \"data\" directory" : "Kann das \"Daten\"-Verzeichnis nicht erstellen.",
"This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s",
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Berechtigungen können zumeist korrigiert werden indem dem Web-Server Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s.",
"Setting locale to %s failed" : "Das Setzen der Umgebungslokale auf %s ist fehlgeschlagen",
- "Please install one of these locales on your system and restart your webserver." : "Bitte installiere eine dieser Sprachen auf Deinem System und starte den Webserver neu.",
+ "Please install one of these locales on your system and restart your webserver." : "Bitte installiere eine dieser Sprachen auf deinem System und starte den Webserver neu.",
"mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload ist nicht auf den erwarteten Wert „0“, sondern stattdessen auf „%s“ gesetzt",
- "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in Deiner php.ini auf <code>0</code>.",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in deiner php.ini auf <code>0</code>.",
"PostgreSQL >= 9 required" : "PostgreSQL >= 9 benötigt",
- "Please upgrade your database version" : "Bitte aktualisiere Deine Datenbankversion",
+ "Please upgrade your database version" : "Bitte aktualisiere deine Datenbankversion",
"Your data directory is readable by other users" : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden",
"Your data directory must be an absolute path" : "Dein Datenverzeichnis muss einen eindeutigen Pfad haben",
- "Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
+ "Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in deiner Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/de.json b/lib/l10n/de.json
index a3dec1fe691..c24b6770eac 100644
--- a/lib/l10n/de.json
+++ b/lib/l10n/de.json
@@ -1,16 +1,16 @@
{ "translations": {
"Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!",
"This can usually be fixed by giving the web server write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.",
- "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn Du jedoch möchtest dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true.",
+ "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn du jedoch möchtest dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true.",
"See %s" : "Siehe %s",
"The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %1$swurden nicht korrekt ersetzt. Stelle sicher, dass es sich um eine mit dem Server kompatible Version handelt.",
"Sample configuration detected" : "Beispielkonfiguration gefunden",
- "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
"%s email verification" : "%s E-Mail-Überprüfung",
"Email verification" : "E-Mail-Überprüfung",
- "Click the following button to confirm your email." : "Klicke die folgende Schaltfläche, um Deine E-Mail-Adresse zu bestätigen.",
- "Click the following link to confirm your email." : "Klicke den nachfolgenden Link, um Deine E-Mail-Adresse zu bestätigen",
- "Confirm your email" : "Bestätige Deine E-Mail-Adresse",
+ "Click the following button to confirm your email." : "Klicke die folgende Schaltfläche, um deine E-Mail-Adresse zu bestätigen.",
+ "Click the following link to confirm your email." : "Klicke den nachfolgenden Link, um deine E-Mail-Adresse zu bestätigen",
+ "Confirm your email" : "Bestätige deine E-Mail-Adresse",
"Other activities" : "Andere Aktivitäten",
"%1$s and %2$s" : "%1$s und %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s und %3$s",
@@ -121,19 +121,19 @@
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X wird nicht unterstützt und %s wird auf dieser Plattform nicht richtig funktionieren. Die Benutzung erfolgt auf eigene Gefahr!",
"For the best results, please consider using a GNU/Linux server instead." : "Zur Gewährleistung eines optimalen Betriebs sollte stattdessen ein GNU/Linux-Server verwendet werden.",
"It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Es scheint, dass diese %s-Instanz unter einer 32-Bit-PHP-Umgebung läuft und open_basedir in der Datei php.ini konfiguriert worden ist. Von einem solchen Betrieb wird dringend abgeraten, weil es dabei zu Problemen mit Dateien kommt, deren Größe 4 GB übersteigt.",
- "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entferne die open_basedir-Einstellung in Deiner php.ini oder wechsele zu 64-Bit-PHP.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entferne die open_basedir-Einstellung in deiner php.ini oder wechsele zu 64-Bit-PHP.",
"Set an admin username." : "Einen Administrator-Benutzernamen setzen.",
"Set an admin password." : "Ein Administrator-Passwort setzen.",
"Cannot create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.",
"Sharing backend %s must implement the interface OCP\\Share_Backend" : "Freigabe-Backend %s muss in der OCP\\Share_Backend - Schnittstelle implementiert werden",
"Sharing backend %s not found" : "Freigabe-Backend %s nicht gefunden",
"Sharing backend for %s not found" : "Freigabe-Backend für %s nicht gefunden",
- "%1$s shared »%2$s« with you and wants to add:" : "%1$shat » %2$s«  mit Dir geteilt und möchte folgendes hinzufügen:",
- "%1$s shared »%2$s« with you and wants to add" : "%1$shat »%2$s« mit Dir geteilt und möchte folgendes hinzufügen",
- "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit Dir geteilten Datei hinzugefügt",
+ "%1$s shared »%2$s« with you and wants to add:" : "%1$shat » %2$s«  mit dir geteilt und möchte folgendes hinzufügen:",
+ "%1$s shared »%2$s« with you and wants to add" : "%1$shat »%2$s« mit dir geteilt und möchte folgendes hinzufügen",
+ "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit dir geteilten Datei hinzugefügt",
"Open »%s«" : "»%s« öffnen",
"%1$s via %2$s" : "%1$s über %2$s",
- "You are not allowed to share %s" : "Die Freigabe von %s ist Dir nicht erlaubt",
+ "You are not allowed to share %s" : "Die Freigabe von %s ist dir nicht erlaubt",
"Cannot increase permissions of %s" : "Kann die Berechtigungen von %s nicht erhöhen",
"Files cannot be shared with delete permissions" : "Dateien mit Lösch-Berechtigungen können nicht geteilt werden",
"Files cannot be shared with create permissions" : "Dateien mit Erstell-Berechtigungen können nicht geteilt werden",
@@ -141,8 +141,8 @@
"_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Das Ablaufdatum kann nicht mehr als %n Tag in der Zukunft liegen","Das Ablaufdatum kann nicht mehr als %n Tage in der Zukunft liegen"],
"Sharing is only allowed with group members" : "Teilen ist nur mit Gruppenmitgliedern erlaubt",
"Sharing %s failed, because this item is already shared with user %s" : "Freigabe von %s fehlgeschlagen, da dieses Element schon mit dem Benutzer %s geteilt wird",
- "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit Dir geteilt",
- "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit Dir geteilt.",
+ "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit dir geteilt",
+ "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit dir geteilt.",
"Click the button below to open it." : "Klicke zum Öffnen auf die untere Schaltfläche.",
"The requested share does not exist anymore" : "Die angeforderte Freigabe existiert nicht mehr",
"Could not find category \"%s\"" : "Die Kategorie \"%s“ konnte nicht gefunden werden",
@@ -203,16 +203,15 @@
"User disabled" : "Benutzer deaktiviert",
"Login canceled by app" : "Anmeldung durch die App abgebrochen",
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s",
- "a safe home for all your data" : "ein sicherer Ort für all Deine Daten",
+ "a safe home for all your data" : "ein sicherer Ort für all deine Daten",
"File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte versuche es später noch einmal",
- "Cannot read file" : "Datei kann nicht gelesen werden",
"Application is not enabled" : "Die Anwendung ist nicht aktiviert",
"Authentication error" : "Authentifizierungsfehler",
"Token expired. Please reload page." : "Token abgelaufen. Bitte lade die Seite neu.",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Keine Datenbanktreiber (SQLite, MySQL oder PostgreSQL) installiert.",
"Cannot write into \"config\" directory." : "Schreiben in das „config“-Verzeichnis ist nicht möglich.",
"This can usually be fixed by giving the web server write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
- "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn Du lieber möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true. Siehe %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn du lieber möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true. Siehe %s",
"Cannot write into \"apps\" directory." : "Schreiben in das „apps“-Verzeichnis ist nicht möglich.",
"This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird oder der App-Store in der Konfigurationsdatei deaktiviert wird.",
"Cannot create \"data\" directory." : "Kann das \"Daten\"-Verzeichnis nicht erstellen.",
@@ -220,27 +219,27 @@
"Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Berechtigungen können zumeist korrigiert werden, indem dem Webserver Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s. ",
"Your data directory is not writable." : "Dein Datenverzeichnis ist schreibgeschützt.",
"Setting locale to %s failed." : "Das Setzen der Spracheeinstellung auf %s ist fehlgeschlagen.",
- "Please install one of these locales on your system and restart your web server." : "Bitte installiere eine dieser Sprachen auf Deinem System und starte den Webserver neu.",
+ "Please install one of these locales on your system and restart your web server." : "Bitte installiere eine dieser Sprachen auf deinem System und starte den Webserver neu.",
"PHP module %s not installed." : "PHP-Modul %s nicht installiert.",
- "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls Deinen Server-Administrator kontaktieren.",
+ "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls deinen Server-Administrator kontaktieren.",
"PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung „%s“ ist nicht auf „%s“ gesetzt.",
- "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann Deine Nextcloud wieder lauffähig machen.",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann deine Nextcloud wieder lauffähig machen.",
"<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> ist auf <code>%s</code> gesetzt und nicht auf den erwarteten Wert <code>0</code>.",
- "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in Deiner php.ini auf <code>0</code>.",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in deiner php.ini auf <code>0</code>.",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 2.7.0 ist mindestestens erforderlich. Im Moment ist %s installiert.",
- "To fix this issue update your libxml2 version and restart your web server." : "Um den Fehler zu beheben, musst Du die libxml2 Version aktualisieren und den Webserver neustarten.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Um den Fehler zu beheben, musst du die libxml2 Version aktualisieren und den Webserver neustarten.",
"PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ist offenbar so konfiguriert, dass PHPDoc-Blöcke in der Anweisung entfernt werden. Dadurch sind mehrere Kern-Apps nicht erreichbar.",
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dies wird wahrscheinlich durch Zwischenspeicher/Beschleuniger wie etwa Zend OPcache oder eAccelerator verursacht.",
"PHP modules have been installed, but they are still listed as missing?" : "PHP-Module wurden installiert, werden aber als noch fehlend gelistet?",
- "Please ask your server administrator to restart the web server." : "Bitte kontaktiere Deinen Server-Administrator und bitte um den Neustart des Webservers.",
+ "Please ask your server administrator to restart the web server." : "Bitte kontaktiere deinen Server-Administrator und bitte um den Neustart des Webservers.",
"The required %s config variable is not configured in the config.php file." : "Die erforderliche %s Konfigurationsvariable ist in der config.php nicht konfiguriert.",
- "Please ask your server administrator to check the Nextcloud configuration." : "Bitte Deinen Server-Administrator, die Nextcloud-Konfiguration zu überprüfen.",
+ "Please ask your server administrator to check the Nextcloud configuration." : "Bitte deinen Server-Administrator, die Nextcloud-Konfiguration zu überprüfen.",
"PostgreSQL >= 9 required." : "PostgreSQL >= 9 benötigt",
- "Please upgrade your database version." : "Bitte aktualisiere Deine Datenbankversion",
+ "Please upgrade your database version." : "Bitte aktualisiere deine Datenbankversion",
"Your data directory is readable by other users." : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden",
"Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bitte ändere die Berechtigungen auf 0770, sodass das Verzeichnis nicht von anderen Benutzern angezeigt werden kann.",
"Your data directory must be an absolute path." : "Dein Datenverzeichnis muss einen eindeutigen Pfad haben",
- "Check the value of \"datadirectory\" in your configuration." : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
+ "Check the value of \"datadirectory\" in your configuration." : "Überprüfe bitte die Angabe unter „datadirectory“ in deiner Konfiguration",
"Your data directory is invalid." : "Dein Datenverzeichnis ist ungültig",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
"Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
@@ -255,22 +254,23 @@
"Storage is temporarily not available" : "Speicher ist vorübergehend nicht verfügbar",
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.",
+ "Cannot read file" : "Datei kann nicht gelesen werden",
"Cannot write into \"config\" directory" : "Schreiben in das „config“-Verzeichnis ist nicht möglich",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
"Cannot write into \"apps\" directory" : "Schreiben in das „apps“-Verzeichnis ist nicht möglich",
"This can usually be fixed by giving the webserver write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird oder der App-Store in der Konfigurationsdatei deaktiviert wird.",
- "Cannot create \"data\" directory" : "Kann das \"Daten\"-Verzeichnis nicht erstellen",
+ "Cannot create \"data\" directory" : "Kann das \"Daten\"-Verzeichnis nicht erstellen.",
"This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s",
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Berechtigungen können zumeist korrigiert werden indem dem Web-Server Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s.",
"Setting locale to %s failed" : "Das Setzen der Umgebungslokale auf %s ist fehlgeschlagen",
- "Please install one of these locales on your system and restart your webserver." : "Bitte installiere eine dieser Sprachen auf Deinem System und starte den Webserver neu.",
+ "Please install one of these locales on your system and restart your webserver." : "Bitte installiere eine dieser Sprachen auf deinem System und starte den Webserver neu.",
"mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload ist nicht auf den erwarteten Wert „0“, sondern stattdessen auf „%s“ gesetzt",
- "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in Deiner php.ini auf <code>0</code>.",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in deiner php.ini auf <code>0</code>.",
"PostgreSQL >= 9 required" : "PostgreSQL >= 9 benötigt",
- "Please upgrade your database version" : "Bitte aktualisiere Deine Datenbankversion",
+ "Please upgrade your database version" : "Bitte aktualisiere deine Datenbankversion",
"Your data directory is readable by other users" : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden",
"Your data directory must be an absolute path" : "Dein Datenverzeichnis muss einen eindeutigen Pfad haben",
- "Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
+ "Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in deiner Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js
index d7b983dba66..2fc511f01fc 100644
--- a/lib/l10n/de_DE.js
+++ b/lib/l10n/de_DE.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s",
"a safe home for all your data" : "ein sicherer Ort für all Ihre Daten",
"File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte versuchen Sie es später noch einmal",
- "Cannot read file" : "Datei kann nicht gelesen werden",
+ "Cannot download file" : "Datei kann nicht heruntergeladen werden",
"Application is not enabled" : "Die Anwendung ist nicht aktiviert",
"Authentication error" : "Authentifizierungsfehler",
"Token expired. Please reload page." : "Token abgelaufen. Bitte laden Sie die Seite neu.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Speicher ist vorübergehend nicht verfügbar",
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.",
+ "Cannot read file" : "Datei kann nicht gelesen werden",
"Cannot write into \"config\" directory" : "Schreiben in das „config“-Verzeichnis ist nicht möglich",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
"Cannot write into \"apps\" directory" : "Schreiben in das „apps“-Verzeichnis ist nicht möglich",
diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json
index c456ac01d75..95f217f8968 100644
--- a/lib/l10n/de_DE.json
+++ b/lib/l10n/de_DE.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s",
"a safe home for all your data" : "ein sicherer Ort für all Ihre Daten",
"File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte versuchen Sie es später noch einmal",
- "Cannot read file" : "Datei kann nicht gelesen werden",
+ "Cannot download file" : "Datei kann nicht heruntergeladen werden",
"Application is not enabled" : "Die Anwendung ist nicht aktiviert",
"Authentication error" : "Authentifizierungsfehler",
"Token expired. Please reload page." : "Token abgelaufen. Bitte laden Sie die Seite neu.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Speicher ist vorübergehend nicht verfügbar",
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.",
+ "Cannot read file" : "Datei kann nicht gelesen werden",
"Cannot write into \"config\" directory" : "Schreiben in das „config“-Verzeichnis ist nicht möglich",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
"Cannot write into \"apps\" directory" : "Schreiben in das „apps“-Verzeichnis ist nicht möglich",
diff --git a/lib/l10n/el.js b/lib/l10n/el.js
index 84bd8b77d65..d0011407a62 100644
--- a/lib/l10n/el.js
+++ b/lib/l10n/el.js
@@ -207,7 +207,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Η εφαρμογή \"%1$s\" δεν μπορεί να εγκατασταθεί επειδή δεν πληρούνται τα προαπαιτούμενα: %2$s",
"a safe home for all your data" : "ένα ασφαλές μέρος για όλα τα δεδομένα σας",
"File is currently busy, please try again later" : "Το αρχείο χρησιμοποιείται αυτή τη στιγμή, παρακαλούμε προσπαθήστε αργότερα",
- "Cannot read file" : "Δεν είναι δυνατή η ανάγνωση του αρχείου",
"Application is not enabled" : "Δεν ενεργοποιήθηκε η εφαρμογή",
"Authentication error" : "Σφάλμα πιστοποίησης",
"Token expired. Please reload page." : "Το αναγνωριστικό έληξε. Παρακαλούμε φορτώστε ξανά την σελίδα.",
@@ -255,6 +254,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Ο χώρος αποθήκευσης δεν είναι διαθέσιμος προσωρινά",
"Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Αυτό μπορεί συνήθως να διορθωθεί παρέχοντας δικαιώματα εγγραφής για το φάκελο config στον διακομιστή ιστού.",
+ "Cannot read file" : "Δεν είναι δυνατή η ανάγνωση του αρχείου",
"Cannot write into \"config\" directory" : "Αδυναμία εγγραφής στον κατάλογο \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Αυτό μπορεί συνήθως να διορθωθεί δίνοντας στον διακομιστή ιστού δικαιώματα εγγραφής στον κατάλογο config. Δείτε το%s",
"Cannot write into \"apps\" directory" : "Αδυναμία εγγραφής στον κατάλογο \"apps\"",
diff --git a/lib/l10n/el.json b/lib/l10n/el.json
index 4b947c61b57..d52815ac6f6 100644
--- a/lib/l10n/el.json
+++ b/lib/l10n/el.json
@@ -205,7 +205,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Η εφαρμογή \"%1$s\" δεν μπορεί να εγκατασταθεί επειδή δεν πληρούνται τα προαπαιτούμενα: %2$s",
"a safe home for all your data" : "ένα ασφαλές μέρος για όλα τα δεδομένα σας",
"File is currently busy, please try again later" : "Το αρχείο χρησιμοποιείται αυτή τη στιγμή, παρακαλούμε προσπαθήστε αργότερα",
- "Cannot read file" : "Δεν είναι δυνατή η ανάγνωση του αρχείου",
"Application is not enabled" : "Δεν ενεργοποιήθηκε η εφαρμογή",
"Authentication error" : "Σφάλμα πιστοποίησης",
"Token expired. Please reload page." : "Το αναγνωριστικό έληξε. Παρακαλούμε φορτώστε ξανά την σελίδα.",
@@ -253,6 +252,7 @@
"Storage is temporarily not available" : "Ο χώρος αποθήκευσης δεν είναι διαθέσιμος προσωρινά",
"Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Αυτό μπορεί συνήθως να διορθωθεί παρέχοντας δικαιώματα εγγραφής για το φάκελο config στον διακομιστή ιστού.",
+ "Cannot read file" : "Δεν είναι δυνατή η ανάγνωση του αρχείου",
"Cannot write into \"config\" directory" : "Αδυναμία εγγραφής στον κατάλογο \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Αυτό μπορεί συνήθως να διορθωθεί δίνοντας στον διακομιστή ιστού δικαιώματα εγγραφής στον κατάλογο config. Δείτε το%s",
"Cannot write into \"apps\" directory" : "Αδυναμία εγγραφής στον κατάλογο \"apps\"",
diff --git a/lib/l10n/es.js b/lib/l10n/es.js
index b35778453e6..efd49e6c020 100644
--- a/lib/l10n/es.js
+++ b/lib/l10n/es.js
@@ -207,7 +207,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "No se ha podido instlaar la app «%1$s» porque no se cumplen las siguientes dependencias: %2$s",
"a safe home for all your data" : "un hogar seguro para todos tus datos",
"File is currently busy, please try again later" : "El archivo se encuentra actualmente ocupado, por favor inténtelo de nuevo más tarde",
- "Cannot read file" : "No se puede leer archivo",
"Application is not enabled" : "La aplicación no está habilitada",
"Authentication error" : "Error de autenticación",
"Token expired. Please reload page." : "Token caducado. Por favor, recarge la página.",
@@ -257,6 +256,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "El almacenamiento no esta disponible temporalmente",
"Storage connection timeout. %s" : "Tiempo de conexión de almacenamiento agotado. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración.",
+ "Cannot read file" : "No se puede leer archivo",
"Cannot write into \"config\" directory" : "No se puede escribir el el directorio de configuración",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración. Ver %s",
"Cannot write into \"apps\" directory" : "No se puede escribir en el directorio de \"apps\"",
diff --git a/lib/l10n/es.json b/lib/l10n/es.json
index 36fd13d858b..ae9b87df314 100644
--- a/lib/l10n/es.json
+++ b/lib/l10n/es.json
@@ -205,7 +205,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "No se ha podido instlaar la app «%1$s» porque no se cumplen las siguientes dependencias: %2$s",
"a safe home for all your data" : "un hogar seguro para todos tus datos",
"File is currently busy, please try again later" : "El archivo se encuentra actualmente ocupado, por favor inténtelo de nuevo más tarde",
- "Cannot read file" : "No se puede leer archivo",
"Application is not enabled" : "La aplicación no está habilitada",
"Authentication error" : "Error de autenticación",
"Token expired. Please reload page." : "Token caducado. Por favor, recarge la página.",
@@ -255,6 +254,7 @@
"Storage is temporarily not available" : "El almacenamiento no esta disponible temporalmente",
"Storage connection timeout. %s" : "Tiempo de conexión de almacenamiento agotado. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración.",
+ "Cannot read file" : "No se puede leer archivo",
"Cannot write into \"config\" directory" : "No se puede escribir el el directorio de configuración",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración. Ver %s",
"Cannot write into \"apps\" directory" : "No se puede escribir en el directorio de \"apps\"",
diff --git a/lib/l10n/es_SV.js b/lib/l10n/es_SV.js
index bd67423a4f2..774e0b91879 100644
--- a/lib/l10n/es_SV.js
+++ b/lib/l10n/es_SV.js
@@ -190,4 +190,4 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Verifica el valor de \"datadirectory\" en tu configuración",
"Your data directory is invalid" : "Tu directorio de datos es inválido"
},
-"nplurals=2; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/lib/l10n/es_SV.json b/lib/l10n/es_SV.json
index 67f776a0276..5d7f1d512ba 100644
--- a/lib/l10n/es_SV.json
+++ b/lib/l10n/es_SV.json
@@ -187,5 +187,5 @@
"Your data directory must be an absolute path" : "Tu directorio data debe ser una ruta absoluta",
"Check the value of \"datadirectory\" in your configuration" : "Verifica el valor de \"datadirectory\" en tu configuración",
"Your data directory is invalid" : "Tu directorio de datos es inválido"
-},"pluralForm" :"nplurals=2; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/lib/l10n/eu.js b/lib/l10n/eu.js
index ffe6d4d8808..94244be5607 100644
--- a/lib/l10n/eu.js
+++ b/lib/l10n/eu.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "\"%1$s\" aplikazioa ezin da instalatu, menpekotasun hauek betetzen ez direlako:%2$s",
"a safe home for all your data" : "zure datu guztientzako toki segurua",
"File is currently busy, please try again later" : "Fitxategia lanpetuta dago, saiatu berriro geroago",
- "Cannot read file" : "Ezin da fitxategia irakurri",
+ "Cannot download file" : "Ezin da fitxategia deskargatu",
"Application is not enabled" : "Aplikazioa ez dago gaituta",
"Authentication error" : "Autentifikazio errorea",
"Token expired. Please reload page." : "Tokena iraungitu da. Mesedez birkargatu orria.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Biltegia ez dago erabilgarri aldi baterako",
"Storage connection timeout. %s" : "Biltegiratze-konexioa denboraz kanpo geratu da. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Hau normalean web zerbitzarira config karpetan idazteko baimenak emanez konpondu daiteke.",
+ "Cannot read file" : "Ezin da fitxategia irakurri",
"Cannot write into \"config\" directory" : "Ezin da idatzi \"config\" karpetan",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Hau normalean konpondu daiteke web zerbitzariari konfigurazio direktoriorako sarbidea emanez. Ikus %s",
"Cannot write into \"apps\" directory" : "Ezin da idatzi \"apps\" karpetan",
diff --git a/lib/l10n/eu.json b/lib/l10n/eu.json
index 98461448e2d..0eac90e1da9 100644
--- a/lib/l10n/eu.json
+++ b/lib/l10n/eu.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "\"%1$s\" aplikazioa ezin da instalatu, menpekotasun hauek betetzen ez direlako:%2$s",
"a safe home for all your data" : "zure datu guztientzako toki segurua",
"File is currently busy, please try again later" : "Fitxategia lanpetuta dago, saiatu berriro geroago",
- "Cannot read file" : "Ezin da fitxategia irakurri",
+ "Cannot download file" : "Ezin da fitxategia deskargatu",
"Application is not enabled" : "Aplikazioa ez dago gaituta",
"Authentication error" : "Autentifikazio errorea",
"Token expired. Please reload page." : "Tokena iraungitu da. Mesedez birkargatu orria.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Biltegia ez dago erabilgarri aldi baterako",
"Storage connection timeout. %s" : "Biltegiratze-konexioa denboraz kanpo geratu da. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Hau normalean web zerbitzarira config karpetan idazteko baimenak emanez konpondu daiteke.",
+ "Cannot read file" : "Ezin da fitxategia irakurri",
"Cannot write into \"config\" directory" : "Ezin da idatzi \"config\" karpetan",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Hau normalean konpondu daiteke web zerbitzariari konfigurazio direktoriorako sarbidea emanez. Ikus %s",
"Cannot write into \"apps\" directory" : "Ezin da idatzi \"apps\" karpetan",
diff --git a/lib/l10n/fi.js b/lib/l10n/fi.js
index 93c4d632aef..13ebcfcffeb 100644
--- a/lib/l10n/fi.js
+++ b/lib/l10n/fi.js
@@ -116,7 +116,11 @@ OC.L10N.register(
"Set an admin password." : "Aseta ylläpitäjän salasana.",
"Sharing backend %s not found" : "Jakamisen taustaosaa %s ei löytynyt",
"Sharing backend for %s not found" : "Jakamisen taustaosaa kohteelle %s ei löytynyt",
+ "%1$s shared »%2$s« with you and wants to add:" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä:",
+ "%1$s shared »%2$s« with you and wants to add" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä",
+ "»%s« added a note to a file shared with you" : "»%s« lisäsi huomion jakamaasi tiedostoon",
"Open »%s«" : "Avaa »%s«",
+ "%1$s via %2$s" : "%1$s palvelun %2$s kautta",
"You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.",
"Cannot increase permissions of %s" : "Kohteen %s käyttöoikeuksien lisääminen ei onnistu",
"Files cannot be shared with delete permissions" : "Tiedostoja ei voi jakaa poistamisoikeuksilla",
@@ -189,7 +193,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Sovellusta \"%1$s\" ei voi asentaa, koska seuraavat riippuvuudet eivät täyty: %2$s",
"a safe home for all your data" : "turvallinen koti kaikille tiedostoillesi",
"File is currently busy, please try again later" : "Tiedosto on parhaillaan käytössä, yritä myöhemmin uudelleen",
- "Cannot read file" : "Tiedostoa ei voi lukea",
+ "Cannot download file" : "Tiedostoa ei voi ladata",
"Application is not enabled" : "Sovellusta ei ole otettu käyttöön",
"Authentication error" : "Tunnistautumisvirhe",
"Token expired. Please reload page." : "Valtuutus vanheni. Lataa sivu uudelleen.",
@@ -221,6 +225,7 @@ OC.L10N.register(
"Storage connection error. %s" : "Tallennustilan yhteysvirhe. %s",
"Storage is temporarily not available" : "Tallennustila on tilapäisesti pois käytöstä",
"Storage connection timeout. %s" : "Tallennustilan yhteyden aikakatkaisu. %s",
+ "Cannot read file" : "Tiedostoa ei voi lukea",
"Cannot write into \"config\" directory" : "Hakemistoon \"config\" kirjoittaminen ei onnistu",
"Cannot write into \"apps\" directory" : "Hakemistoon \"apps\" kirjoittaminen ei onnistu",
"Cannot create \"data\" directory" : "Hakemiston \"data\" luominen ei onnistu",
diff --git a/lib/l10n/fi.json b/lib/l10n/fi.json
index 02470bb0054..2aa4fdcd0d5 100644
--- a/lib/l10n/fi.json
+++ b/lib/l10n/fi.json
@@ -114,7 +114,11 @@
"Set an admin password." : "Aseta ylläpitäjän salasana.",
"Sharing backend %s not found" : "Jakamisen taustaosaa %s ei löytynyt",
"Sharing backend for %s not found" : "Jakamisen taustaosaa kohteelle %s ei löytynyt",
+ "%1$s shared »%2$s« with you and wants to add:" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä:",
+ "%1$s shared »%2$s« with you and wants to add" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä",
+ "»%s« added a note to a file shared with you" : "»%s« lisäsi huomion jakamaasi tiedostoon",
"Open »%s«" : "Avaa »%s«",
+ "%1$s via %2$s" : "%1$s palvelun %2$s kautta",
"You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.",
"Cannot increase permissions of %s" : "Kohteen %s käyttöoikeuksien lisääminen ei onnistu",
"Files cannot be shared with delete permissions" : "Tiedostoja ei voi jakaa poistamisoikeuksilla",
@@ -187,7 +191,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Sovellusta \"%1$s\" ei voi asentaa, koska seuraavat riippuvuudet eivät täyty: %2$s",
"a safe home for all your data" : "turvallinen koti kaikille tiedostoillesi",
"File is currently busy, please try again later" : "Tiedosto on parhaillaan käytössä, yritä myöhemmin uudelleen",
- "Cannot read file" : "Tiedostoa ei voi lukea",
+ "Cannot download file" : "Tiedostoa ei voi ladata",
"Application is not enabled" : "Sovellusta ei ole otettu käyttöön",
"Authentication error" : "Tunnistautumisvirhe",
"Token expired. Please reload page." : "Valtuutus vanheni. Lataa sivu uudelleen.",
@@ -219,6 +223,7 @@
"Storage connection error. %s" : "Tallennustilan yhteysvirhe. %s",
"Storage is temporarily not available" : "Tallennustila on tilapäisesti pois käytöstä",
"Storage connection timeout. %s" : "Tallennustilan yhteyden aikakatkaisu. %s",
+ "Cannot read file" : "Tiedostoa ei voi lukea",
"Cannot write into \"config\" directory" : "Hakemistoon \"config\" kirjoittaminen ei onnistu",
"Cannot write into \"apps\" directory" : "Hakemistoon \"apps\" kirjoittaminen ei onnistu",
"Cannot create \"data\" directory" : "Hakemiston \"data\" luominen ei onnistu",
diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js
index 7a40ad0a772..fce71090c61 100644
--- a/lib/l10n/fr.js
+++ b/lib/l10n/fr.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "L'application \"%1$s\" ne peut pas être installée à cause des dépendances suivantes non satisfaites : %2$s",
"a safe home for all your data" : "un lieu sûr pour toutes vos données",
"File is currently busy, please try again later" : "Le fichier est actuellement utilisé, veuillez réessayer plus tard",
- "Cannot read file" : "Impossible de lire le fichier",
+ "Cannot download file" : "Impossible de télécharger le fichier",
"Application is not enabled" : "L'application n'est pas activée",
"Authentication error" : "Erreur d'authentification",
"Token expired. Please reload page." : "La session a expiré. Veuillez recharger la page.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Le support de stockage est temporairement indisponible",
"Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire de configuration.",
+ "Cannot read file" : "Impossible de lire le fichier",
"Cannot write into \"config\" directory" : "Impossible d’écrire dans le répertoire \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\". Voir %s",
"Cannot write into \"apps\" directory" : "Impossible d’écrire dans le répertoire \"apps\"",
diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json
index 39541e997cf..f9ff67188b0 100644
--- a/lib/l10n/fr.json
+++ b/lib/l10n/fr.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "L'application \"%1$s\" ne peut pas être installée à cause des dépendances suivantes non satisfaites : %2$s",
"a safe home for all your data" : "un lieu sûr pour toutes vos données",
"File is currently busy, please try again later" : "Le fichier est actuellement utilisé, veuillez réessayer plus tard",
- "Cannot read file" : "Impossible de lire le fichier",
+ "Cannot download file" : "Impossible de télécharger le fichier",
"Application is not enabled" : "L'application n'est pas activée",
"Authentication error" : "Erreur d'authentification",
"Token expired. Please reload page." : "La session a expiré. Veuillez recharger la page.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Le support de stockage est temporairement indisponible",
"Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire de configuration.",
+ "Cannot read file" : "Impossible de lire le fichier",
"Cannot write into \"config\" directory" : "Impossible d’écrire dans le répertoire \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\". Voir %s",
"Cannot write into \"apps\" directory" : "Impossible d’écrire dans le répertoire \"apps\"",
diff --git a/lib/l10n/hr.js b/lib/l10n/hr.js
index 60e5aa3e240..e448f3fd030 100644
--- a/lib/l10n/hr.js
+++ b/lib/l10n/hr.js
@@ -206,7 +206,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Aplikaciju „%1$s” nije moguće instalirati jer nisu ispunjene sljedeće ovisnosti: %2$s",
"a safe home for all your data" : "siguran dom za sve vaše podatke",
"File is currently busy, please try again later" : "Datoteka je trenutno zauzeta, pokušajte ponovo kasnije",
- "Cannot read file" : "Datoteku nije moguće pročitati",
"Application is not enabled" : "Aplikacija nije omogućena",
"Authentication error" : "Pogrešna autentifikacija",
"Token expired. Please reload page." : "Token je istekao. Ponovno učitajte stranicu.",
@@ -236,6 +235,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Pohrana privremeno nije dostupna",
"Storage connection timeout. %s" : "Istek veze pohrane. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ovo se obično može ispraviti tako da se web-poslužitelju dopusti pristup za pisanje u direktoriju config.",
+ "Cannot read file" : "Datoteku nije moguće pročitati",
"Cannot write into \"config\" directory" : "Pisanje u direktorij „config” nije moguće",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ovo se obično može popraviti tako da se web poslužitelju dopusti pristup za pisanje u konfiguracijski direktorij. Pogledajte %s",
"Cannot write into \"apps\" directory" : "Nije moguće pisati u direktorij „apps”",
diff --git a/lib/l10n/hr.json b/lib/l10n/hr.json
index d78f720c81f..2760ab38adb 100644
--- a/lib/l10n/hr.json
+++ b/lib/l10n/hr.json
@@ -204,7 +204,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Aplikaciju „%1$s” nije moguće instalirati jer nisu ispunjene sljedeće ovisnosti: %2$s",
"a safe home for all your data" : "siguran dom za sve vaše podatke",
"File is currently busy, please try again later" : "Datoteka je trenutno zauzeta, pokušajte ponovo kasnije",
- "Cannot read file" : "Datoteku nije moguće pročitati",
"Application is not enabled" : "Aplikacija nije omogućena",
"Authentication error" : "Pogrešna autentifikacija",
"Token expired. Please reload page." : "Token je istekao. Ponovno učitajte stranicu.",
@@ -234,6 +233,7 @@
"Storage is temporarily not available" : "Pohrana privremeno nije dostupna",
"Storage connection timeout. %s" : "Istek veze pohrane. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ovo se obično može ispraviti tako da se web-poslužitelju dopusti pristup za pisanje u direktoriju config.",
+ "Cannot read file" : "Datoteku nije moguće pročitati",
"Cannot write into \"config\" directory" : "Pisanje u direktorij „config” nije moguće",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ovo se obično može popraviti tako da se web poslužitelju dopusti pristup za pisanje u konfiguracijski direktorij. Pogledajte %s",
"Cannot write into \"apps\" directory" : "Nije moguće pisati u direktorij „apps”",
diff --git a/lib/l10n/hu.js b/lib/l10n/hu.js
index 6e4113507b5..6d37257854c 100644
--- a/lib/l10n/hu.js
+++ b/lib/l10n/hu.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "A(z) „%1$s” alkalmazást nem lehet telepíteni, mert a következő függőségek nem teljesülnek: %2$s",
"a safe home for all your data" : "egy biztonságos hely az adataidnak",
"File is currently busy, please try again later" : "A fájl jelenleg foglalt, próbálja újra később",
- "Cannot read file" : "A fájl nem olvasható",
+ "Cannot download file" : "A fájl nem tölthető le",
"Application is not enabled" : "Az alkalmazás nincs engedélyezve",
"Authentication error" : "Hitelesítési hiba",
"Token expired. Please reload page." : "A token lejárt. Frissítse az oldalt.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "A tároló átmenetileg nem érhető el",
"Storage connection timeout. %s" : "Időtúllépés a tárolókapcsolatban. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ez általában úgy javítható, hogy a webkiszolgálónak írási hozzáférést biztosít a konfigurációs könyvtárhoz.",
+ "Cannot read file" : "A fájl nem olvasható",
"Cannot write into \"config\" directory" : "A „config” könyvtár nem írható",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ez általában úgy javítható, hogy a webkiszolgálónak írási hozzáférést biztosít a konfigurációs könyvtárhoz. Lásd: %s.",
"Cannot write into \"apps\" directory" : "Az „apps” könyvtár nem írható",
diff --git a/lib/l10n/hu.json b/lib/l10n/hu.json
index 01d41e53248..09245fbe1e5 100644
--- a/lib/l10n/hu.json
+++ b/lib/l10n/hu.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "A(z) „%1$s” alkalmazást nem lehet telepíteni, mert a következő függőségek nem teljesülnek: %2$s",
"a safe home for all your data" : "egy biztonságos hely az adataidnak",
"File is currently busy, please try again later" : "A fájl jelenleg foglalt, próbálja újra később",
- "Cannot read file" : "A fájl nem olvasható",
+ "Cannot download file" : "A fájl nem tölthető le",
"Application is not enabled" : "Az alkalmazás nincs engedélyezve",
"Authentication error" : "Hitelesítési hiba",
"Token expired. Please reload page." : "A token lejárt. Frissítse az oldalt.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "A tároló átmenetileg nem érhető el",
"Storage connection timeout. %s" : "Időtúllépés a tárolókapcsolatban. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ez általában úgy javítható, hogy a webkiszolgálónak írási hozzáférést biztosít a konfigurációs könyvtárhoz.",
+ "Cannot read file" : "A fájl nem olvasható",
"Cannot write into \"config\" directory" : "A „config” könyvtár nem írható",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ez általában úgy javítható, hogy a webkiszolgálónak írási hozzáférést biztosít a konfigurációs könyvtárhoz. Lásd: %s.",
"Cannot write into \"apps\" directory" : "Az „apps” könyvtár nem írható",
diff --git a/lib/l10n/id.js b/lib/l10n/id.js
index fe5faa7baba..2f03d5e814f 100644
--- a/lib/l10n/id.js
+++ b/lib/l10n/id.js
@@ -16,6 +16,7 @@ OC.L10N.register(
"Authentication" : "Otentikasi",
"Unknown filetype" : "Tipe berkas tak dikenal",
"Invalid image" : "Gambar tidak sah",
+ "View profile" : "Tampilkan profil",
"today" : "hari ini",
"yesterday" : "kemarin",
"_%n day ago_::_%n days ago_" : ["%n hari yang lalu"],
diff --git a/lib/l10n/id.json b/lib/l10n/id.json
index 737bf890755..1cae9975fe3 100644
--- a/lib/l10n/id.json
+++ b/lib/l10n/id.json
@@ -14,6 +14,7 @@
"Authentication" : "Otentikasi",
"Unknown filetype" : "Tipe berkas tak dikenal",
"Invalid image" : "Gambar tidak sah",
+ "View profile" : "Tampilkan profil",
"today" : "hari ini",
"yesterday" : "kemarin",
"_%n day ago_::_%n days ago_" : ["%n hari yang lalu"],
diff --git a/lib/l10n/is.js b/lib/l10n/is.js
index 0e189143ad0..09f31373d69 100644
--- a/lib/l10n/is.js
+++ b/lib/l10n/is.js
@@ -62,6 +62,7 @@ OC.L10N.register(
"seconds ago" : "sekúndum síðan",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Eining með auðkenni: %s er ekki til. Virkjaðu hana í forritastillingum eða hafðu samband við kerfisstjóra.",
"File already exists" : "Skrá er þegar til",
+ "Templates" : "Sniðmát",
"File name is a reserved word" : "Skráarheiti er þegar frátekið orð",
"File name contains at least one invalid character" : "Skráarheitið inniheldur að minnsta kosti einn ógildan staf",
"File name is too long" : "Skráarheiti er of langt",
diff --git a/lib/l10n/is.json b/lib/l10n/is.json
index 503adc055e0..c1e4211b173 100644
--- a/lib/l10n/is.json
+++ b/lib/l10n/is.json
@@ -60,6 +60,7 @@
"seconds ago" : "sekúndum síðan",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Eining með auðkenni: %s er ekki til. Virkjaðu hana í forritastillingum eða hafðu samband við kerfisstjóra.",
"File already exists" : "Skrá er þegar til",
+ "Templates" : "Sniðmát",
"File name is a reserved word" : "Skráarheiti er þegar frátekið orð",
"File name contains at least one invalid character" : "Skráarheitið inniheldur að minnsta kosti einn ógildan staf",
"File name is too long" : "Skráarheiti er of langt",
diff --git a/lib/l10n/it.js b/lib/l10n/it.js
index 608db04d9da..9c5ff2d767b 100644
--- a/lib/l10n/it.js
+++ b/lib/l10n/it.js
@@ -207,7 +207,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "L'applicazione \"%1$s\" non può essere installata poiché le seguenti dipendenze non sono soddisfatte: %2$s",
"a safe home for all your data" : "un posto sicuro per tutti i tuoi dati",
"File is currently busy, please try again later" : "Il file è attualmente occupato, riprova più tardi",
- "Cannot read file" : "Impossibile leggere il file",
"Application is not enabled" : "L'applicazione non è abilitata",
"Authentication error" : "Errore di autenticazione",
"Token expired. Please reload page." : "Token scaduto. Ricarica la pagina.",
@@ -255,6 +254,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "L'archiviazione è temporaneamente non disponibile",
"Storage connection timeout. %s" : "Timeout di connessione all'archiviazione. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella \"config\".",
+ "Cannot read file" : "Impossibile leggere il file",
"Cannot write into \"config\" directory" : "Impossibile scrivere nella cartella \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella di configurazione. Vedi %s",
"Cannot write into \"apps\" directory" : "Impossibile scrivere nella cartella \"apps\"",
diff --git a/lib/l10n/it.json b/lib/l10n/it.json
index f7c10f383fc..2f664a14281 100644
--- a/lib/l10n/it.json
+++ b/lib/l10n/it.json
@@ -205,7 +205,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "L'applicazione \"%1$s\" non può essere installata poiché le seguenti dipendenze non sono soddisfatte: %2$s",
"a safe home for all your data" : "un posto sicuro per tutti i tuoi dati",
"File is currently busy, please try again later" : "Il file è attualmente occupato, riprova più tardi",
- "Cannot read file" : "Impossibile leggere il file",
"Application is not enabled" : "L'applicazione non è abilitata",
"Authentication error" : "Errore di autenticazione",
"Token expired. Please reload page." : "Token scaduto. Ricarica la pagina.",
@@ -253,6 +252,7 @@
"Storage is temporarily not available" : "L'archiviazione è temporaneamente non disponibile",
"Storage connection timeout. %s" : "Timeout di connessione all'archiviazione. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella \"config\".",
+ "Cannot read file" : "Impossibile leggere il file",
"Cannot write into \"config\" directory" : "Impossibile scrivere nella cartella \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella di configurazione. Vedi %s",
"Cannot write into \"apps\" directory" : "Impossibile scrivere nella cartella \"apps\"",
diff --git a/lib/l10n/ja.js b/lib/l10n/ja.js
index 38c6547a63c..5b4164dba39 100644
--- a/lib/l10n/ja.js
+++ b/lib/l10n/ja.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "次の依存関係を満たしていないため、アプリ \"%1$s\" をインストールできません: %2$s",
"a safe home for all your data" : "すべてのデータを安全に保管します",
"File is currently busy, please try again later" : "現在ファイルはビジーです。後でもう一度試してください。",
- "Cannot read file" : "ファイルを読み込めません",
+ "Cannot download file" : "ファイルをダウンロードできません",
"Application is not enabled" : "アプリケーションは無効です",
"Authentication error" : "認証エラー",
"Token expired. Please reload page." : "トークンが無効になりました。ページを再読込してください。",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "ストレージは一時的に利用できません",
"Storage connection timeout. %s" : "ストレージへの接続がタイムアウト。 %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Webサーバーにconfigディレクトリへの書き込み権限を与えることで解決する可能性があります。",
+ "Cannot read file" : "ファイルを読み込めません",
"Cannot write into \"config\" directory" : "\"config\" ディレクトリに書き込みができません",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "多くの場合、Webサーバーの configディレクトリ に書き込み権限を与えることで直ります。%s を見てください",
"Cannot write into \"apps\" directory" : "\"apps\" ディレクトリに書き込みができません",
diff --git a/lib/l10n/ja.json b/lib/l10n/ja.json
index 878f4fbdd13..ccfdd45c430 100644
--- a/lib/l10n/ja.json
+++ b/lib/l10n/ja.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "次の依存関係を満たしていないため、アプリ \"%1$s\" をインストールできません: %2$s",
"a safe home for all your data" : "すべてのデータを安全に保管します",
"File is currently busy, please try again later" : "現在ファイルはビジーです。後でもう一度試してください。",
- "Cannot read file" : "ファイルを読み込めません",
+ "Cannot download file" : "ファイルをダウンロードできません",
"Application is not enabled" : "アプリケーションは無効です",
"Authentication error" : "認証エラー",
"Token expired. Please reload page." : "トークンが無効になりました。ページを再読込してください。",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "ストレージは一時的に利用できません",
"Storage connection timeout. %s" : "ストレージへの接続がタイムアウト。 %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Webサーバーにconfigディレクトリへの書き込み権限を与えることで解決する可能性があります。",
+ "Cannot read file" : "ファイルを読み込めません",
"Cannot write into \"config\" directory" : "\"config\" ディレクトリに書き込みができません",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "多くの場合、Webサーバーの configディレクトリ に書き込み権限を与えることで直ります。%s を見てください",
"Cannot write into \"apps\" directory" : "\"apps\" ディレクトリに書き込みができません",
diff --git a/lib/l10n/ko.js b/lib/l10n/ko.js
index a2329ec6590..039f738edd9 100644
--- a/lib/l10n/ko.js
+++ b/lib/l10n/ko.js
@@ -79,6 +79,7 @@ OC.L10N.register(
"About" : "정보",
"Full name" : "전체 이름",
"Headline" : "표제",
+ "Organisation" : "조직",
"Role" : "직책",
"Unknown user" : "알려지지 않은 사용자",
"Additional settings" : "고급 설정",
diff --git a/lib/l10n/ko.json b/lib/l10n/ko.json
index c431ac654b9..81f384b4c3a 100644
--- a/lib/l10n/ko.json
+++ b/lib/l10n/ko.json
@@ -77,6 +77,7 @@
"About" : "정보",
"Full name" : "전체 이름",
"Headline" : "표제",
+ "Organisation" : "조직",
"Role" : "직책",
"Unknown user" : "알려지지 않은 사용자",
"Additional settings" : "고급 설정",
diff --git a/lib/l10n/mk.js b/lib/l10n/mk.js
index 6a94177fd32..bffc6debf01 100644
--- a/lib/l10n/mk.js
+++ b/lib/l10n/mk.js
@@ -206,7 +206,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Апликацијата \"%1$s\" не може да се инсталира затоа што следниве зависности не се исполнети: %2$s",
"a safe home for all your data" : "безбеден дом за сите ваши податоци",
"File is currently busy, please try again later" : "Датотеката моментално е зафатена, обидете се повторно",
- "Cannot read file" : "Неможе да се прочита датотеката",
"Application is not enabled" : "Апликацијата не е овозможена",
"Authentication error" : "Грешка во автентикација",
"Token expired. Please reload page." : "Жетонот е истечен. Ве молам превчитајте ја страницата.",
@@ -236,6 +235,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Складиштето моментално не е достапно",
"Storage connection timeout. %s" : "Поврзувањето со складиштето не успеа. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ова најчесто се поправа со давање на дозвола веб серверот за запишување во config папката.",
+ "Cannot read file" : "Неможе да се прочита датотеката",
"Cannot write into \"config\" directory" : "Не може да зе запишува во \"config\" директориумот",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ова најчесто се поправа со давање дозвола на веб серверот за запишување во config папката. Видете %s",
"Cannot write into \"apps\" directory" : "Не може да зе запишува во \"apps\" директориумот",
diff --git a/lib/l10n/mk.json b/lib/l10n/mk.json
index 6fe249d9c17..f86bfb14998 100644
--- a/lib/l10n/mk.json
+++ b/lib/l10n/mk.json
@@ -204,7 +204,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Апликацијата \"%1$s\" не може да се инсталира затоа што следниве зависности не се исполнети: %2$s",
"a safe home for all your data" : "безбеден дом за сите ваши податоци",
"File is currently busy, please try again later" : "Датотеката моментално е зафатена, обидете се повторно",
- "Cannot read file" : "Неможе да се прочита датотеката",
"Application is not enabled" : "Апликацијата не е овозможена",
"Authentication error" : "Грешка во автентикација",
"Token expired. Please reload page." : "Жетонот е истечен. Ве молам превчитајте ја страницата.",
@@ -234,6 +233,7 @@
"Storage is temporarily not available" : "Складиштето моментално не е достапно",
"Storage connection timeout. %s" : "Поврзувањето со складиштето не успеа. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Ова најчесто се поправа со давање на дозвола веб серверот за запишување во config папката.",
+ "Cannot read file" : "Неможе да се прочита датотеката",
"Cannot write into \"config\" directory" : "Не може да зе запишува во \"config\" директориумот",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ова најчесто се поправа со давање дозвола на веб серверот за запишување во config папката. Видете %s",
"Cannot write into \"apps\" directory" : "Не може да зе запишува во \"apps\" директориумот",
diff --git a/lib/l10n/nb.js b/lib/l10n/nb.js
index cd3822384e6..023f43b136c 100644
--- a/lib/l10n/nb.js
+++ b/lib/l10n/nb.js
@@ -5,6 +5,11 @@ OC.L10N.register(
"See %s" : "Se %s",
"Sample configuration detected" : "Eksempeloppsett oppdaget",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Det ble oppdaget at eksempeloppsettet er blitt kopiert. Dette kan ødelegge installasjonen din og støttes ikke. Les dokumentasjonen før du gjør endringer i config.php",
+ "%s email verification" : "%s e-postbekreftelse",
+ "Email verification" : "E-postbekreftelse",
+ "Click the following button to confirm your email." : "Klikk på følgende knapp for å bekrefte e-posten din.",
+ "Click the following link to confirm your email." : "Klikk på følgende lenke for å bekrefte e-posten din.",
+ "Confirm your email" : "Bekreft din e-post",
"%1$s and %2$s" : "%1$s og %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s",
"%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s",
@@ -45,8 +50,10 @@ OC.L10N.register(
"_%n minute ago_::_%n minutes ago_" : ["for %n minutt siden","for %n minutter siden"],
"in a few seconds" : "om noen sekunder",
"seconds ago" : "for få sekunder siden",
+ "Empty file" : "Tom fil",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul med ID: %s finnes ikke. Skru den på i app-innstillingene eller kontakt en administrator.",
"File already exists" : "Filen finnes allerede",
+ "Invalid path" : "Ugyldig filbane",
"File name is a reserved word" : "Filnavnet er et reservert ord",
"File name contains at least one invalid character" : "Filnavnet inneholder minst ett ulovlig tegn",
"File name is too long" : "Filnavnet er for langt",
@@ -62,13 +69,20 @@ OC.L10N.register(
"Log out" : "Logg ut",
"Users" : "Brukere",
"Email" : "E-post",
+ "Mail %s" : "E-post til %s",
"Phone" : "Telefon",
+ "Call %s" : "Ring %s",
"Twitter" : "Twitter",
+ "View %s on Twitter" : "Se %s på Twitter",
"Website" : "Nettsted",
+ "Visit %s" : "Besøk %s",
"Address" : "Adresse",
"Profile picture" : "Profilbilde",
"About" : "Om",
"Full name" : "Fullt nav",
+ "Headline" : "Overskrift",
+ "Organisation" : "Organisasion",
+ "Role" : "Rolle",
"Unknown user" : "Ukjent bruker",
"Additional settings" : "Flere innstillinger",
"%s enter the database username and name." : "%s legg inn database brukernavn og navn.",
@@ -158,6 +172,7 @@ OC.L10N.register(
"Login canceled by app" : "Innlogging avbrutt av app",
"a safe home for all your data" : "et sikkert hjem for alle dine data",
"File is currently busy, please try again later" : "Filen er opptatt for øyeblikket, prøv igjen senere",
+ "Cannot download file" : "Kan ikke laste ned fil",
"Application is not enabled" : "Appen er ikke aktivert",
"Authentication error" : "Autentikasjonsfeil",
"Token expired. Please reload page." : "Symbol utløpt. Last inn siden på nytt.",
@@ -180,6 +195,7 @@ OC.L10N.register(
"Storage connection error. %s" : "Tilkoblingsfeil for lager. %s",
"Storage is temporarily not available" : "Lagring er midlertidig utilgjengelig",
"Storage connection timeout. %s" : "Tidsavbrudd ved tilkobling av lager: %s",
+ "Cannot read file" : "Kan ikke lese fil",
"Cannot write into \"config\" directory" : "Kan ikke skrive i \"config\"-mappen",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dette kan vanligvis ordnes ved å gi webserveren skrivetilgang til config-mappen. Se %s",
"Cannot write into \"apps\" directory" : "Kan ikke skrive i \"apps\"-mappen",
diff --git a/lib/l10n/nb.json b/lib/l10n/nb.json
index ee405c25723..1f0f6b629c7 100644
--- a/lib/l10n/nb.json
+++ b/lib/l10n/nb.json
@@ -3,6 +3,11 @@
"See %s" : "Se %s",
"Sample configuration detected" : "Eksempeloppsett oppdaget",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Det ble oppdaget at eksempeloppsettet er blitt kopiert. Dette kan ødelegge installasjonen din og støttes ikke. Les dokumentasjonen før du gjør endringer i config.php",
+ "%s email verification" : "%s e-postbekreftelse",
+ "Email verification" : "E-postbekreftelse",
+ "Click the following button to confirm your email." : "Klikk på følgende knapp for å bekrefte e-posten din.",
+ "Click the following link to confirm your email." : "Klikk på følgende lenke for å bekrefte e-posten din.",
+ "Confirm your email" : "Bekreft din e-post",
"%1$s and %2$s" : "%1$s og %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s",
"%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s",
@@ -43,8 +48,10 @@
"_%n minute ago_::_%n minutes ago_" : ["for %n minutt siden","for %n minutter siden"],
"in a few seconds" : "om noen sekunder",
"seconds ago" : "for få sekunder siden",
+ "Empty file" : "Tom fil",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul med ID: %s finnes ikke. Skru den på i app-innstillingene eller kontakt en administrator.",
"File already exists" : "Filen finnes allerede",
+ "Invalid path" : "Ugyldig filbane",
"File name is a reserved word" : "Filnavnet er et reservert ord",
"File name contains at least one invalid character" : "Filnavnet inneholder minst ett ulovlig tegn",
"File name is too long" : "Filnavnet er for langt",
@@ -60,13 +67,20 @@
"Log out" : "Logg ut",
"Users" : "Brukere",
"Email" : "E-post",
+ "Mail %s" : "E-post til %s",
"Phone" : "Telefon",
+ "Call %s" : "Ring %s",
"Twitter" : "Twitter",
+ "View %s on Twitter" : "Se %s på Twitter",
"Website" : "Nettsted",
+ "Visit %s" : "Besøk %s",
"Address" : "Adresse",
"Profile picture" : "Profilbilde",
"About" : "Om",
"Full name" : "Fullt nav",
+ "Headline" : "Overskrift",
+ "Organisation" : "Organisasion",
+ "Role" : "Rolle",
"Unknown user" : "Ukjent bruker",
"Additional settings" : "Flere innstillinger",
"%s enter the database username and name." : "%s legg inn database brukernavn og navn.",
@@ -156,6 +170,7 @@
"Login canceled by app" : "Innlogging avbrutt av app",
"a safe home for all your data" : "et sikkert hjem for alle dine data",
"File is currently busy, please try again later" : "Filen er opptatt for øyeblikket, prøv igjen senere",
+ "Cannot download file" : "Kan ikke laste ned fil",
"Application is not enabled" : "Appen er ikke aktivert",
"Authentication error" : "Autentikasjonsfeil",
"Token expired. Please reload page." : "Symbol utløpt. Last inn siden på nytt.",
@@ -178,6 +193,7 @@
"Storage connection error. %s" : "Tilkoblingsfeil for lager. %s",
"Storage is temporarily not available" : "Lagring er midlertidig utilgjengelig",
"Storage connection timeout. %s" : "Tidsavbrudd ved tilkobling av lager: %s",
+ "Cannot read file" : "Kan ikke lese fil",
"Cannot write into \"config\" directory" : "Kan ikke skrive i \"config\"-mappen",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dette kan vanligvis ordnes ved å gi webserveren skrivetilgang til config-mappen. Se %s",
"Cannot write into \"apps\" directory" : "Kan ikke skrive i \"apps\"-mappen",
diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js
index 76423ca4486..f1787eff27d 100644
--- a/lib/l10n/nl.js
+++ b/lib/l10n/nl.js
@@ -207,7 +207,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "App \"%1$s\" kan niet worden geïnstalleerd, omdat de volgende afhankelijkheden niet zijn ingevuld: %2$s",
"a safe home for all your data" : "een veilige plek voor al je gegevens",
"File is currently busy, please try again later" : "Bestandsverwerking bezig, probeer het later opnieuw",
- "Cannot read file" : "Kan bestand niet lezen",
"Application is not enabled" : "De applicatie is niet ingeschakeld",
"Authentication error" : "Authenticatiefout",
"Token expired. Please reload page." : "Token verlopen. Herlaad de pagina.",
@@ -253,6 +252,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Opslag is tijdelijk niet beschikbaar",
"Storage connection timeout. %s" : "Opslag verbinding time-out. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Dit kan opgelost worden door de config map op de webserver schrijfrechten te geven.",
+ "Cannot read file" : "Kan bestand niet lezen",
"Cannot write into \"config\" directory" : "Kan niet schrijven naar de \"config\" directory",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dit kan opgelost worden door de config map op de webserver schrijf rechten te geven. See %s",
"Cannot write into \"apps\" directory" : "Kan niet schrijven naar de \"apps\" directory",
diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json
index 79b39acd2c1..5c1eff0b199 100644
--- a/lib/l10n/nl.json
+++ b/lib/l10n/nl.json
@@ -205,7 +205,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "App \"%1$s\" kan niet worden geïnstalleerd, omdat de volgende afhankelijkheden niet zijn ingevuld: %2$s",
"a safe home for all your data" : "een veilige plek voor al je gegevens",
"File is currently busy, please try again later" : "Bestandsverwerking bezig, probeer het later opnieuw",
- "Cannot read file" : "Kan bestand niet lezen",
"Application is not enabled" : "De applicatie is niet ingeschakeld",
"Authentication error" : "Authenticatiefout",
"Token expired. Please reload page." : "Token verlopen. Herlaad de pagina.",
@@ -251,6 +250,7 @@
"Storage is temporarily not available" : "Opslag is tijdelijk niet beschikbaar",
"Storage connection timeout. %s" : "Opslag verbinding time-out. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Dit kan opgelost worden door de config map op de webserver schrijfrechten te geven.",
+ "Cannot read file" : "Kan bestand niet lezen",
"Cannot write into \"config\" directory" : "Kan niet schrijven naar de \"config\" directory",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dit kan opgelost worden door de config map op de webserver schrijf rechten te geven. See %s",
"Cannot write into \"apps\" directory" : "Kan niet schrijven naar de \"apps\" directory",
diff --git a/lib/l10n/nn_NO.js b/lib/l10n/nn_NO.js
index 33a31973071..924adc60a85 100644
--- a/lib/l10n/nn_NO.js
+++ b/lib/l10n/nn_NO.js
@@ -1,6 +1,7 @@
OC.L10N.register(
"lib",
{
+ "Authentication" : "Godkjenning",
"Unknown filetype" : "Ukjend filtype",
"Invalid image" : "Ugyldig bilete",
"today" : "i dag",
@@ -13,9 +14,10 @@ OC.L10N.register(
"_%n hour ago_::_%n hours ago_" : ["%n time sidan","%n timar sidan"],
"_%n minute ago_::_%n minutes ago_" : ["%n minutt sidan","%n minutt sidan"],
"seconds ago" : "sekund sidan",
+ "File name is too long" : "Filnamnet er for langt",
"__language_name__" : "Nynorsk",
"Help" : "Hjelp",
- "Apps" : "Program",
+ "Apps" : "Appar",
"Settings" : "Instillingar",
"Log out" : "Logg ut",
"Users" : "Brukarar",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Full name" : "Fult namn",
"Unknown user" : "Ukjend brukar",
"Additional settings" : "Tilleggsinnstillingar",
+ "Set an admin password." : "Vel eit admin-passord.",
"Open »%s«" : "Opna »%s«",
"Sunday" : "Søndag",
"Monday" : "Måndag",
@@ -75,6 +78,8 @@ OC.L10N.register(
"Dec." : "Des.",
"A valid username must be provided" : "Du må oppgje eit gyldig brukarnamn",
"A valid password must be provided" : "Du må oppgje eit gyldig passord",
+ "User disabled" : "Brukar deaktivert",
+ "Login canceled by app" : "Innlogging avbroten av app",
"Authentication error" : "Feil i autentisering"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/nn_NO.json b/lib/l10n/nn_NO.json
index 53b50337a17..219148e7b1b 100644
--- a/lib/l10n/nn_NO.json
+++ b/lib/l10n/nn_NO.json
@@ -1,4 +1,5 @@
{ "translations": {
+ "Authentication" : "Godkjenning",
"Unknown filetype" : "Ukjend filtype",
"Invalid image" : "Ugyldig bilete",
"today" : "i dag",
@@ -11,9 +12,10 @@
"_%n hour ago_::_%n hours ago_" : ["%n time sidan","%n timar sidan"],
"_%n minute ago_::_%n minutes ago_" : ["%n minutt sidan","%n minutt sidan"],
"seconds ago" : "sekund sidan",
+ "File name is too long" : "Filnamnet er for langt",
"__language_name__" : "Nynorsk",
"Help" : "Hjelp",
- "Apps" : "Program",
+ "Apps" : "Appar",
"Settings" : "Instillingar",
"Log out" : "Logg ut",
"Users" : "Brukarar",
@@ -25,6 +27,7 @@
"Full name" : "Fult namn",
"Unknown user" : "Ukjend brukar",
"Additional settings" : "Tilleggsinnstillingar",
+ "Set an admin password." : "Vel eit admin-passord.",
"Open »%s«" : "Opna »%s«",
"Sunday" : "Søndag",
"Monday" : "Måndag",
@@ -73,6 +76,8 @@
"Dec." : "Des.",
"A valid username must be provided" : "Du må oppgje eit gyldig brukarnamn",
"A valid password must be provided" : "Du må oppgje eit gyldig passord",
+ "User disabled" : "Brukar deaktivert",
+ "Login canceled by app" : "Innlogging avbroten av app",
"Authentication error" : "Feil i autentisering"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js
index 1cea063ff4f..eb9255cda36 100644
--- a/lib/l10n/pl.js
+++ b/lib/l10n/pl.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Nie można zainstalować aplikacji \"%1$s\", ponieważ nie są spełnione następujące zależności: %2$s",
"a safe home for all your data" : "bezpieczny dom dla wszystkich danych",
"File is currently busy, please try again later" : "Plik jest obecnie niedostępny, spróbuj później",
- "Cannot read file" : "Nie można odczytać pliku",
+ "Cannot download file" : "Nie można pobrać pliku",
"Application is not enabled" : "Aplikacja nie jest włączona",
"Authentication error" : "Błąd uwierzytelniania",
"Token expired. Please reload page." : "Token wygasł. Przeładuj stronę.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Magazyn jest tymczasowo niedostępny",
"Storage connection timeout. %s" : "Limit czasu połączenia do magazynu. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Zwykle można to naprawić, nadając serwerowi WWW dostęp do zapisu do katalogu config.",
+ "Cannot read file" : "Nie można odczytać pliku",
"Cannot write into \"config\" directory" : "Nie można zapisać do katalogu \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Zwykle można to naprawić, nadając serwerowi WWW dostęp do zapisu do katalogu config. Zobacz %s",
"Cannot write into \"apps\" directory" : "Nie można zapisać do katalogu \"apps\"",
diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json
index 89ca47e5d33..208cfee7853 100644
--- a/lib/l10n/pl.json
+++ b/lib/l10n/pl.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Nie można zainstalować aplikacji \"%1$s\", ponieważ nie są spełnione następujące zależności: %2$s",
"a safe home for all your data" : "bezpieczny dom dla wszystkich danych",
"File is currently busy, please try again later" : "Plik jest obecnie niedostępny, spróbuj później",
- "Cannot read file" : "Nie można odczytać pliku",
+ "Cannot download file" : "Nie można pobrać pliku",
"Application is not enabled" : "Aplikacja nie jest włączona",
"Authentication error" : "Błąd uwierzytelniania",
"Token expired. Please reload page." : "Token wygasł. Przeładuj stronę.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Magazyn jest tymczasowo niedostępny",
"Storage connection timeout. %s" : "Limit czasu połączenia do magazynu. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Zwykle można to naprawić, nadając serwerowi WWW dostęp do zapisu do katalogu config.",
+ "Cannot read file" : "Nie można odczytać pliku",
"Cannot write into \"config\" directory" : "Nie można zapisać do katalogu \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Zwykle można to naprawić, nadając serwerowi WWW dostęp do zapisu do katalogu config. Zobacz %s",
"Cannot write into \"apps\" directory" : "Nie można zapisać do katalogu \"apps\"",
diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js
index fa592b6cc4d..68f00800412 100644
--- a/lib/l10n/pt_BR.js
+++ b/lib/l10n/pt_BR.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "O aplicativo \"%1$s\" não pode ser instalado devido à estas dependências: %2$s",
"a safe home for all your data" : "Um lar seguro para todos os seus dados",
"File is currently busy, please try again later" : "O arquivo está ocupado, tente novamente mais tarde",
- "Cannot read file" : "Não foi possível ler o arquivo",
+ "Cannot download file" : "Não é possível baixar o arquivo",
"Application is not enabled" : "O aplicativo não está habilitado",
"Authentication error" : "Erro de autenticação",
"Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Armazenamento temporariamente indisponível",
"Storage connection timeout. %s" : "Atingido o tempo limite de conexão ao armazenamento. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Geralmente, isso pode ser corrigido concedendo ao servidor web acesso de gravação ao diretório de configuração.",
+ "Cannot read file" : "Não foi possível ler o arquivo",
"Cannot write into \"config\" directory" : "Não foi possível gravar no diretório \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Normalmente isso pode ser resolvido dando ao webserver permissão de escritura no diretório config. Veja %s",
"Cannot write into \"apps\" directory" : "Não foi possível gravar no diretório \"apps\"",
diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json
index 206f786d991..4e4bf30845b 100644
--- a/lib/l10n/pt_BR.json
+++ b/lib/l10n/pt_BR.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "O aplicativo \"%1$s\" não pode ser instalado devido à estas dependências: %2$s",
"a safe home for all your data" : "Um lar seguro para todos os seus dados",
"File is currently busy, please try again later" : "O arquivo está ocupado, tente novamente mais tarde",
- "Cannot read file" : "Não foi possível ler o arquivo",
+ "Cannot download file" : "Não é possível baixar o arquivo",
"Application is not enabled" : "O aplicativo não está habilitado",
"Authentication error" : "Erro de autenticação",
"Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Armazenamento temporariamente indisponível",
"Storage connection timeout. %s" : "Atingido o tempo limite de conexão ao armazenamento. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Geralmente, isso pode ser corrigido concedendo ao servidor web acesso de gravação ao diretório de configuração.",
+ "Cannot read file" : "Não foi possível ler o arquivo",
"Cannot write into \"config\" directory" : "Não foi possível gravar no diretório \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Normalmente isso pode ser resolvido dando ao webserver permissão de escritura no diretório config. Veja %s",
"Cannot write into \"apps\" directory" : "Não foi possível gravar no diretório \"apps\"",
diff --git a/lib/l10n/pt_PT.js b/lib/l10n/pt_PT.js
index 651e0fe4b9e..81bc932c91a 100644
--- a/lib/l10n/pt_PT.js
+++ b/lib/l10n/pt_PT.js
@@ -178,7 +178,6 @@ OC.L10N.register(
"Login canceled by app" : "Sessão cancelada pela app",
"a safe home for all your data" : "Um lugar seguro para todos os seus dados",
"File is currently busy, please try again later" : "O ficheiro está ocupado, por favor, tente mais tarde",
- "Cannot read file" : "Não é possível ler o ficheiro",
"Application is not enabled" : "A aplicação não está activada",
"Authentication error" : "Erro na autenticação",
"Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.",
@@ -207,6 +206,7 @@ OC.L10N.register(
"Storage connection error. %s" : "Erro de ligação ao armazenamento. %s",
"Storage is temporarily not available" : "Armazenamento temporariamente indisponível",
"Storage connection timeout. %s" : "Tempo de ligação ao armazenamento expirou. %s",
+ "Cannot read file" : "Não é possível ler o ficheiro",
"Cannot write into \"config\" directory" : "Não é possível escrever na directoria \"configurar\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Isto pode geralmente ser corrigido ao adicionar permissões de escrita à pasta de configuração ao servidor web. Ver %s.",
"Cannot write into \"apps\" directory" : "Não é possivel escrever na directoria \"aplicações\"",
diff --git a/lib/l10n/pt_PT.json b/lib/l10n/pt_PT.json
index 8abe9f8c6a0..e3fc3a345ef 100644
--- a/lib/l10n/pt_PT.json
+++ b/lib/l10n/pt_PT.json
@@ -176,7 +176,6 @@
"Login canceled by app" : "Sessão cancelada pela app",
"a safe home for all your data" : "Um lugar seguro para todos os seus dados",
"File is currently busy, please try again later" : "O ficheiro está ocupado, por favor, tente mais tarde",
- "Cannot read file" : "Não é possível ler o ficheiro",
"Application is not enabled" : "A aplicação não está activada",
"Authentication error" : "Erro na autenticação",
"Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.",
@@ -205,6 +204,7 @@
"Storage connection error. %s" : "Erro de ligação ao armazenamento. %s",
"Storage is temporarily not available" : "Armazenamento temporariamente indisponível",
"Storage connection timeout. %s" : "Tempo de ligação ao armazenamento expirou. %s",
+ "Cannot read file" : "Não é possível ler o ficheiro",
"Cannot write into \"config\" directory" : "Não é possível escrever na directoria \"configurar\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Isto pode geralmente ser corrigido ao adicionar permissões de escrita à pasta de configuração ao servidor web. Ver %s.",
"Cannot write into \"apps\" directory" : "Não é possivel escrever na directoria \"aplicações\"",
diff --git a/lib/l10n/ro.js b/lib/l10n/ro.js
index f3385376e1b..075e7364752 100644
--- a/lib/l10n/ro.js
+++ b/lib/l10n/ro.js
@@ -32,6 +32,7 @@ OC.L10N.register(
"in a few seconds" : "în câteva secunde",
"seconds ago" : "secunde în urmă",
"File already exists" : "Fișierul există deja",
+ "Templates" : "Șabloane",
"File name is a reserved word" : "Numele fișierului este un cuvânt rezervat",
"File name contains at least one invalid character" : "Numele fișierului conține cel puțin un caracter invalid",
"File name is too long" : "Numele fișierului este prea lung",
diff --git a/lib/l10n/ro.json b/lib/l10n/ro.json
index 9ade0ceffc2..72bfb83985b 100644
--- a/lib/l10n/ro.json
+++ b/lib/l10n/ro.json
@@ -30,6 +30,7 @@
"in a few seconds" : "în câteva secunde",
"seconds ago" : "secunde în urmă",
"File already exists" : "Fișierul există deja",
+ "Templates" : "Șabloane",
"File name is a reserved word" : "Numele fișierului este un cuvânt rezervat",
"File name contains at least one invalid character" : "Numele fișierului conține cel puțin un caracter invalid",
"File name is too long" : "Numele fișierului este prea lung",
diff --git a/lib/l10n/ru.js b/lib/l10n/ru.js
index 2d2cbdb1d8f..85f11c1a5ea 100644
--- a/lib/l10n/ru.js
+++ b/lib/l10n/ru.js
@@ -81,7 +81,7 @@ OC.L10N.register(
"Failed to create file from template" : "Не удалось создать файл на основе шаблона",
"Templates" : "Шаблоны",
"File name is a reserved word" : "Имя файла является зарезервированным словом",
- "File name contains at least one invalid character" : "Имя файла содержит по крайней мере один некорректный символ",
+ "File name contains at least one invalid character" : "Имя файла содержит по крайней мере один недопустимый символ",
"File name is too long" : "Имя файла слишком длинное.",
"Dot files are not allowed" : "Файлы начинающиеся с точки не допускаются",
"Empty filename is not allowed" : "Пустое имя файла не допускается",
@@ -207,7 +207,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Приложение «%1$s» не может быть установлено, так как не удовлетворены следующие зависимости: %2$s",
"a safe home for all your data" : "надёжный дом для всех ваших данных",
"File is currently busy, please try again later" : "Файл в данный момент используется, повторите попытку позже.",
- "Cannot read file" : "Не удается прочитать файл",
"Application is not enabled" : "Приложение не разрешено",
"Authentication error" : "Ошибка аутентификации",
"Token expired. Please reload page." : "Токен просрочен. Перезагрузите страницу.",
@@ -220,7 +219,7 @@ OC.L10N.register(
"Cannot create \"data\" directory." : "Невозможно создать каталог «data».",
"This can usually be fixed by giving the web server write access to the root directory. See %s" : "Обычно это можно исправить, предоставив веб-серверу права на запись в корневой каталог. Обратитесь к %s",
"Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Разрешения обычно можно исправить, предоставив веб-серверу право на запись в корневой каталог. Обратитесь к %s.",
- "Your data directory is not writable." : "Каталог данных не доступен для записи.",
+ "Your data directory is not writable." : "Каталог данных недоступен для записи.",
"Setting locale to %s failed." : "Не удалось настроить локаль %s.",
"Please install one of these locales on your system and restart your web server." : "Установите один из этих языковых пакетов и перезапустите веб-сервер.",
"PHP module %s not installed." : "Не установлен PHP-модуль %s.",
@@ -235,6 +234,8 @@ OC.L10N.register(
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Возможно это вызвано кешем/ускорителем вроде Zend OPcache или eAccelerator.",
"PHP modules have been installed, but they are still listed as missing?" : "Модули PHP были установлены, но они все еще перечислены как недостающие?",
"Please ask your server administrator to restart the web server." : "Пожалуйста, попросите вашего администратора перезапустить веб-сервер.",
+ "The required %s config variable is not configured in the config.php file." : "Необходимая переменная %s не настроена в файле config.php.",
+ "Please ask your server administrator to check the Nextcloud configuration." : "Пожалуйста, попросите администратора вашего сервера проверить конфигурацию Nextcloud.",
"PostgreSQL >= 9 required." : "Требуется PostgreSQL версии 9 или более новый.",
"Please upgrade your database version." : "Обновите базу данных.",
"Your data directory is readable by other users." : "Каталог данных доступен для чтения другим пользователям.",
@@ -255,6 +256,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Хранилище временно недоступно",
"Storage connection timeout. %s" : "Истекло время ожидания подключения к хранилищу. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации.",
+ "Cannot read file" : "Не удается прочитать файл",
"Cannot write into \"config\" directory" : "Запись в каталог «config» невозможна",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации. Изучите %s.",
"Cannot write into \"apps\" directory" : "Запись в каталог «app» невозможна",
diff --git a/lib/l10n/ru.json b/lib/l10n/ru.json
index 9e6fdb6538e..e5e20754874 100644
--- a/lib/l10n/ru.json
+++ b/lib/l10n/ru.json
@@ -79,7 +79,7 @@
"Failed to create file from template" : "Не удалось создать файл на основе шаблона",
"Templates" : "Шаблоны",
"File name is a reserved word" : "Имя файла является зарезервированным словом",
- "File name contains at least one invalid character" : "Имя файла содержит по крайней мере один некорректный символ",
+ "File name contains at least one invalid character" : "Имя файла содержит по крайней мере один недопустимый символ",
"File name is too long" : "Имя файла слишком длинное.",
"Dot files are not allowed" : "Файлы начинающиеся с точки не допускаются",
"Empty filename is not allowed" : "Пустое имя файла не допускается",
@@ -205,7 +205,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Приложение «%1$s» не может быть установлено, так как не удовлетворены следующие зависимости: %2$s",
"a safe home for all your data" : "надёжный дом для всех ваших данных",
"File is currently busy, please try again later" : "Файл в данный момент используется, повторите попытку позже.",
- "Cannot read file" : "Не удается прочитать файл",
"Application is not enabled" : "Приложение не разрешено",
"Authentication error" : "Ошибка аутентификации",
"Token expired. Please reload page." : "Токен просрочен. Перезагрузите страницу.",
@@ -218,7 +217,7 @@
"Cannot create \"data\" directory." : "Невозможно создать каталог «data».",
"This can usually be fixed by giving the web server write access to the root directory. See %s" : "Обычно это можно исправить, предоставив веб-серверу права на запись в корневой каталог. Обратитесь к %s",
"Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Разрешения обычно можно исправить, предоставив веб-серверу право на запись в корневой каталог. Обратитесь к %s.",
- "Your data directory is not writable." : "Каталог данных не доступен для записи.",
+ "Your data directory is not writable." : "Каталог данных недоступен для записи.",
"Setting locale to %s failed." : "Не удалось настроить локаль %s.",
"Please install one of these locales on your system and restart your web server." : "Установите один из этих языковых пакетов и перезапустите веб-сервер.",
"PHP module %s not installed." : "Не установлен PHP-модуль %s.",
@@ -233,6 +232,8 @@
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Возможно это вызвано кешем/ускорителем вроде Zend OPcache или eAccelerator.",
"PHP modules have been installed, but they are still listed as missing?" : "Модули PHP были установлены, но они все еще перечислены как недостающие?",
"Please ask your server administrator to restart the web server." : "Пожалуйста, попросите вашего администратора перезапустить веб-сервер.",
+ "The required %s config variable is not configured in the config.php file." : "Необходимая переменная %s не настроена в файле config.php.",
+ "Please ask your server administrator to check the Nextcloud configuration." : "Пожалуйста, попросите администратора вашего сервера проверить конфигурацию Nextcloud.",
"PostgreSQL >= 9 required." : "Требуется PostgreSQL версии 9 или более новый.",
"Please upgrade your database version." : "Обновите базу данных.",
"Your data directory is readable by other users." : "Каталог данных доступен для чтения другим пользователям.",
@@ -253,6 +254,7 @@
"Storage is temporarily not available" : "Хранилище временно недоступно",
"Storage connection timeout. %s" : "Истекло время ожидания подключения к хранилищу. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации.",
+ "Cannot read file" : "Не удается прочитать файл",
"Cannot write into \"config\" directory" : "Запись в каталог «config» невозможна",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации. Изучите %s.",
"Cannot write into \"apps\" directory" : "Запись в каталог «app» невозможна",
diff --git a/lib/l10n/sc.js b/lib/l10n/sc.js
index c6e13e64a56..2417ed4b2f3 100644
--- a/lib/l10n/sc.js
+++ b/lib/l10n/sc.js
@@ -194,7 +194,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Non faghet a installare s'aplicatzione %1$s ca is dipendèntzias in fatu non sunt satisfatos:%2$s",
"a safe home for all your data" : "unu logu siguru pro totu is datos tuos",
"File is currently busy, please try again later" : "Pro immoe s'archìviu est impreadu, torra a proare a coa",
- "Cannot read file" : "Impossìbile a lèghere s'archìviu",
"Application is not enabled" : "S'aplicatzione no est ativada",
"Authentication error" : "Errore de autenticatzione",
"Token expired. Please reload page." : "Token iscadidu. Torra a carrigare sa pàgina.",
@@ -224,6 +223,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "S'archiviatzione no est disponìbile pro immoe.",
"Storage connection timeout. %s" : "Tempus de connessione a s'archiviatzione iscadidu. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Custu in generale si podet assentare dende a su serbidore atzessu a s'iscritura in sa cartella config.",
+ "Cannot read file" : "Impossìbile a lèghere s'archìviu",
"Cannot write into \"config\" directory" : "No faghet a iscriere in sa cartella \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Custu in generale si podet assentare dende a su serbidore atzessu a s'iscritura in sa cartella config. Càstia %s",
"Cannot write into \"apps\" directory" : "No faghet a iscriere in sa cartella \"apps\"",
diff --git a/lib/l10n/sc.json b/lib/l10n/sc.json
index 7f3eabbd6fd..482152a4e87 100644
--- a/lib/l10n/sc.json
+++ b/lib/l10n/sc.json
@@ -192,7 +192,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Non faghet a installare s'aplicatzione %1$s ca is dipendèntzias in fatu non sunt satisfatos:%2$s",
"a safe home for all your data" : "unu logu siguru pro totu is datos tuos",
"File is currently busy, please try again later" : "Pro immoe s'archìviu est impreadu, torra a proare a coa",
- "Cannot read file" : "Impossìbile a lèghere s'archìviu",
"Application is not enabled" : "S'aplicatzione no est ativada",
"Authentication error" : "Errore de autenticatzione",
"Token expired. Please reload page." : "Token iscadidu. Torra a carrigare sa pàgina.",
@@ -222,6 +221,7 @@
"Storage is temporarily not available" : "S'archiviatzione no est disponìbile pro immoe.",
"Storage connection timeout. %s" : "Tempus de connessione a s'archiviatzione iscadidu. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Custu in generale si podet assentare dende a su serbidore atzessu a s'iscritura in sa cartella config.",
+ "Cannot read file" : "Impossìbile a lèghere s'archìviu",
"Cannot write into \"config\" directory" : "No faghet a iscriere in sa cartella \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Custu in generale si podet assentare dende a su serbidore atzessu a s'iscritura in sa cartella config. Càstia %s",
"Cannot write into \"apps\" directory" : "No faghet a iscriere in sa cartella \"apps\"",
diff --git a/lib/l10n/sk.js b/lib/l10n/sk.js
index 9a9999f230b..c9bbfd28aa9 100644
--- a/lib/l10n/sk.js
+++ b/lib/l10n/sk.js
@@ -207,7 +207,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Aplikáciu \"%1$s\" nie je možné inštalovať, pretože nie sú splnené nasledovné závislosti: %2$s",
"a safe home for all your data" : "bezpečný domov pre všetky vaše dáta",
"File is currently busy, please try again later" : "Súbor sa práve používa, skúste prosím neskôr",
- "Cannot read file" : "Nemožno čítať súbor.",
"Application is not enabled" : "Aplikácia nie je zapnutá",
"Authentication error" : "Chyba autentifikácie",
"Token expired. Please reload page." : "Token vypršal. Obnovte, prosím, stránku.",
@@ -257,6 +256,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Úložisko je dočasne nedostupné",
"Storage connection timeout. %s" : "Vypršanie pripojenia k úložisku. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Toto sa zvyčajne dá opraviť poskytnutím práva webového servera na zápis do priečinka s nastaveniami.",
+ "Cannot read file" : "Nemožno čítať súbor.",
"Cannot write into \"config\" directory" : "Nie je možné zapisovať do priečinka \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "To je zvyčajne možné opraviť tým, že udelíte webovému serveru oprávnenie na zápis do adresára s konfiguráciou. Viď %s",
"Cannot write into \"apps\" directory" : "Nie je možné zapisovať do priečinka \"apps\"",
diff --git a/lib/l10n/sk.json b/lib/l10n/sk.json
index 4cc681cb466..bdc26a5cef4 100644
--- a/lib/l10n/sk.json
+++ b/lib/l10n/sk.json
@@ -205,7 +205,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Aplikáciu \"%1$s\" nie je možné inštalovať, pretože nie sú splnené nasledovné závislosti: %2$s",
"a safe home for all your data" : "bezpečný domov pre všetky vaše dáta",
"File is currently busy, please try again later" : "Súbor sa práve používa, skúste prosím neskôr",
- "Cannot read file" : "Nemožno čítať súbor.",
"Application is not enabled" : "Aplikácia nie je zapnutá",
"Authentication error" : "Chyba autentifikácie",
"Token expired. Please reload page." : "Token vypršal. Obnovte, prosím, stránku.",
@@ -255,6 +254,7 @@
"Storage is temporarily not available" : "Úložisko je dočasne nedostupné",
"Storage connection timeout. %s" : "Vypršanie pripojenia k úložisku. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Toto sa zvyčajne dá opraviť poskytnutím práva webového servera na zápis do priečinka s nastaveniami.",
+ "Cannot read file" : "Nemožno čítať súbor.",
"Cannot write into \"config\" directory" : "Nie je možné zapisovať do priečinka \"config\"",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "To je zvyčajne možné opraviť tým, že udelíte webovému serveru oprávnenie na zápis do adresára s konfiguráciou. Viď %s",
"Cannot write into \"apps\" directory" : "Nie je možné zapisovať do priečinka \"apps\"",
diff --git a/lib/l10n/sl.js b/lib/l10n/sl.js
index 6bf62591ffd..eb2fe3434ba 100644
--- a/lib/l10n/sl.js
+++ b/lib/l10n/sl.js
@@ -200,7 +200,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Programa »%1$s« ni mogoče namestiti zaradi nerešenih odvisnosti: %2$s",
"a safe home for all your data" : "Varno okolje za vaše podatke!",
"File is currently busy, please try again later" : "Datoteka je trenutno v uporabi. Poskusite znova kasneje.",
- "Cannot read file" : "Datoteke ni mogoče prebrati.",
"Application is not enabled" : "Program ni omogočen",
"Authentication error" : "Napaka overjanja",
"Token expired. Please reload page." : "Žeton je pretekel. Stran je treba ponovno naložiti.",
@@ -230,6 +229,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Shramba trenutno ni na voljo",
"Storage connection timeout. %s" : "Povezava do shrambe je časovno potekla. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Napako je mogoče odpraviti z dodelitvijo dovoljenja spletnemu strežniku za pisanje v nastavitveno mapo.",
+ "Cannot read file" : "Datoteke ni mogoče prebrati.",
"Cannot write into \"config\" directory" : "Mapa »config« nima nastavljenih ustreznih dovoljenj za pisanje!",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Napako je mogoče odpraviti z dodelitvijo dovoljenja spletnemu strežniku za pisanje v nastavitveno mapo. Poglejte %s",
"Cannot write into \"apps\" directory" : "V mapo »apps« ni mogoče zapisovati!",
diff --git a/lib/l10n/sl.json b/lib/l10n/sl.json
index ecafd64721c..175d8246b3c 100644
--- a/lib/l10n/sl.json
+++ b/lib/l10n/sl.json
@@ -198,7 +198,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Programa »%1$s« ni mogoče namestiti zaradi nerešenih odvisnosti: %2$s",
"a safe home for all your data" : "Varno okolje za vaše podatke!",
"File is currently busy, please try again later" : "Datoteka je trenutno v uporabi. Poskusite znova kasneje.",
- "Cannot read file" : "Datoteke ni mogoče prebrati.",
"Application is not enabled" : "Program ni omogočen",
"Authentication error" : "Napaka overjanja",
"Token expired. Please reload page." : "Žeton je pretekel. Stran je treba ponovno naložiti.",
@@ -228,6 +227,7 @@
"Storage is temporarily not available" : "Shramba trenutno ni na voljo",
"Storage connection timeout. %s" : "Povezava do shrambe je časovno potekla. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Napako je mogoče odpraviti z dodelitvijo dovoljenja spletnemu strežniku za pisanje v nastavitveno mapo.",
+ "Cannot read file" : "Datoteke ni mogoče prebrati.",
"Cannot write into \"config\" directory" : "Mapa »config« nima nastavljenih ustreznih dovoljenj za pisanje!",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Napako je mogoče odpraviti z dodelitvijo dovoljenja spletnemu strežniku za pisanje v nastavitveno mapo. Poglejte %s",
"Cannot write into \"apps\" directory" : "V mapo »apps« ni mogoče zapisovati!",
diff --git a/lib/l10n/sv.js b/lib/l10n/sv.js
index 901bf146efe..cf59cbb3954 100644
--- a/lib/l10n/sv.js
+++ b/lib/l10n/sv.js
@@ -206,7 +206,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Appen \"%1$s\" kan inte installeras eftersom följande beroenden inte är uppfyllda: %2$s",
"a safe home for all your data" : "ett säkert hem för all din data",
"File is currently busy, please try again later" : "Filen är för tillfället upptagen, försök igen senare",
- "Cannot read file" : "Kan inte läsa fil",
"Application is not enabled" : "Applikationen är inte aktiverad",
"Authentication error" : "Fel vid autentisering",
"Token expired. Please reload page." : "Token har löpt ut. Uppdatera sidan.",
@@ -236,6 +235,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Lagringsutrymme är för tillfället inte tillgängligt",
"Storage connection timeout. %s" : "Lagringsutrymme lyckas inte ansluta \"timeout\". %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Detta kan vanligtvis åtgärdas genom att ge webbservern skrivåtkomst till config-katalogen.",
+ "Cannot read file" : "Kan inte läsa fil",
"Cannot write into \"config\" directory" : "Kan inte skriva till \"config\" katalogen",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Detta kan vanligtvis åtgärda genom att ge webbservern skrivåtkomst till konfigureringsmappen. Se %s",
"Cannot write into \"apps\" directory" : "Kan inte skriva till \"apps\" katalogen!",
diff --git a/lib/l10n/sv.json b/lib/l10n/sv.json
index 8bce5388bc6..4181ff7620b 100644
--- a/lib/l10n/sv.json
+++ b/lib/l10n/sv.json
@@ -204,7 +204,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Appen \"%1$s\" kan inte installeras eftersom följande beroenden inte är uppfyllda: %2$s",
"a safe home for all your data" : "ett säkert hem för all din data",
"File is currently busy, please try again later" : "Filen är för tillfället upptagen, försök igen senare",
- "Cannot read file" : "Kan inte läsa fil",
"Application is not enabled" : "Applikationen är inte aktiverad",
"Authentication error" : "Fel vid autentisering",
"Token expired. Please reload page." : "Token har löpt ut. Uppdatera sidan.",
@@ -234,6 +233,7 @@
"Storage is temporarily not available" : "Lagringsutrymme är för tillfället inte tillgängligt",
"Storage connection timeout. %s" : "Lagringsutrymme lyckas inte ansluta \"timeout\". %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Detta kan vanligtvis åtgärdas genom att ge webbservern skrivåtkomst till config-katalogen.",
+ "Cannot read file" : "Kan inte läsa fil",
"Cannot write into \"config\" directory" : "Kan inte skriva till \"config\" katalogen",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Detta kan vanligtvis åtgärda genom att ge webbservern skrivåtkomst till konfigureringsmappen. Se %s",
"Cannot write into \"apps\" directory" : "Kan inte skriva till \"apps\" katalogen!",
diff --git a/lib/l10n/th.js b/lib/l10n/th.js
index 687a78ecf07..c0d7cad0c25 100644
--- a/lib/l10n/th.js
+++ b/lib/l10n/th.js
@@ -127,7 +127,6 @@ OC.L10N.register(
"User disabled" : "ผู้ใช้ถูกปิดใช้งาน",
"a safe home for all your data" : "บ้านที่ปลอดภัยสำหรับข้อมูลของคุณ",
"File is currently busy, please try again later" : "ขณะนี้ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง",
- "Cannot read file" : "ไม่สามารถอ่านไฟล์",
"Application is not enabled" : "แอพพลิเคชั่นดังกล่าวยังไม่ได้เปิดใช้งาน",
"Authentication error" : "เกิดข้อผิดพลาดในสิทธิ์การเข้าใช้งาน",
"Token expired. Please reload page." : "รหัสยืนยันความถูกต้องหมดอายุ กรุณาโหลดหน้าเว็บใหม่",
@@ -147,6 +146,7 @@ OC.L10N.register(
"Storage connection error. %s" : "ข้อผิดพลาดการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s",
"Storage is temporarily not available" : "พื้นที่จัดเก็บข้อมูลไม่สามารถใช้งานได้ชั่วคราว",
"Storage connection timeout. %s" : "หมดเวลาการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s",
+ "Cannot read file" : "ไม่สามารถอ่านไฟล์",
"Cannot write into \"config\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"config\"",
"Cannot write into \"apps\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"apps\"",
"Setting locale to %s failed" : "ตั้งค่าตำแหน่งที่ตั้งเป็น %s ล้มเหลว",
diff --git a/lib/l10n/th.json b/lib/l10n/th.json
index 70eb589442c..7c08e27d33d 100644
--- a/lib/l10n/th.json
+++ b/lib/l10n/th.json
@@ -125,7 +125,6 @@
"User disabled" : "ผู้ใช้ถูกปิดใช้งาน",
"a safe home for all your data" : "บ้านที่ปลอดภัยสำหรับข้อมูลของคุณ",
"File is currently busy, please try again later" : "ขณะนี้ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง",
- "Cannot read file" : "ไม่สามารถอ่านไฟล์",
"Application is not enabled" : "แอพพลิเคชั่นดังกล่าวยังไม่ได้เปิดใช้งาน",
"Authentication error" : "เกิดข้อผิดพลาดในสิทธิ์การเข้าใช้งาน",
"Token expired. Please reload page." : "รหัสยืนยันความถูกต้องหมดอายุ กรุณาโหลดหน้าเว็บใหม่",
@@ -145,6 +144,7 @@
"Storage connection error. %s" : "ข้อผิดพลาดการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s",
"Storage is temporarily not available" : "พื้นที่จัดเก็บข้อมูลไม่สามารถใช้งานได้ชั่วคราว",
"Storage connection timeout. %s" : "หมดเวลาการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s",
+ "Cannot read file" : "ไม่สามารถอ่านไฟล์",
"Cannot write into \"config\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"config\"",
"Cannot write into \"apps\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"apps\"",
"Setting locale to %s failed" : "ตั้งค่าตำแหน่งที่ตั้งเป็น %s ล้มเหลว",
diff --git a/lib/l10n/tr.js b/lib/l10n/tr.js
index f6262e13b40..53de08e4f73 100644
--- a/lib/l10n/tr.js
+++ b/lib/l10n/tr.js
@@ -206,11 +206,11 @@ OC.L10N.register(
"Login canceled by app" : "Oturum açma uygulama tarafından iptal edildi",
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "\"%1$s\" uygulaması, şu gereklilikler sağlanmadığı için kurulamıyor: %2$s",
"a safe home for all your data" : "verileriniz için güvenli bir barınak",
- "File is currently busy, please try again later" : "Dosya şu anda meşgul, lütfen daha sonra deneyin",
- "Cannot read file" : "Dosya okunamadı",
+ "File is currently busy, please try again later" : "Dosya şu anda meşgul. Lütfen bir süre sonra yeniden deneyin",
+ "Cannot download file" : "Dosya indirilemedi",
"Application is not enabled" : "Uygulama etkinleştirilmemiş",
"Authentication error" : "Kimlik doğrulama sorunu",
- "Token expired. Please reload page." : "Kodun süresi dolmuş. Lütfen sayfayı yenileyin.",
+ "Token expired. Please reload page." : "Kodun geçerlilik süresi dolmuş. Lütfen sayfayı yenileyin.",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Herhangi bir veritabanı sürücüsü (sqlite, mysql ya da postgresql) kurulmamış.",
"Cannot write into \"config\" directory." : "\"config\" klasörüne yazılamadı.",
"This can usually be fixed by giving the web server write access to the config directory. See %s" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir. %s bölümüne bakın",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "Depolama geçici olarak kullanılamıyor",
"Storage connection timeout. %s" : "Depolama bağlantısı zaman aşımı. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir.",
+ "Cannot read file" : "Dosya okunamadı",
"Cannot write into \"config\" directory" : "\"config\" klasörüne yazılamıyor",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir. %s bölümüne bakın",
"Cannot write into \"apps\" directory" : "\"apps\" klasörüne yazılamıyor",
diff --git a/lib/l10n/tr.json b/lib/l10n/tr.json
index 894fca744d5..eb666c3b364 100644
--- a/lib/l10n/tr.json
+++ b/lib/l10n/tr.json
@@ -204,11 +204,11 @@
"Login canceled by app" : "Oturum açma uygulama tarafından iptal edildi",
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "\"%1$s\" uygulaması, şu gereklilikler sağlanmadığı için kurulamıyor: %2$s",
"a safe home for all your data" : "verileriniz için güvenli bir barınak",
- "File is currently busy, please try again later" : "Dosya şu anda meşgul, lütfen daha sonra deneyin",
- "Cannot read file" : "Dosya okunamadı",
+ "File is currently busy, please try again later" : "Dosya şu anda meşgul. Lütfen bir süre sonra yeniden deneyin",
+ "Cannot download file" : "Dosya indirilemedi",
"Application is not enabled" : "Uygulama etkinleştirilmemiş",
"Authentication error" : "Kimlik doğrulama sorunu",
- "Token expired. Please reload page." : "Kodun süresi dolmuş. Lütfen sayfayı yenileyin.",
+ "Token expired. Please reload page." : "Kodun geçerlilik süresi dolmuş. Lütfen sayfayı yenileyin.",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Herhangi bir veritabanı sürücüsü (sqlite, mysql ya da postgresql) kurulmamış.",
"Cannot write into \"config\" directory." : "\"config\" klasörüne yazılamadı.",
"This can usually be fixed by giving the web server write access to the config directory. See %s" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir. %s bölümüne bakın",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "Depolama geçici olarak kullanılamıyor",
"Storage connection timeout. %s" : "Depolama bağlantısı zaman aşımı. %s",
"This can usually be fixed by giving the webserver write access to the config directory." : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir.",
+ "Cannot read file" : "Dosya okunamadı",
"Cannot write into \"config\" directory" : "\"config\" klasörüne yazılamıyor",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir. %s bölümüne bakın",
"Cannot write into \"apps\" directory" : "\"apps\" klasörüne yazılamıyor",
diff --git a/lib/l10n/uk.js b/lib/l10n/uk.js
index 8a59156aa77..8f204020c65 100644
--- a/lib/l10n/uk.js
+++ b/lib/l10n/uk.js
@@ -12,8 +12,10 @@ OC.L10N.register(
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s та %5$s",
"PHP %s or higher is required." : "Необхідно PHP %s або вище",
"PHP with a version lower than %s is required." : "Потрібна версія PHP нижче %s ",
+ "%sbit or higher PHP required." : "%sнеобхідний PHP біт або вище.",
"The command line tool %s could not be found" : "Утиліту командного рядка %s не знайдено",
"The library %s is not available." : "Бібліотека %s недоступна.",
+ "Server version %s or higher is required." : "Потрібна версія сервера %s або вище.",
"Remote wipe started" : "Розпочато віддалене стирання",
"Remote wipe finished" : "Віддалене стирання завершено",
"Authentication" : "Автентифікація",
@@ -27,9 +29,11 @@ OC.L10N.register(
"_%n day ago_::_%n days ago_" : ["%n день тому","%n днів тому","%n днів тому","%n днів тому"],
"next month" : "наступноого місяця",
"last month" : "минулого місяця",
+ "_%n month ago_::_%n months ago_" : ["%n місяць тому","%n місяць тому","%n місяців тому","%n місяців тому"],
"next year" : "наступного року",
"last year" : "минулого року",
"_%n year ago_::_%n years ago_" : ["%n рік тому","%n років тому","%n років тому","%n років тому"],
+ "_%n hour ago_::_%n hours ago_" : ["%nгодину тому","%n годин тому","%n годин тому","%n годин тому"],
"in a few seconds" : "через кілька секунд",
"seconds ago" : "секунди тому",
"Empty file" : "Порожній файл",
@@ -146,6 +150,7 @@ OC.L10N.register(
"PHP module %s not installed." : "%s модуль PHP не встановлено.",
"Please ask your server administrator to install the module." : "Будь ласка, зверніться до адміністратора, щоб встановити модуль.",
"PHP setting \"%s\" is not set to \"%s\"." : "Параметр PHP \"%s\" не встановлено в \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Налаштування цього параметра у php.ini змусить Nextcloud запуститися знову",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "Необхідно libxml2 версії принаймні 2.7.0. На разі встановлена %s.",
"To fix this issue update your libxml2 version and restart your web server." : "Що виправити це оновіть версію libxml2 та перезапустіть веб-сервер.",
"PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Схоже, що PHP налаштовано на вичищення блоків вбудованої документації. Це зробить кілька основних додатків недоступними.",
diff --git a/lib/l10n/uk.json b/lib/l10n/uk.json
index 1d63813505d..24ae8d496ba 100644
--- a/lib/l10n/uk.json
+++ b/lib/l10n/uk.json
@@ -10,8 +10,10 @@
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s та %5$s",
"PHP %s or higher is required." : "Необхідно PHP %s або вище",
"PHP with a version lower than %s is required." : "Потрібна версія PHP нижче %s ",
+ "%sbit or higher PHP required." : "%sнеобхідний PHP біт або вище.",
"The command line tool %s could not be found" : "Утиліту командного рядка %s не знайдено",
"The library %s is not available." : "Бібліотека %s недоступна.",
+ "Server version %s or higher is required." : "Потрібна версія сервера %s або вище.",
"Remote wipe started" : "Розпочато віддалене стирання",
"Remote wipe finished" : "Віддалене стирання завершено",
"Authentication" : "Автентифікація",
@@ -25,9 +27,11 @@
"_%n day ago_::_%n days ago_" : ["%n день тому","%n днів тому","%n днів тому","%n днів тому"],
"next month" : "наступноого місяця",
"last month" : "минулого місяця",
+ "_%n month ago_::_%n months ago_" : ["%n місяць тому","%n місяць тому","%n місяців тому","%n місяців тому"],
"next year" : "наступного року",
"last year" : "минулого року",
"_%n year ago_::_%n years ago_" : ["%n рік тому","%n років тому","%n років тому","%n років тому"],
+ "_%n hour ago_::_%n hours ago_" : ["%nгодину тому","%n годин тому","%n годин тому","%n годин тому"],
"in a few seconds" : "через кілька секунд",
"seconds ago" : "секунди тому",
"Empty file" : "Порожній файл",
@@ -144,6 +148,7 @@
"PHP module %s not installed." : "%s модуль PHP не встановлено.",
"Please ask your server administrator to install the module." : "Будь ласка, зверніться до адміністратора, щоб встановити модуль.",
"PHP setting \"%s\" is not set to \"%s\"." : "Параметр PHP \"%s\" не встановлено в \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Налаштування цього параметра у php.ini змусить Nextcloud запуститися знову",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "Необхідно libxml2 версії принаймні 2.7.0. На разі встановлена %s.",
"To fix this issue update your libxml2 version and restart your web server." : "Що виправити це оновіть версію libxml2 та перезапустіть веб-сервер.",
"PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Схоже, що PHP налаштовано на вичищення блоків вбудованої документації. Це зробить кілька основних додатків недоступними.",
diff --git a/lib/l10n/zh_CN.js b/lib/l10n/zh_CN.js
index 45137513e09..ba27df9184b 100644
--- a/lib/l10n/zh_CN.js
+++ b/lib/l10n/zh_CN.js
@@ -206,7 +206,6 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "应用 \"%1$s\" 无法安装,因为不能满足以下依赖: %2$s",
"a safe home for all your data" : "给您所有数据一个安全的家",
"File is currently busy, please try again later" : "文件当前正忙,请稍后再试",
- "Cannot read file" : "无法读取文件",
"Application is not enabled" : "应用程序未启用",
"Authentication error" : "认证出错",
"Token expired. Please reload page." : "Token 过期,请刷新页面。",
@@ -237,6 +236,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "存储暂时不可用",
"Storage connection timeout. %s" : "存储连接超时。%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "通常可以通过授予 Web 服务器对 config 目录的写访问权限来解决此问题。",
+ "Cannot read file" : "无法读取文件",
"Cannot write into \"config\" directory" : "无法写入“config”目录",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "这个通常可以通过赋予写入权限到 config 目录来修复。查看:%s",
"Cannot write into \"apps\" directory" : "无法写入“apps”目录",
diff --git a/lib/l10n/zh_CN.json b/lib/l10n/zh_CN.json
index afd4a0e70dc..f05d7446af2 100644
--- a/lib/l10n/zh_CN.json
+++ b/lib/l10n/zh_CN.json
@@ -204,7 +204,6 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "应用 \"%1$s\" 无法安装,因为不能满足以下依赖: %2$s",
"a safe home for all your data" : "给您所有数据一个安全的家",
"File is currently busy, please try again later" : "文件当前正忙,请稍后再试",
- "Cannot read file" : "无法读取文件",
"Application is not enabled" : "应用程序未启用",
"Authentication error" : "认证出错",
"Token expired. Please reload page." : "Token 过期,请刷新页面。",
@@ -235,6 +234,7 @@
"Storage is temporarily not available" : "存储暂时不可用",
"Storage connection timeout. %s" : "存储连接超时。%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "通常可以通过授予 Web 服务器对 config 目录的写访问权限来解决此问题。",
+ "Cannot read file" : "无法读取文件",
"Cannot write into \"config\" directory" : "无法写入“config”目录",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "这个通常可以通过赋予写入权限到 config 目录来修复。查看:%s",
"Cannot write into \"apps\" directory" : "无法写入“apps”目录",
diff --git a/lib/l10n/zh_HK.js b/lib/l10n/zh_HK.js
index cbc133fbe3e..b83d186a24d 100644
--- a/lib/l10n/zh_HK.js
+++ b/lib/l10n/zh_HK.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "應用程式 \"%1$s\" 無法被安裝,缺少下列所需元件: %2$s",
"a safe home for all your data" : "您資料的安全屋",
"File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試",
- "Cannot read file" : "無法讀取檔案",
+ "Cannot download file" : "無法下載檔案",
"Application is not enabled" : "應用程式未啟用",
"Authentication error" : "認證錯誤",
"Token expired. Please reload page." : "Token 過期,請重新整理頁面。",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "儲存空間暫時無法使用",
"Storage connection timeout. %s" : "儲存空間連線逾時。%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題",
+ "Cannot read file" : "無法讀取檔案",
"Cannot write into \"config\" directory" : "無法寫入 config 目錄",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題,詳見 %s",
"Cannot write into \"apps\" directory" : "無法寫入 apps 目錄",
diff --git a/lib/l10n/zh_HK.json b/lib/l10n/zh_HK.json
index 36fdc2cbaf7..b9335c27727 100644
--- a/lib/l10n/zh_HK.json
+++ b/lib/l10n/zh_HK.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "應用程式 \"%1$s\" 無法被安裝,缺少下列所需元件: %2$s",
"a safe home for all your data" : "您資料的安全屋",
"File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試",
- "Cannot read file" : "無法讀取檔案",
+ "Cannot download file" : "無法下載檔案",
"Application is not enabled" : "應用程式未啟用",
"Authentication error" : "認證錯誤",
"Token expired. Please reload page." : "Token 過期,請重新整理頁面。",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "儲存空間暫時無法使用",
"Storage connection timeout. %s" : "儲存空間連線逾時。%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題",
+ "Cannot read file" : "無法讀取檔案",
"Cannot write into \"config\" directory" : "無法寫入 config 目錄",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題,詳見 %s",
"Cannot write into \"apps\" directory" : "無法寫入 apps 目錄",
diff --git a/lib/l10n/zh_TW.js b/lib/l10n/zh_TW.js
index d8c668d8f41..7d04bd7d3e7 100644
--- a/lib/l10n/zh_TW.js
+++ b/lib/l10n/zh_TW.js
@@ -207,7 +207,7 @@ OC.L10N.register(
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "應用程式 \"%1$s\" 無法被安裝,缺少下列所需元件: %2$s",
"a safe home for all your data" : "您資料的安全屋",
"File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試",
- "Cannot read file" : "無法讀取檔案",
+ "Cannot download file" : "無法下載檔案",
"Application is not enabled" : "應用程式未啟用",
"Authentication error" : "認證錯誤",
"Token expired. Please reload page." : "Token 過期,請重新整理頁面。",
@@ -257,6 +257,7 @@ OC.L10N.register(
"Storage is temporarily not available" : "儲存空間暫時無法使用",
"Storage connection timeout. %s" : "儲存空間連線逾時。%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題",
+ "Cannot read file" : "無法讀取檔案",
"Cannot write into \"config\" directory" : "無法寫入 config 目錄",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題,詳見 %s",
"Cannot write into \"apps\" directory" : "無法寫入 apps 目錄",
diff --git a/lib/l10n/zh_TW.json b/lib/l10n/zh_TW.json
index feac90fc2d9..c522a9f7277 100644
--- a/lib/l10n/zh_TW.json
+++ b/lib/l10n/zh_TW.json
@@ -205,7 +205,7 @@
"App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "應用程式 \"%1$s\" 無法被安裝,缺少下列所需元件: %2$s",
"a safe home for all your data" : "您資料的安全屋",
"File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試",
- "Cannot read file" : "無法讀取檔案",
+ "Cannot download file" : "無法下載檔案",
"Application is not enabled" : "應用程式未啟用",
"Authentication error" : "認證錯誤",
"Token expired. Please reload page." : "Token 過期,請重新整理頁面。",
@@ -255,6 +255,7 @@
"Storage is temporarily not available" : "儲存空間暫時無法使用",
"Storage connection timeout. %s" : "儲存空間連線逾時。%s",
"This can usually be fixed by giving the webserver write access to the config directory." : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題",
+ "Cannot read file" : "無法讀取檔案",
"Cannot write into \"config\" directory" : "無法寫入 config 目錄",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題,詳見 %s",
"Cannot write into \"apps\" directory" : "無法寫入 apps 目錄",
diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php
index bdf33d73c29..20e0add1ccb 100644
--- a/lib/private/Accounts/AccountManager.php
+++ b/lib/private/Accounts/AccountManager.php
@@ -42,7 +42,7 @@ use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use OC\Profile\TProfileHelper;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCA\Settings\BackgroundJobs\VerifyUserData;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php
index f282baee146..2a0e8f53b14 100644
--- a/lib/private/AllConfig.php
+++ b/lib/private/AllConfig.php
@@ -32,7 +32,7 @@
*/
namespace OC;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection;
@@ -353,8 +353,8 @@ class AllConfig implements IConfig {
$qb = $this->connection->getQueryBuilder();
$qb->delete('preferences')
->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
- ->where($qb->expr()->eq('appid', $qb->createNamedParameter($appName, IQueryBuilder::PARAM_STR)))
- ->where($qb->expr()->eq('configkey', $qb->createNamedParameter($key, IQueryBuilder::PARAM_STR)))
+ ->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName, IQueryBuilder::PARAM_STR)))
+ ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key, IQueryBuilder::PARAM_STR)))
->executeStatement();
if (isset($this->userCache[$userId][$appName])) {
diff --git a/lib/private/App/AppStore/Bundles/HubBundle.php b/lib/private/App/AppStore/Bundles/HubBundle.php
index a52de1dfbd4..d5d236a1855 100644
--- a/lib/private/App/AppStore/Bundles/HubBundle.php
+++ b/lib/private/App/AppStore/Bundles/HubBundle.php
@@ -39,8 +39,8 @@ class HubBundle extends Bundle {
'mail',
];
- $architecture = php_uname('m');
- if (PHP_OS_FAMILY === 'Linux' && in_array($architecture, ['x86_64', 'aarch64'])) {
+ $architecture = function_exists('php_uname') ? php_uname('m') : null;
+ if (isset($architecture) && PHP_OS_FAMILY === 'Linux' && in_array($architecture, ['x86_64', 'aarch64'])) {
$hubApps[] = 'richdocuments';
$hubApps[] = 'richdocumentscode' . ($architecture === 'aarch64' ? '_arm64' : '');
}
diff --git a/lib/private/App/CompareVersion.php b/lib/private/App/CompareVersion.php
index d155945fff1..a349c7aa6f2 100644
--- a/lib/private/App/CompareVersion.php
+++ b/lib/private/App/CompareVersion.php
@@ -41,7 +41,7 @@ class CompareVersion {
* so '13.0.1', '13.0' and '13' are valid.
*
* @param string $actual version as major.minor.patch notation
- * @param string $required version where major is requried and minor and patch are optional
+ * @param string $required version where major is required and minor and patch are optional
* @param string $comparator passed to `version_compare`
* @return bool whether the requirement is fulfilled
* @throws InvalidArgumentException if versions specified in an invalid format
diff --git a/lib/private/App/Platform.php b/lib/private/App/Platform.php
index 12097abbc78..01bf6748654 100644
--- a/lib/private/App/Platform.php
+++ b/lib/private/App/Platform.php
@@ -26,6 +26,7 @@
namespace OC\App;
use OCP\IConfig;
+use OCP\IBinaryFinder;
/**
* Class Platform
@@ -35,40 +36,26 @@ use OCP\IConfig;
* @package OC\App
*/
class Platform {
+ private IConfig $config;
- /**
- * @param IConfig $config
- */
public function __construct(IConfig $config) {
$this->config = $config;
}
- /**
- * @return string
- */
- public function getPhpVersion() {
+ public function getPhpVersion(): string {
return phpversion();
}
- /**
- * @return int
- */
- public function getIntSize() {
+ public function getIntSize(): int {
return PHP_INT_SIZE;
}
- /**
- * @return string
- */
- public function getOcVersion() {
+ public function getOcVersion(): string {
$v = \OCP\Util::getVersion();
return implode('.', $v);
}
- /**
- * @return string
- */
- public function getDatabase() {
+ public function getDatabase(): string {
$dbType = $this->config->getSystemValue('dbtype', 'sqlite');
if ($dbType === 'sqlite3') {
$dbType = 'sqlite';
@@ -77,23 +64,18 @@ class Platform {
return $dbType;
}
- /**
- * @return string
- */
- public function getOS() {
+ public function getOS(): string {
return php_uname('s');
}
/**
* @param $command
- * @return bool
*/
- public function isCommandKnown($command) {
- $path = \OC_Helper::findBinaryPath($command);
- return ($path !== null);
+ public function isCommandKnown(string $command): bool {
+ return \OCP\Server::get(IBinaryFinder::class)->findBinaryPath($command) !== false;
}
- public function getLibraryVersion($name) {
+ public function getLibraryVersion(string $name): ?string {
$repo = new PlatformRepository();
return $repo->findLibrary($name);
}
diff --git a/lib/private/App/PlatformRepository.php b/lib/private/App/PlatformRepository.php
index 94fac5260e1..4166c2ead03 100644
--- a/lib/private/App/PlatformRepository.php
+++ b/lib/private/App/PlatformRepository.php
@@ -31,11 +31,13 @@ namespace OC\App;
* @package OC\App
*/
class PlatformRepository {
+ private array $packages;
+
public function __construct() {
$this->packages = $this->initialize();
}
- protected function initialize() {
+ protected function initialize(): array {
$loadedExtensions = get_loaded_extensions();
$packages = [];
@@ -121,15 +123,11 @@ class PlatformRepository {
return $packages;
}
- private function buildPackageName($name) {
+ private function buildPackageName(string $name): string {
return str_replace(' ', '-', $name);
}
- /**
- * @param $name
- * @return string
- */
- public function findLibrary($name) {
+ public function findLibrary(string $name): ?string {
$extName = $this->buildPackageName($name);
if (isset($this->packages[$extName])) {
return $this->packages[$extName];
@@ -137,19 +135,17 @@ class PlatformRepository {
return null;
}
- private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
+ private static string $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
/**
* Normalizes a version string to be able to perform comparisons on it
*
* https://github.com/composer/composer/blob/master/src/Composer/Package/Version/VersionParser.php#L94
*
- * @param string $version
* @param string $fullVersion optional complete version string to give more context
* @throws \UnexpectedValueException
- * @return string
*/
- public function normalizeVersion($version, $fullVersion = null) {
+ public function normalizeVersion(string $version, ?string $fullVersion = null): string {
$version = trim($version);
if (null === $fullVersion) {
$fullVersion = $version;
@@ -204,10 +200,7 @@ class PlatformRepository {
throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
}
- /**
- * @param string $stability
- */
- private function expandStability($stability) {
+ private function expandStability(string $stability): string {
$stability = strtolower($stability);
switch ($stability) {
case 'a':
diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php
index feebb32d5bc..170acba0689 100644
--- a/lib/private/AppFramework/App.php
+++ b/lib/private/AppFramework/App.php
@@ -237,8 +237,6 @@ class App {
/**
* Shortcut for calling a controller method and printing the result.
* Similar to App:main except that no headers will be sent.
- * This should be used for example when registering sections via
- * \OC\AppFramework\Core\API::registerAdmin()
*
* @param string $controllerName the name of the controller under which it is
* stored in the DI container
diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
index 8f6aff228e1..3ade98e334f 100644
--- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php
+++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
@@ -32,6 +32,7 @@ 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\Talk\ITalkBackend;
use RuntimeException;
use function array_shift;
@@ -121,6 +122,12 @@ class RegistrationContext {
/** @var ServiceRegistration<ICalendarProvider>[] */
private $calendarProviders = [];
+ /** @var ServiceRegistration<IReferenceProvider>[] */
+ private array $referenceProviders = [];
+
+ /** @var ParameterRegistration[] */
+ private $sensitiveMethods = [];
+
/** @var LoggerInterface */
private $logger;
@@ -270,6 +277,13 @@ class RegistrationContext {
);
}
+ public function registerReferenceProvider(string $class): void {
+ $this->context->registerReferenceProvider(
+ $this->appId,
+ $class
+ );
+ }
+
public function registerProfileLinkAction(string $actionClass): void {
$this->context->registerProfileLinkAction(
$this->appId,
@@ -304,6 +318,14 @@ class RegistrationContext {
$migratorClass
);
}
+
+ public function registerSensitiveMethods(string $class, array $methods): void {
+ $this->context->registerSensitiveMethods(
+ $this->appId,
+ $class,
+ $methods
+ );
+ }
};
}
@@ -387,6 +409,10 @@ class RegistrationContext {
$this->calendarProviders[] = new ServiceRegistration($appId, $class);
}
+ public function registerReferenceProvider(string $appId, string $class): void {
+ $this->referenceProviders[] = new ServiceRegistration($appId, $class);
+ }
+
/**
* @psalm-param class-string<ILinkAction> $actionClass
*/
@@ -430,6 +456,11 @@ class RegistrationContext {
$this->userMigrators[] = new ServiceRegistration($appId, $migratorClass);
}
+ public function registerSensitiveMethods(string $appId, string $class, array $methods): void {
+ $methods = array_filter($methods, 'is_string');
+ $this->sensitiveMethods[] = new ParameterRegistration($appId, $class, $methods);
+ }
+
/**
* @param App[] $apps
*/
@@ -676,6 +707,13 @@ class RegistrationContext {
}
/**
+ * @return ServiceRegistration<IReferenceProvider>[]
+ */
+ public function getReferenceProviders(): array {
+ return $this->referenceProviders;
+ }
+
+ /**
* @return ServiceRegistration<ILinkAction>[]
*/
public function getProfileLinkActions(): array {
@@ -712,4 +750,11 @@ class RegistrationContext {
public function getUserMigrators(): array {
return $this->userMigrators;
}
+
+ /**
+ * @return ParameterRegistration[]
+ */
+ public function getSensitiveMethods(): array {
+ return $this->sensitiveMethods;
+ }
}
diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php
index 21d61bc95aa..c1a203a7165 100644
--- a/lib/private/AppFramework/Http/Dispatcher.php
+++ b/lib/private/AppFramework/Http/Dispatcher.php
@@ -118,7 +118,7 @@ class Dispatcher {
$out = [null, [], null];
try {
- // prefill reflector with everything thats needed for the
+ // prefill reflector with everything that's needed for the
// middlewares
$this->reflector->reflect($controller, $methodName);
@@ -156,7 +156,7 @@ class Dispatcher {
// if an exception appears, the middleware checks if it can handle the
// exception and creates a response. If no response is created, it is
- // assumed that theres no middleware who can handle it and the error is
+ // assumed that there's no middleware who can handle it and the error is
// thrown again
} catch (\Exception $exception) {
$response = $this->middlewareDispatcher->afterException(
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index 010d889070e..496a845dd4a 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -25,6 +25,7 @@ declare(strict_types=1);
* @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>
*
* @license AGPL-3.0
*
@@ -50,6 +51,7 @@ use OCP\IConfig;
use OCP\IRequest;
use OCP\IRequestId;
use OCP\Security\ICrypto;
+use Symfony\Component\HttpFoundation\IpUtils;
/**
* Class for accessing variables in the request.
@@ -342,7 +344,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
/**
* Returns all params that were received, be it from the request
- * (as GET or POST) or throuh the URL by the route
+ * (as GET or POST) or through the URL by the route
* @return array the array with all parameters
*/
public function getParams(): array {
@@ -573,41 +575,12 @@ class Request implements \ArrayAccess, \Countable, IRequest {
}
/**
- * Checks if given $remoteAddress matches given $trustedProxy.
- * If $trustedProxy is an IPv4 IP range given in CIDR notation, true will be returned if
- * $remoteAddress is an IPv4 address within that IP range.
- * Otherwise $remoteAddress will be compared to $trustedProxy literally and the result
- * will be returned.
- * @return boolean true if $remoteAddress matches $trustedProxy, false otherwise
- */
- protected function matchesTrustedProxy($trustedProxy, $remoteAddress) {
- $cidrre = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2})$/';
-
- if (preg_match($cidrre, $trustedProxy, $match)) {
- $net = $match[1];
- $shiftbits = min(32, max(0, 32 - intval($match[2])));
- $netnum = ip2long($net) >> $shiftbits;
- $ipnum = ip2long($remoteAddress) >> $shiftbits;
-
- return $ipnum === $netnum;
- }
-
- return $trustedProxy === $remoteAddress;
- }
-
- /**
* Checks if given $remoteAddress matches any entry in the given array $trustedProxies.
* For details regarding what "match" means, refer to `matchesTrustedProxy`.
* @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise
*/
protected function isTrustedProxy($trustedProxies, $remoteAddress) {
- foreach ($trustedProxies as $tp) {
- if ($this->matchesTrustedProxy($tp, $remoteAddress)) {
- return true;
- }
- }
-
- return false;
+ return IpUtils::checkIp($remoteAddress, $trustedProxies);
}
/**
diff --git a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
index 950ef8a13a3..adf17e53caa 100644
--- a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
+++ b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
@@ -46,7 +46,7 @@ class MiddlewareDispatcher {
private $middlewares;
/**
- * @var int counter which tells us what middlware was executed once an
+ * @var int counter which tells us what middleware was executed once an
* exception occurs
*/
private $middlewareCounter;
diff --git a/lib/private/AppFramework/Middleware/SessionMiddleware.php b/lib/private/AppFramework/Middleware/SessionMiddleware.php
index f3fd2c99173..32ac2b17ae5 100644
--- a/lib/private/AppFramework/Middleware/SessionMiddleware.php
+++ b/lib/private/AppFramework/Middleware/SessionMiddleware.php
@@ -51,8 +51,8 @@ class SessionMiddleware extends Middleware {
*/
public function beforeController($controller, $methodName) {
$useSession = $this->reflector->hasAnnotation('UseSession');
- if (!$useSession) {
- $this->session->close();
+ if ($useSession) {
+ $this->session->reopen();
}
}
diff --git a/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
index 2fb05159d09..5e657be0763 100644
--- a/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
@@ -72,12 +72,12 @@ class UserDeletedFilesCleanupListener implements IEventListener {
}
$storage = $this->homeStorageCache[$event->getUser()->getUID()];
$cache = $storage->getCache();
+ $storage->rmdir('');
if ($cache instanceof Cache) {
$cache->clear();
} else {
throw new \Exception("Home storage has invalid cache");
}
- $storage->rmdir('');
}
}
}
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php
index 0a145bfd7e6..33e0ad46263 100644
--- a/lib/private/Authentication/Token/IProvider.php
+++ b/lib/private/Authentication/Token/IProvider.php
@@ -158,7 +158,7 @@ interface IProvider {
public function setPassword(IToken $token, string $tokenId, string $password);
/**
- * Rotate the token. Usefull for for example oauth tokens
+ * Rotate the token. Useful for for example oauth tokens
*
* @param IToken $token
* @param string $oldTokenId
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
index a1d75828e27..0f1767e845b 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
@@ -34,7 +34,7 @@ use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\TokenPasswordExpiredException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
use OC\Authentication\Exceptions\WipeTokenException;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
@@ -346,7 +346,7 @@ class PublicKeyTokenProvider implements IProvider {
$config = array_merge([
'digest_alg' => 'sha512',
- 'private_key_bits' => 2048,
+ 'private_key_bits' => $password !== null && strlen($password) > 250 ? 4096 : 2048,
], $this->config->getSystemValue('openssl', []));
// Generate new key
@@ -368,7 +368,10 @@ class PublicKeyTokenProvider implements IProvider {
$dbToken->setPublicKey($publicKey);
$dbToken->setPrivateKey($this->encrypt($privateKey, $token));
- if (!is_null($password)) {
+ if (!is_null($password) && $this->config->getSystemValueBool('auth.storeCryptedPassword', true)) {
+ if (strlen($password) > 469) {
+ throw new \RuntimeException('Trying to save a password with more than 469 characters is not supported. If you want to use big passwords, disable the auth.storeCryptedPassword option in config.php');
+ }
$dbToken->setPassword($this->encryptPassword($password, $publicKey));
}
@@ -398,7 +401,7 @@ class PublicKeyTokenProvider implements IProvider {
$this->cache->clear();
// prevent setting an empty pw as result of pw-less-login
- if ($password === '') {
+ if ($password === '' || !$this->config->getSystemValueBool('auth.storeCryptedPassword', true)) {
return;
}
@@ -406,9 +409,12 @@ class PublicKeyTokenProvider implements IProvider {
$tokens = $this->mapper->getTokenByUser($uid);
foreach ($tokens as $t) {
$publicKey = $t->getPublicKey();
- $t->setPassword($this->encryptPassword($password, $publicKey));
- $t->setPasswordInvalid(false);
- $this->updateToken($t);
+ $encryptedPassword = $this->encryptPassword($password, $publicKey);
+ if ($t->getPassword() !== $encryptedPassword) {
+ $t->setPassword($encryptedPassword);
+ $t->setPasswordInvalid(false);
+ $this->updateToken($t);
+ }
}
}
diff --git a/lib/private/Authentication/Token/TokenCleanupJob.php b/lib/private/Authentication/Token/TokenCleanupJob.php
new file mode 100644
index 00000000000..292f8f310e8
--- /dev/null
+++ b/lib/private/Authentication/Token/TokenCleanupJob.php
@@ -0,0 +1,41 @@
+<?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/>
+ *
+ */
+namespace OC\Authentication\Token;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\TimedJob;
+
+class TokenCleanupJob extends TimedJob {
+ private IProvider $provider;
+
+ public function __construct(ITimeFactory $time, IProvider $provider) {
+ parent::__construct($time);
+ $this->provider = $provider;
+ // Run once a day at off-peak time
+ $this->setInterval(24 * 60 * 60);
+ $this->setTimeSensitivity(self::TIME_INSENSITIVE);
+ }
+
+ protected function run($argument) {
+ $this->provider->invalidateOldTokens();
+ }
+}
diff --git a/lib/private/Avatar/Avatar.php b/lib/private/Avatar/Avatar.php
index f0e14ad8b2f..0eb8f8816d8 100644
--- a/lib/private/Avatar/Avatar.php
+++ b/lib/private/Avatar/Avatar.php
@@ -37,7 +37,7 @@ declare(strict_types=1);
namespace OC\Avatar;
use Imagick;
-use OC\Color;
+use OCP\Color;
use OCP\Files\NotFoundException;
use OCP\IAvatar;
use Psr\Log\LoggerInterface;
@@ -46,9 +46,7 @@ use Psr\Log\LoggerInterface;
* This class gets and sets users avatars.
*/
abstract class Avatar implements IAvatar {
-
- /** @var LoggerInterface */
- protected $logger;
+ protected LoggerInterface $logger;
/**
* https://github.com/sebdesign/cap-height -- for 500px height
@@ -57,10 +55,8 @@ abstract class Avatar implements IAvatar {
* (0.4 letter-to-total-height ratio, 500*0.4=200), so: 200/0.715 = 280px.
* Since we start from the baseline (text-anchor) we need to
* shift the y axis by 100px (half the caps height): 500/2+100=350
- *
- * @var string
*/
- private $svgTemplate = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ private string $svgTemplate = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="{size}" height="{size}" version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="#{fill}"></rect>
<text x="50%" y="350" style="font-weight:normal;font-size:280px;font-family:\'Noto Sans\';text-anchor:middle;fill:#fff">{letter}</text>
@@ -72,15 +68,11 @@ abstract class Avatar implements IAvatar {
/**
* Returns the user display name.
- *
- * @return string
*/
abstract public function getDisplayName(): string;
/**
* Returns the first letter of the display name, or "?" if no name given.
- *
- * @return string
*/
private function getAvatarText(): string {
$displayName = $this->getDisplayName();
@@ -96,9 +88,7 @@ abstract class Avatar implements IAvatar {
/**
* @inheritdoc
*/
- public function get($size = 64) {
- $size = (int) $size;
-
+ public function get(int $size = 64) {
try {
$file = $this->getFile($size);
} catch (NotFoundException $e) {
@@ -124,7 +114,7 @@ abstract class Avatar implements IAvatar {
protected function getAvatarVector(int $size): string {
$userDisplayName = $this->getDisplayName();
$bgRGB = $this->avatarBackgroundColor($userDisplayName);
- $bgHEX = sprintf("%02x%02x%02x", $bgRGB->r, $bgRGB->g, $bgRGB->b);
+ $bgHEX = sprintf("%02x%02x%02x", $bgRGB->red(), $bgRGB->green(), $bgRGB->blue());
$text = $this->getAvatarText();
$toReplace = ['{size}', '{fill}', '{letter}'];
return str_replace($toReplace, [$size, $bgHEX, $text], $this->svgTemplate);
@@ -132,13 +122,10 @@ abstract class Avatar implements IAvatar {
/**
* Generate png avatar from svg with Imagick
- *
- * @param int $size
- * @return string|boolean
*/
- protected function generateAvatarFromSvg(int $size) {
+ protected function generateAvatarFromSvg(int $size): ?string {
if (!extension_loaded('imagick')) {
- return false;
+ return null;
}
try {
$font = __DIR__ . '/../../core/fonts/NotoSans-Regular.ttf';
@@ -149,30 +136,25 @@ abstract class Avatar implements IAvatar {
$avatar->setImageFormat('png');
$image = new \OCP\Image();
$image->loadFromData((string)$avatar);
- $data = $image->data();
- return $data === null ? false : $data;
+ return $image->data();
} catch (\Exception $e) {
- return false;
+ return null;
}
}
/**
* Generate png avatar with GD
- *
- * @param string $userDisplayName
- * @param int $size
- * @return string
*/
- protected function generateAvatar($userDisplayName, $size) {
+ protected function generateAvatar(string $userDisplayName, int $size): string {
$text = $this->getAvatarText();
$backgroundColor = $this->avatarBackgroundColor($userDisplayName);
$im = imagecreatetruecolor($size, $size);
$background = imagecolorallocate(
$im,
- $backgroundColor->r,
- $backgroundColor->g,
- $backgroundColor->b
+ $backgroundColor->red(),
+ $backgroundColor->green(),
+ $backgroundColor->blue()
);
$white = imagecolorallocate($im, 255, 255, 255);
imagefilledrectangle($im, 0, 0, $size, $size, $background);
@@ -209,7 +191,7 @@ abstract class Avatar implements IAvatar {
string $text,
string $font,
int $size,
- $angle = 0
+ int $angle = 0
): array {
// Image width & height
$xi = imagesx($image);
@@ -229,37 +211,6 @@ abstract class Avatar implements IAvatar {
return [$x, $y];
}
- /**
- * Calculate steps between two Colors
- * @param object Color $steps start color
- * @param object Color $ends end color
- * @return array [r,g,b] steps for each color to go from $steps to $ends
- */
- private function stepCalc($steps, $ends) {
- $step = [];
- $step[0] = ($ends[1]->r - $ends[0]->r) / $steps;
- $step[1] = ($ends[1]->g - $ends[0]->g) / $steps;
- $step[2] = ($ends[1]->b - $ends[0]->b) / $steps;
- return $step;
- }
-
- /**
- * Convert a string to an integer evenly
- * @param string $hash the text to parse
- * @param int $maximum the maximum range
- * @return int[] between 0 and $maximum
- */
- private function mixPalette($steps, $color1, $color2) {
- $palette = [$color1];
- $step = $this->stepCalc($steps, [$color1, $color2]);
- for ($i = 1; $i < $steps; $i++) {
- $r = intval($color1->r + ($step[0] * $i));
- $g = intval($color1->g + ($step[1] * $i));
- $b = intval($color1->b + ($step[2] * $i));
- $palette[] = new Color($r, $g, $b);
- }
- return $palette;
- }
/**
* Convert a string to an integer evenly
@@ -267,7 +218,7 @@ abstract class Avatar implements IAvatar {
* @param int $maximum the maximum range
* @return int between 0 and $maximum
*/
- private function hashToInt($hash, $maximum) {
+ private function hashToInt(string $hash, int $maximum): int {
$final = 0;
$result = [];
@@ -285,10 +236,9 @@ abstract class Avatar implements IAvatar {
}
/**
- * @param string $hash
- * @return Color Object containting r g b int in the range [0, 255]
+ * @return Color Object containing r g b int in the range [0, 255]
*/
- public function avatarBackgroundColor(string $hash) {
+ public function avatarBackgroundColor(string $hash): Color {
// Normalize hash
$hash = strtolower($hash);
@@ -308,9 +258,9 @@ abstract class Avatar implements IAvatar {
// 3 colors * 6 will result in 18 generated colors
$steps = 6;
- $palette1 = $this->mixPalette($steps, $red, $yellow);
- $palette2 = $this->mixPalette($steps, $yellow, $blue);
- $palette3 = $this->mixPalette($steps, $blue, $red);
+ $palette1 = Color::mixPalette($steps, $red, $yellow);
+ $palette2 = Color::mixPalette($steps, $yellow, $blue);
+ $palette3 = Color::mixPalette($steps, $blue, $red);
$finalPalette = array_merge($palette1, $palette2, $palette3);
diff --git a/lib/private/Avatar/GuestAvatar.php b/lib/private/Avatar/GuestAvatar.php
index f0297b3a93c..79d7e6ee094 100644
--- a/lib/private/Avatar/GuestAvatar.php
+++ b/lib/private/Avatar/GuestAvatar.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
*/
namespace OC\Avatar;
+use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\InMemoryFile;
use Psr\Log\LoggerInterface;
@@ -35,16 +36,13 @@ use Psr\Log\LoggerInterface;
class GuestAvatar extends Avatar {
/**
* Holds the guest user display name.
- *
- * @var string
*/
- private $userDisplayName;
+ private string $userDisplayName;
/**
* GuestAvatar constructor.
*
* @param string $userDisplayName The guest user display name
- * @param LoggerInterface $logger The logger
*/
public function __construct(string $userDisplayName, LoggerInterface $logger) {
parent::__construct($logger);
@@ -53,17 +51,14 @@ class GuestAvatar extends Avatar {
/**
* Tests if the user has an avatar.
- *
- * @return true Guests always have an avatar.
*/
- public function exists() {
+ public function exists(): bool {
+ // Guests always have an avatar.
return true;
}
/**
* Returns the guest user display name.
- *
- * @return string
*/
public function getDisplayName(): string {
return $this->userDisplayName;
@@ -75,24 +70,21 @@ class GuestAvatar extends Avatar {
* @param \OCP\IImage|resource|string $data
* @return void
*/
- public function set($data) {
+ public function set($data): void {
// unimplemented for guest user avatars
}
/**
* Removing avatars isn't implemented for guests.
*/
- public function remove() {
+ public function remove(bool $silent = false): void {
// unimplemented for guest user avatars
}
/**
* Generates an avatar for the guest.
- *
- * @param int $size The desired image size.
- * @return InMemoryFile
*/
- public function getFile($size) {
+ public function getFile(int $size): ISimpleFile {
$avatar = $this->generateAvatar($this->userDisplayName, $size);
return new InMemoryFile('avatar.png', $avatar);
}
@@ -103,9 +95,8 @@ class GuestAvatar extends Avatar {
* @param string $feature The changed feature
* @param mixed $oldValue The previous value
* @param mixed $newValue The new value
- * @return void
*/
- public function userChanged($feature, $oldValue, $newValue) {
+ public function userChanged(string $feature, $oldValue, $newValue): void {
if ($feature === 'displayName') {
$this->userDisplayName = $newValue;
}
@@ -113,8 +104,6 @@ class GuestAvatar extends Avatar {
/**
* Guests don't have custom avatars.
- *
- * @return bool
*/
public function isCustomAvatar(): bool {
return false;
diff --git a/lib/private/Avatar/PlaceholderAvatar.php b/lib/private/Avatar/PlaceholderAvatar.php
index df7a490cbe4..504e5c1457d 100644
--- a/lib/private/Avatar/PlaceholderAvatar.php
+++ b/lib/private/Avatar/PlaceholderAvatar.php
@@ -44,11 +44,8 @@ use Psr\Log\LoggerInterface;
* for faster retrieval, unlike the GuestAvatar.
*/
class PlaceholderAvatar extends Avatar {
- /** @var ISimpleFolder */
- private $folder;
-
- /** @var User */
- private $user;
+ private ISimpleFolder $folder;
+ private User $user;
/**
* UserAvatar constructor.
@@ -71,10 +68,8 @@ class PlaceholderAvatar extends Avatar {
/**
* Check if an avatar exists for the user
- *
- * @return bool
*/
- public function exists() {
+ public function exists(): bool {
return true;
}
@@ -87,14 +82,14 @@ class PlaceholderAvatar extends Avatar {
* @throws NotSquareException if the image is not square
* @return void
*/
- public function set($data) {
+ public function set($data): void {
// unimplemented for placeholder avatars
}
/**
* Removes the users avatar.
*/
- public function remove(bool $silent = false) {
+ public function remove(bool $silent = false): void {
$avatars = $this->folder->getDirectoryListing();
foreach ($avatars as $avatar) {
@@ -113,9 +108,7 @@ class PlaceholderAvatar extends Avatar {
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\PreConditionNotMetException
*/
- public function getFile($size) {
- $size = (int) $size;
-
+ public function getFile(int $size): ISimpleFile {
$ext = 'png';
if ($size === -1) {
@@ -149,8 +142,6 @@ class PlaceholderAvatar extends Avatar {
/**
* Returns the user display name.
- *
- * @return string
*/
public function getDisplayName(): string {
return $this->user->getDisplayName();
@@ -165,14 +156,12 @@ class PlaceholderAvatar extends Avatar {
* @throws NotPermittedException
* @throws \OCP\PreConditionNotMetException
*/
- public function userChanged($feature, $oldValue, $newValue) {
+ public function userChanged(string $feature, $oldValue, $newValue): void {
$this->remove();
}
/**
* Check if the avatar of a user is a custom uploaded one
- *
- * @return bool
*/
public function isCustomAvatar(): bool {
return false;
diff --git a/lib/private/Avatar/UserAvatar.php b/lib/private/Avatar/UserAvatar.php
index 6cca5a1c355..f5a1d7e77b1 100644
--- a/lib/private/Avatar/UserAvatar.php
+++ b/lib/private/Avatar/UserAvatar.php
@@ -44,17 +44,10 @@ use Psr\Log\LoggerInterface;
* This class represents a registered user's avatar.
*/
class UserAvatar extends Avatar {
- /** @var IConfig */
- private $config;
-
- /** @var ISimpleFolder */
- private $folder;
-
- /** @var IL10N */
- private $l;
-
- /** @var User */
- private $user;
+ private IConfig $config;
+ private ISimpleFolder $folder;
+ private IL10N $l;
+ private User $user;
/**
* UserAvatar constructor.
@@ -68,7 +61,7 @@ class UserAvatar extends Avatar {
public function __construct(
ISimpleFolder $folder,
IL10N $l,
- $user,
+ User $user,
LoggerInterface $logger,
IConfig $config) {
parent::__construct($logger);
@@ -80,10 +73,8 @@ class UserAvatar extends Avatar {
/**
* Check if an avatar exists for the user
- *
- * @return bool
*/
- public function exists() {
+ public function exists(): bool {
return $this->folder->fileExists('avatar.jpg') || $this->folder->fileExists('avatar.png');
}
@@ -96,7 +87,7 @@ class UserAvatar extends Avatar {
* @throws NotSquareException if the image is not square
* @return void
*/
- public function set($data) {
+ public function set($data): void {
$img = $this->getAvatarImage($data);
$data = $img->data();
@@ -124,7 +115,7 @@ class UserAvatar extends Avatar {
* @param IImage|resource|string|\GdImage $data An image object, imagedata or path to the avatar
* @return IImage
*/
- private function getAvatarImage($data) {
+ private function getAvatarImage($data): IImage {
if ($data instanceof IImage) {
return $data;
}
@@ -156,11 +147,8 @@ class UserAvatar extends Avatar {
/**
* Returns the avatar image type.
- *
- * @param IImage $avatar
- * @return string
*/
- private function getAvatarImageType(IImage $avatar) {
+ private function getAvatarImageType(IImage $avatar): string {
$type = substr($avatar->mimeType(), -3);
if ($type === 'peg') {
$type = 'jpg';
@@ -179,7 +167,7 @@ class UserAvatar extends Avatar {
* @throws \Exception if the provided image is not valid
* @throws NotSquareException if the image is not square
*/
- private function validateAvatar(IImage $avatar) {
+ private function validateAvatar(IImage $avatar): void {
$type = $this->getAvatarImageType($avatar);
if ($type !== 'jpg' && $type !== 'png') {
@@ -197,15 +185,14 @@ class UserAvatar extends Avatar {
/**
* Removes the users avatar.
- * @return void
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\PreConditionNotMetException
*/
- public function remove(bool $silent = false) {
+ public function remove(bool $silent = false): void {
$avatars = $this->folder->getDirectoryListing();
$this->config->setUserValue($this->user->getUID(), 'avatar', 'version',
- (int) $this->config->getUserValue($this->user->getUID(), 'avatar', 'version', 0) + 1);
+ (string)((int)$this->config->getUserValue($this->user->getUID(), 'avatar', 'version', '0') + 1));
foreach ($avatars as $avatar) {
$avatar->delete();
@@ -219,10 +206,9 @@ class UserAvatar extends Avatar {
/**
* Get the extension of the avatar. If there is no avatar throw Exception
*
- * @return string
* @throws NotFoundException
*/
- private function getExtension() {
+ private function getExtension(): string {
if ($this->folder->fileExists('avatar.jpg')) {
return 'jpg';
} elseif ($this->folder->fileExists('avatar.png')) {
@@ -242,9 +228,7 @@ class UserAvatar extends Avatar {
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\PreConditionNotMetException
*/
- public function getFile($size) {
- $size = (int) $size;
-
+ public function getFile(int $size): ISimpleFile {
try {
$ext = $this->getExtension();
} catch (NotFoundException $e) {
@@ -304,8 +288,6 @@ class UserAvatar extends Avatar {
/**
* Returns the user display name.
- *
- * @return string
*/
public function getDisplayName(): string {
return $this->user->getDisplayName();
@@ -320,7 +302,7 @@ class UserAvatar extends Avatar {
* @throws NotPermittedException
* @throws \OCP\PreConditionNotMetException
*/
- public function userChanged($feature, $oldValue, $newValue) {
+ public function userChanged(string $feature, $oldValue, $newValue): void {
// If the avatar is not generated (so an uploaded image) we skip this
if (!$this->folder->fileExists('generated')) {
return;
@@ -331,8 +313,6 @@ class UserAvatar extends Avatar {
/**
* Check if the avatar of a user is a custom uploaded one
- *
- * @return bool
*/
public function isCustomAvatar(): bool {
return $this->config->getUserValue($this->user->getUID(), 'avatar', 'generated', 'false') !== 'true';
diff --git a/lib/private/BackgroundJob/Job.php b/lib/private/BackgroundJob/Job.php
index 399ff05134e..ffcaaf8c36d 100644
--- a/lib/private/BackgroundJob/Job.php
+++ b/lib/private/BackgroundJob/Job.php
@@ -66,6 +66,10 @@ abstract class Job implements IJob {
}
}
+ public function start(IJobList $jobList): void {
+ $this->execute($jobList);
+ }
+
abstract protected function run($argument);
public function setId(int $id) {
diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php
index 7ab86df8455..20176e45125 100644
--- a/lib/private/BackgroundJob/JobList.php
+++ b/lib/private/BackgroundJob/JobList.php
@@ -40,21 +40,10 @@ use OCP\IConfig;
use OCP\IDBConnection;
class JobList implements IJobList {
+ protected IDBConnection $connection;
+ protected IConfig $config;
+ protected ITimeFactory $timeFactory;
- /** @var IDBConnection */
- protected $connection;
-
- /**@var IConfig */
- protected $config;
-
- /**@var ITimeFactory */
- protected $timeFactory;
-
- /**
- * @param IDBConnection $connection
- * @param IConfig $config
- * @param ITimeFactory $timeFactory
- */
public function __construct(IDBConnection $connection, IConfig $config, ITimeFactory $timeFactory) {
$this->connection = $connection;
$this->config = $config;
@@ -62,10 +51,10 @@ class JobList implements IJobList {
}
/**
- * @param IJob|string $job
+ * @param IJob|class-string<IJob> $job
* @param mixed $argument
*/
- public function add($job, $argument = null) {
+ public function add($job, $argument = null): void {
if ($job instanceof IJob) {
$class = get_class($job);
} else {
@@ -101,7 +90,7 @@ class JobList implements IJobList {
* @param IJob|string $job
* @param mixed $argument
*/
- public function remove($job, $argument = null) {
+ public function remove($job, $argument = null): void {
if ($job instanceof IJob) {
$class = get_class($job);
} else {
@@ -133,24 +122,20 @@ class JobList implements IJobList {
}
}
- /**
- * @param int $id
- */
- protected function removeById($id) {
+ protected function removeById(int $id): void {
$query = $this->connection->getQueryBuilder();
$query->delete('jobs')
->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
- $query->execute();
+ $query->executeStatement();
}
/**
* check if a job is in the list
*
- * @param IJob|string $job
+ * @param IJob|class-string<IJob> $job
* @param mixed $argument
- * @return bool
*/
- public function has($job, $argument) {
+ public function has($job, $argument): bool {
if ($job instanceof IJob) {
$class = get_class($job);
} else {
@@ -165,7 +150,7 @@ class JobList implements IJobList {
->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(md5($argument))))
->setMaxResults(1);
- $result = $query->execute();
+ $result = $query->executeQuery();
$row = $result->fetch();
$result->closeCursor();
@@ -177,13 +162,33 @@ class JobList implements IJobList {
*
* @return IJob[]
* @deprecated 9.0.0 - This method is dangerous since it can cause load and
- * memory problems when creating too many instances.
+ * memory problems when creating too many instances. Use getJobs instead.
+ */
+ public function getAll(): array {
+ return $this->getJobs(null, null, 0);
+ }
+
+ /**
+ * @param IJob|class-string<IJob>|null $job
+ * @return IJob[]
*/
- public function getAll() {
+ public function getJobs($job, ?int $limit, int $offset): array {
$query = $this->connection->getQueryBuilder();
$query->select('*')
- ->from('jobs');
- $result = $query->execute();
+ ->from('jobs')
+ ->setMaxResults($limit)
+ ->setFirstResult($offset);
+
+ if ($job !== null) {
+ if ($job instanceof IJob) {
+ $class = get_class($job);
+ } else {
+ $class = $job;
+ }
+ $query->where($query->expr()->eq('class', $query->createNamedParameter($class)));
+ }
+
+ $result = $query->executeQuery();
$jobs = [];
while ($row = $result->fetch()) {
@@ -199,9 +204,6 @@ class JobList implements IJobList {
/**
* get the next job in the list
- *
- * @param bool $onlyTimeSensitive
- * @return IJob|null
*/
public function getNext(bool $onlyTimeSensitive = false): ?IJob {
$query = $this->connection->getQueryBuilder();
@@ -224,7 +226,7 @@ class JobList implements IJobList {
->andWhere($update->expr()->eq('reserved_at', $update->createParameter('reserved_at')))
->andWhere($update->expr()->eq('last_checked', $update->createParameter('last_checked')));
- $result = $query->execute();
+ $result = $query->executeQuery();
$row = $result->fetch();
$result->closeCursor();
@@ -232,7 +234,7 @@ class JobList implements IJobList {
$update->setParameter('jobid', $row['id']);
$update->setParameter('reserved_at', $row['reserved_at']);
$update->setParameter('last_checked', $row['last_checked']);
- $count = $update->execute();
+ $count = $update->executeStatement();
if ($count === 0) {
// Background job already executed elsewhere, try again.
@@ -247,7 +249,7 @@ class JobList implements IJobList {
->set('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT))
->set('last_checked', $reset->createNamedParameter($this->timeFactory->getTime() + 12 * 3600, IQueryBuilder::PARAM_INT))
->where($reset->expr()->eq('id', $reset->createNamedParameter($row['id'], IQueryBuilder::PARAM_INT)));
- $reset->execute();
+ $reset->executeStatement();
// Background job from disabled app, try again.
return $this->getNext($onlyTimeSensitive);
@@ -259,11 +261,7 @@ class JobList implements IJobList {
}
}
- /**
- * @param int $id
- * @return IJob|null
- */
- public function getById($id) {
+ public function getById(int $id): ?IJob {
$row = $this->getDetailsById($id);
if ($row) {
@@ -292,15 +290,14 @@ class JobList implements IJobList {
/**
* get the job object from a row in the db
*
- * @param array $row
- * @return IJob|null
+ * @param array{class:class-string<IJob>, id:mixed, last_run:mixed, argument:string} $row
*/
- private function buildJob($row) {
+ private function buildJob(array $row): ?IJob {
try {
try {
// Try to load the job as a service
/** @var IJob $job */
- $job = \OC::$server->query($row['class']);
+ $job = \OCP\Server::get($row['class']);
} catch (QueryException $e) {
if (class_exists($row['class'])) {
$class = $row['class'];
@@ -327,33 +324,27 @@ class JobList implements IJobList {
/**
* set the job that was last ran
- *
- * @param IJob $job
*/
- public function setLastJob(IJob $job) {
+ public function setLastJob(IJob $job): void {
$this->unlockJob($job);
- $this->config->setAppValue('backgroundjob', 'lastjob', $job->getId());
+ $this->config->setAppValue('backgroundjob', 'lastjob', (string)$job->getId());
}
/**
* Remove the reservation for a job
- *
- * @param IJob $job
*/
- public function unlockJob(IJob $job) {
+ public function unlockJob(IJob $job): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
- $query->execute();
+ $query->executeStatement();
}
/**
* set the lastRun of $job to now
- *
- * @param IJob $job
*/
- public function setLastRun(IJob $job) {
+ public function setLastRun(IJob $job): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
->set('last_run', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
@@ -364,25 +355,23 @@ class JobList implements IJobList {
$query->set('time_sensitive', $query->createNamedParameter(IJob::TIME_INSENSITIVE));
}
- $query->execute();
+ $query->executeStatement();
}
/**
- * @param IJob $job
- * @param $timeTaken
+ * @param int $timeTaken
*/
- public function setExecutionTime(IJob $job, $timeTaken) {
+ public function setExecutionTime(IJob $job, $timeTaken): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
->set('execution_duration', $query->createNamedParameter($timeTaken, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
- $query->execute();
+ $query->executeStatement();
}
/**
* Reset the $job so it executes on the next trigger
*
- * @param IJob $job
* @since 23.0.0
*/
public function resetBackgroundJob(IJob $job): void {
diff --git a/lib/private/BinaryFinder.php b/lib/private/BinaryFinder.php
new file mode 100644
index 00000000000..a7ef55237db
--- /dev/null
+++ b/lib/private/BinaryFinder.php
@@ -0,0 +1,71 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OC;
+
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IBinaryFinder;
+use Symfony\Component\Process\ExecutableFinder;
+
+/**
+ * Service that find the binary path for a program
+ */
+class BinaryFinder implements IBinaryFinder {
+ private ICache $cache;
+
+ public function __construct(ICacheFactory $cacheFactory) {
+ $this->cache = $cacheFactory->createLocal('findBinaryPath');
+ }
+
+ /**
+ * Try to find a program
+ *
+ * @return false|string
+ */
+ public function findBinaryPath(string $program) {
+ $result = $this->cache->get($program);
+ if ($result !== null) {
+ return $result;
+ }
+ $result = false;
+ if (\OCP\Util::isFunctionEnabled('exec')) {
+ $exeSniffer = new ExecutableFinder();
+ // Returns null if nothing is found
+ $result = $exeSniffer->find($program, null, [
+ '/usr/local/sbin',
+ '/usr/local/bin',
+ '/usr/sbin',
+ '/usr/bin',
+ '/sbin',
+ '/bin',
+ '/opt/bin',
+ ]);
+ if ($result === null) {
+ $result = false;
+ }
+ }
+ // store the value for 5 minutes
+ $this->cache->set($program, $result, 300);
+ return $result;
+ }
+}
diff --git a/lib/private/Cache/CappedMemoryCache.php b/lib/private/Cache/CappedMemoryCache.php
index 6063b5e7110..31e8ef3e720 100644
--- a/lib/private/Cache/CappedMemoryCache.php
+++ b/lib/private/Cache/CappedMemoryCache.php
@@ -28,6 +28,7 @@ use OCP\ICache;
*
* Uses a simple FIFO expiry mechanism
* @template T
+ * @deprecated use OCP\Cache\CappedMemoryCache instead
*/
class CappedMemoryCache implements ICache, \ArrayAccess {
private $capacity;
diff --git a/lib/private/Calendar/Manager.php b/lib/private/Calendar/Manager.php
index 16e142264aa..f0b8e9fd50d 100644
--- a/lib/private/Calendar/Manager.php
+++ b/lib/private/Calendar/Manager.php
@@ -27,12 +27,19 @@ declare(strict_types=1);
namespace OC\Calendar;
use OC\AppFramework\Bootstrap\Coordinator;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Calendar\Exceptions\CalendarException;
use OCP\Calendar\ICalendar;
use OCP\Calendar\ICalendarProvider;
use OCP\Calendar\ICalendarQuery;
+use OCP\Calendar\ICreateFromString;
use OCP\Calendar\IManager;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
+use Sabre\VObject\Component\VCalendar;
+use Sabre\VObject\Component\VEvent;
+use Sabre\VObject\Property\VCard\DateTime;
+use Sabre\VObject\Reader;
use Throwable;
use function array_map;
use function array_merge;
@@ -58,12 +65,17 @@ class Manager implements IManager {
/** @var LoggerInterface */
private $logger;
+ private ITimeFactory $timeFactory;
+
+
public function __construct(Coordinator $coordinator,
ContainerInterface $container,
- LoggerInterface $logger) {
+ LoggerInterface $logger,
+ ITimeFactory $timeFactory) {
$this->coordinator = $coordinator;
$this->container = $container;
$this->logger = $logger;
+ $this->timeFactory = $timeFactory;
}
/**
@@ -167,6 +179,11 @@ class Manager implements IManager {
$this->calendarLoaders = [];
}
+ /**
+ * @param string $principalUri
+ * @param array $calendarUris
+ * @return ICreateFromString[]
+ */
public function getCalendarsForPrincipal(string $principalUri, array $calendarUris = []): array {
$context = $this->coordinator->getRegistrationContext();
if ($context === null) {
@@ -198,7 +215,6 @@ class Manager implements IManager {
);
$results = [];
- /** @var ICalendar $calendar */
foreach ($calendars as $calendar) {
$r = $calendar->search(
$query->getSearchPattern() ?? '',
@@ -219,4 +235,137 @@ class Manager implements IManager {
public function newQuery(string $principalUri): ICalendarQuery {
return new CalendarQuery($principalUri);
}
+
+ /**
+ * @throws \OCP\DB\Exception
+ */
+ public function handleIMipReply(string $principalUri, string $sender, string $recipient, string $calendarData): bool {
+ /** @var VCalendar $vObject */
+ $vObject = Reader::read($calendarData);
+ /** @var VEvent $vEvent */
+ $vEvent = $vObject->{'VEVENT'};
+
+ // First, we check if the correct method is passed to us
+ if (strcasecmp('REPLY', $vObject->{'METHOD'}->getValue()) !== 0) {
+ $this->logger->warning('Wrong method provided for processing');
+ return false;
+ }
+
+ // check if mail recipient and organizer are one and the same
+ $organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7);
+
+ if (strcasecmp($recipient, $organizer) !== 0) {
+ $this->logger->warning('Recipient and ORGANIZER must be identical');
+ return false;
+ }
+
+ //check if the event is in the future
+ /** @var DateTime $eventTime */
+ $eventTime = $vEvent->{'DTSTART'};
+ if ($eventTime->getDateTime()->getTimeStamp() < $this->timeFactory->getTime()) { // this might cause issues with recurrences
+ $this->logger->warning('Only events in the future are processed');
+ return false;
+ }
+
+ $calendars = $this->getCalendarsForPrincipal($principalUri);
+ if (empty($calendars)) {
+ $this->logger->warning('Could not find any calendars for principal ' . $principalUri);
+ return false;
+ }
+
+ $found = null;
+ // if the attendee has been found in at least one calendar event with the UID of the iMIP event
+ // we process it.
+ // Benefit: no attendee lost
+ // Drawback: attendees that have been deleted will still be able to update their partstat
+ foreach ($calendars as $calendar) {
+ // We should not search in writable calendars
+ if ($calendar instanceof ICreateFromString) {
+ $o = $calendar->search($sender, ['ATTENDEE'], ['uid' => $vEvent->{'UID'}->getValue()]);
+ if (!empty($o)) {
+ $found = $calendar;
+ $name = $o[0]['uri'];
+ break;
+ }
+ }
+ }
+
+ if (empty($found)) {
+ $this->logger->info('Event not found in any calendar for principal ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue());
+ return false;
+ }
+
+ try {
+ $found->handleIMipMessage($name, $calendarData); // sabre will handle the scheduling behind the scenes
+ } catch (CalendarException $e) {
+ $this->logger->error('Could not update calendar for iMIP processing', ['exception' => $e]);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @since 25.0.0
+ * @throws \OCP\DB\Exception
+ */
+ public function handleIMipCancel(string $principalUri, string $sender, ?string $replyTo, string $recipient, string $calendarData): bool {
+ $vObject = Reader::read($calendarData);
+ /** @var VEvent $vEvent */
+ $vEvent = $vObject->{'VEVENT'};
+
+ // First, we check if the correct method is passed to us
+ if (strcasecmp('CANCEL', $vObject->{'METHOD'}->getValue()) !== 0) {
+ $this->logger->warning('Wrong method provided for processing');
+ return false;
+ }
+
+ $attendee = substr($vEvent->{'ATTENDEE'}->getValue(), 7);
+ if (strcasecmp($recipient, $attendee) !== 0) {
+ $this->logger->warning('Recipient must be an ATTENDEE of this event');
+ return false;
+ }
+
+ // Thirdly, we need to compare the email address the CANCEL is coming from (in Mail)
+ // or the Reply- To Address submitted with the CANCEL email
+ // to the email address in the ORGANIZER.
+ // We don't want to accept a CANCEL request from just anyone
+ $organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7);
+ if (strcasecmp($sender, $organizer) !== 0 && strcasecmp($replyTo, $organizer) !== 0) {
+ $this->logger->warning('Sender must be the ORGANIZER of this event');
+ return false;
+ }
+
+ $calendars = $this->getCalendarsForPrincipal($principalUri);
+ $found = null;
+ // if the attendee has been found in at least one calendar event with the UID of the iMIP event
+ // we process it.
+ // Benefit: no attendee lost
+ // Drawback: attendees that have been deleted will still be able to update their partstat
+ foreach ($calendars as $calendar) {
+ // We should not search in writable calendars
+ if ($calendar instanceof ICreateFromString) {
+ $o = $calendar->search($recipient, ['ATTENDEE'], ['uid' => $vEvent->{'UID'}->getValue()]);
+ if (!empty($o)) {
+ $found = $calendar;
+ $name = $o[0]['uri'];
+ break;
+ }
+ }
+ }
+
+ if (empty($found)) {
+ $this->logger->info('Event not found in any calendar for principal ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue());
+ // this is a safe operation
+ // we can ignore events that have been cancelled but were not in the calendar anyway
+ return true;
+ }
+
+ try {
+ $found->handleIMipMessage($name, $calendarData); // sabre will handle the scheduling behind the scenes
+ return true;
+ } catch (CalendarException $e) {
+ $this->logger->error('Could not update calendar for iMIP processing', ['exception' => $e]);
+ return false;
+ }
+ }
}
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php
new file mode 100644
index 00000000000..6ccae9903dc
--- /dev/null
+++ b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php
@@ -0,0 +1,61 @@
+<?php
+
+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/>.
+ */
+
+namespace OC\Collaboration\Reference\File;
+
+use OCP\Collaboration\Reference\IReferenceManager;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\Node\NodeDeletedEvent;
+use OCP\Share\Events\ShareCreatedEvent;
+use OCP\Share\Events\ShareDeletedEvent;
+
+class FileReferenceEventListener implements \OCP\EventDispatcher\IEventListener {
+ private IReferenceManager $manager;
+
+ public function __construct(IReferenceManager $manager) {
+ $this->manager = $manager;
+ }
+
+ public static function register(IEventDispatcher $eventDispatcher): void {
+ $eventDispatcher->addServiceListener(NodeDeletedEvent::class, FileReferenceEventListener::class);
+ $eventDispatcher->addServiceListener(ShareDeletedEvent::class, FileReferenceEventListener::class);
+ $eventDispatcher->addServiceListener(ShareCreatedEvent::class, FileReferenceEventListener::class);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function handle(Event $event): void {
+ if ($event instanceof NodeDeletedEvent) {
+ $this->manager->invalidateCache((string)$event->getNode()->getId());
+ }
+ if ($event instanceof ShareDeletedEvent) {
+ $this->manager->invalidateCache((string)$event->getShare()->getNodeId());
+ }
+ if ($event instanceof ShareCreatedEvent) {
+ $this->manager->invalidateCache((string)$event->getShare()->getNodeId());
+ }
+ }
+}
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
new file mode 100644
index 00000000000..39cdb62b09a
--- /dev/null
+++ b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
@@ -0,0 +1,153 @@
+<?php
+
+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/>.
+ */
+
+namespace OC\Collaboration\Reference\File;
+
+use OC\Collaboration\Reference\Reference;
+use OC\User\NoUserException;
+use OCP\Collaboration\Reference\IReference;
+use OCP\Collaboration\Reference\IReferenceProvider;
+use OCP\Files\InvalidPathException;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\IPreview;
+use OCP\IURLGenerator;
+use OCP\IUserSession;
+
+class FileReferenceProvider implements IReferenceProvider {
+ private IURLGenerator $urlGenerator;
+ private IRootFolder $rootFolder;
+ private ?string $userId;
+ private IPreview $previewManager;
+
+ public function __construct(IURLGenerator $urlGenerator, IRootFolder $rootFolder, IUserSession $userSession, IPreview $previewManager) {
+ $this->urlGenerator = $urlGenerator;
+ $this->rootFolder = $rootFolder;
+ $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
+ $this->previewManager = $previewManager;
+ }
+
+ public function matchReference(string $referenceText): bool {
+ return $this->getFilesAppLinkId($referenceText) !== null;
+ }
+
+ private function getFilesAppLinkId(string $referenceText): ?int {
+ $start = $this->urlGenerator->getAbsoluteURL('/apps/files');
+ $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/files');
+
+ $fileId = null;
+
+ if (mb_strpos($referenceText, $start) === 0) {
+ $parts = parse_url($referenceText);
+ parse_str($parts['query'], $query);
+ $fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId;
+ $fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId;
+ }
+
+ if (mb_strpos($referenceText, $startIndex) === 0) {
+ $parts = parse_url($referenceText);
+ parse_str($parts['query'], $query);
+ $fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId;
+ $fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId;
+ }
+
+ if (mb_strpos($referenceText, $this->urlGenerator->getAbsoluteURL('/index.php/f/')) === 0) {
+ $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/index.php/f/'), '', $referenceText);
+ }
+
+ if (mb_strpos($referenceText, $this->urlGenerator->getAbsoluteURL('/f/')) === 0) {
+ $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/f/'), '', $referenceText);
+ }
+
+ return $fileId !== null ? (int)$fileId : null;
+ }
+
+ public function resolveReference(string $referenceText): ?IReference {
+ if ($this->matchReference($referenceText)) {
+ $reference = new Reference($referenceText);
+ try {
+ $this->fetchReference($reference);
+ } catch (NotFoundException $e) {
+ $reference->setRichObject('file', null);
+ $reference->setAccessible(false);
+ }
+ return $reference;
+ }
+
+ return null;
+ }
+
+ /**
+ * @throws NotFoundException
+ */
+ private function fetchReference(Reference $reference): void {
+ if ($this->userId === null) {
+ throw new NotFoundException();
+ }
+
+ $fileId = $this->getFilesAppLinkId($reference->getId());
+ if ($fileId === null) {
+ throw new NotFoundException();
+ }
+
+ try {
+ $userFolder = $this->rootFolder->getUserFolder($this->userId);
+ $files = $userFolder->getById($fileId);
+
+ if (empty($files)) {
+ 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));
+ $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 1600, 'y' => 630, 'fileId' => $fileId]));
+
+ $reference->setRichObject('file', [
+ 'id' => $file->getId(),
+ 'name' => $file->getName(),
+ 'size' => $file->getSize(),
+ 'path' => $file->getPath(),
+ 'link' => $reference->getUrl(),
+ 'mimetype' => $file->getMimetype(),
+ 'preview-available' => $this->previewManager->isAvailable($file)
+ ]);
+ } catch (InvalidPathException|NotFoundException|NotPermittedException|NoUserException $e) {
+ throw new NotFoundException();
+ }
+ }
+
+ public function getCachePrefix(string $referenceId): string {
+ return (string)$this->getFilesAppLinkId($referenceId);
+ }
+
+ public function getCacheKey(string $referenceId): ?string {
+ return $this->userId ?? '';
+ }
+}
diff --git a/lib/private/Collaboration/Reference/LinkReferenceProvider.php b/lib/private/Collaboration/Reference/LinkReferenceProvider.php
new file mode 100644
index 00000000000..36fbdd0b168
--- /dev/null
+++ b/lib/private/Collaboration/Reference/LinkReferenceProvider.php
@@ -0,0 +1,162 @@
+<?php
+
+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/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+use Fusonic\OpenGraph\Consumer;
+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\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;
+
+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 {
+ $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 {
+ $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 (\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;
+ }
+}
diff --git a/lib/private/Collaboration/Reference/Reference.php b/lib/private/Collaboration/Reference/Reference.php
new file mode 100644
index 00000000000..22dc57782d8
--- /dev/null
+++ b/lib/private/Collaboration/Reference/Reference.php
@@ -0,0 +1,163 @@
+<?php
+
+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/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+use OCP\Collaboration\Reference\IReference;
+
+class Reference implements IReference {
+ private string $reference;
+
+ private bool $accessible = true;
+
+ private ?string $title = null;
+ private ?string $description = null;
+ private ?string $imageUrl = null;
+ private ?string $contentType = null;
+ private ?string $url = null;
+
+ private ?string $richObjectType = null;
+ private ?array $richObject = null;
+
+ public function __construct(string $reference) {
+ $this->reference = $reference;
+ }
+
+ public function getId(): string {
+ return $this->reference;
+ }
+
+ public function setAccessible(bool $accessible): void {
+ $this->accessible = $accessible;
+ }
+
+ public function getAccessible(): bool {
+ return $this->accessible;
+ }
+
+ public function setTitle(string $title): void {
+ $this->title = $title;
+ }
+
+ public function getTitle(): string {
+ return $this->title ?? $this->reference;
+ }
+
+ public function setDescription(?string $description): void {
+ $this->description = $description;
+ }
+
+ public function getDescription(): ?string {
+ return $this->description;
+ }
+
+ public function setImageUrl(?string $imageUrl): void {
+ $this->imageUrl = $imageUrl;
+ }
+
+ public function getImageUrl(): ?string {
+ return $this->imageUrl;
+ }
+
+ public function setImageContentType(?string $contentType): void {
+ $this->contentType = $contentType;
+ }
+
+ public function getImageContentType(): ?string {
+ return $this->contentType;
+ }
+
+ public function setUrl(?string $url): void {
+ $this->url = $url;
+ }
+
+ public function getUrl(): ?string {
+ return $this->url;
+ }
+
+ public function setRichObject(string $type, ?array $richObject): void {
+ $this->richObjectType = $type;
+ $this->richObject = $richObject;
+ }
+
+ public function getRichObjectType(): string {
+ if ($this->richObjectType === null) {
+ return 'open-graph';
+ }
+ return $this->richObjectType;
+ }
+
+ public function getRichObject(): array {
+ if ($this->richObject === null) {
+ return $this->getOpenGraphObject();
+ }
+ return $this->richObject;
+ }
+
+ public function getOpenGraphObject(): array {
+ return [
+ 'id' => $this->getId(),
+ 'name' => $this->getTitle(),
+ 'description' => $this->getDescription(),
+ 'thumb' => $this->getImageUrl(),
+ 'link' => $this->getUrl()
+ ];
+ }
+
+ public static function toCache(IReference $reference): array {
+ return [
+ 'id' => $reference->getId(),
+ 'title' => $reference->getTitle(),
+ 'imageUrl' => $reference->getImageUrl(),
+ 'imageContentType' => $reference->getImageContentType(),
+ 'description' => $reference->getDescription(),
+ 'link' => $reference->getUrl(),
+ 'accessible' => $reference->getAccessible(),
+ 'richObjectType' => $reference->getRichObjectType(),
+ 'richObject' => $reference->getRichObject(),
+ ];
+ }
+
+ public static function fromCache(array $cache): IReference {
+ $reference = new Reference($cache['id']);
+ $reference->setTitle($cache['title']);
+ $reference->setDescription($cache['description']);
+ $reference->setImageUrl($cache['imageUrl']);
+ $reference->setImageContentType($cache['imageContentType']);
+ $reference->setUrl($cache['link']);
+ $reference->setRichObject($cache['richObjectType'], $cache['richObject']);
+ $reference->setAccessible($cache['accessible']);
+ return $reference;
+ }
+
+ public function jsonSerialize() {
+ return [
+ 'richObjectType' => $this->getRichObjectType(),
+ 'richObject' => $this->getRichObject(),
+ 'openGraphObject' => $this->getOpenGraphObject(),
+ 'accessible' => $this->accessible
+ ];
+ }
+}
diff --git a/lib/private/Collaboration/Reference/ReferenceManager.php b/lib/private/Collaboration/Reference/ReferenceManager.php
new file mode 100644
index 00000000000..304d693804f
--- /dev/null
+++ b/lib/private/Collaboration/Reference/ReferenceManager.php
@@ -0,0 +1,169 @@
+<?php
+
+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/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\Collaboration\Reference\File\FileReferenceProvider;
+use OCP\Collaboration\Reference\IReference;
+use OCP\Collaboration\Reference\IReferenceManager;
+use OCP\Collaboration\Reference\IReferenceProvider;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IURLGenerator;
+use Psr\Container\ContainerInterface;
+use Psr\Log\LoggerInterface;
+use Throwable;
+
+class ReferenceManager implements IReferenceManager {
+ public const CACHE_TTL = 3600;
+
+ /** @var IReferenceProvider[]|null */
+ private ?array $providers = null;
+ private ICache $cache;
+ private Coordinator $coordinator;
+ private ContainerInterface $container;
+ private LinkReferenceProvider $linkReferenceProvider;
+ private LoggerInterface $logger;
+
+ public function __construct(LinkReferenceProvider $linkReferenceProvider, ICacheFactory $cacheFactory, Coordinator $coordinator, ContainerInterface $container, LoggerInterface $logger) {
+ $this->linkReferenceProvider = $linkReferenceProvider;
+ $this->cache = $cacheFactory->createDistributed('reference');
+ $this->coordinator = $coordinator;
+ $this->container = $container;
+ $this->logger = $logger;
+ }
+
+ public function extractReferences(string $text): array {
+ preg_match_all(IURLGenerator::URL_REGEX, $text, $matches);
+ $references = $matches[0] ?? [];
+ return array_map(function ($reference) {
+ return trim($reference);
+ }, $references);
+ }
+
+ public function getReferenceFromCache(string $referenceId): ?IReference {
+ $matchedProvider = $this->getMatchedProvider($referenceId);
+
+ if ($matchedProvider === null) {
+ return null;
+ }
+
+ $cacheKey = $this->getFullCacheKey($matchedProvider, $referenceId);
+ return $this->getReferenceByCacheKey($cacheKey);
+ }
+
+ public function getReferenceByCacheKey(string $cacheKey): ?IReference {
+ $cached = $this->cache->get($cacheKey);
+ if ($cached) {
+ return Reference::fromCache($cached);
+ }
+
+ return null;
+ }
+
+ public function resolveReference(string $referenceId): ?IReference {
+ $matchedProvider = $this->getMatchedProvider($referenceId);
+
+ if ($matchedProvider === null) {
+ return null;
+ }
+
+ $cacheKey = $this->getFullCacheKey($matchedProvider, $referenceId);
+ $cached = $this->cache->get($cacheKey);
+ if ($cached) {
+ return Reference::fromCache($cached);
+ }
+
+ $reference = $matchedProvider->resolveReference($referenceId);
+ if ($reference) {
+ $this->cache->set($cacheKey, Reference::toCache($reference), self::CACHE_TTL);
+ return $reference;
+ }
+
+ return null;
+ }
+
+ private function getMatchedProvider(string $referenceId): ?IReferenceProvider {
+ $matchedProvider = null;
+ foreach ($this->getProviders() as $provider) {
+ $matchedProvider = $provider->matchReference($referenceId) ? $provider : null;
+ if ($matchedProvider !== null) {
+ break;
+ }
+ }
+
+ if ($matchedProvider === null && $this->linkReferenceProvider->matchReference($referenceId)) {
+ $matchedProvider = $this->linkReferenceProvider;
+ }
+
+ return $matchedProvider;
+ }
+
+ private function getFullCacheKey(IReferenceProvider $provider, string $referenceId): string {
+ $cacheKey = $provider->getCacheKey($referenceId);
+ return md5($provider->getCachePrefix($referenceId)) . (
+ $cacheKey !== null ? ('-' . md5($cacheKey)) : ''
+ );
+ }
+
+ public function invalidateCache(string $cachePrefix, ?string $cacheKey = null): void {
+ if ($cacheKey === null) {
+ $this->cache->clear(md5($cachePrefix));
+ return;
+ }
+
+ $this->cache->remove(md5($cachePrefix) . '-' . md5($cacheKey));
+ }
+
+ /**
+ * @return IReferenceProvider[]
+ */
+ public function getProviders(): array {
+ if ($this->providers === null) {
+ $context = $this->coordinator->getRegistrationContext();
+ if ($context === null) {
+ return [];
+ }
+
+ $this->providers = array_filter(array_map(function ($registration): ?IReferenceProvider {
+ try {
+ /** @var IReferenceProvider $provider */
+ $provider = $this->container->get($registration->getService());
+ } catch (Throwable $e) {
+ $this->logger->error('Could not load reference provider ' . $registration->getService() . ': ' . $e->getMessage(), [
+ 'exception' => $e,
+ ]);
+ return null;
+ }
+
+ return $provider;
+ }, $context->getReferenceProviders()));
+
+ $this->providers[] = $this->container->get(FileReferenceProvider::class);
+ }
+
+ return $this->providers;
+ }
+}
diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php
index 0128dc8defd..c481e36f95b 100644
--- a/lib/private/Comments/Comment.php
+++ b/lib/private/Comments/Comment.php
@@ -351,13 +351,9 @@ class Comment implements IComment {
}
/**
- * sets the date of the most recent child
- *
- * @param \DateTime $dateTime
- * @return IComment
- * @since 9.0.0
+ * @inheritDoc
*/
- public function setLatestChildDateTime(\DateTime $dateTime = null) {
+ public function setLatestChildDateTime(?\DateTime $dateTime = null) {
$this->data['latestChildDT'] = $dateTime;
return $this;
}
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index f21f9ec76b2..53603e51e56 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -170,7 +170,6 @@ class Manager implements ICommentsManager {
if ($comment->getId() === '') {
$comment->setChildrenCount(0);
- $comment->setLatestChildDateTime(new \DateTime('0000-00-00 00:00:00', new \DateTimeZone('UTC')));
$comment->setLatestChildDateTime(null);
}
@@ -1650,14 +1649,18 @@ class Manager implements ICommentsManager {
/**
* @inheritDoc
*/
- public function deleteMessageExpiredAtObject(string $objectType, string $objectId): bool {
+ public function deleteCommentsExpiredAtObject(string $objectType, string $objectId = ''): bool {
$qb = $this->dbConn->getQueryBuilder();
- $affectedRows = $qb->delete('comments')
- ->where($qb->expr()->lt('expire_date',
+ $qb->delete('comments')
+ ->where($qb->expr()->lte('expire_date',
$qb->createNamedParameter($this->timeFactory->getDateTime(), IQueryBuilder::PARAM_DATE)))
- ->andWhere($qb->expr()->eq('object_type', $qb->createNamedParameter($objectType)))
- ->andWhere($qb->expr()->eq('object_id', $qb->createNamedParameter($objectId)))
- ->executeStatement();
+ ->andWhere($qb->expr()->eq('object_type', $qb->createNamedParameter($objectType)));
+
+ if ($objectId !== '') {
+ $qb->andWhere($qb->expr()->eq('object_id', $qb->createNamedParameter($objectId)));
+ }
+
+ $affectedRows = $qb->executeStatement();
$this->commentsCache = [];
diff --git a/lib/private/Config.php b/lib/private/Config.php
index b044d0731a3..37708357339 100644
--- a/lib/private/Config.php
+++ b/lib/private/Config.php
@@ -231,6 +231,14 @@ class Config {
unset($CONFIG);
include $file;
+ 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));
+ if (!defined('OC_CONSOLE')) {
+ print(\OCP\Util::sanitizeHTML($errorMessage));
+ }
+ throw new \Exception($errorMessage);
+ }
if (isset($CONFIG) && is_array($CONFIG)) {
$this->cache = array_merge($this->cache, $CONFIG);
}
diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php
index 12d54b48fa9..fc48f57e499 100644
--- a/lib/private/Console/Application.php
+++ b/lib/private/Console/Application.php
@@ -34,6 +34,7 @@ use OC\MemoryInfo;
use OC\NeedsUpdateException;
use OC_App;
use OCP\AppFramework\QueryException;
+use OCP\App\IAppManager;
use OCP\Console\ConsoleEvent;
use OCP\IConfig;
use OCP\IRequest;
@@ -117,13 +118,14 @@ class Application {
$this->writeMaintenanceModeInfo($input, $output);
} else {
OC_App::loadApps();
- foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
+ $appManager = \OCP\Server::get(IAppManager::class);
+ foreach ($appManager->getInstalledApps() as $app) {
$appPath = \OC_App::getAppPath($app);
if ($appPath === false) {
continue;
}
// load commands using info.xml
- $info = \OC_App::getAppInfo($app);
+ $info = $appManager->getAppInfo($app);
if (isset($info['commands'])) {
$this->loadCommandsFromInfoXml($info['commands']);
}
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index 020e8604910..dd4bd973fa9 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -123,7 +123,7 @@ class ContactsStore implements IContactsStore {
* 2. if the `shareapi_exclude_groups` config option is enabled and the
* current user is in an excluded group it will filter all local users.
* 3. if the `shareapi_only_share_with_group_members` config option is
- * enabled it will filter all users which doens't have a common group
+ * enabled it will filter all users which doesn't have a common group
* with the current user.
*
* @param IUser $self
@@ -150,7 +150,7 @@ class ContactsStore implements IContactsStore {
$selfGroups = $this->groupManager->getUserGroupIds($self);
if ($excludedGroups) {
- $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list');
+ $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$decodedExcludeGroups = json_decode($excludedGroups, true);
$excludeGroupsList = $decodedExcludeGroups ?? [];
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index 22c2bbbb793..73e0f4b4ac2 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -588,7 +588,7 @@ class Connection extends \Doctrine\DBAL\Connection {
$random = \OC::$server->getSecureRandom();
$platform = $this->getDatabasePlatform();
$config = \OC::$server->getConfig();
- $dispatcher = \OC::$server->getEventDispatcher();
+ $dispatcher = \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class);
if ($platform instanceof SqlitePlatform) {
return new SQLiteMigrator($this, $config, $dispatcher);
} elseif ($platform instanceof OraclePlatform) {
diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php
index 13bbe8dc5d0..4b7e4d3a040 100644
--- a/lib/private/DB/MigrationService.php
+++ b/lib/private/DB/MigrationService.php
@@ -45,35 +45,25 @@ use OCP\Migration\IOutput;
use Psr\Log\LoggerInterface;
class MigrationService {
-
- /** @var boolean */
- private $migrationTableCreated;
- /** @var array */
- private $migrations;
- /** @var IOutput */
- private $output;
- /** @var Connection */
- private $connection;
- /** @var string */
- private $appName;
- /** @var bool */
- private $checkOracle;
+ private bool $migrationTableCreated;
+ private array $migrations;
+ private string $migrationsPath;
+ private string $migrationsNamespace;
+ private IOutput $output;
+ private Connection $connection;
+ private string $appName;
+ private bool $checkOracle;
/**
- * MigrationService constructor.
- *
- * @param $appName
- * @param Connection $connection
- * @param AppLocator $appLocator
- * @param IOutput|null $output
* @throws \Exception
*/
- public function __construct($appName, Connection $connection, IOutput $output = null, AppLocator $appLocator = null) {
+ public function __construct($appName, Connection $connection, ?IOutput $output = null, ?AppLocator $appLocator = null) {
$this->appName = $appName;
$this->connection = $connection;
- $this->output = $output;
- if (null === $this->output) {
+ if ($output === null) {
$this->output = new SimpleOutput(\OC::$server->get(LoggerInterface::class), $appName);
+ } else {
+ $this->output = $output;
}
if ($appName === 'core') {
@@ -104,6 +94,7 @@ class MigrationService {
}
}
}
+ $this->migrationTableCreated = false;
}
/**
diff --git a/lib/private/DB/Migrator.php b/lib/private/DB/Migrator.php
index 9ca37d7180a..5dc07be1d2b 100644
--- a/lib/private/DB/Migrator.php
+++ b/lib/private/DB/Migrator.php
@@ -27,48 +27,41 @@
*/
namespace OC\DB;
+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\IConfig;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
use function preg_match;
+use OCP\EventDispatcher\IEventDispatcher;
class Migrator {
- /** @var \Doctrine\DBAL\Connection */
+ /** @var Connection */
protected $connection;
/** @var IConfig */
protected $config;
- /** @var EventDispatcherInterface */
- private $dispatcher;
+ private ?IEventDispatcher $dispatcher;
/** @var bool */
private $noEmit = false;
- /**
- * @param \Doctrine\DBAL\Connection $connection
- * @param IConfig $config
- * @param EventDispatcherInterface $dispatcher
- */
- public function __construct(\Doctrine\DBAL\Connection $connection,
+ public function __construct(Connection $connection,
IConfig $config,
- EventDispatcherInterface $dispatcher = null) {
+ ?IEventDispatcher $dispatcher = null) {
$this->connection = $connection;
$this->config = $config;
$this->dispatcher = $dispatcher;
}
/**
- * @param \Doctrine\DBAL\Schema\Schema $targetSchema
- *
* @throws Exception
*/
public function migrate(Schema $targetSchema) {
@@ -77,7 +70,6 @@ class Migrator {
}
/**
- * @param \Doctrine\DBAL\Schema\Schema $targetSchema
* @return string
*/
public function generateChangeScript(Schema $targetSchema) {
@@ -108,11 +100,9 @@ class Migrator {
}
/**
- * @param Schema $targetSchema
- * @param \Doctrine\DBAL\Connection $connection
- * @return \Doctrine\DBAL\Schema\SchemaDiff
+ * @return SchemaDiff
*/
- protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
+ protected function getDiff(Schema $targetSchema, Connection $connection) {
// adjust varchar columns with a length higher then getVarcharMaxLength to clob
foreach ($targetSchema->getTables() as $table) {
foreach ($table->getColumns() as $column) {
@@ -153,12 +143,9 @@ class Migrator {
}
/**
- * @param \Doctrine\DBAL\Schema\Schema $targetSchema
- * @param \Doctrine\DBAL\Connection $connection
- *
* @throws Exception
*/
- protected function applySchema(Schema $targetSchema, \Doctrine\DBAL\Connection $connection = null) {
+ protected function applySchema(Schema $targetSchema, Connection $connection = null) {
if (is_null($connection)) {
$connection = $this->connection;
}
@@ -194,13 +181,13 @@ class Migrator {
return '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/';
}
- protected function emit($sql, $step, $max) {
+ protected function emit(string $sql, int $step, int $max): void {
if ($this->noEmit) {
return;
}
if (is_null($this->dispatcher)) {
return;
}
- $this->dispatcher->dispatch('\OC\DB\Migrator::executeSql', new GenericEvent($sql, [$step + 1, $max]));
+ $this->dispatcher->dispatchTyped(new MigratorExecuteSqlEvent($sql, $step, $max));
}
}
diff --git a/lib/private/DB/MigratorExecuteSqlEvent.php b/lib/private/DB/MigratorExecuteSqlEvent.php
new file mode 100644
index 00000000000..997a4eee53a
--- /dev/null
+++ b/lib/private/DB/MigratorExecuteSqlEvent.php
@@ -0,0 +1,55 @@
+<?php
+
+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/>
+ *
+ */
+namespace OC\DB;
+
+use OCP\EventDispatcher\Event;
+
+class MigratorExecuteSqlEvent extends Event {
+ private string $sql;
+ private int $current;
+ private int $max;
+
+ public function __construct(
+ string $sql,
+ int $current,
+ int $max
+ ) {
+ $this->sql = $sql;
+ $this->current = $current;
+ $this->max = $max;
+ }
+
+ public function getSql(): string {
+ return $this->sql;
+ }
+
+ public function getCurrentStep(): int {
+ return $this->current;
+ }
+
+ public function getMaxStep(): int {
+ return $this->max;
+ }
+}
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
index 333984bde71..ae4f19f5d18 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
@@ -114,12 +114,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function comparison($x, string $operator, $y, $type = null): IQueryFunction {
+ public function comparison($x, string $operator, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->comparison($x, $operator, $y));
+ return $this->expressionBuilder->comparison($x, $operator, $y);
}
/**
@@ -137,12 +137,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function eq($x, $y, $type = null): IQueryFunction {
+ public function eq($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->eq($x, $y));
+ return $this->expressionBuilder->eq($x, $y);
}
/**
@@ -159,12 +159,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function neq($x, $y, $type = null): IQueryFunction {
+ public function neq($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->neq($x, $y));
+ return $this->expressionBuilder->neq($x, $y);
}
/**
@@ -181,12 +181,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function lt($x, $y, $type = null): IQueryFunction {
+ public function lt($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->lt($x, $y));
+ return $this->expressionBuilder->lt($x, $y);
}
/**
@@ -203,12 +203,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function lte($x, $y, $type = null): IQueryFunction {
+ public function lte($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->lte($x, $y));
+ return $this->expressionBuilder->lte($x, $y);
}
/**
@@ -225,12 +225,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function gt($x, $y, $type = null): IQueryFunction {
+ public function gt($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->gt($x, $y));
+ return $this->expressionBuilder->gt($x, $y);
}
/**
@@ -247,12 +247,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function gte($x, $y, $type = null): IQueryFunction {
+ public function gte($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->gte($x, $y));
+ return $this->expressionBuilder->gte($x, $y);
}
/**
@@ -260,11 +260,11 @@ class ExpressionBuilder implements IExpressionBuilder {
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be restricted by IS NULL.
*
- * @return IQueryFunction
+ * @return string
*/
- public function isNull($x): IQueryFunction {
+ public function isNull($x): string {
$x = $this->helper->quoteColumnName($x);
- return new QueryFunction($this->expressionBuilder->isNull($x));
+ return $this->expressionBuilder->isNull($x);
}
/**
@@ -272,11 +272,11 @@ class ExpressionBuilder implements IExpressionBuilder {
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be restricted by IS NOT NULL.
*
- * @return IQueryFunction
+ * @return string
*/
- public function isNotNull($x): IQueryFunction {
+ public function isNotNull($x): string {
$x = $this->helper->quoteColumnName($x);
- return new QueryFunction($this->expressionBuilder->isNotNull($x));
+ return $this->expressionBuilder->isNotNull($x);
}
/**
@@ -287,12 +287,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function like($x, $y, $type = null): IQueryFunction {
+ public function like($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->like($x, $y));
+ return $this->expressionBuilder->like($x, $y);
}
/**
@@ -303,11 +303,11 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 9.0.0
*/
- public function iLike($x, $y, $type = null): IQueryFunction {
- return new QueryFunction($this->expressionBuilder->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y)));
+ public function iLike($x, $y, $type = null): string {
+ return $this->expressionBuilder->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y));
}
/**
@@ -318,12 +318,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function notLike($x, $y, $type = null): IQueryFunction {
+ public function notLike($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->notLike($x, $y));
+ return $this->expressionBuilder->notLike($x, $y);
}
/**
@@ -334,12 +334,12 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function in($x, $y, $type = null): IQueryFunction {
+ public function in($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnNames($y);
- return new QueryFunction($this->expressionBuilder->in($x, $y));
+ return $this->expressionBuilder->in($x, $y);
}
/**
@@ -350,34 +350,34 @@ class ExpressionBuilder implements IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
*/
- public function notIn($x, $y, $type = null): IQueryFunction {
+ public function notIn($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnNames($y);
- return new QueryFunction($this->expressionBuilder->notIn($x, $y));
+ return $this->expressionBuilder->notIn($x, $y);
}
/**
* Creates a $x = '' statement, because Oracle needs a different check
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison.
- * @return IQueryFunction
+ * @return string
* @since 13.0.0
*/
- public function emptyString($x): IQueryFunction {
- return new QueryFunction($this->eq($x, $this->literal('', IQueryBuilder::PARAM_STR)));
+ public function emptyString($x): string {
+ return $this->eq($x, $this->literal('', IQueryBuilder::PARAM_STR));
}
/**
* Creates a `$x <> ''` statement, because Oracle needs a different check
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison.
- * @return IQueryFunction
+ * @return string
* @since 13.0.0
*/
- public function nonEmptyString($x): IQueryFunction {
- return new QueryFunction($this->neq($x, $this->literal('', IQueryBuilder::PARAM_STR)));
+ public function nonEmptyString($x): string {
+ return $this->neq($x, $this->literal('', IQueryBuilder::PARAM_STR));
}
/**
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
index 74209d0c3da..3bb54d4b26e 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
@@ -49,10 +49,10 @@ class MySqlExpressionBuilder extends ExpressionBuilder {
/**
* @inheritdoc
*/
- public function iLike($x, $y, $type = null): IQueryFunction {
+ public function iLike($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->comparison($x, ' COLLATE ' . $this->collation . ' LIKE', $y));
+ return $this->expressionBuilder->comparison($x, ' COLLATE ' . $this->collation . ' LIKE', $y);
}
/**
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php
index 20d68b30b33..f9b58d7d8ed 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php
@@ -49,101 +49,101 @@ class OCIExpressionBuilder extends ExpressionBuilder {
/**
* @inheritdoc
*/
- public function comparison($x, string $operator, $y, $type = null): IQueryFunction {
+ public function comparison($x, string $operator, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->comparison($x, $operator, $y));
+ return $this->expressionBuilder->comparison($x, $operator, $y);
}
/**
* @inheritdoc
*/
- public function eq($x, $y, $type = null): IQueryFunction {
+ public function eq($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->eq($x, $y));
+ return $this->expressionBuilder->eq($x, $y);
}
/**
* @inheritdoc
*/
- public function neq($x, $y, $type = null): IQueryFunction {
+ public function neq($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->neq($x, $y));
+ return $this->expressionBuilder->neq($x, $y);
}
/**
* @inheritdoc
*/
- public function lt($x, $y, $type = null): IQueryFunction {
+ public function lt($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->lt($x, $y));
+ return $this->expressionBuilder->lt($x, $y);
}
/**
* @inheritdoc
*/
- public function lte($x, $y, $type = null): IQueryFunction {
+ public function lte($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->lte($x, $y));
+ return $this->expressionBuilder->lte($x, $y);
}
/**
* @inheritdoc
*/
- public function gt($x, $y, $type = null): IQueryFunction {
+ public function gt($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->gt($x, $y));
+ return $this->expressionBuilder->gt($x, $y);
}
/**
* @inheritdoc
*/
- public function gte($x, $y, $type = null): IQueryFunction {
+ public function gte($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->gte($x, $y));
+ return $this->expressionBuilder->gte($x, $y);
}
/**
* @inheritdoc
*/
- public function in($x, $y, $type = null): IQueryFunction {
+ public function in($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->in($x, $y));
+ return $this->expressionBuilder->in($x, $y);
}
/**
* @inheritdoc
*/
- public function notIn($x, $y, $type = null): IQueryFunction {
+ public function notIn($x, $y, $type = null): string {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
- return new QueryFunction($this->expressionBuilder->notIn($x, $y));
+ return $this->expressionBuilder->notIn($x, $y);
}
/**
* Creates a $x = '' statement, because Oracle needs a different check
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison.
- * @return IQueryFunction
+ * @return string
* @since 13.0.0
*/
- public function emptyString($x): IQueryFunction {
+ public function emptyString($x): string {
return $this->isNull($x);
}
@@ -151,10 +151,10 @@ class OCIExpressionBuilder extends ExpressionBuilder {
* Creates a `$x <> ''` statement, because Oracle needs a different check
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison.
- * @return IQueryFunction
+ * @return string
* @since 13.0.0
*/
- public function nonEmptyString($x): IQueryFunction {
+ public function nonEmptyString($x): string {
return $this->isNotNull($x);
}
@@ -182,14 +182,14 @@ class OCIExpressionBuilder extends ExpressionBuilder {
/**
* @inheritdoc
*/
- public function like($x, $y, $type = null): IQueryFunction {
- return new QueryFunction(parent::like($x, $y, $type) . " ESCAPE '\\'");
+ public function like($x, $y, $type = null): string {
+ return parent::like($x, $y, $type) . " ESCAPE '\\'";
}
/**
* @inheritdoc
*/
- public function iLike($x, $y, $type = null): IQueryFunction {
+ public function iLike($x, $y, $type = null): string {
return $this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y));
}
}
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php
index cbebe97ae87..0fba5363a28 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php
@@ -52,9 +52,9 @@ class PgSqlExpressionBuilder extends ExpressionBuilder {
/**
* @inheritdoc
*/
- public function iLike($x, $y, $type = null): IQueryFunction {
+ public function iLike($x, $y, $type = null): string {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return new QueryFunction($this->expressionBuilder->comparison($x, 'ILIKE', $y));
+ return $this->expressionBuilder->comparison($x, 'ILIKE', $y);
}
}
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
index 5425138fa6c..289aa09b003 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
@@ -23,18 +23,15 @@
*/
namespace OC\DB\QueryBuilder\ExpressionBuilder;
-use OC\DB\QueryBuilder\QueryFunction;
-use OCP\DB\QueryBuilder\IQueryFunction;
-
class SqliteExpressionBuilder extends ExpressionBuilder {
/**
* @inheritdoc
*/
- public function like($x, $y, $type = null): IQueryFunction {
- return new QueryFunction(parent::like($x, $y, $type) . " ESCAPE '\\'");
+ public function like($x, $y, $type = null): string {
+ return parent::like($x, $y, $type) . " ESCAPE '\\'";
}
- public function iLike($x, $y, $type = null): IQueryFunction {
- return new QueryFunction($this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y), $type));
+ public function iLike($x, $y, $type = null): string {
+ return $this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y), $type);
}
}
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
index 408a879d624..e0a7549a0ad 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
@@ -121,15 +121,4 @@ class FunctionBuilder implements IFunctionBuilder {
public function least($x, $y): IQueryFunction {
return new QueryFunction('LEAST(' . $this->helper->quoteColumnName($x) . ', ' . $this->helper->quoteColumnName($y) . ')');
}
-
- public function case(array $whens, $else): IQueryFunction {
- if (count($whens) < 1) {
- return new QueryFunction($this->helper->quoteColumnName($else));
- }
-
- $whenParts = array_map(function (array $when) {
- return 'WHEN ' . $this->helper->quoteColumnName($when['when']) . ' THEN ' . $this->helper->quoteColumnName($when['then']);
- }, $whens);
- return new QueryFunction('CASE ' . implode(' ', $whenParts) . ' ELSE ' . $this->helper->quoteColumnName($else) . ' END');
- }
}
diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php
index 8fc66755a99..e81ba61b3a7 100644
--- a/lib/private/DB/QueryBuilder/QueryBuilder.php
+++ b/lib/private/DB/QueryBuilder/QueryBuilder.php
@@ -715,12 +715,11 @@ class QueryBuilder implements IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
*/
public function join($fromAlias, $join, $alias, $condition = null) {
- $condition = $condition !== null ? (string)$condition : null;
$this->queryBuilder->join(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
@@ -744,12 +743,11 @@ class QueryBuilder implements IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
*/
public function innerJoin($fromAlias, $join, $alias, $condition = null) {
- $condition = $condition !== null ? (string)$condition : null;
$this->queryBuilder->innerJoin(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
@@ -773,12 +771,11 @@ class QueryBuilder implements IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
*/
public function leftJoin($fromAlias, $join, $alias, $condition = null) {
- $condition = $condition !== null ? (string)$condition : null;
$this->queryBuilder->leftJoin(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
@@ -802,12 +799,11 @@ class QueryBuilder implements IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
*/
public function rightJoin($fromAlias, $join, $alias, $condition = null) {
- $condition = $condition !== null ? (string)$condition : null;
$this->queryBuilder->rightJoin(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
@@ -852,7 +848,7 @@ class QueryBuilder implements IQueryBuilder {
* ->from('users', 'u')
* ->where('u.id = ?');
*
- * // You can optionally programatically build and/or expressions
+ * // You can optionally programmatically build and/or expressions
* $qb = $conn->getQueryBuilder();
*
* $or = $qb->expr()->orx();
diff --git a/lib/private/Diagnostics/QueryLogger.php b/lib/private/Diagnostics/QueryLogger.php
index 40d68d94ae3..5f401751077 100644
--- a/lib/private/Diagnostics/QueryLogger.php
+++ b/lib/private/Diagnostics/QueryLogger.php
@@ -24,7 +24,7 @@
*/
namespace OC\Diagnostics;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCP\Diagnostics\IQueryLogger;
class QueryLogger implements IQueryLogger {
diff --git a/lib/private/Encryption/File.php b/lib/private/Encryption/File.php
index 2d7e23a8883..87bc35bc159 100644
--- a/lib/private/Encryption/File.php
+++ b/lib/private/Encryption/File.php
@@ -27,29 +27,24 @@
*/
namespace OC\Encryption;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCA\Files_External\Service\GlobalStoragesService;
+use OCP\App\IAppManager;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Share\IManager;
class File implements \OCP\Encryption\IFile {
-
- /** @var Util */
- protected $util;
-
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IManager */
- private $shareManager;
+ protected Util $util;
+ private IRootFolder $rootFolder;
+ private IManager $shareManager;
/**
- * cache results of already checked folders
- *
+ * Cache results of already checked folders
* @var CappedMemoryCache<array>
*/
protected CappedMemoryCache $cache;
+ private ?IAppManager $appManager = null;
public function __construct(Util $util,
IRootFolder $rootFolder,
@@ -60,6 +55,14 @@ class File implements \OCP\Encryption\IFile {
$this->shareManager = $shareManager;
}
+ public function getAppManager(): IAppManager {
+ // Lazy evaluate app manager as it initialize the db too early otherwise
+ if ($this->appManager) {
+ return $this->appManager;
+ }
+ $this->appManager = \OCP\Server::get(IAppManager::class);
+ return $this->appManager;
+ }
/**
* Get list of users with access to the file
@@ -110,7 +113,7 @@ class File implements \OCP\Encryption\IFile {
}
// check if it is a group mount
- if (\OCP\App::isEnabled("files_external")) {
+ if ($this->getAppManager()->isEnabledForUser("files_external")) {
/** @var GlobalStoragesService $storageService */
$storageService = \OC::$server->get(GlobalStoragesService::class);
$storages = $storageService->getAllStorages();
diff --git a/lib/private/Encryption/Util.php b/lib/private/Encryption/Util.php
index 174af2e8b89..bf7bbce8ad7 100644
--- a/lib/private/Encryption/Util.php
+++ b/lib/private/Encryption/Util.php
@@ -32,11 +32,12 @@ use OC\Encryption\Exceptions\EncryptionHeaderToLargeException;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
use OC\Files\Filesystem;
use OC\Files\View;
-use OCA\Files_External\Lib\StorageConfig;
-use OCA\Files_External\Service\GlobalStoragesService;
use OCP\Encryption\IEncryptionModule;
+use OCP\Files\Mount\ISystemMountPoint;
use OCP\IConfig;
+use OCP\IGroupManager;
use OCP\IUser;
+use OCP\IUserManager;
class Util {
public const HEADER_START = 'HBEGIN';
@@ -65,29 +66,23 @@ class Util {
/** @var array */
protected $ocHeaderKeys;
- /** @var \OC\User\Manager */
- protected $userManager;
-
/** @var IConfig */
protected $config;
/** @var array paths excluded from encryption */
protected $excludedPaths;
-
- /** @var \OC\Group\Manager $manager */
- protected $groupManager;
+ protected IGroupManager $groupManager;
+ protected IUserManager $userManager;
/**
*
* @param View $rootView
- * @param \OC\User\Manager $userManager
- * @param \OC\Group\Manager $groupManager
* @param IConfig $config
*/
public function __construct(
View $rootView,
- \OC\User\Manager $userManager,
- \OC\Group\Manager $groupManager,
+ IUserManager $userManager,
+ IGroupManager $groupManager,
IConfig $config) {
$this->ocHeaderKeys = [
self::HEADER_ENCRYPTION_MODULE_KEY
@@ -275,7 +270,7 @@ class Util {
} else {
$result = array_merge($result, $users);
- $groupManager = \OC::$server->getGroupManager();
+ $groupManager = $this->groupManager;
foreach ($groups as $group) {
$groupObject = $groupManager->get($group);
if ($groupObject) {
@@ -298,45 +293,9 @@ class Util {
* @param string $uid
* @return boolean
*/
- public function isSystemWideMountPoint($path, $uid) {
- if (\OCP\App::isEnabled("files_external")) {
- /** @var GlobalStoragesService $storageService */
- $storageService = \OC::$server->get(GlobalStoragesService::class);
- $storages = $storageService->getAllStorages();
- foreach ($storages as $storage) {
- if (strpos($path, '/files/' . ltrim($storage->getMountPoint(), '/')) === 0) {
- if ($this->isMountPointApplicableToUser($storage, $uid)) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * check if mount point is applicable to user
- *
- * @param StorageConfig $mount
- * @param string $uid
- * @return boolean
- */
- private function isMountPointApplicableToUser(StorageConfig $mount, string $uid) {
- if ($mount->getApplicableUsers() === [] && $mount->getApplicableGroups() === []) {
- // applicable for everyone
- return true;
- }
- // check if mount point is applicable for the user
- if (array_search($uid, $mount->getApplicableUsers()) !== false) {
- return true;
- }
- // check if mount point is applicable for group where the user is a member
- foreach ($mount->getApplicableGroups() as $gid) {
- if ($this->groupManager->isInGroup($uid, $gid)) {
- return true;
- }
- }
- return false;
+ public function isSystemWideMountPoint(string $path, string $uid) {
+ $mount = Filesystem::getMountManager()->find('/' . $uid . $path);
+ return $mount instanceof ISystemMountPoint;
}
/**
@@ -377,32 +336,29 @@ class Util {
}
/**
- * check if recovery key is enabled for user
- *
- * @param string $uid
- * @return boolean
+ * Check if recovery key is enabled for user
*/
- public function recoveryEnabled($uid) {
+ public function recoveryEnabled(string $uid): bool {
$enabled = $this->config->getUserValue($uid, 'encryption', 'recovery_enabled', '0');
return $enabled === '1';
}
/**
- * set new key storage root
+ * Set new key storage root
*
* @param string $root new key store root relative to the data folder
*/
- public function setKeyStorageRoot($root) {
+ public function setKeyStorageRoot(string $root): void {
$this->config->setAppValue('core', 'encryption_key_storage_root', $root);
}
/**
- * get key storage root
+ * Get key storage root
*
* @return string key storage root
*/
- public function getKeyStorageRoot() {
+ public function getKeyStorageRoot(): string {
return $this->config->getAppValue('core', 'encryption_key_storage_root', '');
}
}
diff --git a/lib/private/Files/AppData/AppData.php b/lib/private/Files/AppData/AppData.php
index 471de799c2f..237fcb42e03 100644
--- a/lib/private/Files/AppData/AppData.php
+++ b/lib/private/Files/AppData/AppData.php
@@ -26,7 +26,7 @@ declare(strict_types=1);
*/
namespace OC\Files\AppData;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OC\Files\SimpleFS\SimpleFolder;
use OC\SystemConfig;
use OCP\Files\Folder;
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php
index c6cadf14f86..ec284282178 100644
--- a/lib/private/Files/Cache/Cache.php
+++ b/lib/private/Files/Cache/Cache.php
@@ -64,7 +64,7 @@ use Psr\Log\LoggerInterface;
/**
* Metadata cache for a storage
*
- * The cache stores the metadata for all files and folders in a storage and is kept up to date trough the following mechanisms:
+ * The cache stores the metadata for all files and folders in a storage and is kept up to date through the following mechanisms:
*
* - Scanner: scans the storage and updates the cache where needed
* - Watcher: checks for changes made to the filesystem outside of the Nextcloud instance and rescans files and folder when a change is detected
@@ -540,7 +540,7 @@ class Cache implements ICache {
public function remove($file) {
$entry = $this->get($file);
- if ($entry) {
+ if ($entry instanceof ICacheEntry) {
$query = $this->getQueryBuilder();
$query->delete('filecache')
->whereFileId($entry->getId());
@@ -582,7 +582,7 @@ class Cache implements ICache {
$parentIds = [$entry->getId()];
$queue = [$entry->getId()];
- // we walk depth first trough the file tree, removing all filecache_extended attributes while we walk
+ // we walk depth first through the file tree, removing all filecache_extended attributes while we walk
// and collecting all folder ids to later use to delete the filecache entries
while ($entryId = array_pop($queue)) {
$children = $this->getFolderContentsById($entryId);
@@ -875,26 +875,32 @@ class Cache implements ICache {
$id = $entry['fileid'];
$query = $this->getQueryBuilder();
- $query->selectAlias($query->func()->sum('size'), 'size_sum')
- ->selectAlias($query->func()->min('size'), 'size_min')
- // in case of encryption being enabled after some files are already uploaded, some entries will have an unencrypted_size of 0 and a non-zero size
- ->selectAlias($query->func()->sum(
- $query->func()->case([
- ['when' => $query->expr()->eq('unencrypted_size', $query->expr()->literal(0, IQueryBuilder::PARAM_INT)), 'then' => 'size'],
- ], 'unencrypted_size')
- ), 'unencrypted_sum')
- ->selectAlias($query->func()->min('unencrypted_size'), 'unencrypted_min')
- ->selectAlias($query->func()->max('unencrypted_size'), 'unencrypted_max')
+ $query->select('size', 'unencrypted_size')
->from('filecache')
- ->whereStorageId($this->getNumericStorageId())
->whereParent($id);
$result = $query->execute();
- $row = $result->fetch();
+ $rows = $result->fetchAll();
$result->closeCursor();
- if ($row) {
- ['size_sum' => $sum, 'size_min' => $min, 'unencrypted_sum' => $unencryptedSum, 'unencrypted_min' => $unencryptedMin, 'unencrypted_max' => $unencryptedMax] = $row;
+ if ($rows) {
+ $sizes = array_map(function (array $row) {
+ return (int)$row['size'];
+ }, $rows);
+ $unencryptedOnlySizes = array_map(function (array $row) {
+ return (int)$row['unencrypted_size'];
+ }, $rows);
+ $unencryptedSizes = array_map(function (array $row) {
+ return (int)(($row['unencrypted_size'] > 0) ? $row['unencrypted_size'] : $row['size']);
+ }, $rows);
+
+ $sum = array_sum($sizes);
+ $min = min($sizes);
+
+ $unencryptedSum = array_sum($unencryptedSizes);
+ $unencryptedMin = min($unencryptedSizes);
+ $unencryptedMax = max($unencryptedOnlySizes);
+
$sum = 0 + $sum;
$min = 0 + $min;
if ($min === -1) {
@@ -907,18 +913,22 @@ class Cache implements ICache {
} else {
$unencryptedTotal = $unencryptedSum;
}
- if ($entry['size'] !== $totalSize) {
- // only set unencrypted size for a folder if any child entries have it set
- if ($unencryptedMax > 0) {
- $this->update($id, [
- 'size' => $totalSize,
- 'unencrypted_size' => $unencryptedTotal,
- ]);
- } else {
- $this->update($id, [
- 'size' => $totalSize,
- ]);
- }
+ } else {
+ $totalSize = 0;
+ $unencryptedTotal = 0;
+ $unencryptedMax = 0;
+ }
+ if ($entry['size'] !== $totalSize) {
+ // only set unencrypted size for a folder if any child entries have it set, or the folder is empty
+ if ($unencryptedMax > 0 || $totalSize === 0) {
+ $this->update($id, [
+ 'size' => $totalSize,
+ 'unencrypted_size' => $unencryptedTotal,
+ ]);
+ } else {
+ $this->update($id, [
+ 'size' => $totalSize,
+ ]);
}
}
}
@@ -952,7 +962,7 @@ class Cache implements ICache {
* use the one with the highest id gives the best result with the background scanner, since that is most
* likely the folder where we stopped scanning previously
*
- * @return string|bool the path of the folder or false when no folder matched
+ * @return string|false the path of the folder or false when no folder matched
*/
public function getIncomplete() {
$query = $this->getQueryBuilder();
diff --git a/lib/private/Files/Cache/CacheQueryBuilder.php b/lib/private/Files/Cache/CacheQueryBuilder.php
index b92e79aa229..496a8361d77 100644
--- a/lib/private/Files/Cache/CacheQueryBuilder.php
+++ b/lib/private/Files/Cache/CacheQueryBuilder.php
@@ -41,12 +41,16 @@ class CacheQueryBuilder extends QueryBuilder {
parent::__construct($connection, $systemConfig, $logger);
}
- public function selectFileCache(string $alias = null) {
+ public function selectFileCache(string $alias = null, bool $joinExtendedCache = true) {
$name = $alias ? $alias : 'filecache';
$this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", "$name.name", 'mimetype', 'mimepart', 'size', 'mtime',
- 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time', 'unencrypted_size')
- ->from('filecache', $name)
- ->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid'));
+ 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'unencrypted_size')
+ ->from('filecache', $name);
+
+ if ($joinExtendedCache) {
+ $this->addSelect('metadata_etag', 'creation_time', 'upload_time');
+ $this->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid'));
+ }
$this->alias = $name;
diff --git a/lib/private/Files/Cache/Propagator.php b/lib/private/Files/Cache/Propagator.php
index afff2fb51ff..2909e998bf9 100644
--- a/lib/private/Files/Cache/Propagator.php
+++ b/lib/private/Files/Cache/Propagator.php
@@ -66,7 +66,7 @@ class Propagator implements IPropagator {
* @param int $sizeDifference number of bytes the file has grown
*/
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
- // Do not propogate changes in ignored paths
+ // Do not propagate changes in ignored paths
foreach ($this->ignore as $ignore) {
if (strpos($internalPath, $ignore) === 0) {
return;
@@ -116,18 +116,18 @@ class Propagator implements IPropagator {
if ($this->storage->instanceOfStorage(Encryption::class)) {
// in case of encryption being enabled after some files are already uploaded, some entries will have an unencrypted_size of 0 and a non-zero size
+ $eq = $builder->expr()->eq('unencrypted_size', $builder->expr()->literal(0, IQueryBuilder::PARAM_INT));
+ $sizeColumn = $builder->getColumnName('size');
+ $unencryptedSizeColumn = $builder->getColumnName('unencrypted_size');
$builder->set('unencrypted_size', $builder->func()->greatest(
$builder->func()->add(
- $builder->func()->case([
- ['when' => $builder->expr()->eq('unencrypted_size', $builder->expr()->literal(0, IQueryBuilder::PARAM_INT)), 'then' => 'size']
- ], 'unencrypted_size'),
+ $builder->createFunction("CASE WHEN $eq THEN $unencryptedSizeColumn ELSE $sizeColumn END"),
$builder->createNamedParameter($sizeDifference)
),
$builder->createNamedParameter(-1, IQueryBuilder::PARAM_INT)
));
}
- $a = $builder->getSQL();
$builder->execute();
}
}
diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php
index e7bccbf521c..3529ede9746 100644
--- a/lib/private/Files/Cache/QuerySearchHelper.php
+++ b/lib/private/Files/Cache/QuerySearchHelper.php
@@ -103,7 +103,7 @@ class QuerySearchHelper {
$builder = $this->getQueryBuilder();
- $query = $builder->selectFileCache('file');
+ $query = $builder->selectFileCache('file', false);
if ($this->searchBuilder->shouldJoinTags($searchQuery->getSearchOperation())) {
$user = $searchQuery->getUser();
@@ -158,7 +158,7 @@ class QuerySearchHelper {
$result->closeCursor();
- // loop trough all caches for each result to see if the result matches that storage
+ // loop through all caches for each result to see if the result matches that storage
// results are grouped by the same array keys as the caches argument to allow the caller to distringuish the source of the results
$results = array_fill_keys(array_keys($caches), []);
foreach ($rawEntries as $rawEntry) {
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php
index fb32b64c012..4799c3bff7d 100644
--- a/lib/private/Files/Cache/Scanner.php
+++ b/lib/private/Files/Cache/Scanner.php
@@ -339,7 +339,7 @@ class Scanner extends BasicEmitter implements IScanner {
try {
$data = $this->scanFile($path, $reuse, -1, null, $lock);
if ($data and $data['mimetype'] === 'httpd/unix-directory') {
- $size = $this->scanChildren($path, $recursive, $reuse, $data['fileid'], $lock);
+ $size = $this->scanChildren($path, $recursive, $reuse, $data['fileid'], $lock, $data);
$data['size'] = $size;
}
} finally {
@@ -376,9 +376,10 @@ class Scanner extends BasicEmitter implements IScanner {
* @param int $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 array $data the data of the folder before (re)scanning the children
* @return int the size of the scanned folder or -1 if the size is unknown at this stage
*/
- protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true) {
+ protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = []) {
if ($reuse === -1) {
$reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG;
}
@@ -397,7 +398,8 @@ class Scanner extends BasicEmitter implements IScanner {
$size += $childSize;
}
}
- if ($this->cacheActive) {
+ $oldSize = $data['size'] ?? null;
+ if ($this->cacheActive && $oldSize !== $size) {
$this->cache->update($folderId, ['size' => $size]);
}
$this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', [$path, $this->storageId]);
@@ -409,6 +411,11 @@ class Scanner extends BasicEmitter implements IScanner {
$existingChildren = $this->getExistingChildren($folderId);
$newChildren = iterator_to_array($this->storage->getDirectoryContent($path));
+ if (count($existingChildren) === 0 && count($newChildren) === 0) {
+ // no need to do a transaction
+ return [];
+ }
+
if ($this->useTransactions) {
\OC::$server->getDatabaseConnection()->beginTransaction();
}
diff --git a/lib/private/Files/Cache/SearchBuilder.php b/lib/private/Files/Cache/SearchBuilder.php
index b5f548dd563..1a8c3637063 100644
--- a/lib/private/Files/Cache/SearchBuilder.php
+++ b/lib/private/Files/Cache/SearchBuilder.php
@@ -54,7 +54,7 @@ class SearchBuilder {
ISearchComparison::COMPARE_GREATER_THAN => 'lte',
ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt',
ISearchComparison::COMPARE_LESS_THAN => 'gte',
- ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt',
+ ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'gt',
];
public const TAG_FAVORITE = '_$!<Favorite>!$_';
diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php
index fb9e5500658..f77c9b71dd7 100644
--- a/lib/private/Files/Cache/Storage.php
+++ b/lib/private/Files/Cache/Storage.php
@@ -40,7 +40,7 @@ use Psr\Log\LoggerInterface;
* a string id which is generated by the storage backend and reflects the configuration of the storage (e.g. 'smb://user@host/share')
* and a numeric storage id which is referenced in the file cache
*
- * A mapping between the two storage ids is stored in the database and accessible trough this class
+ * A mapping between the two storage ids is stored in the database and accessible through this class
*
* @package OC\Files\Cache
*/
@@ -135,7 +135,7 @@ class Storage {
* Get the numeric of the storage with the provided string id
*
* @param $storageId
- * @return int|null either the numeric storage id or null if the storage id is not knwon
+ * @return int|null either the numeric storage id or null if the storage id is not known
*/
public static function getNumericStorageId($storageId) {
$storageId = self::adjustStorageId($storageId);
diff --git a/lib/private/Files/Cache/StorageGlobal.php b/lib/private/Files/Cache/StorageGlobal.php
index a898c435415..74cbd5abdb2 100644
--- a/lib/private/Files/Cache/StorageGlobal.php
+++ b/lib/private/Files/Cache/StorageGlobal.php
@@ -33,7 +33,7 @@ use OCP\IDBConnection;
* a string id which is generated by the storage backend and reflects the configuration of the storage (e.g. 'smb://user@host/share')
* and a numeric storage id which is referenced in the file cache
*
- * A mapping between the two storage ids is stored in the database and accessible trough this class
+ * A mapping between the two storage ids is stored in the database and accessible through this class
*
* @package OC\Files\Cache
*/
diff --git a/lib/private/Files/Cache/Updater.php b/lib/private/Files/Cache/Updater.php
index 98fb51fe264..f8c187996e6 100644
--- a/lib/private/Files/Cache/Updater.php
+++ b/lib/private/Files/Cache/Updater.php
@@ -73,14 +73,14 @@ class Updater implements IUpdater {
}
/**
- * Disable updating the cache trough this updater
+ * Disable updating the cache through this updater
*/
public function disable() {
$this->enabled = false;
}
/**
- * Re-enable the updating of the cache trough this updater
+ * Re-enable the updating of the cache through this updater
*/
public function enable() {
$this->enabled = true;
diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php
index 7183a6c0d2a..996f0c02603 100644
--- a/lib/private/Files/Cache/Wrapper/CacheJail.php
+++ b/lib/private/Files/Cache/Wrapper/CacheJail.php
@@ -267,7 +267,7 @@ class CacheJail extends CacheWrapper {
* use the one with the highest id gives the best result with the background scanner, since that is most
* likely the folder where we stopped scanning previously
*
- * @return string|bool the path of the folder or false when no folder matched
+ * @return string|false the path of the folder or false when no folder matched
*/
public function getIncomplete() {
// not supported
@@ -306,10 +306,14 @@ class CacheJail extends CacheWrapper {
}
public function getQueryFilterForStorage(): ISearchOperator {
+ return $this->addJailFilterQuery($this->getCache()->getQueryFilterForStorage());
+ }
+
+ protected function addJailFilterQuery(ISearchOperator $filter): ISearchOperator {
if ($this->getGetUnjailedRoot() !== '' && $this->getGetUnjailedRoot() !== '/') {
return new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND,
[
- $this->getCache()->getQueryFilterForStorage(),
+ $filter,
new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR,
[
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
@@ -319,16 +323,18 @@ class CacheJail extends CacheWrapper {
]
);
} else {
- return $this->getCache()->getQueryFilterForStorage();
+ return $filter;
}
}
public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
- $rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
- if ($rawEntry) {
- $jailedPath = $this->getJailedPath($rawEntry->getPath());
- if ($jailedPath !== null) {
- return $this->formatCacheEntry(clone $rawEntry) ?: null;
+ if ($this->getGetUnjailedRoot() === '' || strpos($rawEntry->getPath(), $this->getGetUnjailedRoot()) === 0) {
+ $rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
+ if ($rawEntry) {
+ $jailedPath = $this->getJailedPath($rawEntry->getPath());
+ if ($jailedPath !== null) {
+ return $this->formatCacheEntry(clone $rawEntry) ?: null;
+ }
}
}
diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php
index e5300dc75f5..66ae83fd144 100644
--- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php
+++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php
@@ -267,7 +267,7 @@ class CacheWrapper extends Cache {
* use the one with the highest id gives the best result with the background scanner, since that is most
* likely the folder where we stopped scanning previously
*
- * @return string|bool the path of the folder or false when no folder matched
+ * @return string|false the path of the folder or false when no folder matched
*/
public function getIncomplete() {
return $this->getCache()->getIncomplete();
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index c326eeb0b6c..3540b563742 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -28,7 +28,7 @@
*/
namespace OC\Files\Config;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCA\Files_Sharing\SharedMount;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Config\ICachedMountFileInfo;
@@ -42,7 +42,7 @@ use OCP\IUserManager;
use Psr\Log\LoggerInterface;
/**
- * Cache mounts points per user in the cache so we can easilly look them up
+ * Cache mounts points per user in the cache so we can easily look them up
*/
class UserMountCache implements IUserMountCache {
private IDBConnection $connection;
@@ -90,7 +90,12 @@ class UserMountCache implements IUserMountCache {
$cachedMounts = $this->getMountsForUser($user);
if (is_array($mountProviderClasses)) {
- $cachedMounts = array_filter($cachedMounts, function (ICachedMountInfo $mountInfo) use ($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
+ if ($mountInfo->getMountProvider() === '' && isset($newMounts[$mountInfo->getRootId()])) {
+ return true;
+ }
return in_array($mountInfo->getMountProvider(), $mountProviderClasses);
});
}
diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php
index 5912eefcf9c..47c893ebbf1 100644
--- a/lib/private/Files/FileInfo.php
+++ b/lib/private/Files/FileInfo.php
@@ -101,7 +101,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
$this->data = $data;
$this->mount = $mount;
$this->owner = $owner;
- if (isset($this->data['unencrypted_size'])) {
+ if (isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] !== 0) {
$this->rawSize = $this->data['unencrypted_size'];
} else {
$this->rawSize = $this->data['size'] ?? 0;
@@ -414,7 +414,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
if (isset($data['etag'])) {
// prefix the etag with the relative path of the subentry to propagate etag on mount moves
$relativeEntryPath = substr($entryPath, strlen($this->getPath()));
- // attach the permissions to propagate etag on permision changes of submounts
+ // attach the permissions to propagate etag on permission changes of submounts
$permissions = isset($data['permissions']) ? $data['permissions'] : 0;
$this->childEtags[] = $relativeEntryPath . '/' . $data['etag'] . $permissions;
}
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index 20b44e2736a..9542666b03c 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -37,7 +37,7 @@
*/
namespace OC\Files;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OC\Files\Mount\MountPoint;
use OC\User\NoUserException;
use OCP\EventDispatcher\IEventDispatcher;
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 69285018d17..9ba0e504058 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -29,7 +29,7 @@ declare(strict_types=1);
namespace OC\Files\Mount;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
use OC\Files\SetupManager;
use OC\Files\SetupManagerFactory;
diff --git a/lib/private/Files/Node/File.php b/lib/private/Files/Node/File.php
index e125715e6a8..d8a6741dc6e 100644
--- a/lib/private/Files/Node/File.php
+++ b/lib/private/Files/Node/File.php
@@ -131,7 +131,6 @@ class File extends Node implements \OCP\Files\File {
$this->view->unlink($this->path);
$nonExisting = new NonExistingFile($this->root, $this->view, $this->path, $fileInfo);
$this->sendHooks(['postDelete'], [$nonExisting]);
- $this->exists = false;
$this->fileInfo = null;
} else {
throw new NotPermittedException();
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index b0df1c91293..f09faf78288 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -102,9 +102,9 @@ class Folder extends Node implements \OCP\Files\Folder {
return array_map(function (FileInfo $info) {
if ($info->getMimetype() === FileInfo::MIMETYPE_FOLDER) {
- return new Folder($this->root, $this->view, $info->getPath(), $info);
+ return new Folder($this->root, $this->view, $info->getPath(), $info, $this);
} else {
- return new File($this->root, $this->view, $info->getPath(), $info);
+ return new File($this->root, $this->view, $info->getPath(), $info, $this);
}
}, $folderContent);
}
@@ -120,10 +120,11 @@ class Folder extends Node implements \OCP\Files\Folder {
} else {
$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
}
+ $parent = dirname($path) === $this->getPath() ? $this : null;
if ($isDir) {
- return new Folder($this->root, $this->view, $path, $info);
+ return new Folder($this->root, $this->view, $path, $info, $parent);
} else {
- return new File($this->root, $this->view, $path, $info);
+ return new File($this->root, $this->view, $path, $info, $parent);
}
}
@@ -164,7 +165,8 @@ class Folder extends Node implements \OCP\Files\Folder {
if (!$this->view->mkdir($fullPath)) {
throw new NotPermittedException('Could not create folder "' . $fullPath . '"');
}
- $node = new Folder($this->root, $this->view, $fullPath);
+ $parent = dirname($fullPath) === $this->getPath() ? $this : null;
+ $node = new Folder($this->root, $this->view, $fullPath, null, $parent);
$this->sendHooks(['postWrite', 'postCreate'], [$node]);
return $node;
} else {
@@ -194,7 +196,7 @@ class Folder extends Node implements \OCP\Files\Folder {
if ($result === false) {
throw new NotPermittedException('Could not create path "' . $fullPath . '"');
}
- $node = new File($this->root, $this->view, $fullPath);
+ $node = new File($this->root, $this->view, $fullPath, null, $this);
$this->sendHooks(['postWrite', 'postCreate'], [$node]);
return $node;
}
@@ -263,7 +265,7 @@ class Folder extends Node implements \OCP\Files\Folder {
$searchHelper = \OC::$server->get(QuerySearchHelper::class);
$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
- // loop trough all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
+ // loop through all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
$files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
$mount = $mountByMountPoint[$relativeMountPoint];
return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
@@ -297,7 +299,7 @@ class Folder extends Node implements \OCP\Files\Folder {
private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
$cacheEntry['internalPath'] = $cacheEntry['path'];
- $cacheEntry['path'] = $appendRoot . $cacheEntry->getPath();
+ $cacheEntry['path'] = rtrim($appendRoot . $cacheEntry->getPath(), '/');
$subPath = $cacheEntry['path'] !== '' ? '/' . $cacheEntry['path'] : '';
return new \OC\Files\FileInfo($this->path . $subPath, $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
}
@@ -389,7 +391,6 @@ class Folder extends Node implements \OCP\Files\Folder {
$this->view->rmdir($this->path);
$nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
$this->sendHooks(['postDelete'], [$nonExisting]);
- $this->exists = false;
} else {
throw new NotPermittedException('No delete permission for path "' . $this->path . '"');
}
diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php
index c8975154059..bfa4d6861ea 100644
--- a/lib/private/Files/Node/Node.php
+++ b/lib/private/Files/Node/Node.php
@@ -62,16 +62,22 @@ class Node implements \OCP\Files\Node {
protected $fileInfo;
/**
+ * @var Node|null
+ */
+ protected $parent;
+
+ /**
* @param \OC\Files\View $view
* @param \OCP\Files\IRootFolder $root
* @param string $path
* @param FileInfo $fileInfo
*/
- public function __construct($root, $view, $path, $fileInfo = null) {
+ public function __construct($root, $view, $path, $fileInfo = null, ?Node $parent = null) {
$this->view = $view;
$this->root = $root;
$this->path = $path;
$this->fileInfo = $fileInfo;
+ $this->parent = $parent;
}
/**
@@ -278,11 +284,16 @@ class Node implements \OCP\Files\Node {
* @return Node
*/
public function getParent() {
- $newPath = dirname($this->path);
- if ($newPath === '' || $newPath === '.' || $newPath === '/') {
- return $this->root;
+ if ($this->parent === null) {
+ $newPath = dirname($this->path);
+ if ($newPath === '' || $newPath === '.' || $newPath === '/') {
+ return $this->root;
+ }
+
+ $this->parent = $this->root->get($newPath);
}
- return $this->root->get($newPath);
+
+ return $this->parent;
}
/**
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index 6dd65a4291d..ca930c1002c 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -32,7 +32,7 @@
namespace OC\Files\Node;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OC\Files\FileInfo;
use OC\Files\Mount\Manager;
use OC\Files\Mount\MountPoint;
@@ -427,7 +427,7 @@ class Root extends Folder implements IRootFolder {
$mountsContainingFile = $mountCache->getMountsForFileId($id, $user);
}
- // when a user has access trough the same storage trough multiple paths
+ // when a user has access through the same storage through multiple paths
// (such as an external storage that is both mounted for a user and shared to the user)
// the mount cache will only hold a single entry for the storage
// this can lead to issues as the different ways the user has access to a storage can have different permissions
diff --git a/lib/private/Files/ObjectStore/NoopScanner.php b/lib/private/Files/ObjectStore/NoopScanner.php
index 3b8cbdb18bb..bdfc93758d4 100644
--- a/lib/private/Files/ObjectStore/NoopScanner.php
+++ b/lib/private/Files/ObjectStore/NoopScanner.php
@@ -68,7 +68,7 @@ class NoopScanner extends Scanner {
* @param array $folderData existing cache data for the folder to be scanned
* @return int the size of the scanned folder or -1 if the size is unknown at this stage
*/
- protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true) {
+ protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = []) {
return 0;
}
diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
index c3836749c6d..8286321450d 100644
--- a/lib/private/Files/ObjectStore/S3ConnectionTrait.php
+++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
@@ -28,6 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OC\Files\ObjectStore;
use Aws\ClientResolver;
@@ -121,15 +122,6 @@ trait S3ConnectionTrait {
)
);
- // since we store the certificate bundles on the primary storage, we can't get the bundle while setting up the primary storage
- if (!isset($this->params['primary_storage'])) {
- /** @var ICertificateManager $certManager */
- $certManager = \OC::$server->get(ICertificateManager::class);
- $certPath = $certManager->getAbsoluteBundlePath();
- } else {
- $certPath = \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
- }
-
$options = [
'version' => isset($this->params['version']) ? $this->params['version'] : 'latest',
'credentials' => $provider,
@@ -139,7 +131,7 @@ trait S3ConnectionTrait {
'signature_provider' => \Aws\or_chain([self::class, 'legacySignatureProvider'], ClientResolver::_default_signature_provider()),
'csm' => false,
'use_arn_region' => false,
- 'http' => ['verify' => $certPath],
+ 'http' => ['verify' => $this->getCertificateBundlePath()],
];
if ($this->getProxy()) {
$options['http']['proxy'] = $this->getProxy();
@@ -152,7 +144,7 @@ trait S3ConnectionTrait {
if (!$this->connection::isBucketDnsCompatible($this->bucket)) {
$logger = \OC::$server->get(LoggerInterface::class);
$logger->debug('Bucket "' . $this->bucket . '" This bucket name is not dns compatible, it may contain invalid characters.',
- ['app' => 'objectstore']);
+ ['app' => 'objectstore']);
}
if ($this->params['verify_bucket_exists'] && !$this->connection->doesBucketExist($this->bucket)) {
@@ -203,7 +195,7 @@ trait S3ConnectionTrait {
/**
* This function creates a credential provider based on user parameter file
*/
- protected function paramCredentialProvider() : callable {
+ protected function paramCredentialProvider(): callable {
return function () {
$key = empty($this->params['key']) ? null : $this->params['key'];
$secret = empty($this->params['secret']) ? null : $this->params['secret'];
@@ -218,4 +210,19 @@ trait S3ConnectionTrait {
return new RejectedPromise(new CredentialsException($msg));
};
}
+
+ protected function getCertificateBundlePath(): ?string {
+ if ((int)($this->params['use_nextcloud_bundle'] ?? "0")) {
+ // since we store the certificate bundles on the primary storage, we can't get the bundle while setting up the primary storage
+ if (!isset($this->params['primary_storage'])) {
+ /** @var ICertificateManager $certManager */
+ $certManager = \OC::$server->get(ICertificateManager::class);
+ return $certManager->getAbsoluteBundlePath();
+ } else {
+ return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
+ }
+ } else {
+ return null;
+ }
+ }
}
diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php
index 4e54a26e98a..9d692e01a23 100644
--- a/lib/private/Files/ObjectStore/S3ObjectTrait.php
+++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php
@@ -43,6 +43,8 @@ trait S3ObjectTrait {
*/
abstract protected function getConnection();
+ abstract protected function getCertificateBundlePath(): ?string;
+
/**
* @param string $urn the unified resource name used to identify the object
* @return resource stream with the read data
@@ -67,8 +69,14 @@ trait S3ObjectTrait {
'http' => [
'protocol_version' => $request->getProtocolVersion(),
'header' => $headers,
- ],
+ ]
];
+ $bundle = $this->getCertificateBundlePath();
+ if ($bundle) {
+ $opts['ssl'] = [
+ 'cafile' => $bundle
+ ];
+ }
if ($this->getProxy()) {
$opts['http']['proxy'] = $this->getProxy();
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 876514b473c..5782a5a72a6 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -82,6 +82,7 @@ class SetupManager {
private IConfig $config;
private bool $listeningForProviders;
private array $fullSetupRequired = [];
+ private bool $setupBuiltinWrappersDone = false;
public function __construct(
IEventLogger $eventLogger,
@@ -121,6 +122,15 @@ class SetupManager {
}
private function setupBuiltinWrappers() {
+ if ($this->setupBuiltinWrappersDone) {
+ return;
+ }
+ $this->setupBuiltinWrappersDone = true;
+
+ // load all filesystem apps before, so no setup-hook gets lost
+ OC_App::loadApps(['filesystem']);
+ $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
+
Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
if ($storage->instanceOfStorage(Common::class)) {
$storage->setMountOptions($mount->getOptions());
@@ -188,6 +198,8 @@ class SetupManager {
}
return $storage;
});
+
+ Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
}
/**
@@ -223,6 +235,9 @@ class SetupManager {
return;
}
$this->setupUsers[] = $user->getUID();
+
+ $this->setupBuiltinWrappers();
+
$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]);
@@ -321,14 +336,8 @@ class SetupManager {
$this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
- // load all filesystem apps before, so no setup-hook gets lost
- OC_App::loadApps(['filesystem']);
- $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
-
$this->setupBuiltinWrappers();
- Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
-
$rootMounts = $this->mountProviderCollection->getRootMounts();
foreach ($rootMounts as $rootMountProvider) {
$this->mountManager->addMount($rootMountProvider);
@@ -554,10 +563,10 @@ class SetupManager {
});
$genericEvents = [
- '\OCA\Circles::onCircleCreation',
- '\OCA\Circles::onCircleDestruction',
- '\OCA\Circles::onMemberNew',
- '\OCA\Circles::onMemberLeaving',
+ 'OCA\Circles\Events\CreatingCircleEvent',
+ 'OCA\Circles\Events\DestroyingCircleEvent',
+ 'OCA\Circles\Events\AddingCircleMemberEvent',
+ 'OCA\Circles\Events\RemovingCircleMemberEvent',
];
foreach ($genericEvents as $genericEvent) {
diff --git a/lib/private/Files/SimpleFS/NewSimpleFile.php b/lib/private/Files/SimpleFS/NewSimpleFile.php
index 76fc69ebbe7..b2a183b7d29 100644
--- a/lib/private/Files/SimpleFS/NewSimpleFile.php
+++ b/lib/private/Files/SimpleFS/NewSimpleFile.php
@@ -34,15 +34,12 @@ use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
class NewSimpleFile implements ISimpleFile {
- private $parentFolder;
- private $name;
- /** @var File|null */
- private $file = null;
+ private Folder $parentFolder;
+ private string $name;
+ private ?File $file = null;
/**
* File constructor.
- *
- * @param File $file
*/
public function __construct(Folder $parentFolder, string $name) {
$this->parentFolder = $parentFolder;
@@ -51,19 +48,15 @@ class NewSimpleFile implements ISimpleFile {
/**
* Get the name
- *
- * @return string
*/
- public function getName() {
+ public function getName(): string {
return $this->name;
}
/**
* Get the size in bytes
- *
- * @return int
*/
- public function getSize() {
+ public function getSize(): int {
if ($this->file) {
return $this->file->getSize();
} else {
@@ -73,10 +66,8 @@ class NewSimpleFile implements ISimpleFile {
/**
* Get the ETag
- *
- * @return string
*/
- public function getETag() {
+ public function getETag(): string {
if ($this->file) {
return $this->file->getEtag();
} else {
@@ -86,10 +77,8 @@ class NewSimpleFile implements ISimpleFile {
/**
* Get the last modification time
- *
- * @return int
*/
- public function getMTime() {
+ public function getMTime(): int {
if ($this->file) {
return $this->file->getMTime();
} else {
@@ -100,11 +89,10 @@ class NewSimpleFile implements ISimpleFile {
/**
* Get the content
*
- * @return string
* @throws NotFoundException
* @throws NotPermittedException
*/
- public function getContent() {
+ public function getContent(): string {
if ($this->file) {
$result = $this->file->getContent();
@@ -125,7 +113,7 @@ class NewSimpleFile implements ISimpleFile {
* @throws NotPermittedException
* @throws NotFoundException
*/
- public function putContent($data) {
+ public function putContent($data): void {
try {
if ($this->file) {
$this->file->putContent($data);
@@ -139,7 +127,7 @@ class NewSimpleFile implements ISimpleFile {
/**
* Sometimes there are some issues with the AppData. Most of them are from
- * user error. But we should handle them gracefull anyway.
+ * user error. But we should handle them gracefully anyway.
*
* If for some reason the current file can't be found. We remove it.
* Then traverse up and check all folders if they exists. This so that the
@@ -147,7 +135,7 @@ class NewSimpleFile implements ISimpleFile {
*
* @throws NotFoundException
*/
- private function checkFile() {
+ private function checkFile(): void {
$cur = $this->file;
while ($cur->stat() === false) {
@@ -171,7 +159,7 @@ class NewSimpleFile implements ISimpleFile {
*
* @throws NotPermittedException
*/
- public function delete() {
+ public function delete(): void {
if ($this->file) {
$this->file->delete();
}
@@ -182,7 +170,7 @@ class NewSimpleFile implements ISimpleFile {
*
* @return string
*/
- public function getMimeType() {
+ public function getMimeType(): string {
if ($this->file) {
return $this->file->getMimeType();
} else {
diff --git a/lib/private/Files/SimpleFS/SimpleFile.php b/lib/private/Files/SimpleFS/SimpleFile.php
index 21a2fd92dcb..a2571ac50e8 100644
--- a/lib/private/Files/SimpleFS/SimpleFile.php
+++ b/lib/private/Files/SimpleFS/SimpleFile.php
@@ -30,52 +30,37 @@ use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
class SimpleFile implements ISimpleFile {
+ private File $file;
- /** @var File $file */
- private $file;
-
- /**
- * File constructor.
- *
- * @param File $file
- */
public function __construct(File $file) {
$this->file = $file;
}
/**
* Get the name
- *
- * @return string
*/
- public function getName() {
+ public function getName(): string {
return $this->file->getName();
}
/**
* Get the size in bytes
- *
- * @return int
*/
- public function getSize() {
+ public function getSize(): int {
return $this->file->getSize();
}
/**
* Get the ETag
- *
- * @return string
*/
- public function getETag() {
+ public function getETag(): string {
return $this->file->getEtag();
}
/**
* Get the last modification time
- *
- * @return int
*/
- public function getMTime() {
+ public function getMTime(): int {
return $this->file->getMTime();
}
@@ -84,9 +69,8 @@ class SimpleFile implements ISimpleFile {
*
* @throws NotPermittedException
* @throws NotFoundException
- * @return string
*/
- public function getContent() {
+ public function getContent(): string {
$result = $this->file->getContent();
if ($result === false) {
@@ -103,9 +87,9 @@ class SimpleFile implements ISimpleFile {
* @throws NotPermittedException
* @throws NotFoundException
*/
- public function putContent($data) {
+ public function putContent($data): void {
try {
- return $this->file->putContent($data);
+ $this->file->putContent($data);
} catch (NotFoundException $e) {
$this->checkFile();
}
@@ -113,7 +97,7 @@ class SimpleFile implements ISimpleFile {
/**
* Sometimes there are some issues with the AppData. Most of them are from
- * user error. But we should handle them gracefull anyway.
+ * user error. But we should handle them gracefully anyway.
*
* If for some reason the current file can't be found. We remove it.
* Then traverse up and check all folders if they exists. This so that the
@@ -121,7 +105,7 @@ class SimpleFile implements ISimpleFile {
*
* @throws NotFoundException
*/
- private function checkFile() {
+ private function checkFile(): void {
$cur = $this->file;
while ($cur->stat() === false) {
@@ -145,16 +129,14 @@ class SimpleFile implements ISimpleFile {
*
* @throws NotPermittedException
*/
- public function delete() {
+ public function delete(): void {
$this->file->delete();
}
/**
* Get the MimeType
- *
- * @return string
*/
- public function getMimeType() {
+ public function getMimeType(): string {
return $this->file->getMimeType();
}
@@ -179,7 +161,7 @@ class SimpleFile implements ISimpleFile {
/**
* Open the file as stream for writing, resulting resource can be operated as stream like the result from php's own fopen
*
- * @return resource
+ * @return resource|false
* @throws \OCP\Files\NotPermittedException
* @since 14.0.0
*/
diff --git a/lib/private/Files/SimpleFS/SimpleFolder.php b/lib/private/Files/SimpleFS/SimpleFolder.php
index cd2a712019e..263c25a8873 100644
--- a/lib/private/Files/SimpleFS/SimpleFolder.php
+++ b/lib/private/Files/SimpleFS/SimpleFolder.php
@@ -29,6 +29,7 @@ use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\Files\SimpleFS\ISimpleFile;
class SimpleFolder implements ISimpleFolder {
@@ -44,11 +45,11 @@ class SimpleFolder implements ISimpleFolder {
$this->folder = $folder;
}
- public function getName() {
+ public function getName(): string {
return $this->folder->getName();
}
- public function getDirectoryListing() {
+ public function getDirectoryListing(): array {
$listing = $this->folder->getDirectoryListing();
$fileListing = array_map(function (Node $file) {
@@ -63,15 +64,15 @@ class SimpleFolder implements ISimpleFolder {
return array_values($fileListing);
}
- public function delete() {
+ public function delete(): void {
$this->folder->delete();
}
- public function fileExists($name) {
+ public function fileExists(string $name): bool {
return $this->folder->nodeExists($name);
}
- public function getFile($name) {
+ public function getFile(string $name): ISimpleFile {
$file = $this->folder->get($name);
if (!($file instanceof File)) {
@@ -81,7 +82,7 @@ class SimpleFolder implements ISimpleFolder {
return new SimpleFile($file);
}
- public function newFile($name, $content = null) {
+ public function newFile(string $name, $content = null): ISimpleFile {
if ($content === null) {
// delay creating the file until it's written to
return new NewSimpleFile($this->folder, $name);
diff --git a/lib/private/Files/Storage/Wrapper/Encoding.php b/lib/private/Files/Storage/Wrapper/Encoding.php
index d6201dc8877..ac9cc248ce6 100644
--- a/lib/private/Files/Storage/Wrapper/Encoding.php
+++ b/lib/private/Files/Storage/Wrapper/Encoding.php
@@ -28,7 +28,7 @@
*/
namespace OC\Files\Storage\Wrapper;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
use OCP\Files\Storage\IStorage;
use OCP\ICache;
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index 2b6732e2ba0..e5394e72ffe 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -49,9 +49,7 @@ namespace OC\Files;
use Icewind\Streams\CallbackWrapper;
use OC\Files\Mount\MoveableMount;
use OC\Files\Storage\Storage;
-use OC\User\DisplayNameCache;
use OC\User\LazyUser;
-use OC\User\User;
use OCA\Files_Sharing\SharedMount;
use OCP\Constants;
use OCP\Files\Cache\ICacheEntry;
@@ -103,8 +101,6 @@ class View {
private LoggerInterface $logger;
- private DisplayNameCache $displayNameCache;
-
/**
* @param string $root
* @throws \Exception If $root contains an invalid path
@@ -121,7 +117,6 @@ class View {
$this->lockingProvider = \OC::$server->getLockingProvider();
$this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider);
$this->userManager = \OC::$server->getUserManager();
- $this->displayNameCache = \OC::$server->get(DisplayNameCache::class);
$this->logger = \OC::$server->get(LoggerInterface::class);
}
@@ -1164,7 +1159,7 @@ class View {
try {
$this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
} catch (LockedException $e) {
- // release the shared lock we acquired before quiting
+ // release the shared lock we acquired before quitting
$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
throw $e;
}
@@ -1319,7 +1314,7 @@ class View {
* @return IUser
*/
private function getUserObjectForOwner(string $ownerId) {
- return new LazyUser($ownerId, $this->displayNameCache, $this->userManager);
+ return new LazyUser($ownerId, $this->userManager);
}
/**
@@ -1725,7 +1720,7 @@ class View {
/**
* Get the path of a file by id, relative to the view
*
- * Note that the resulting path is not guarantied to be unique for the id, multiple paths can point to the same file
+ * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
*
* @param int $id
* @param int|null $storageId
diff --git a/lib/private/HintException.php b/lib/private/HintException.php
index 735832266cf..20f7142d1c0 100644
--- a/lib/private/HintException.php
+++ b/lib/private/HintException.php
@@ -31,7 +31,7 @@ namespace OC;
* An Exception class with the intention to be presented to the end user
*
* @package OC
- * @depreacted 23.0.0 Use \OCP\HintException
+ * @deprecated 23.0.0 Use \OCP\HintException
*/
class HintException extends \OCP\HintException {
}
diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php
index 3ba85a2dd9f..4bf7fd02400 100644
--- a/lib/private/Http/Client/Client.php
+++ b/lib/private/Http/Client/Client.php
@@ -128,7 +128,7 @@ class Client implements IClient {
}
/**
- * Returns a null or an associative array specifiying the proxy URI for
+ * Returns a null or an associative array specifying the proxy URI for
* 'http' and 'https' schemes, in addition to a 'no' key value pair
* providing a list of host names that should not be proxied to.
*
diff --git a/lib/private/Http/Client/LocalAddressChecker.php b/lib/private/Http/Client/LocalAddressChecker.php
index c69d1007a16..f4fea503ab9 100644
--- a/lib/private/Http/Client/LocalAddressChecker.php
+++ b/lib/private/Http/Client/LocalAddressChecker.php
@@ -27,6 +27,7 @@ namespace OC\Http\Client;
use OCP\Http\Client\LocalServerException;
use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\IpUtils;
class LocalAddressChecker {
private LoggerInterface $logger;
@@ -36,7 +37,16 @@ class LocalAddressChecker {
}
public function ThrowIfLocalIp(string $ip) : void {
- if ((bool)filter_var($ip, FILTER_VALIDATE_IP) && !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
+ $localRanges = [
+ '100.64.0.0/10', // See RFC 6598
+ '192.0.0.0/24', // See RFC 6890
+ ];
+ if (
+ (bool)filter_var($ip, FILTER_VALIDATE_IP) &&
+ (
+ !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) ||
+ IpUtils::checkIp($ip, $localRanges)
+ )) {
$this->logger->warning("Host $ip was not connected to because it violates local access rules");
throw new LocalServerException('Host violates local access rules');
}
@@ -46,7 +56,9 @@ class LocalAddressChecker {
$delimiter = strrpos($ip, ':'); // Get last colon
$ipv4Address = substr($ip, $delimiter + 1);
- if (!filter_var($ipv4Address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
+ if (
+ !filter_var($ipv4Address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) ||
+ IpUtils::checkIp($ip, $localRanges)) {
$this->logger->warning("Host $ip was not connected to because it violates local access rules");
throw new LocalServerException('Host violates local access rules');
}
diff --git a/lib/private/LargeFileHelper.php b/lib/private/LargeFileHelper.php
index e2984b4bacf..82b3c5ae760 100755
--- a/lib/private/LargeFileHelper.php
+++ b/lib/private/LargeFileHelper.php
@@ -147,7 +147,7 @@ class LargeFileHelper {
* null on failure.
*/
public function getFileSizeViaExec($filename) {
- if (\OC_Helper::is_function_enabled('exec')) {
+ if (\OCP\Util::isFunctionEnabled('exec')) {
$os = strtolower(php_uname('s'));
$arg = escapeshellarg($filename);
$result = null;
@@ -195,7 +195,7 @@ class LargeFileHelper {
$result = - 1;
}
if ($result < 0) {
- if (\OC_Helper::is_function_enabled('exec')) {
+ if (\OCP\Util::isFunctionEnabled('exec')) {
$os = strtolower(php_uname('s'));
if (strpos($os, 'linux') !== false) {
return $this->exec('stat -c %Y ' . escapeshellarg($fullPath));
diff --git a/lib/private/Log.php b/lib/private/Log.php
index 95e0a833b66..4ab647bc6c1 100644
--- a/lib/private/Log.php
+++ b/lib/private/Log.php
@@ -36,8 +36,11 @@ declare(strict_types=1);
*/
namespace OC;
+use Exception;
use Nextcloud\LogNormalizer\Normalizer;
+use OC\AppFramework\Bootstrap\Coordinator;
use OCP\Log\IDataLogger;
+use Throwable;
use function array_merge;
use OC\Log\ExceptionSerializer;
use OCP\ILogger;
@@ -228,7 +231,7 @@ class Log implements ILogger, IDataLogger {
$this->crashReporters->delegateBreadcrumb($entry['message'], 'log', $context);
}
}
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
@@ -300,19 +303,19 @@ class Log implements ILogger, IDataLogger {
/**
* Logs an exception very detailed
*
- * @param \Exception|\Throwable $exception
+ * @param Exception|Throwable $exception
* @param array $context
* @return void
* @since 8.2.0
*/
- public function logException(\Throwable $exception, array $context = []) {
+ public function logException(Throwable $exception, array $context = []) {
$app = $context['app'] ?? 'no app in context';
$level = $context['level'] ?? ILogger::ERROR;
// if an error is raised before the autoloader is properly setup, we can't serialize exceptions
try {
- $serializer = new ExceptionSerializer($this->config);
- } catch (\Throwable $e) {
+ $serializer = $this->getSerializer();
+ } catch (Throwable $e) {
$this->error("Failed to load ExceptionSerializer serializer while trying to log " . $exception->getMessage());
return;
}
@@ -338,7 +341,7 @@ class Log implements ILogger, IDataLogger {
if (!is_null($this->crashReporters)) {
$this->crashReporters->delegateReport($exception, $context);
}
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
@@ -361,7 +364,7 @@ class Log implements ILogger, IDataLogger {
}
$context['level'] = $level;
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
@@ -401,4 +404,26 @@ class Log implements ILogger, IDataLogger {
}
return array_merge(array_diff_key($context, $usedContextKeys), [$messageKey => strtr($message, $replace)]);
}
+
+ /**
+ * @throws Throwable
+ */
+ protected function getSerializer(): ExceptionSerializer {
+ $serializer = new ExceptionSerializer($this->config);
+ try {
+ /** @var Coordinator $coordinator */
+ $coordinator = \OCP\Server::get(Coordinator::class);
+ foreach ($coordinator->getRegistrationContext()->getSensitiveMethods() as $registration) {
+ $serializer->enlistSensitiveMethods($registration->getName(), $registration->getValue());
+ }
+ // For not every app might be initialized at this time, we cannot assume that the return value
+ // of getSensitiveMethods() is complete. Running delegates in Coordinator::registerApps() is
+ // not possible due to dependencies on the one hand. On the other it would work only with
+ // adding public methods to the PsrLoggerAdapter and this class.
+ // Thus, serializer cannot be a property.
+ } catch (Throwable $t) {
+ // ignore app-defined sensitive methods in this case - they weren't loaded anyway
+ }
+ return $serializer;
+ }
}
diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php
index 3c3ff95f8e1..aaf6a39235e 100644
--- a/lib/private/Log/ExceptionSerializer.php
+++ b/lib/private/Log/ExceptionSerializer.php
@@ -109,7 +109,7 @@ class ExceptionSerializer {
$this->systemConfig = $systemConfig;
}
- public const methodsWithSensitiveParametersByClass = [
+ protected array $methodsWithSensitiveParametersByClass = [
SetupController::class => [
'run',
'display',
@@ -190,8 +190,8 @@ class ExceptionSerializer {
$sensitiveValues = [];
$trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
$className = $traceLine['class'] ?? '';
- if ($className && isset(self::methodsWithSensitiveParametersByClass[$className])
- && in_array($traceLine['function'], self::methodsWithSensitiveParametersByClass[$className], true)) {
+ if ($className && isset($this->methodsWithSensitiveParametersByClass[$className])
+ && in_array($traceLine['function'], $this->methodsWithSensitiveParametersByClass[$className], true)) {
return $this->editTrace($sensitiveValues, $traceLine);
}
foreach (self::methodsWithSensitiveParameters as $sensitiveMethod) {
@@ -289,4 +289,11 @@ class ExceptionSerializer {
return $data;
}
+
+ public function enlistSensitiveMethods(string $class, array $methods): void {
+ if (!isset($this->methodsWithSensitiveParametersByClass[$class])) {
+ $this->methodsWithSensitiveParametersByClass[$class] = [];
+ }
+ $this->methodsWithSensitiveParametersByClass[$class] = array_merge($this->methodsWithSensitiveParametersByClass[$class], $methods);
+ }
}
diff --git a/lib/private/Log/Rotate.php b/lib/private/Log/Rotate.php
index 58b2932b417..20bc3327f92 100644
--- a/lib/private/Log/Rotate.php
+++ b/lib/private/Log/Rotate.php
@@ -32,7 +32,7 @@ use OCP\Log\RotationTrait;
* For more professional log management set the 'logfile' config to a different
* location and manage that with your own tools.
*/
-class Rotate extends \OC\BackgroundJob\Job {
+class Rotate extends \OCP\BackgroundJob\Job {
use RotationTrait;
public function run($dummy) {
diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php
index 2f3480498be..d0c3b04eacb 100644
--- a/lib/private/Mail/Mailer.php
+++ b/lib/private/Mail/Mailer.php
@@ -39,6 +39,7 @@ use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\RFCValidation;
use OCP\Defaults;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IBinaryFinder;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IURLGenerator;
@@ -71,19 +72,14 @@ use Psr\Log\LoggerInterface;
class Mailer implements IMailer {
/** @var \Swift_Mailer Cached mailer */
private $instance = null;
- /** @var IConfig */
- private $config;
+ private IConfig $config;
private LoggerInterface $logger;
/** @var Defaults */
private $defaults;
- /** @var IURLGenerator */
- private $urlGenerator;
- /** @var IL10N */
- private $l10n;
- /** @var IEventDispatcher */
- private $dispatcher;
- /** @var IFactory */
- private $l10nFactory;
+ private IURLGenerator $urlGenerator;
+ private IL10N $l10n;
+ private IEventDispatcher $dispatcher;
+ private IFactory $l10nFactory;
public function __construct(IConfig $config,
LoggerInterface $logger,
@@ -196,6 +192,9 @@ class Mailer implements IMailer {
// Debugging logging
$logMessage = sprintf('Sent mail to "%s" with subject "%s"', print_r($message->getTo(), true), $message->getSubject());
+ if (!empty($failedRecipients)) {
+ $logMessage .= sprintf(' (failed for "%s")', print_r($failedRecipients, true));
+ }
$this->logger->debug($logMessage, ['app' => 'core']);
if ($debugMode && isset($mailLogger)) {
$this->logger->debug($mailLogger->dump(), ['app' => 'core']);
@@ -306,7 +305,7 @@ class Mailer implements IMailer {
$binaryPath = '/var/qmail/bin/sendmail';
break;
default:
- $sendmail = \OC_Helper::findBinaryPath('sendmail');
+ $sendmail = \OCP\Server::get(IBinaryFinder::class)->findBinaryPath('sendmail');
if ($sendmail === null) {
$sendmail = '/usr/sbin/sendmail';
}
diff --git a/lib/private/MemoryInfo.php b/lib/private/MemoryInfo.php
index 074e9f915fe..ed6617d879d 100644
--- a/lib/private/MemoryInfo.php
+++ b/lib/private/MemoryInfo.php
@@ -68,7 +68,7 @@ class MemoryInfo {
$last = strtolower(substr($memoryLimit, -1));
$memoryLimit = (int)substr($memoryLimit, 0, -1);
- // intended fall trough
+ // intended fall through
switch ($last) {
case 'g':
$memoryLimit *= 1024;
diff --git a/lib/private/Metadata/IMetadataManager.php b/lib/private/Metadata/IMetadataManager.php
index d2d37f15c25..fa0bcc22801 100644
--- a/lib/private/Metadata/IMetadataManager.php
+++ b/lib/private/Metadata/IMetadataManager.php
@@ -29,7 +29,7 @@ interface IMetadataManager {
public function fetchMetadataFor(string $group, array $fileIds): array;
/**
- * Get the capabilites as an array of mimetype regex to the type provided
+ * Get the capabilities as an array of mimetype regex to the type provided
*/
public function getCapabilities(): array;
}
diff --git a/lib/private/Metadata/Provider/ExifProvider.php b/lib/private/Metadata/Provider/ExifProvider.php
index 2e1eb1d4208..892671556b3 100644
--- a/lib/private/Metadata/Provider/ExifProvider.php
+++ b/lib/private/Metadata/Provider/ExifProvider.php
@@ -17,7 +17,7 @@ class ExifProvider implements IMetadataProvider {
public function execute(File $file): array {
$fileDescriptor = $file->fopen('rb');
- $data = @exif_read_data($fileDescriptor, 'ANY_TAG', true);
+ $data = exif_read_data($fileDescriptor, 'COMPUTED', true);
$size = new FileMetadata();
$size->setGroupName('size');
diff --git a/lib/private/Migration/BackgroundRepair.php b/lib/private/Migration/BackgroundRepair.php
index 03a3d3f4a7c..579ba494e58 100644
--- a/lib/private/Migration/BackgroundRepair.php
+++ b/lib/private/Migration/BackgroundRepair.php
@@ -26,15 +26,14 @@
*/
namespace OC\Migration;
-use OC\BackgroundJob\JobList;
-use OC\BackgroundJob\TimedJob;
+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\BackgroundJob\IJobList;
-use OCP\ILogger;
use Psr\Log\LoggerInterface;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Class BackgroundRepair
@@ -42,33 +41,16 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* @package OC\Migration
*/
class BackgroundRepair extends TimedJob {
+ private IJobList $jobList;
+ private LoggerInterface $logger;
+ private IEventDispatcher $dispatcher;
- /** @var IJobList */
- private $jobList;
-
- /** @var ILogger */
- private $logger;
-
- /** @var EventDispatcherInterface */
- private $dispatcher;
-
- public function __construct(EventDispatcherInterface $dispatcher) {
+ public function __construct(IEventDispatcher $dispatcher, ITimeFactory $time, LoggerInterface $logger, IJobList $jobList) {
+ parent::__construct($time);
$this->dispatcher = $dispatcher;
- }
-
- /**
- * run the job, then remove it from the job list
- *
- * @param JobList $jobList
- * @param ILogger|null $logger
- */
- public function execute($jobList, ILogger $logger = null) {
- // add an interval of 15 mins
- $this->setInterval(15 * 60);
-
- $this->jobList = $jobList;
$this->logger = $logger;
- parent::execute($jobList, $logger);
+ $this->jobList = $jobList;
+ $this->setInterval(15 * 60);
}
/**
@@ -97,8 +79,9 @@ class BackgroundRepair extends TimedJob {
try {
$repair->addStep($step);
} catch (\Exception $ex) {
- $this->logger->logException($ex, [
- 'app' => 'migration'
+ $this->logger->error($ex->getMessage(), [
+ 'app' => 'migration',
+ 'exception' => $ex,
]);
// remove the job - we can never execute it
diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php
index 2ffd25df9b8..bbf28d2c142 100644
--- a/lib/private/NavigationManager.php
+++ b/lib/private/NavigationManager.php
@@ -211,17 +211,37 @@ class NavigationManager implements INavigationManager {
'icon' => $this->urlGenerator->imagePath('settings', 'apps.svg'),
'name' => $l->t('Apps'),
]);
- }
- // Personal and (if applicable) admin settings
- $this->add([
- 'type' => 'settings',
- 'id' => 'settings',
- 'order' => 2,
- 'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
- 'name' => $l->t('Settings'),
- 'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
- ]);
+ // Personal settings
+ $this->add([
+ 'type' => 'settings',
+ 'id' => 'settings',
+ 'order' => 2,
+ 'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
+ 'name' => $l->t('Personal settings'),
+ 'icon' => $this->urlGenerator->imagePath('settings', 'personal.svg'),
+ ]);
+
+ // Admin settings
+ $this->add([
+ 'type' => 'settings',
+ 'id' => 'admin_settings',
+ 'order' => 3,
+ 'href' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'overview']),
+ 'name' => $l->t('Admin settings'),
+ 'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
+ ]);
+ } else {
+ // Personal settings
+ $this->add([
+ 'type' => 'settings',
+ 'id' => 'settings',
+ 'order' => 2,
+ 'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
+ 'name' => $l->t('Settings'),
+ 'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
+ ]);
+ }
$logoutUrl = \OC_User::getLogoutUrl($this->urlGenerator);
if ($logoutUrl !== '') {
diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php
index c707884355b..d758cae428f 100644
--- a/lib/private/Notification/Manager.php
+++ b/lib/private/Notification/Manager.php
@@ -27,7 +27,6 @@ declare(strict_types=1);
namespace OC\Notification;
use OC\AppFramework\Bootstrap\Coordinator;
-use OCP\AppFramework\Utility\ITimeFactory;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IUserManager;
@@ -50,8 +49,6 @@ class Manager implements IManager {
private $userManager;
/** @var ICache */
protected $cache;
- /** @var ITimeFactory */
- protected $timeFactory;
/** @var IRegistry */
protected $subscription;
/** @var LoggerInterface */
@@ -79,14 +76,12 @@ class Manager implements IManager {
public function __construct(IValidator $validator,
IUserManager $userManager,
ICacheFactory $cacheFactory,
- ITimeFactory $timeFactory,
IRegistry $subscription,
LoggerInterface $logger,
Coordinator $coordinator) {
$this->validator = $validator;
$this->userManager = $userManager;
$this->cache = $cacheFactory->createDistributed('notifications');
- $this->timeFactory = $timeFactory;
$this->subscription = $subscription;
$this->logger = $logger;
$this->coordinator = $coordinator;
@@ -310,10 +305,7 @@ class Manager implements IManager {
* users overload our infrastructure. For this reason we have to rate-limit the
* use of push notifications. If you need this feature, consider using Nextcloud Enterprise.
*/
- // TODO Remove time check after 1st March 2022
- $isFairUse = $this->timeFactory->getTime() < 1646089200
- || $this->subscription->delegateHasValidSubscription()
- || $this->userManager->countSeenUsers() < 5000;
+ $isFairUse = $this->subscription->delegateHasValidSubscription() || $this->userManager->countSeenUsers() < 500;
$pushAllowed = $isFairUse ? 'yes' : 'no';
$this->cache->set('push_fair_use', $pushAllowed, 3600);
}
diff --git a/lib/private/OCS/DiscoveryService.php b/lib/private/OCS/DiscoveryService.php
index 1d10bbac870..7ab876811e7 100644
--- a/lib/private/OCS/DiscoveryService.php
+++ b/lib/private/OCS/DiscoveryService.php
@@ -62,7 +62,7 @@ class DiscoveryService implements IDiscoveryService {
*
* @param string $remote
* @param string $service the service you want to discover
- * @param bool $skipCache We won't check if the data is in the cache. This is usefull if a background job is updating the status
+ * @param bool $skipCache We won't check if the data is in the cache. This is useful if a background job is updating the status
* @return array
*/
public function discover(string $remote, string $service, bool $skipCache = false): array {
diff --git a/lib/private/Preview/ProviderV1Adapter.php b/lib/private/Preview/ProviderV1Adapter.php
index 22db380d30d..5e50db9d8da 100644
--- a/lib/private/Preview/ProviderV1Adapter.php
+++ b/lib/private/Preview/ProviderV1Adapter.php
@@ -55,7 +55,7 @@ class ProviderV1Adapter implements IProviderV2 {
}
private function getViewAndPath(File $file) {
- $view = new View($file->getParent()->getPath());
+ $view = new View(dirname($file->getPath()));
$path = $file->getName();
return [$view, $path];
diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php
index 6c17dd58b4b..e78bdefda8d 100644
--- a/lib/private/PreviewManager.php
+++ b/lib/private/PreviewManager.php
@@ -39,6 +39,7 @@ use OCP\Files\IAppData;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\IBinaryFinder;
use OCP\IConfig;
use OCP\IPreview;
use OCP\IServerContainer;
@@ -47,73 +48,41 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use function array_key_exists;
class PreviewManager implements IPreview {
- /** @var IConfig */
- protected $config;
-
- /** @var IRootFolder */
- protected $rootFolder;
-
- /** @var IAppData */
- protected $appData;
-
- /** @var EventDispatcherInterface */
- protected $eventDispatcher;
-
- /** @var Generator */
- private $generator;
-
- /** @var GeneratorHelper */
- private $helper;
-
- /** @var bool */
- protected $providerListDirty = false;
-
- /** @var bool */
- protected $registeredCoreProviders = false;
-
- /** @var array */
- protected $providers = [];
+ protected IConfig $config;
+ protected IRootFolder $rootFolder;
+ protected IAppData $appData;
+ protected EventDispatcherInterface $eventDispatcher;
+ private ?Generator $generator = null;
+ private GeneratorHelper $helper;
+ protected bool $providerListDirty = false;
+ protected bool $registeredCoreProviders = false;
+ protected array $providers = [];
/** @var array mime type => support status */
- protected $mimeTypeSupportMap = [];
-
- /** @var array */
- protected $defaultProviders;
-
- /** @var string */
- protected $userId;
-
- /** @var Coordinator */
- private $bootstrapCoordinator;
+ protected array $mimeTypeSupportMap = [];
+ protected ?array $defaultProviders = null;
+ protected ?string $userId;
+ private Coordinator $bootstrapCoordinator;
/**
* Hash map (without value) of loaded bootstrap providers
- *
- * @var null[]
* @psalm-var array<string, null>
*/
- private $loadedBootstrapProviders = [];
-
- /** @var IServerContainer */
- private $container;
-
- /**
- * PreviewManager constructor.
- *
- * @param IConfig $config
- * @param IRootFolder $rootFolder
- * @param IAppData $appData
- * @param EventDispatcherInterface $eventDispatcher
- * @param string $userId
- */
- public function __construct(IConfig $config,
- IRootFolder $rootFolder,
- IAppData $appData,
- EventDispatcherInterface $eventDispatcher,
- GeneratorHelper $helper,
- $userId,
- Coordinator $bootstrapCoordinator,
- IServerContainer $container) {
+ private array $loadedBootstrapProviders = [];
+ private IServerContainer $container;
+ private IBinaryFinder $binaryFinder;
+
+ public function __construct(
+ IConfig $config,
+ IRootFolder $rootFolder,
+ IAppData $appData,
+ EventDispatcherInterface $eventDispatcher,
+ GeneratorHelper $helper,
+ ?string $userId,
+ Coordinator $bootstrapCoordinator,
+ IServerContainer $container,
+ IBinaryFinder $binaryFinder
+ ) {
$this->config = $config;
$this->rootFolder = $rootFolder;
$this->appData = $appData;
@@ -122,6 +91,7 @@ class PreviewManager implements IPreview {
$this->userId = $userId;
$this->bootstrapCoordinator = $bootstrapCoordinator;
$this->container = $container;
+ $this->binaryFinder = $binaryFinder;
}
/**
@@ -134,7 +104,7 @@ class PreviewManager implements IPreview {
* @param \Closure $callable
* @return void
*/
- public function registerProvider($mimeTypeRegex, \Closure $callable) {
+ public function registerProvider($mimeTypeRegex, \Closure $callable): void {
if (!$this->config->getSystemValue('enable_previews', true)) {
return;
}
@@ -148,9 +118,8 @@ class PreviewManager implements IPreview {
/**
* Get all providers
- * @return array
*/
- public function getProviders() {
+ public function getProviders(): array {
if (!$this->config->getSystemValue('enable_previews', true)) {
return [];
}
@@ -168,9 +137,8 @@ class PreviewManager implements IPreview {
/**
* Does the manager have any providers
- * @return bool
*/
- public function hasProviders() {
+ public function hasProviders(): bool {
$this->registerCoreProviders();
return !empty($this->providers);
}
@@ -257,11 +225,8 @@ class PreviewManager implements IPreview {
/**
* Check if a preview can be generated for a file
- *
- * @param \OCP\Files\FileInfo $file
- * @return bool
*/
- public function isAvailable(\OCP\Files\FileInfo $file) {
+ public function isAvailable(\OCP\Files\FileInfo $file): bool {
if (!$this->config->getSystemValue('enable_previews', true)) {
return false;
}
@@ -421,10 +386,10 @@ class PreviewManager implements IPreview {
// Office requires openoffice or libreoffice
$officeBinary = $this->config->getSystemValue('preview_libreoffice_path', null);
if (is_null($officeBinary)) {
- $officeBinary = \OC_Helper::findBinaryPath('libreoffice');
+ $officeBinary = $this->binaryFinder->findBinaryPath('libreoffice');
}
if (is_null($officeBinary)) {
- $officeBinary = \OC_Helper::findBinaryPath('openoffice');
+ $officeBinary = $this->binaryFinder->findBinaryPath('openoffice');
}
if (is_string($officeBinary)) {
@@ -439,9 +404,9 @@ class PreviewManager implements IPreview {
// Video requires avconv or ffmpeg
if (in_array(Preview\Movie::class, $this->getEnabledDefaultProvider())) {
- $movieBinary = \OC_Helper::findBinaryPath('avconv');
+ $movieBinary = $this->binaryFinder->findBinaryPath('avconv');
if (is_null($movieBinary)) {
- $movieBinary = \OC_Helper::findBinaryPath('ffmpeg');
+ $movieBinary = $this->binaryFinder->findBinaryPath('ffmpeg');
}
if (is_string($movieBinary)) {
@@ -469,7 +434,7 @@ class PreviewManager implements IPreview {
$this->registerProvider($provider->getMimeTypeRegex(), function () use ($provider) {
try {
- return $this->container->query($provider->getService());
+ return $this->container->get($provider->getService());
} catch (QueryException $e) {
return null;
}
diff --git a/lib/private/Profile/ProfileManager.php b/lib/private/Profile/ProfileManager.php
index edb51458c66..f038986cf6d 100644
--- a/lib/private/Profile/ProfileManager.php
+++ b/lib/private/Profile/ProfileManager.php
@@ -44,6 +44,7 @@ use OCP\IConfig;
use OCP\IUser;
use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
+use OCP\Cache\CappedMemoryCache;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@@ -81,6 +82,8 @@ class ProfileManager {
/** @var null|ILinkAction[] */
private $sortedActions = null;
+ /** @var CappedMemoryCache<ProfileConfig> */
+ private CappedMemoryCache $configCache;
private const CORE_APP_ID = 'core';
@@ -127,6 +130,7 @@ class ProfileManager {
$this->l10nFactory = $l10nFactory;
$this->logger = $logger;
$this->coordinator = $coordinator;
+ $this->configCache = new CappedMemoryCache();
}
/**
@@ -348,13 +352,13 @@ class ProfileManager {
* Return the default profile config
*/
private function getDefaultProfileConfig(IUser $targetUser, ?IUser $visitingUser): array {
- // Contruct the default config for actions
+ // Construct the default config for actions
$actionsConfig = [];
foreach ($this->getActions($targetUser, $visitingUser) as $action) {
$actionsConfig[$action->getId()] = ['visibility' => ProfileConfig::DEFAULT_VISIBILITY];
}
- // Contruct the default config for account properties
+ // Construct the default config for account properties
$propertiesConfig = [];
foreach (ProfileConfig::DEFAULT_PROPERTY_VISIBILITY as $property => $visibility) {
$propertiesConfig[$property] = ['visibility' => $visibility];
@@ -370,7 +374,10 @@ class ProfileManager {
public function getProfileConfig(IUser $targetUser, ?IUser $visitingUser): array {
$defaultProfileConfig = $this->getDefaultProfileConfig($targetUser, $visitingUser);
try {
- $config = $this->configMapper->get($targetUser->getUID());
+ if (($config = $this->configCache[$targetUser->getUID()]) === null) {
+ $config = $this->configMapper->get($targetUser->getUID());
+ $this->configCache[$targetUser->getUID()] = $config;
+ }
// Merge defaults with the existing config in case the defaults are missing
$config->setConfigArray(array_merge(
$defaultProfileConfig,
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index fb65789dd8a..e2e5da79216 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -34,6 +34,12 @@
*/
namespace OC;
+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\App\AppStore\Bundles\BundleFetcher;
use OC\Avatar\AvatarManager;
use OC\DB\Connection;
@@ -44,14 +50,15 @@ use OC\Repair\CleanTags;
use OC\Repair\ClearFrontendCaches;
use OC\Repair\ClearGeneratedAvatarCache;
use OC\Repair\Collation;
+use OC\Repair\Events\RepairAdvanceEvent;
+use OC\Repair\Events\RepairErrorEvent;
+use OC\Repair\Events\RepairFinishEvent;
+use OC\Repair\Events\RepairInfoEvent;
+use OC\Repair\Events\RepairStartEvent;
+use OC\Repair\Events\RepairStepEvent;
+use OC\Repair\Events\RepairWarningEvent;
use OC\Repair\MoveUpdaterStepFile;
-use OC\Repair\NC22\LookupServerSendCheck;
-use OC\Repair\Owncloud\CleanPreviews;
-use OC\Repair\Owncloud\MigrateOauthTables;
use OC\Repair\NC11\FixMountStorages;
-use OC\Repair\Owncloud\MoveAvatars;
-use OC\Repair\Owncloud\InstallCoreBundle;
-use OC\Repair\Owncloud\UpdateLanguageCodes;
use OC\Repair\NC13\AddLogRotateJob;
use OC\Repair\NC14\AddPreviewBackgroundCleanupJob;
use OC\Repair\NC16\AddClenupLoginFlowV2BackgroundJob;
@@ -63,23 +70,23 @@ use OC\Repair\NC20\EncryptionMigration;
use OC\Repair\NC20\ShippedDashboardEnable;
use OC\Repair\NC21\AddCheckForUserCertificatesJob;
use OC\Repair\NC21\ValidatePhoneNumber;
+use OC\Repair\NC22\LookupServerSendCheck;
+use OC\Repair\NC24\AddTokenCleanupJob;
use OC\Repair\OldGroupMembershipShares;
+use OC\Repair\Owncloud\CleanPreviews;
use OC\Repair\Owncloud\DropAccountTermsTable;
+use OC\Repair\Owncloud\InstallCoreBundle;
+use OC\Repair\Owncloud\MigrateOauthTables;
+use OC\Repair\Owncloud\MoveAvatars;
use OC\Repair\Owncloud\SaveAccountsTableData;
+use OC\Repair\Owncloud\UpdateLanguageCodes;
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\Migration\IOutput;
-use OCP\Migration\IRepairStep;
use Psr\Log\LoggerInterface;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
use Throwable;
class Repair implements IOutput {
@@ -87,8 +94,7 @@ class Repair implements IOutput {
/** @var IRepairStep[] */
private $repairSteps;
- /** @var EventDispatcherInterface */
- private $dispatcher;
+ private IEventDispatcher $dispatcher;
/** @var string */
private $currentStep;
@@ -100,7 +106,7 @@ class Repair implements IOutput {
*
* @param IRepairStep[] $repairSteps array of RepairStep instances
*/
- public function __construct(array $repairSteps, EventDispatcherInterface $dispatcher, LoggerInterface $logger) {
+ public function __construct(array $repairSteps, IEventDispatcher $dispatcher, LoggerInterface $logger) {
$this->repairSteps = $repairSteps;
$this->dispatcher = $dispatcher;
$this->logger = $logger;
@@ -111,19 +117,19 @@ class Repair implements IOutput {
*/
public function run() {
if (count($this->repairSteps) === 0) {
- $this->emit('\OC\Repair', 'info', ['No repair steps available']);
+ $this->dispatcher->dispatchTyped(new RepairInfoEvent('No repair steps available'));
return;
}
// run each repair step
foreach ($this->repairSteps as $step) {
$this->currentStep = $step->getName();
- $this->emit('\OC\Repair', 'step', [$this->currentStep]);
+ $this->dispatcher->dispatchTyped(new RepairStepEvent($this->currentStep));
try {
$step->run($this);
} catch (\Exception $e) {
$this->logger->error("Exception while executing repair step " . $step->getName(), ['exception' => $e]);
- $this->emit('\OC\Repair', 'error', [$e->getMessage()]);
+ $this->dispatcher->dispatchTyped(new RepairErrorEvent($e->getMessage()));
}
}
}
@@ -137,7 +143,7 @@ class Repair implements IOutput {
public function addStep($repairStep) {
if (is_string($repairStep)) {
try {
- $s = \OC::$server->query($repairStep);
+ $s = \OC::$server->get($repairStep);
} catch (QueryException $e) {
if (class_exists($repairStep)) {
try {
@@ -209,6 +215,7 @@ class Repair implements IOutput {
\OC::$server->get(AddCheckForUserCertificatesJob::class),
\OC::$server->get(RepairDavShares::class),
\OC::$server->get(LookupServerSendCheck::class),
+ \OC::$server->get(AddTokenCleanupJob::class),
];
}
@@ -248,20 +255,11 @@ class Repair implements IOutput {
}
/**
- * @param string $scope
- * @param string $method
- * @param array $arguments
+ * @param string $message
*/
- public function emit($scope, $method, array $arguments = []) {
- if (!is_null($this->dispatcher)) {
- $this->dispatcher->dispatch("$scope::$method",
- new GenericEvent("$scope::$method", $arguments));
- }
- }
-
- public function info($string) {
+ public function info($message) {
// for now just emit as we did in the past
- $this->emit('\OC\Repair', 'info', [$string]);
+ $this->dispatcher->dispatchTyped(new RepairInfoEvent($message));
}
/**
@@ -269,7 +267,7 @@ class Repair implements IOutput {
*/
public function warning($message) {
// for now just emit as we did in the past
- $this->emit('\OC\Repair', 'warning', [$message]);
+ $this->dispatcher->dispatchTyped(new RepairWarningEvent($message));
}
/**
@@ -277,16 +275,16 @@ class Repair implements IOutput {
*/
public function startProgress($max = 0) {
// for now just emit as we did in the past
- $this->emit('\OC\Repair', 'startProgress', [$max, $this->currentStep]);
+ $this->dispatcher->dispatchTyped(new RepairStartEvent($max, $this->currentStep));
}
/**
- * @param int $step
+ * @param int $step number of step to advance
* @param string $description
*/
public function advance($step = 1, $description = '') {
// for now just emit as we did in the past
- $this->emit('\OC\Repair', 'advance', [$step, $description]);
+ $this->dispatcher->dispatchTyped(new RepairAdvanceEvent($step, $description));
}
/**
@@ -294,6 +292,6 @@ class Repair implements IOutput {
*/
public function finishProgress() {
// for now just emit as we did in the past
- $this->emit('\OC\Repair', 'finishProgress', []);
+ $this->dispatcher->dispatchTyped(new RepairFinishEvent());
}
}
diff --git a/lib/private/Repair/Events/RepairAdvanceEvent.php b/lib/private/Repair/Events/RepairAdvanceEvent.php
new file mode 100644
index 00000000000..174d4ec48cd
--- /dev/null
+++ b/lib/private/Repair/Events/RepairAdvanceEvent.php
@@ -0,0 +1,48 @@
+<?php
+
+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/>
+ *
+ */
+namespace OC\Repair\Events;
+
+use OCP\EventDispatcher\Event;
+
+class RepairAdvanceEvent extends Event {
+ private int $increment;
+ private string $description;
+
+ public function __construct(
+ int $increment,
+ string $description
+ ) {
+ $this->increment = $increment;
+ $this->description = $description;
+ }
+
+ public function getIncrement(): int {
+ return $this->increment;
+ }
+
+ public function getDescription(): string {
+ return $this->description;
+ }
+}
diff --git a/lib/public/BackgroundJob.php b/lib/private/Repair/Events/RepairErrorEvent.php
index 2be11ab0a6e..7f8a87cfda3 100644
--- a/lib/public/BackgroundJob.php
+++ b/lib/private/Repair/Events/RepairErrorEvent.php
@@ -1,10 +1,11 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
*
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
*
* @license AGPL-3.0
*
@@ -21,25 +22,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
-namespace OCP;
+namespace OC\Repair\Events;
-/**
- * @since 4.5.0
- * @deprecated 14.0.0
- */
-class BackgroundJob {
- /**
- * @since 5.0.0
- * @deprecated 14.0.0
- */
- public static function getExecutionType() {
- return '';
+use OCP\EventDispatcher\Event;
+
+class RepairErrorEvent extends Event {
+ private string $message;
+
+ public function __construct(
+ string $message
+ ) {
+ $this->message = $message;
}
- /**
- * @since 5.0.0
- * @deprecated 14.0.0
- */
- public static function setExecutionType($type) {
+ public function getMessage(): string {
+ return $this->message;
}
}
diff --git a/lib/private/Repair/Events/RepairFinishEvent.php b/lib/private/Repair/Events/RepairFinishEvent.php
new file mode 100644
index 00000000000..abdc2acd1ce
--- /dev/null
+++ b/lib/private/Repair/Events/RepairFinishEvent.php
@@ -0,0 +1,30 @@
+<?php
+
+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/>
+ *
+ */
+namespace OC\Repair\Events;
+
+use OCP\EventDispatcher\Event;
+
+class RepairFinishEvent extends Event {
+}
diff --git a/lib/private/BackgroundJob/Legacy/RegularJob.php b/lib/private/Repair/Events/RepairInfoEvent.php
index 0f337a35eb0..5c2a53fce4f 100644
--- a/lib/private/BackgroundJob/Legacy/RegularJob.php
+++ b/lib/private/Repair/Events/RepairInfoEvent.php
@@ -1,9 +1,11 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
*
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
*
* @license AGPL-3.0
*
@@ -20,22 +22,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
-namespace OC\BackgroundJob\Legacy;
+namespace OC\Repair\Events;
-use OCP\AutoloadNotAllowedException;
+use OCP\EventDispatcher\Event;
-/**
- * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob
- */
-class RegularJob extends \OC\BackgroundJob\Job {
- public function run($argument) {
- try {
- if (is_callable($argument)) {
- call_user_func($argument);
- }
- } catch (AutoloadNotAllowedException $e) {
- // job is from a disabled app, ignore
- return null;
- }
+class RepairInfoEvent extends Event {
+ private string $message;
+
+ public function __construct(
+ string $message
+ ) {
+ $this->message = $message;
+ }
+
+ public function getMessage(): string {
+ return $this->message;
}
}
diff --git a/lib/private/BackgroundJob/Legacy/QueuedJob.php b/lib/private/Repair/Events/RepairStartEvent.php
index fd001738d4f..7bb270595c5 100644
--- a/lib/private/BackgroundJob/Legacy/QueuedJob.php
+++ b/lib/private/Repair/Events/RepairStartEvent.php
@@ -1,10 +1,11 @@
<?php
+
+declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
*
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
*
* @license AGPL-3.0
*
@@ -21,18 +22,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
-namespace OC\BackgroundJob\Legacy;
+namespace OC\Repair\Events;
-/**
- * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob
- */
-class QueuedJob extends \OC\BackgroundJob\QueuedJob {
- public function run($argument) {
- $class = $argument['klass'];
- $method = $argument['method'];
- $parameters = $argument['parameters'];
- if (is_callable([$class, $method])) {
- call_user_func([$class, $method], $parameters);
- }
+use OCP\EventDispatcher\Event;
+
+class RepairStartEvent extends Event {
+ private int $max;
+ private string $current;
+
+ public function __construct(
+ int $max,
+ string $current
+ ) {
+ $this->max = $max;
+ $this->current = $current;
+ }
+
+ public function getMaxStep(): int {
+ return $this->max;
+ }
+
+ public function getCurrentStepName(): string {
+ return $this->current;
}
}
diff --git a/lib/private/Repair/Events/RepairStepEvent.php b/lib/private/Repair/Events/RepairStepEvent.php
new file mode 100644
index 00000000000..82af670b950
--- /dev/null
+++ b/lib/private/Repair/Events/RepairStepEvent.php
@@ -0,0 +1,41 @@
+<?php
+
+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/>
+ *
+ */
+namespace OC\Repair\Events;
+
+use OCP\EventDispatcher\Event;
+
+class RepairStepEvent extends Event {
+ private string $stepName;
+
+ public function __construct(
+ string $stepName
+ ) {
+ $this->stepName = $stepName;
+ }
+
+ public function getStepName(): string {
+ return $this->stepName;
+ }
+}
diff --git a/lib/private/Repair/Events/RepairWarningEvent.php b/lib/private/Repair/Events/RepairWarningEvent.php
new file mode 100644
index 00000000000..2aaa44d4719
--- /dev/null
+++ b/lib/private/Repair/Events/RepairWarningEvent.php
@@ -0,0 +1,41 @@
+<?php
+
+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/>
+ *
+ */
+namespace OC\Repair\Events;
+
+use OCP\EventDispatcher\Event;
+
+class RepairWarningEvent extends Event {
+ private string $message;
+
+ public function __construct(
+ string $message
+ ) {
+ $this->message = $message;
+ }
+
+ public function getMessage(): string {
+ return $this->message;
+ }
+}
diff --git a/lib/private/Repair/NC24/AddTokenCleanupJob.php b/lib/private/Repair/NC24/AddTokenCleanupJob.php
new file mode 100644
index 00000000000..97539c5692f
--- /dev/null
+++ b/lib/private/Repair/NC24/AddTokenCleanupJob.php
@@ -0,0 +1,47 @@
+<?php
+
+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/>.
+ *
+ */
+namespace OC\Repair\NC24;
+
+use OC\Authentication\Token\TokenCleanupJob;
+use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class AddTokenCleanupJob implements IRepairStep {
+ private IJobList $jobList;
+
+ public function __construct(IJobList $jobList) {
+ $this->jobList = $jobList;
+ }
+
+ public function getName(): string {
+ return 'Add token cleanup job';
+ }
+
+ public function run(IOutput $output) {
+ $this->jobList->add(TokenCleanupJob::class);
+ }
+}
diff --git a/lib/private/Repair/RemoveLinkShares.php b/lib/private/Repair/RemoveLinkShares.php
index 1b0270e928d..e1ce78cdbf3 100644
--- a/lib/private/Repair/RemoveLinkShares.php
+++ b/lib/private/Repair/RemoveLinkShares.php
@@ -217,7 +217,7 @@ class RemoveLinkShares implements IRepairStep {
$output->finishProgress();
$shareResult->closeCursor();
- // Notifiy all admins
+ // Notify all admins
$adminGroup = $this->groupManager->get('admin');
$adminUsers = $adminGroup->getUsers();
foreach ($adminUsers as $user) {
diff --git a/lib/private/Route/Router.php b/lib/private/Route/Router.php
index b957173cacc..7e1acd49800 100644
--- a/lib/private/Route/Router.php
+++ b/lib/private/Route/Router.php
@@ -409,7 +409,7 @@ class Router implements IRouter {
* register the routes for the app. The application class will be chosen by
* camelcasing the appname, e.g.: my_app will be turned into
* \OCA\MyApp\AppInfo\Application. If that class does not exist, a default
- * App will be intialized. This makes it optional to ship an
+ * App will be initialized. This makes it optional to ship an
* appinfo/application.php by using the built in query resolver
*
* @param array $routes the application routes
diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php
index c47d102b881..299cab93eb3 100644
--- a/lib/private/Security/Bruteforce/Throttler.php
+++ b/lib/private/Security/Bruteforce/Throttler.php
@@ -36,6 +36,7 @@ use OC\Security\Normalizer\IpAddress;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IDBConnection;
+use OCP\Security\Bruteforce\IThrottler;
use OCP\Security\Bruteforce\MaxDelayReached;
use Psr\Log\LoggerInterface;
@@ -52,11 +53,8 @@ use Psr\Log\LoggerInterface;
*
* @package OC\Security\Bruteforce
*/
-class Throttler {
+class Throttler implements IThrottler {
public const LOGIN_ACTION = 'login';
- public const MAX_DELAY = 25;
- public const MAX_DELAY_MS = 25000; // in milliseconds
- public const MAX_ATTEMPTS = 10;
/** @var IDBConnection */
private $db;
@@ -65,8 +63,8 @@ class Throttler {
private LoggerInterface $logger;
/** @var IConfig */
private $config;
- /** @var bool */
- private $hasAttemptsDeleted = false;
+ /** @var bool[] */
+ private $hasAttemptsDeleted = [];
public function __construct(IDBConnection $db,
ITimeFactory $timeFactory,
@@ -225,7 +223,7 @@ class Throttler {
$maxAgeHours = 48;
}
- if ($ip === '' || $this->hasAttemptsDeleted) {
+ if ($ip === '' || isset($this->hasAttemptsDeleted[$action])) {
return 0;
}
@@ -303,7 +301,7 @@ class Throttler {
$qb->executeStatement();
- $this->hasAttemptsDeleted = true;
+ $this->hasAttemptsDeleted[$action] = true;
}
/**
@@ -311,7 +309,7 @@ class Throttler {
*
* @param string $ip
*/
- public function resetDelayForIP($ip) {
+ public function resetDelayForIP(string $ip): void {
$cutoffTime = $this->getCutoffTimestamp();
$qb = $this->db->getQueryBuilder();
diff --git a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
index f3329135727..1167b3358d2 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
@@ -80,10 +80,8 @@ class ContentSecurityPolicyNonceManager {
public function browserSupportsCspV3(): bool {
$browserWhitelist = [
Request::USER_AGENT_CHROME,
- // Firefox 45+
- '/^Mozilla\/5\.0 \([^)]+\) Gecko\/[0-9.]+ Firefox\/(4[5-9]|[5-9][0-9])\.[0-9.]+$/',
- // Safari 12+
- '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Version\/(?:1[2-9]|[2-9][0-9])\.[0-9]+(?:\.[0-9]+)? Safari\/[0-9.A-Z]+$/',
+ Request::USER_AGENT_FIREFOX,
+ Request::USER_AGENT_SAFARI,
];
if ($this->request->isUserAgent($browserWhitelist)) {
diff --git a/lib/private/Security/TrustedDomainHelper.php b/lib/private/Security/TrustedDomainHelper.php
index 0688ebba5b3..1927af9cb1d 100644
--- a/lib/private/Security/TrustedDomainHelper.php
+++ b/lib/private/Security/TrustedDomainHelper.php
@@ -97,7 +97,7 @@ class TrustedDomainHelper implements ITrustedDomainHelper {
if (preg_match(Request::REGEX_LOCALHOST, $domain) === 1) {
return true;
}
- // Reject misformed domains in any case
+ // Reject malformed domains in any case
if (strpos($domain, '-') === 0 || strpos($domain, '..') !== false) {
return false;
}
diff --git a/lib/private/Security/VerificationToken/CleanUpJob.php b/lib/private/Security/VerificationToken/CleanUpJob.php
index be9d24ece45..4510dcffe0a 100644
--- a/lib/private/Security/VerificationToken/CleanUpJob.php
+++ b/lib/private/Security/VerificationToken/CleanUpJob.php
@@ -28,27 +28,20 @@ namespace OC\Security\VerificationToken;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
-use OCP\ILogger;
use OCP\IUserManager;
+use OCP\BackgroundJob\IJobList;
+use OCP\BackgroundJob\Job;
use OCP\Security\VerificationToken\InvalidTokenException;
use OCP\Security\VerificationToken\IVerificationToken;
-class CleanUpJob extends \OCP\BackgroundJob\Job {
-
- /** @var int */
- protected $runNotBefore;
- /** @var string */
- protected $userId;
- /** @var string */
- protected $subject;
- /** @var string */
- protected $pwdPrefix;
- /** @var IConfig */
- private $config;
- /** @var IVerificationToken */
- private $verificationToken;
- /** @var IUserManager */
- private $userManager;
+class CleanUpJob extends Job {
+ protected ?int $runNotBefore = null;
+ protected ?string $userId = null;
+ protected ?string $subject = null;
+ protected ?string $pwdPrefix = null;
+ private IConfig $config;
+ private IVerificationToken $verificationToken;
+ private IUserManager $userManager;
public function __construct(ITimeFactory $time, IConfig $config, IVerificationToken $verificationToken, IUserManager $userManager) {
parent::__construct($time);
@@ -81,10 +74,10 @@ class CleanUpJob extends \OCP\BackgroundJob\Job {
}
}
- public function execute($jobList, ILogger $logger = null) {
+ public function start(IJobList $jobList): void {
if ($this->time->getTime() >= $this->runNotBefore) {
$jobList->remove($this, $this->argument);
- parent::execute($jobList, $logger);
+ parent::start($jobList);
}
}
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 6e6fa430489..f18ac7b6534 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -73,6 +73,7 @@ use OC\Collaboration\Collaborators\MailPlugin;
use OC\Collaboration\Collaborators\RemoteGroupPlugin;
use OC\Collaboration\Collaborators\RemotePlugin;
use OC\Collaboration\Collaborators\UserPlugin;
+use OC\Collaboration\Reference\ReferenceManager;
use OC\Command\CronBus;
use OC\Comments\ManagerFactory as CommentsManagerFactory;
use OC\Contacts\ContactsMenu\ActionFactory;
@@ -151,6 +152,9 @@ use OC\SystemTag\ManagerFactory as SystemTagManagerFactory;
use OC\Tagging\TagMapper;
use OC\Talk\Broker;
use OC\Template\JSCombiner;
+use OC\User\DisplayNameCache;
+use OC\User\Listeners\UserChangedListener;
+use OC\User\Listeners\UserDeletedListener;
use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
@@ -159,6 +163,7 @@ use OCP\App\IAppManager;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\BackgroundJob\IJobList;
use OCP\Collaboration\AutoComplete\IManager;
+use OCP\Collaboration\Reference\IReferenceManager;
use OCP\Command\IBus;
use OCP\Comments\ICommentsManager;
use OCP\Contacts\ContactsMenu\IActionFactory;
@@ -180,7 +185,6 @@ use OCP\Files\IMimeTypeLoader;
use OCP\Files\IRootFolder;
use OCP\Files\Lock\ILockManager;
use OCP\Files\Mount\IMountManager;
-use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorageFactory;
use OCP\Files\Template\ITemplateManager;
use OCP\FullTextSearch\IFullTextSearchManager;
@@ -200,6 +204,7 @@ use OCP\IAvatarManager;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\ICertificateManager;
+use OCP\IBinaryFinder;
use OCP\IDateTimeFormatter;
use OCP\IDateTimeZone;
use OCP\IDBConnection;
@@ -217,7 +222,6 @@ use OCP\ISession;
use OCP\ITagManager;
use OCP\ITempManager;
use OCP\IURLGenerator;
-use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\L10N\IFactory;
@@ -231,6 +235,7 @@ use OCP\Remote\Api\IApiFactory;
use OCP\Remote\IInstanceFactory;
use OCP\RichObjectStrings\IValidator;
use OCP\Route\IRouter;
+use OCP\Security\Bruteforce\IThrottler;
use OCP\Security\IContentSecurityPolicyManager;
use OCP\Security\ICredentialsManager;
use OCP\Security\ICrypto;
@@ -249,6 +254,7 @@ use OCP\User\Events\BeforeUserLoggedOutEvent;
use OCP\User\Events\PasswordUpdatedEvent;
use OCP\User\Events\PostLoginEvent;
use OCP\User\Events\UserChangedEvent;
+use OCP\User\Events\UserDeletedEvent;
use OCP\User\Events\UserLoggedInEvent;
use OCP\User\Events\UserLoggedInWithCookieEvent;
use OCP\User\Events\UserLoggedOutEvent;
@@ -332,7 +338,8 @@ class Server extends ServerContainer implements IServerContainer {
$c->get(GeneratorHelper::class),
$c->get(ISession::class)->get('user_id'),
$c->get(Coordinator::class),
- $c->get(IServerContainer::class)
+ $c->get(IServerContainer::class),
+ $c->get(IBinaryFinder::class)
);
});
/** @deprecated 19.0.0 */
@@ -351,7 +358,7 @@ class Server extends ServerContainer implements IServerContainer {
return new Profiler($c->get(SystemConfig::class));
});
- $this->registerService(\OCP\Encryption\IManager::class, function (Server $c) {
+ $this->registerService(\OCP\Encryption\IManager::class, function (Server $c): Encryption\Manager {
$view = new View();
$util = new Encryption\Util(
$view,
@@ -472,6 +479,10 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerDeprecatedAlias('UserManager', \OC\User\Manager::class);
$this->registerAlias(\OCP\IUserManager::class, \OC\User\Manager::class);
+ $this->registerService(DisplayNameCache::class, function (ContainerInterface $c) {
+ return $c->get(\OC\User\Manager::class)->getDisplayNameCache();
+ });
+
$this->registerService(\OCP\IGroupManager::class, function (ContainerInterface $c) {
$groupManager = new \OC\Group\Manager(
$this->get(IUserManager::class),
@@ -1001,6 +1012,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(ITrustedDomainHelper::class, TrustedDomainHelper::class);
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('Throttler', Throttler::class);
+ $this->registerAlias(IThrottler::class, Throttler::class);
$this->registerService('IntegrityCodeChecker', function (ContainerInterface $c) {
// IConfig and IAppManager requires a working database. This code
// might however be called when ownCloud is not yet setup.
@@ -1178,14 +1190,12 @@ class Server extends ServerContainer implements IServerContainer {
$manager->registerDisplayNameResolver('user', function ($id) use ($c) {
$manager = $c->get(IUserManager::class);
- $user = $manager->get($id);
- if (is_null($user)) {
- $l = $c->getL10N('core');
- $displayName = $l->t('Unknown user');
- } else {
- $displayName = $user->getDisplayName();
+ $userDisplayName = $manager->getDisplayName($id);
+ if ($userDisplayName === null) {
+ $l = $c->get(IFactory::class)->get('core');
+ return $l->t('Unknown user');
}
- return $displayName;
+ return $userDisplayName;
});
return $manager;
@@ -1330,6 +1340,8 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\Collaboration\Resources\IProviderManager::class, \OC\Collaboration\Resources\ProviderManager::class);
$this->registerAlias(\OCP\Collaboration\Resources\IManager::class, \OC\Collaboration\Resources\Manager::class);
+ $this->registerAlias(IReferenceManager::class, ReferenceManager::class);
+
$this->registerDeprecatedAlias('SettingsManager', \OC\Settings\Manager::class);
$this->registerAlias(\OCP\Settings\IManager::class, \OC\Settings\Manager::class);
$this->registerService(\OC\Files\AppData\Factory::class, function (ContainerInterface $c) {
@@ -1440,6 +1452,8 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\Files\AppData\IAppDataFactory::class, \OC\Files\AppData\Factory::class);
+ $this->registerAlias(IBinaryFinder::class, BinaryFinder::class);
+
$this->connectDispatcher();
}
@@ -1473,52 +1487,13 @@ class Server extends ServerContainer implements IServerContainer {
return $this->get(\OC\Calendar\Room\Manager::class);
}
- private function connectDispatcher() {
- $dispatcher = $this->get(SymfonyAdapter::class);
-
- // Delete avatar on user deletion
- $dispatcher->addListener('OCP\IUser::preDelete', function (GenericEvent $e) {
- $logger = $this->get(LoggerInterface::class);
- $manager = $this->getAvatarManager();
- /** @var IUser $user */
- $user = $e->getSubject();
-
- try {
- $avatar = $manager->getAvatar($user->getUID());
- $avatar->remove();
- } catch (NotFoundException $e) {
- // no avatar to remove
- } catch (\Exception $e) {
- // Ignore exceptions
- $logger->info('Could not cleanup avatar of ' . $user->getUID());
- }
- });
-
- $dispatcher->addListener('OCP\IUser::changeUser', function (GenericEvent $e) {
- $manager = $this->getAvatarManager();
- /** @var IUser $user */
- $user = $e->getSubject();
- $feature = $e->getArgument('feature');
- $oldValue = $e->getArgument('oldValue');
- $value = $e->getArgument('value');
-
- // We only change the avatar on display name changes
- if ($feature !== 'displayName') {
- return;
- }
-
- try {
- $avatar = $manager->getAvatar($user->getUID());
- $avatar->userChanged($feature, $oldValue, $value);
- } catch (NotFoundException $e) {
- // no avatar to remove
- }
- });
-
- /** @var IEventDispatcher $eventDispatched */
- $eventDispatched = $this->get(IEventDispatcher::class);
- $eventDispatched->addServiceListener(LoginFailed::class, LoginFailedListener::class);
- $eventDispatched->addServiceListener(PostLoginEvent::class, UserLoggedInListener::class);
+ private function connectDispatcher(): void {
+ /** @var IEventDispatcher $eventDispatcher */
+ $eventDispatcher = $this->get(IEventDispatcher::class);
+ $eventDispatcher->addServiceListener(LoginFailed::class, LoginFailedListener::class);
+ $eventDispatcher->addServiceListener(PostLoginEvent::class, UserLoggedInListener::class);
+ $eventDispatcher->addServiceListener(UserChangedEvent::class, UserChangedListener::class);
+ $eventDispatcher->addServiceListener(UserDeletedEvent::class, UserDeletedListener::class);
}
/**
diff --git a/lib/private/Session/CryptoSessionData.php b/lib/private/Session/CryptoSessionData.php
index 2e3bd46da5b..b01887e39e2 100644
--- a/lib/private/Session/CryptoSessionData.php
+++ b/lib/private/Session/CryptoSessionData.php
@@ -97,8 +97,17 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param mixed $value
*/
public function set(string $key, $value) {
+ if ($this->get($key) === $value) {
+ // Do not write the session if the value hasn't changed to avoid reopening
+ return;
+ }
+
+ $reopened = $this->reopen();
$this->sessionValues[$key] = $value;
$this->isModified = true;
+ if ($reopened) {
+ $this->close();
+ }
}
/**
@@ -131,9 +140,13 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $key
*/
public function remove(string $key) {
+ $reopened = $this->reopen();
$this->isModified = true;
unset($this->sessionValues[$key]);
$this->session->remove(self::encryptedSessionName);
+ if ($reopened) {
+ $this->close();
+ }
}
/**
@@ -149,6 +162,10 @@ class CryptoSessionData implements \ArrayAccess, ISession {
$this->session->clear();
}
+ public function reopen(): bool {
+ return $this->session->reopen();
+ }
+
/**
* Wrapper around session_regenerate_id
*
diff --git a/lib/private/Session/Internal.php b/lib/private/Session/Internal.php
index 285b6fd7960..87dd5ed6014 100644
--- a/lib/private/Session/Internal.php
+++ b/lib/private/Session/Internal.php
@@ -68,8 +68,11 @@ class Internal extends Session {
* @param integer $value
*/
public function set(string $key, $value) {
- $this->validateSession();
+ $reopened = $this->reopen();
$_SESSION[$key] = $value;
+ if ($reopened) {
+ $this->close();
+ }
}
/**
@@ -101,6 +104,7 @@ class Internal extends Session {
}
public function clear() {
+ $this->reopen();
$this->invoke('session_unset');
$this->regenerateId();
$this->startSession(true);
@@ -120,6 +124,7 @@ class Internal extends Session {
* @return void
*/
public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {
+ $this->reopen();
$oldId = null;
if ($updateToken) {
@@ -171,8 +176,14 @@ class Internal extends Session {
/**
* @throws \Exception
*/
- public function reopen() {
- throw new \Exception('The session cannot be reopened - reopen() is ony to be used in unit testing.');
+ public function reopen(): bool {
+ if ($this->sessionClosed) {
+ $this->startSession(false, false);
+ $this->sessionClosed = false;
+ return true;
+ }
+
+ return false;
}
/**
@@ -214,7 +225,11 @@ class Internal extends Session {
}
}
- private function startSession(bool $silence = false) {
- $this->invoke('session_start', [['cookie_samesite' => 'Lax']], $silence);
+ private function startSession(bool $silence = false, bool $readAndClose = true) {
+ $sessionParams = ['cookie_samesite' => 'Lax'];
+ if (\OC::hasSessionRelaxedExpiry()) {
+ $sessionParams['read_and_close'] = $readAndClose;
+ }
+ $this->invoke('session_start', [$sessionParams], $silence);
}
}
diff --git a/lib/private/Session/Memory.php b/lib/private/Session/Memory.php
index 0afd3703366..b9b3dba54b7 100644
--- a/lib/private/Session/Memory.php
+++ b/lib/private/Session/Memory.php
@@ -53,7 +53,6 @@ class Memory extends Session {
* @param integer $value
*/
public function set(string $key, $value) {
- $this->validateSession();
$this->data[$key] = $value;
}
@@ -80,7 +79,6 @@ class Memory extends Session {
* @param string $key
*/
public function remove(string $key) {
- $this->validateSession();
unset($this->data[$key]);
}
@@ -110,8 +108,10 @@ class Memory extends Session {
/**
* Helper function for PHPUnit execution - don't use in non-test code
*/
- public function reopen() {
+ public function reopen(): bool {
+ $reopened = $this->sessionClosed;
$this->sessionClosed = false;
+ return $reopened;
}
/**
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index 177ede1e292..edbb9b33275 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -53,6 +53,7 @@ use Exception;
use InvalidArgumentException;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\Authentication\Token\PublicKeyTokenProvider;
+use OC\Authentication\Token\TokenCleanupJob;
use OC\Log\Rotate;
use OC\Preview\BackgroundCleanupJob;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -450,6 +451,7 @@ class Setup {
public static function installBackgroundJobs() {
$jobList = \OC::$server->getJobList();
+ $jobList->add(TokenCleanupJob::class);
$jobList->add(Rotate::class);
$jobList->add(BackgroundCleanupJob::class);
}
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
index e878ed4d9aa..e3004c269bc 100644
--- a/lib/private/Setup/MySQL.php
+++ b/lib/private/Setup/MySQL.php
@@ -129,6 +129,7 @@ class MySQL extends AbstractDatabase {
'exception' => $ex,
'app' => 'mysql.setup',
]);
+ throw $ex;
}
}
@@ -137,6 +138,19 @@ class MySQL extends AbstractDatabase {
* @param IDBConnection $connection
*/
private function createSpecificUser($username, $connection): void {
+ $rootUser = $this->dbUser;
+ $rootPassword = $this->dbPassword;
+
+ //create a random password so we don't need to store the admin password in the config file
+ $saveSymbols = str_replace(['\"', '\\', '\'', '`'], '', ISecureRandom::CHAR_SYMBOLS);
+ $password = $this->random->generate(22, ISecureRandom::CHAR_ALPHANUMERIC . $saveSymbols)
+ . $this->random->generate(2, ISecureRandom::CHAR_UPPER)
+ . $this->random->generate(2, ISecureRandom::CHAR_LOWER)
+ . $this->random->generate(2, ISecureRandom::CHAR_DIGITS)
+ . $this->random->generate(2, $saveSymbols)
+ ;
+ $this->dbPassword = str_shuffle($password);
+
try {
//user already specified in config
$oldUser = $this->config->getValue('dbuser', false);
@@ -159,10 +173,6 @@ class MySQL extends AbstractDatabase {
if (count($data) === 0) {
//use the admin login data for the new database user
$this->dbUser = $adminUser;
-
- //create a random password so we don't need to store the admin password in the config file
- $this->dbPassword = $this->random->generate(30, ISecureRandom::CHAR_ALPHANUMERIC);
-
$this->createDBUser($connection);
break;
@@ -179,6 +189,9 @@ class MySQL extends AbstractDatabase {
'exception' => $ex,
'app' => 'mysql.setup',
]);
+ // Restore the original credentials
+ $this->dbUser = $rootUser;
+ $this->dbPassword = $rootPassword;
}
$this->config->setValues([
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index 31c734f94aa..3632a2a26d1 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -79,7 +79,7 @@ class Constants {
public const FORMAT_STATUSES = -2;
public const FORMAT_SOURCES = -3; // ToDo Check if it is still in use otherwise remove it
- public const RESPONSE_FORMAT = 'json'; // default resonse format for ocs calls
+ public const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
public const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility
diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php
index 9018f35ac2a..f47c042df29 100644
--- a/lib/private/Share/Share.php
+++ b/lib/private/Share/Share.php
@@ -732,7 +732,7 @@ class Share extends Constants {
foreach ($result as $key => $r) {
// for file/folder shares we need to compare file_source, otherwise we compare item_source
// only group shares if they already point to the same target, otherwise the file where shared
- // before grouping of shares was added. In this case we don't group them toi avoid confusions
+ // before grouping of shares was added. In this case we don't group them to avoid confusions
if (($fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
(!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) {
// add the first item to the list of grouped shares
@@ -757,7 +757,7 @@ class Share extends Constants {
/**
* construct select statement
* @param int $format
- * @param boolean $fileDependent ist it a file/folder share or a generla share
+ * @param boolean $fileDependent ist it a file/folder share or a general share
* @param string $uidOwner
* @return string select statement
*/
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index 520bd17d3cf..c78cf62e069 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -52,6 +52,7 @@ use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Mail\IMailer;
use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\IAttributes;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
@@ -174,6 +175,8 @@ class DefaultShareProvider implements IShareProvider {
if (method_exists($share, 'getParent')) {
$qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
}
+
+ $qb->setValue('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0, IQueryBuilder::PARAM_INT));
} else {
throw new \Exception('invalid share type!');
}
@@ -193,6 +196,12 @@ class DefaultShareProvider implements IShareProvider {
// set the permissions
$qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
+ // set share attributes
+ $shareAttributes = $this->formatShareAttributes(
+ $share->getAttributes()
+ );
+ $qb->setValue('attributes', $qb->createNamedParameter($shareAttributes));
+
// Set who created this share
$qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
@@ -248,6 +257,8 @@ class DefaultShareProvider implements IShareProvider {
public function update(\OCP\Share\IShare $share) {
$originalShare = $this->getShareById($share->getId());
+ $shareAttributes = $this->formatShareAttributes($share->getAttributes());
+
if ($share->getShareType() === IShare::TYPE_USER) {
/*
* We allow updating the recipient on user shares.
@@ -259,6 +270,7 @@ class DefaultShareProvider implements IShareProvider {
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
+ ->set('attributes', $qb->createNamedParameter($shareAttributes))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
@@ -272,6 +284,7 @@ class DefaultShareProvider implements IShareProvider {
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
+ ->set('attributes', $qb->createNamedParameter($shareAttributes))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
@@ -301,6 +314,7 @@ class DefaultShareProvider implements IShareProvider {
->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
+ ->set('attributes', $qb->createNamedParameter($shareAttributes))
->execute();
} elseif ($share->getShareType() === IShare::TYPE_LINK) {
$qb = $this->dbConn->getQueryBuilder();
@@ -311,6 +325,7 @@ class DefaultShareProvider implements IShareProvider {
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
+ ->set('attributes', $qb->createNamedParameter($shareAttributes))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('token', $qb->createNamedParameter($share->getToken()))
@@ -611,6 +626,10 @@ class DefaultShareProvider implements IShareProvider {
$data = $stmt->fetch();
$stmt->closeCursor();
+ $shareAttributes = $this->formatShareAttributes(
+ $share->getAttributes()
+ );
+
if ($data === false) {
// No usergroup share yet. Create one.
$qb = $this->dbConn->getQueryBuilder();
@@ -626,6 +645,7 @@ class DefaultShareProvider implements IShareProvider {
'file_source' => $qb->createNamedParameter($share->getNodeId()),
'file_target' => $qb->createNamedParameter($share->getTarget()),
'permissions' => $qb->createNamedParameter($share->getPermissions()),
+ 'attributes' => $qb->createNamedParameter($shareAttributes),
'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
])->execute();
} else {
@@ -641,9 +661,12 @@ class DefaultShareProvider implements IShareProvider {
return $share;
}
- public function getSharesInFolder($userId, Folder $node, $reshares) {
+ public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
$qb = $this->dbConn->getQueryBuilder();
- $qb->select('*')
+ $qb->select('s.*',
+ 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
+ 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
+ 'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum')
->from('share', 's')
->andWhere($qb->expr()->orX(
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
@@ -679,12 +702,21 @@ class DefaultShareProvider implements IShareProvider {
}, $childMountNodes);
$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
- $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
- )
- );
+ 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->orderBy('id');
@@ -922,8 +954,8 @@ class DefaultShareProvider implements IShareProvider {
$start = 0;
while (true) {
- $groups = array_slice($allGroups, $start, 100);
- $start += 100;
+ $groups = array_slice($allGroups, $start, 1000);
+ $start += 1000;
if ($groups === []) {
break;
@@ -1061,6 +1093,8 @@ class DefaultShareProvider implements IShareProvider {
$share->setToken($data['token']);
}
+ $share = $this->updateShareAttributes($share, $data['attributes']);
+
$share->setSharedBy($data['uid_initiator']);
$share->setShareOwner($data['uid_owner']);
@@ -1282,7 +1316,7 @@ class DefaultShareProvider implements IShareProvider {
$chunks = array_chunk($ids, 100);
foreach ($chunks as $chunk) {
/*
- * Delete all special shares wit this users for the found group shares
+ * Delete all special shares with this users for the found group shares
*/
$qb->delete('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
@@ -1528,4 +1562,48 @@ class DefaultShareProvider implements IShareProvider {
}
$cursor->closeCursor();
}
+
+ /**
+ * Load from database format (JSON string) to IAttributes
+ *
+ * @return IShare the modified share
+ */
+ private function updateShareAttributes(IShare $share, ?string $data): IShare {
+ if ($data !== null && $data !== '') {
+ $attributes = new ShareAttributes();
+ $compressedAttributes = \json_decode($data, true);
+ if ($compressedAttributes === false || $compressedAttributes === null) {
+ return $share;
+ }
+ foreach ($compressedAttributes as $compressedAttribute) {
+ $attributes->setAttribute(
+ $compressedAttribute[0],
+ $compressedAttribute[1],
+ $compressedAttribute[2]
+ );
+ }
+ $share->setAttributes($attributes);
+ }
+
+ return $share;
+ }
+
+ /**
+ * Format IAttributes to database format (JSON string)
+ */
+ private function formatShareAttributes(?IAttributes $attributes): ?string {
+ if ($attributes === null || empty($attributes->toArray())) {
+ return null;
+ }
+
+ $compressedAttributes = [];
+ foreach ($attributes->toArray() as $attribute) {
+ $compressedAttributes[] = [
+ 0 => $attribute['scope'],
+ 1 => $attribute['key'],
+ 2 => $attribute['enabled']
+ ];
+ }
+ return \json_encode($compressedAttributes);
+ }
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index b1a9783d7b8..2ef61cf3404 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -41,7 +41,7 @@
*/
namespace OC\Share20;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OC\Files\Mount\MoveableMount;
use OC\KnownUser\KnownUserService;
use OC\Share20\Exception\ProviderException;
@@ -650,7 +650,7 @@ class Manager implements IManager {
}
// Check if public upload is allowed
- if (!$this->shareApiLinkAllowPublicUpload() &&
+ if ($share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload() &&
($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
throw new \InvalidArgumentException('Public upload is not allowed');
}
@@ -1093,6 +1093,7 @@ class Manager implements IManager {
'shareWith' => $share->getSharedWith(),
'uidOwner' => $share->getSharedBy(),
'permissions' => $share->getPermissions(),
+ 'attributes' => $share->getAttributes() !== null ? $share->getAttributes()->toArray() : null,
'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
]);
}
@@ -1303,11 +1304,11 @@ class Manager implements IManager {
return $provider->move($share, $recipientId);
}
- public function getSharesInFolder($userId, Folder $node, $reshares = false) {
+ public function getSharesInFolder($userId, Folder $node, $reshares = false, $shallow = true) {
$providers = $this->factory->getAllProviders();
- return array_reduce($providers, function ($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
- $newShares = $provider->getSharesInFolder($userId, $node, $reshares);
+ return array_reduce($providers, function ($shares, IShareProvider $provider) use ($userId, $node, $reshares, $shallow) {
+ $newShares = $provider->getSharesInFolder($userId, $node, $reshares, $shallow);
foreach ($newShares as $fid => $data) {
if (!isset($shares[$fid])) {
$shares[$fid] = [];
@@ -1543,7 +1544,7 @@ class Manager implements IManager {
* Reduce the permissions for link or email shares if public upload is not enabled
*/
if (($share->getShareType() === IShare::TYPE_LINK || $share->getShareType() === IShare::TYPE_EMAIL)
- && !$this->shareApiLinkAllowPublicUpload()) {
+ && $share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload()) {
$share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
}
@@ -2010,7 +2011,7 @@ class Manager implements IManager {
/**
* Copied from \OC_Util::isSharingDisabledForUser
*
- * TODO: Deprecate fuction from OC_Util
+ * TODO: Deprecate function from OC_Util
*
* @param string $userId
* @return bool
diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php
index 7ed03832e4c..c2d45503696 100644
--- a/lib/private/Share20/Share.php
+++ b/lib/private/Share20/Share.php
@@ -37,6 +37,7 @@ use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IUserManager;
use OCP\Share\Exceptions\IllegalIDChangeException;
+use OCP\Share\IAttributes;
use OCP\Share\IShare;
class Share implements IShare {
@@ -65,6 +66,8 @@ class Share implements IShare {
private $shareOwner;
/** @var int */
private $permissions;
+ /** @var IAttributes */
+ private $attributes;
/** @var int */
private $status;
/** @var string */
@@ -319,7 +322,7 @@ class Share implements IShare {
* @inheritdoc
*/
public function setPermissions($permissions) {
- //TODO checkes
+ //TODO checks
$this->permissions = $permissions;
return $this;
@@ -335,6 +338,28 @@ class Share implements IShare {
/**
* @inheritdoc
*/
+ public function newAttributes(): IAttributes {
+ return new ShareAttributes();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setAttributes(?IAttributes $attributes) {
+ $this->attributes = $attributes;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAttributes(): ?IAttributes {
+ return $this->attributes;
+ }
+
+ /**
+ * @inheritdoc
+ */
public function setStatus(int $status): IShare {
$this->status = $status;
return $this;
@@ -511,7 +536,7 @@ class Share implements IShare {
* Set the parent of this share
*
* @param int parent
- * @return \OCP\Share\IShare
+ * @return IShare
* @deprecated The new shares do not have parents. This is just here for legacy reasons.
*/
public function setParent($parent) {
diff --git a/lib/private/Share20/ShareAttributes.php b/lib/private/Share20/ShareAttributes.php
new file mode 100644
index 00000000000..92f034e6783
--- /dev/null
+++ b/lib/private/Share20/ShareAttributes.php
@@ -0,0 +1,73 @@
+<?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/>
+ *
+ */
+namespace OC\Share20;
+
+use OCP\Share\IAttributes;
+
+class ShareAttributes implements IAttributes {
+
+ /** @var array */
+ private $attributes;
+
+ public function __construct() {
+ $this->attributes = [];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setAttribute($scope, $key, $enabled) {
+ if (!\array_key_exists($scope, $this->attributes)) {
+ $this->attributes[$scope] = [];
+ }
+ $this->attributes[$scope][$key] = $enabled;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAttribute($scope, $key) {
+ if (\array_key_exists($scope, $this->attributes) &&
+ \array_key_exists($key, $this->attributes[$scope])) {
+ return $this->attributes[$scope][$key];
+ }
+ return null;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function toArray() {
+ $result = [];
+ foreach ($this->attributes as $scope => $keys) {
+ foreach ($keys as $key => $enabled) {
+ $result[] = [
+ "scope" => $scope,
+ "key" => $key,
+ "enabled" => $enabled
+ ];
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php
index 5f23b471837..61f0c4e39cd 100644
--- a/lib/private/Template/JSConfigHelper.php
+++ b/lib/private/Template/JSConfigHelper.php
@@ -293,6 +293,8 @@ class JSConfigHelper {
]);
}
+ $this->initialStateService->provideInitialState('core', 'projects_enabled', $this->config->getSystemValueBool('projects.enabled', false));
+
$this->initialStateService->provideInitialState('core', 'config', $config);
$this->initialStateService->provideInitialState('core', 'capabilities', $capabilities);
diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php
index 95ae0d3d832..9e76655aba2 100644
--- a/lib/private/Template/JSResourceLocator.php
+++ b/lib/private/Template/JSResourceLocator.php
@@ -71,12 +71,14 @@ class JSResourceLocator extends ResourceLocator {
} elseif ($this->appendIfExist($this->serverroot, $theme_dir.'apps/'.$script.'.js')
|| $this->appendIfExist($this->serverroot, $theme_dir.$script.'.js')
|| $this->appendIfExist($this->serverroot, $script.'.js')
+ || $this->appendIfExist($this->serverroot, $theme_dir . "dist/$app-$scriptName.js")
|| $this->appendIfExist($this->serverroot, "dist/$app-$scriptName.js")
|| $this->appendIfExist($this->serverroot, 'apps/'.$script.'.js')
|| $this->cacheAndAppendCombineJsonIfExist($this->serverroot, $script.'.json')
|| $this->appendIfExist($this->serverroot, $theme_dir.'core/'.$script.'.js')
|| $this->appendIfExist($this->serverroot, 'core/'.$script.'.js')
- || (strpos($scriptName, '/') === -1 && $this->appendIfExist($this->serverroot, "dist/core-$scriptName.js"))
+ || (strpos($scriptName, '/') === -1 && ($this->appendIfExist($this->serverroot, $theme_dir . "dist/core-$scriptName.js")
+ || $this->appendIfExist($this->serverroot, "dist/core-$scriptName.js")))
|| $this->cacheAndAppendCombineJsonIfExist($this->serverroot, 'core/'.$script.'.json')
) {
return;
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index a5aabc04b61..d041db2a7c2 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -100,6 +100,7 @@ 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)2));
$this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes');
@@ -281,6 +282,9 @@ class TemplateLayout extends \OC_Template {
}
$this->assign('initialStates', $this->initialState->getInitialStates());
+
+ $this->assign('id-app-content', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-content' : '#content');
+ $this->assign('id-app-navigation', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-navigation' : null);
}
/**
diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php
index 753a4a217d1..7be2895a1ef 100644
--- a/lib/private/URLGenerator.php
+++ b/lib/private/URLGenerator.php
@@ -42,6 +42,8 @@ namespace OC;
use OC\Route\Router;
use OCA\Theming\ThemingDefaults;
+use OCP\App\AppPathNotFoundException;
+use OCP\App\IAppManager;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IRequest;
@@ -65,12 +67,14 @@ class URLGenerator implements IURLGenerator {
private $router;
/** @var null|string */
private $baseUrl = null;
+ private ?IAppManager $appManager = null;
public function __construct(IConfig $config,
IUserSession $userSession,
ICacheFactory $cacheFactory,
IRequest $request,
- Router $router) {
+ Router $router
+ ) {
$this->config = $config;
$this->userSession = $userSession;
$this->cacheFactory = $cacheFactory;
@@ -78,6 +82,14 @@ class URLGenerator implements IURLGenerator {
$this->router = $router;
}
+ private function getAppManager(): IAppManager {
+ if ($this->appManager !== null) {
+ return $this->appManager;
+ }
+ $this->appManager = \OCP\Server::get(IAppManager::class);
+ return $this->appManager;
+ }
+
/**
* Creates an url using a defined route
*
@@ -132,9 +144,9 @@ class URLGenerator implements IURLGenerator {
$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
if ($appName !== '') {
- $app_path = \OC_App::getAppPath($appName);
+ $app_path = $this->getAppManager()->getAppPath($appName);
// Check if the app is in the app folder
- if ($app_path && file_exists($app_path . '/' . $file)) {
+ if (file_exists($app_path . '/' . $file)) {
if (substr($file, -3) === 'php') {
$urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $appName;
if ($frontControllerActive) {
@@ -142,7 +154,7 @@ class URLGenerator implements IURLGenerator {
}
$urlLinkTo .= ($file !== 'index.php') ? '/' . $file : '';
} else {
- $urlLinkTo = \OC_App::getAppWebPath($appName) . '/' . $file;
+ $urlLinkTo = $this->getAppManager()->getAppWebPath($appName) . '/' . $file;
}
} else {
$urlLinkTo = \OC::$WEBROOT . '/' . $appName . '/' . $file;
@@ -189,11 +201,20 @@ class URLGenerator implements IURLGenerator {
//if a theme has a png but not an svg always use the png
$basename = substr(basename($file), 0, -4);
- $appPath = \OC_App::getAppPath($appName);
+ try {
+ $appPath = $this->getAppManager()->getAppPath($appName);
+ } catch (AppPathNotFoundException $e) {
+ if ($appName === 'core' || $appName === '') {
+ $appName = 'core';
+ $appPath = false;
+ } else {
+ throw new RuntimeException('image not found: image: ' . $file . ' webroot: ' . \OC::$WEBROOT . ' serverroot: ' . \OC::$SERVERROOT);
+ }
+ }
// Check if the app is in the app folder
$path = '';
- $themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
+ $themingEnabled = $this->config->getSystemValue('installed', false) && $this->getAppManager()->isEnabledForUser('theming');
$themingImagePath = false;
if ($themingEnabled) {
$themingDefaults = \OC::$server->getThemingDefaults();
@@ -220,10 +241,10 @@ class URLGenerator implements IURLGenerator {
} elseif ($themingEnabled && $themingImagePath) {
$path = $themingImagePath;
} elseif ($appPath && file_exists($appPath . "/img/$file")) {
- $path = \OC_App::getAppWebPath($appName) . "/img/$file";
+ $path = $this->getAppManager()->getAppWebPath($appName) . "/img/$file";
} elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")
&& file_exists($appPath . "/img/$basename.png")) {
- $path = \OC_App::getAppWebPath($appName) . "/img/$basename.png";
+ $path = $this->getAppManager()->getAppWebPath($appName) . "/img/$basename.png";
} elseif (!empty($appName) and file_exists(\OC::$SERVERROOT . "/$appName/img/$file")) {
$path = \OC::$WEBROOT . "/$appName/img/$file";
} elseif (!empty($appName) and (!file_exists(\OC::$SERVERROOT . "/$appName/img/$basename.svg")
@@ -320,7 +341,7 @@ class URLGenerator implements IURLGenerator {
* @return string base url of the current request
*/
public function getBaseUrl(): string {
- // BaseUrl can be equal to 'http(s)://' during the first steps of the intial setup.
+ // BaseUrl can be equal to 'http(s)://' during the first steps of the initial setup.
if ($this->baseUrl === null || $this->baseUrl === "http://" || $this->baseUrl === "https://") {
$this->baseUrl = $this->request->getServerProtocol() . '://' . $this->request->getServerHost() . \OC::$WEBROOT;
}
diff --git a/lib/private/Updater.php b/lib/private/Updater.php
index 2c06cffcb19..78613ddbb0c 100644
--- a/lib/private/Updater.php
+++ b/lib/private/Updater.php
@@ -40,19 +40,28 @@ declare(strict_types=1);
*/
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\DB\Connection;
use OC\DB\MigrationService;
+use OC\DB\MigratorExecuteSqlEvent;
use OC\Hooks\BasicEmitter;
use OC\IntegrityCheck\Checker;
+use OC\Repair\Events\RepairAdvanceEvent;
+use OC\Repair\Events\RepairErrorEvent;
+use OC\Repair\Events\RepairFinishEvent;
+use OC\Repair\Events\RepairInfoEvent;
+use OC\Repair\Events\RepairStartEvent;
+use OC\Repair\Events\RepairStepEvent;
+use OC\Repair\Events\RepairWarningEvent;
use OC_App;
-use OCP\App\IAppManager;
-use OCP\HintException;
-use OCP\IConfig;
-use OCP\ILogger;
-use OCP\Util;
use Psr\Log\LoggerInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Class that handles autoupdating of ownCloud
@@ -102,7 +111,6 @@ class Updater extends BasicEmitter {
* @return bool true if the operation succeeded, false otherwise
*/
public function upgrade(): bool {
- $this->emitRepairEvents();
$this->logAllEvents();
$logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
@@ -248,7 +256,7 @@ class Updater extends BasicEmitter {
file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
// pre-upgrade repairs
- $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher(), \OC::$server->get(LoggerInterface::class));
+ $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->get(LoggerInterface::class));
$repair->run();
$this->doCoreUpgrade();
@@ -289,11 +297,11 @@ class Updater extends BasicEmitter {
}
// post-upgrade repairs
- $repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher(), \OC::$server->get(LoggerInterface::class));
+ $repair = new Repair(Repair::getRepairSteps(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->get(LoggerInterface::class));
$repair->run();
//Invalidate update feed
- $this->config->setAppValue('core', 'lastupdatedat', 0);
+ $this->config->setAppValue('core', 'lastupdatedat', '0');
// Check for code integrity if not disabled
if (\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
@@ -378,7 +386,7 @@ class Updater extends BasicEmitter {
$appManager = \OC::$server->getAppManager();
foreach ($apps as $app) {
// check if the app is compatible with this version of Nextcloud
- $info = OC_App::getAppInfo($app);
+ $info = $appManager->getAppInfo($app);
if ($info === null || !OC_App::isAppCompatible($version, $info)) {
if ($appManager->isShipped($app)) {
throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
@@ -432,91 +440,47 @@ class Updater extends BasicEmitter {
}
}
- /**
- * Forward messages emitted by the repair routine
- */
- private function emitRepairEvents(): void {
- $dispatcher = \OC::$server->getEventDispatcher();
- $dispatcher->addListener('\OC\Repair::warning', function ($event) {
- if ($event instanceof GenericEvent) {
- $this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
- }
- });
- $dispatcher->addListener('\OC\Repair::error', function ($event) {
- if ($event instanceof GenericEvent) {
- $this->emit('\OC\Updater', 'repairError', $event->getArguments());
- }
- });
- $dispatcher->addListener('\OC\Repair::info', function ($event) {
- if ($event instanceof GenericEvent) {
- $this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
- }
- });
- $dispatcher->addListener('\OC\Repair::step', function ($event) {
- if ($event instanceof GenericEvent) {
- $this->emit('\OC\Updater', 'repairStep', $event->getArguments());
- }
- });
- }
-
private function logAllEvents(): void {
$log = $this->log;
- $dispatcher = \OC::$server->getEventDispatcher();
- $dispatcher->addListener('\OC\DB\Migrator::executeSql', function ($event) use ($log) {
- if (!$event instanceof GenericEvent) {
- return;
- }
- $log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
- });
- $dispatcher->addListener('\OC\DB\Migrator::checkTable', function ($event) use ($log) {
- if (!$event instanceof GenericEvent) {
- return;
+ /** @var IEventDispatcher $dispatcher */
+ $dispatcher = \OC::$server->get(IEventDispatcher::class);
+ $dispatcher->addListener(
+ MigratorExecuteSqlEvent::class,
+ function (MigratorExecuteSqlEvent $event) use ($log): void {
+ $log->info(get_class($event).': ' . $event->getSql() . ' (' . $event->getCurrentStep() . ' of ' . $event->getMaxStep() . ')', ['app' => 'updater']);
}
- $log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
- });
-
- $repairListener = function ($event) use ($log) {
- if (!$event instanceof GenericEvent) {
- return;
- }
- switch ($event->getSubject()) {
- case '\OC\Repair::startProgress':
- $log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
- break;
- case '\OC\Repair::advance':
- $desc = $event->getArgument(1);
- if (empty($desc)) {
- $desc = '';
- }
- $log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
-
- break;
- case '\OC\Repair::finishProgress':
- $log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
- break;
- case '\OC\Repair::step':
- $log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
- break;
- case '\OC\Repair::info':
- $log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
- break;
- case '\OC\Repair::warning':
- $log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
- break;
- case '\OC\Repair::error':
- $log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
- break;
+ );
+
+ $repairListener = function (Event $event) use ($log): void {
+ if ($event instanceof RepairStartEvent) {
+ $log->info(get_class($event).': Starting ... ' . $event->getMaxStep() . ' (' . $event->getCurrentStepName() . ')', ['app' => 'updater']);
+ } elseif ($event instanceof RepairAdvanceEvent) {
+ $desc = $event->getDescription();
+ if (empty($desc)) {
+ $desc = '';
+ }
+ $log->info(get_class($event).': ' . $desc . ' (' . $event->getIncrement() . ')', ['app' => 'updater']);
+ } elseif ($event instanceof RepairFinishEvent) {
+ $log->info(get_class($event), ['app' => 'updater']);
+ } elseif ($event instanceof RepairStepEvent) {
+ $log->info(get_class($event).': Repair step: ' . $event->getStepName(), ['app' => 'updater']);
+ } elseif ($event instanceof RepairInfoEvent) {
+ $log->info(get_class($event).': Repair info: ' . $event->getMessage(), ['app' => 'updater']);
+ } elseif ($event instanceof RepairWarningEvent) {
+ $log->warning(get_class($event).': Repair warning: ' . $event->getMessage(), ['app' => 'updater']);
+ } elseif ($event instanceof RepairErrorEvent) {
+ $log->error(get_class($event).': Repair error: ' . $event->getMessage(), ['app' => 'updater']);
}
};
- $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
- $dispatcher->addListener('\OC\Repair::advance', $repairListener);
- $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
- $dispatcher->addListener('\OC\Repair::step', $repairListener);
- $dispatcher->addListener('\OC\Repair::info', $repairListener);
- $dispatcher->addListener('\OC\Repair::warning', $repairListener);
- $dispatcher->addListener('\OC\Repair::error', $repairListener);
+ $dispatcher->addListener(RepairStartEvent::class, $repairListener);
+ $dispatcher->addListener(RepairAdvanceEvent::class, $repairListener);
+ $dispatcher->addListener(RepairFinishEvent::class, $repairListener);
+ $dispatcher->addListener(RepairStepEvent::class, $repairListener);
+ $dispatcher->addListener(RepairInfoEvent::class, $repairListener);
+ $dispatcher->addListener(RepairWarningEvent::class, $repairListener);
+ $dispatcher->addListener(RepairErrorEvent::class, $repairListener);
$this->listen('\OC\Updater', 'maintenanceEnabled', function () use ($log) {
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index 4821a2fc632..0b38f04bfe3 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -45,7 +45,7 @@ declare(strict_types=1);
*/
namespace OC\User;
-use OC\Cache\CappedMemoryCache;
+use OCP\Cache\CappedMemoryCache;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IDBConnection;
use OCP\Security\Events\ValidatePasswordPolicyEvent;
@@ -215,6 +215,10 @@ class Database extends ABackend implements
* Change the display name of a user
*/
public function setDisplayName(string $uid, string $displayName): bool {
+ if (mb_strlen($displayName) > 64) {
+ return false;
+ }
+
$this->fixDI();
if ($this->userExists($uid)) {
diff --git a/lib/private/User/DisplayNameCache.php b/lib/private/User/DisplayNameCache.php
index 22a79863e49..5d1cc8940d7 100644
--- a/lib/private/User/DisplayNameCache.php
+++ b/lib/private/User/DisplayNameCache.php
@@ -47,7 +47,7 @@ class DisplayNameCache implements IEventListener {
$this->userManager = $userManager;
}
- public function getDisplayName(string $userId) {
+ public function getDisplayName(string $userId): ?string {
if (isset($this->cache[$userId])) {
return $this->cache[$userId];
}
@@ -61,7 +61,7 @@ class DisplayNameCache implements IEventListener {
if ($user) {
$displayName = $user->getDisplayName();
} else {
- $displayName = $userId;
+ $displayName = null;
}
$this->cache[$userId] = $displayName;
$this->memCache->set($userId, $displayName, 60 * 10); // 10 minutes
diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php
index 8e93d6481ab..096578b8f37 100644
--- a/lib/private/User/LazyUser.php
+++ b/lib/private/User/LazyUser.php
@@ -29,12 +29,10 @@ use OCP\UserInterface;
class LazyUser implements IUser {
private ?IUser $user = null;
- private DisplayNameCache $displayNameCache;
private string $uid;
private IUserManager $userManager;
- public function __construct(string $uid, DisplayNameCache $displayNameCache, IUserManager $userManager) {
- $this->displayNameCache = $displayNameCache;
+ public function __construct(string $uid, IUserManager $userManager) {
$this->uid = $uid;
$this->userManager = $userManager;
}
@@ -53,7 +51,7 @@ class LazyUser implements IUser {
}
public function getDisplayName() {
- return $this->displayNameCache->getDisplayName($this->uid);
+ return $this->userManager->getDisplayName($this->uid) ?? $this->uid;
}
public function setDisplayName($displayName) {
diff --git a/lib/private/User/Listeners/UserChangedListener.php b/lib/private/User/Listeners/UserChangedListener.php
new file mode 100644
index 00000000000..a561db2423d
--- /dev/null
+++ b/lib/private/User/Listeners/UserChangedListener.php
@@ -0,0 +1,62 @@
+<?php
+
+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/>.
+ *
+ */
+namespace OC\User\Listeners;
+
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\User\Events\UserChangedEvent;
+use OCP\Files\NotFoundException;
+use OCP\IAvatarManager;
+
+/**
+ * @template-implements IEventListener<UserChangedEvent>
+ */
+class UserChangedListener implements IEventListener {
+ private IAvatarManager $avatarManager;
+
+ public function __construct(IAvatarManager $avatarManager) {
+ $this->avatarManager = $avatarManager;
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof UserChangedEvent)) {
+ return;
+ }
+
+ $user = $event->getUser();
+ $feature = $event->getFeature();
+ $oldValue = $event->getOldValue();
+ $value = $event->getValue();
+
+ // We only change the avatar on display name changes
+ if ($feature === 'displayName') {
+ try {
+ $avatar = $this->avatarManager->getAvatar($user->getUID());
+ $avatar->userChanged($feature, $oldValue, $value);
+ } catch (NotFoundException $e) {
+ // no avatar to remove
+ }
+ }
+ }
+}
diff --git a/lib/private/User/Listeners/UserDeletedListener.php b/lib/private/User/Listeners/UserDeletedListener.php
new file mode 100644
index 00000000000..7c9c46ef371
--- /dev/null
+++ b/lib/private/User/Listeners/UserDeletedListener.php
@@ -0,0 +1,65 @@
+<?php
+
+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/>.
+ *
+ */
+namespace OC\User\Listeners;
+
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\User\Events\UserDeletedEvent;
+use OCP\Files\NotFoundException;
+use OCP\IAvatarManager;
+use Psr\Log\LoggerInterface;
+
+/**
+ * @template-implements IEventListener<UserDeletedEvent>
+ */
+class UserDeletedListener implements IEventListener {
+ private IAvatarManager $avatarManager;
+ private LoggerInterface $logger;
+
+ public function __construct(LoggerInterface $logger, IAvatarManager $avatarManager) {
+ $this->avatarManager = $avatarManager;
+ $this->logger = $logger;
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof UserDeletedEvent)) {
+ return;
+ }
+
+ $user = $event->getUser();
+
+ // Delete avatar on user deletion
+ try {
+ $avatar = $this->avatarManager->getAvatar($user->getUID());
+ $avatar->remove(true);
+ } catch (NotFoundException $e) {
+ // no avatar to remove
+ } catch (\Exception $e) {
+ // Ignore exceptions
+ $this->logger->info('Could not cleanup avatar of ' . $user->getUID(), [
+ 'exception' => $e,
+ ]);
+ }
+ }
+}
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index a6f56585325..be5151313c4 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -95,6 +95,8 @@ class Manager extends PublicEmitter implements IUserManager {
/** @var IEventDispatcher */
private $eventDispatcher;
+ private DisplayNameCache $displayNameCache;
+
public function __construct(IConfig $config,
EventDispatcherInterface $oldDispatcher,
ICacheFactory $cacheFactory,
@@ -108,6 +110,7 @@ class Manager extends PublicEmitter implements IUserManager {
unset($cachedUsers[$user->getUID()]);
});
$this->eventDispatcher = $eventDispatcher;
+ $this->displayNameCache = new DisplayNameCache($cacheFactory, $this);
}
/**
@@ -185,6 +188,10 @@ class Manager extends PublicEmitter implements IUserManager {
return null;
}
+ public function getDisplayName(string $uid): ?string {
+ return $this->displayNameCache->getDisplayName($uid);
+ }
+
/**
* get or construct the user object
*
@@ -742,4 +749,8 @@ class Manager extends PublicEmitter implements IUserManager {
return !file_exists(rtrim($dataDirectory, '/') . '/' . $uid);
}
+
+ public function getDisplayNameCache(): DisplayNameCache {
+ return $this->displayNameCache;
+ }
}
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index c5306d1df27..7f7d6273e30 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -244,10 +244,15 @@ class User implements IUser {
* updates the timestamp of the most recent login of this user
*/
public function updateLastLoginTimestamp() {
- $firstTimeLogin = ($this->getLastLogin() === 0);
- $this->lastLogin = time();
- $this->config->setUserValue(
- $this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
+ $previousLogin = $this->getLastLogin();
+ $now = time();
+ $firstTimeLogin = $previousLogin === 0;
+
+ if ($now - $previousLogin > 60) {
+ $this->lastLogin = time();
+ $this->config->setUserValue(
+ $this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
+ }
return $firstTimeLogin;
}
diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php
index f290b7a610c..a5eb26d0d4b 100644
--- a/lib/private/legacy/OC_App.php
+++ b/lib/private/legacy/OC_App.php
@@ -50,18 +50,19 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+use OCP\AppFramework\QueryException;
+use OCP\App\ManagerEvent;
+use OCP\Authentication\IAlternativeLogin;
+use OCP\ILogger;
+use OCP\Settings\IManager as ISettingsManager;
+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 OC\ServerNotAvailableException;
-use OCP\App\ManagerEvent;
-use OCP\AppFramework\QueryException;
-use OCP\Authentication\IAlternativeLogin;
-use OCP\ILogger;
-use OCP\Settings\IManager as ISettingsManager;
use Psr\Log\LoggerInterface;
/**
@@ -183,7 +184,7 @@ class OC_App {
'app' => $app,
]);
try {
- self::requireAppFile($app);
+ self::requireAppFile($appPath);
} catch (Throwable $ex) {
if ($ex instanceof ServerNotAvailableException) {
throw $ex;
@@ -679,25 +680,6 @@ class OC_App {
}
/**
- * register an admin form to be shown
- *
- * @param string $app
- * @param string $page
- */
- public static function registerAdmin(string $app, string $page) {
- self::$adminForms[] = $app . '/' . $page . '.php';
- }
-
- /**
- * register a personal form to be shown
- * @param string $app
- * @param string $page
- */
- public static function registerPersonal(string $app, string $page) {
- self::$personalForms[] = $app . '/' . $page . '.php';
- }
-
- /**
* @param array $entry
* @deprecated 20.0.0 Please register your alternative login option using the registerAlternativeLogin() on the RegistrationContext in your Application class implementing the OCP\Authentication\IAlternativeLogin interface
*/
@@ -1066,7 +1048,7 @@ class OC_App {
// load the app
self::loadApp($appId);
- $dispatcher = OC::$server->getEventDispatcher();
+ $dispatcher = \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class);
// load the steps
$r = new Repair([], $dispatcher, \OC::$server->get(LoggerInterface::class));
@@ -1074,7 +1056,7 @@ class OC_App {
try {
$r->addStep($step);
} catch (Exception $ex) {
- $r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
+ $dispatcher->dispatchTyped(new RepairErrorEvent($ex->getMessage()));
\OC::$server->getLogger()->logException($ex);
}
}
diff --git a/lib/private/legacy/OC_Files.php b/lib/private/legacy/OC_Files.php
index 02e15fd08d5..6a3a44d6cc0 100644
--- a/lib/private/legacy/OC_Files.php
+++ b/lib/private/legacy/OC_Files.php
@@ -44,10 +44,12 @@ 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;
/**
* Class for file server access
- *
*/
class OC_Files {
public const FILE = 1;
@@ -167,6 +169,14 @@ class OC_Files {
}
}
+ //Dispatch an event to see if any apps have problem with download
+ $event = new BeforeZipCreatedEvent($dir, is_array($files) ? $files : [$files]);
+ $dispatcher = \OCP\Server::get(IEventDispatcher::class);
+ $dispatcher->dispatchTyped($event);
+ if ((!$event->isSuccessful()) || $event->getErrorMessage() !== null) {
+ throw new \OC\ForbiddenException($event->getErrorMessage());
+ }
+
$streamer = new Streamer(\OC::$server->getRequest(), $fileSize, $numberOfFiles);
OC_Util::obEnd();
@@ -222,13 +232,16 @@ class OC_Files {
self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
OC::$server->getLogger()->logException($ex);
$l = \OC::$server->getL10N('lib');
- \OC_Template::printErrorPage($l->t('Cannot read file'), $ex->getMessage(), 200);
+ \OC_Template::printErrorPage($l->t('Cannot download file'), $ex->getMessage(), 200);
} catch (\Exception $ex) {
self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
OC::$server->getLogger()->logException($ex);
$l = \OC::$server->getL10N('lib');
$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
- \OC_Template::printErrorPage($l->t('Cannot read file'), $hint, 200);
+ if ($event && $event->getErrorMessage() !== null) {
+ $hint .= ' ' . $event->getErrorMessage();
+ }
+ \OC_Template::printErrorPage($l->t('Cannot download file'), $hint, 200);
}
}
@@ -287,6 +300,7 @@ class OC_Files {
* @param string $name
* @param string $dir
* @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
+ * @throws \OC\ForbiddenException
*/
private static function getSingleFile($view, $dir, $name, $params) {
$filename = $dir . '/' . $name;
@@ -322,6 +336,19 @@ class OC_Files {
$rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), $fileSize);
}
+ $dispatcher = \OC::$server->query(IEventDispatcher::class);
+ $event = new BeforeDirectFileDownloadEvent($filename);
+ $dispatcher->dispatchTyped($event);
+
+ if (!\OC\Files\Filesystem::isReadable($filename) || $event->getErrorMessage()) {
+ if ($event->getErrorMessage()) {
+ $msg = $event->getErrorMessage();
+ } else {
+ $msg = 'Access denied';
+ }
+ throw new \OC\ForbiddenException($msg);
+ }
+
self::sendHeaders($filename, $name, $rangeArray);
if (isset($params['head']) && $params['head']) {
diff --git a/lib/private/legacy/OC_Helper.php b/lib/private/legacy/OC_Helper.php
index 226f73a0711..710225c7474 100644
--- a/lib/private/legacy/OC_Helper.php
+++ b/lib/private/legacy/OC_Helper.php
@@ -47,9 +47,9 @@ use bantu\IniGetWrapper\IniGetWrapper;
use OC\Files\Filesystem;
use OCP\Files\Mount\IMountPoint;
use OCP\ICacheFactory;
+use OCP\IBinaryFinder;
use OCP\IUser;
use Psr\Log\LoggerInterface;
-use Symfony\Component\Process\ExecutableFinder;
/**
* Collection of useful functions
@@ -434,47 +434,19 @@ class OC_Helper {
/**
* Checks if a function is available
*
- * @param string $function_name
- * @return bool
+ * @deprecated Since 25.0.0 use \OCP\Util::isFunctionEnabled instead
*/
- public static function is_function_enabled($function_name) {
- if (!function_exists($function_name)) {
- return false;
- }
- $ini = \OC::$server->get(IniGetWrapper::class);
- $disabled = explode(',', $ini->get('disable_functions') ?: '');
- $disabled = array_map('trim', $disabled);
- if (in_array($function_name, $disabled)) {
- return false;
- }
- $disabled = explode(',', $ini->get('suhosin.executor.func.blacklist') ?: '');
- $disabled = array_map('trim', $disabled);
- if (in_array($function_name, $disabled)) {
- return false;
- }
- return true;
+ public static function is_function_enabled(string $function_name): bool {
+ return \OCP\Util::isFunctionEnabled($function_name);
}
/**
* Try to find a program
- *
- * @param string $program
- * @return null|string
+ * @deprecated Since 25.0.0 Use \OC\BinaryFinder directly
*/
- public static function findBinaryPath($program) {
- $memcache = \OC::$server->getMemCacheFactory()->createDistributed('findBinaryPath');
- if ($memcache->hasKey($program)) {
- return $memcache->get($program);
- }
- $result = null;
- if (self::is_function_enabled('exec')) {
- $exeSniffer = new ExecutableFinder();
- // Returns null if nothing is found
- $result = $exeSniffer->find($program, null, ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin', '/opt/bin']);
- }
- // store the value for 5 minutes
- $memcache->set($program, $result, 300);
- return $result;
+ public static function findBinaryPath(string $program): ?string {
+ $result = \OCP\Server::get(IBinaryFinder::class)->findBinaryPath($program);
+ return $result !== false ? $result : null;
}
/**
diff --git a/lib/private/legacy/OC_User.php b/lib/private/legacy/OC_User.php
index b7547be5e82..de066e143b4 100644
--- a/lib/private/legacy/OC_User.php
+++ b/lib/private/legacy/OC_User.php
@@ -178,7 +178,11 @@ class OC_User {
}
$userSession->setLoginName($uid);
$request = OC::$server->getRequest();
- $userSession->createSessionToken($request, $uid, $uid);
+ $password = null;
+ if ($backend instanceof \OCP\Authentication\IProvideUserSecretBackend) {
+ $password = $backend->getCurrentUserSecret();
+ }
+ $userSession->createSessionToken($request, $uid, $uid, $password);
$userSession->createRememberMeToken($userSession->getUser());
// setup the filesystem
OC_Util::setupFS($uid);
@@ -191,7 +195,7 @@ class OC_User {
'post_login',
[
'uid' => $uid,
- 'password' => null,
+ 'password' => $password,
'isTokenLogin' => false,
]
);
diff --git a/lib/public/App.php b/lib/public/App.php
deleted file mode 100644
index 5103e624316..00000000000
--- a/lib/public/App.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @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>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal ownCloud classes
-
-namespace OCP;
-
-/**
- * This class provides functions to manage apps in ownCloud
- * @since 4.0.0
- * @deprecated 14.0.0
- */
-class App {
-
-
- /**
- * Register a Configuration Screen that should appear in the personal settings section.
- * @param string $app appid
- * @param string $page page to be included
- * @return void
- * @since 4.0.0
- * @deprecated 14.0.0 Use settings section in appinfo.xml to register personal admin sections
- */
- public static function registerPersonal($app, $page) {
- \OC_App::registerPersonal($app, $page);
- }
-
- /**
- * Register a Configuration Screen that should appear in the Admin section.
- * @param string $app string appid
- * @param string $page string page to be included
- * @return void
- * @since 4.0.0
- * @deprecated 14.0.0 Use settings section in appinfo.xml to register admin sections
- */
- public static function registerAdmin($app, $page) {
- \OC_App::registerAdmin($app, $page);
- }
-
- /**
- * Read app metadata from the info.xml file
- * @param string $app id of the app or the path of the info.xml file
- * @param boolean $path (optional)
- * @return array|null
- * @deprecated 14.0.0 ise \OC::$server->getAppManager()->getAppInfo($appId)
- * @since 4.0.0
- */
- public static function getAppInfo($app, $path = false) {
- return \OC_App::getAppInfo($app, $path);
- }
-
- /**
- * checks whether or not an app is enabled
- * @param string $app
- * @return boolean
- *
- * This function checks whether or not an app is enabled.
- * @since 4.0.0
- * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
- */
- public static function isEnabled($app) {
- return \OC::$server->getAppManager()->isEnabledForUser($app);
- }
-
- /**
- * Get the last version of the app from appinfo/info.xml
- * @param string $app
- * @return string
- * @since 4.0.0
- * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion($appId)
- */
- public static function getAppVersion($app) {
- return \OC::$server->getAppManager()->getAppVersion($app);
- }
-}
diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php
index 7473b229427..e0b5c049290 100644
--- a/lib/public/App/IAppManager.php
+++ b/lib/public/App/IAppManager.php
@@ -36,6 +36,9 @@ use OCP\IUser;
/**
* Interface IAppManager
*
+ * @warning This interface shouldn't be included with dependency injection in
+ * classes used for installing Nextcloud.
+ *
* @since 8.0.0
*/
interface IAppManager {
diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
index a5d675f14c7..0f398c13979 100644
--- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
+++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
@@ -33,6 +33,7 @@ use OCP\AppFramework\IAppContainer;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Calendar\ICalendarProvider;
use OCP\Capabilities\ICapability;
+use OCP\Collaboration\Reference\IReferenceProvider;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Template\ICustomTemplateProvider;
use OCP\IContainer;
@@ -255,6 +256,15 @@ interface IRegistrationContext {
public function registerCalendarProvider(string $class): void;
/**
+ * Register a reference provider
+ *
+ * @param string $class
+ * @psalm-param class-string<IReferenceProvider> $class
+ * @since 25.0.0
+ */
+ public function registerReferenceProvider(string $class): void;
+
+ /**
* Register an implementation of \OCP\Profile\ILinkAction that
* will handle the implementation of a profile link action
*
@@ -306,4 +316,15 @@ interface IRegistrationContext {
* @since 24.0.0
*/
public function registerUserMigrator(string $migratorClass): void;
+
+ /**
+ * Announce methods of classes that may contain sensitive values, which
+ * should be obfuscated before being logged.
+ *
+ * @param string $class
+ * @param string[] $methods
+ * @return void
+ * @since 25.0.0
+ */
+ public function registerSensitiveMethods(string $class, array $methods): void;
}
diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php
index a059e3a27b0..dcd1c77c042 100644
--- a/lib/public/AppFramework/Db/Entity.php
+++ b/lib/public/AppFramework/Db/Entity.php
@@ -113,6 +113,9 @@ abstract class Entity {
$type = $this->_fieldTypes[$name];
if ($type === 'blob') {
// (B)LOB is treated as string when we read from the DB
+ if (is_resource($args[0])) {
+ $args[0] = stream_get_contents($args[0]);
+ }
$type = 'string';
}
diff --git a/lib/public/Authentication/IProvideUserSecretBackend.php b/lib/public/Authentication/IProvideUserSecretBackend.php
new file mode 100644
index 00000000000..08f4043d828
--- /dev/null
+++ b/lib/public/Authentication/IProvideUserSecretBackend.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021, MichaIng <micha@dietpi.com>
+ *
+ * @author MichaIng <micha@dietpi.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/>
+ *
+ */
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+
+namespace OCP\Authentication;
+
+/**
+ * Interface IProvideUserSecretBackend
+ *
+ * @since 23.0.0
+ */
+interface IProvideUserSecretBackend {
+
+ /**
+ * Optionally returns a stable per-user secret. This secret is for
+ * instance used to secure file encryption keys.
+ * @return string
+ * @since 23.0.0
+ */
+ public function getCurrentUserSecret(): string;
+}
diff --git a/lib/public/BackgroundJob/IJob.php b/lib/public/BackgroundJob/IJob.php
index 3c2da42bf88..24d8e7aad4a 100644
--- a/lib/public/BackgroundJob/IJob.php
+++ b/lib/public/BackgroundJob/IJob.php
@@ -29,7 +29,10 @@ namespace OCP\BackgroundJob;
use OCP\ILogger;
/**
- * Interface IJob
+ * This interface represend a backgroud job run with cron
+ *
+ * To implement a background job, you must extend either \OCP\BackgroundJob\Job,
+ * \OCP\BackgroundJob\TimedJob or \OCP\BackgroundJob\QueuedJob
*
* @since 7.0.0
*/
@@ -49,10 +52,26 @@ interface IJob {
* @param IJobList $jobList The job list that manages the state of this job
* @param ILogger|null $logger
* @since 7.0.0
+ * @deprecated since 25.0.0 Use start() instead. This method will be removed
+ * with the ILogger interface
*/
public function execute(IJobList $jobList, ILogger $logger = null);
/**
+ * Start the background job with the registered argument
+ *
+ * This methods will take care of running the background job, of initializing
+ * the state and cleaning up the job list after running the job.
+ *
+ * For common background job scenario, you will want to use TimedJob or QueuedJob
+ * instead of overwritting this method.
+ *
+ * @param IJobList $jobList The job list that manages the state of this job
+ * @since 25.0.0
+ */
+ public function start(IJobList $jobList): void;
+
+ /**
* @since 7.0.0
*/
public function setId(int $id);
diff --git a/lib/public/BackgroundJob/IJobList.php b/lib/public/BackgroundJob/IJobList.php
index eab37a03f36..8f6449b070b 100644
--- a/lib/public/BackgroundJob/IJobList.php
+++ b/lib/public/BackgroundJob/IJobList.php
@@ -7,6 +7,7 @@
* @author Noveen Sachdeva <noveen.sachdeva@research.iiit.ac.in>
* @author Robin Appelman <robin@icewind.nl>
* @author Robin McCorkell <robin@mccorkell.me.uk>
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
*
* @license AGPL-3.0
*
@@ -41,66 +42,71 @@ namespace OCP\BackgroundJob;
* be specified in the constructor of the job by calling
* $this->setInterval($interval) with $interval in seconds.
*
+ * This interface should be used directly and not implemented by an application.
+ * The implementation is provided by the server.
+ *
* @since 7.0.0
*/
interface IJobList {
/**
* Add a job to the list
*
- * @param \OCP\BackgroundJob\IJob|string $job
+ * @param IJob|class-string<IJob> $job
* @param mixed $argument The argument to be passed to $job->run() when the job is exectured
* @since 7.0.0
*/
- public function add($job, $argument = null);
+ public function add($job, $argument = null): void;
/**
* Remove a job from the list
*
- * @param \OCP\BackgroundJob\IJob|string $job
+ * @param IJob|class-string<IJob> $job
* @param mixed $argument
* @since 7.0.0
*/
- public function remove($job, $argument = null);
+ public function remove($job, $argument = null): void;
/**
* check if a job is in the list
*
- * @param \OCP\BackgroundJob\IJob|string $job
+ * @param IJob|class-string<IJob> $job
* @param mixed $argument
- * @return bool
* @since 7.0.0
*/
- public function has($job, $argument);
+ public function has($job, $argument): bool;
/**
* get all jobs in the list
*
- * @return \OCP\BackgroundJob\IJob[]
+ * @return IJob[]
* @since 7.0.0
* @deprecated 9.0.0 - This method is dangerous since it can cause load and
- * memory problems when creating too many instances.
+ * memory problems when creating too many instances. Use getJobs instead.
+ */
+ public function getAll(): array;
+
+ /**
+ * Get jobs matching the search
+ *
+ * @param IJob|class-string<IJob>|null $job
+ * @return IJob[]
+ * @since 25.0.0
*/
- public function getAll();
+ public function getJobs($job, ?int $limit, int $offset): array;
/**
* get the next job in the list
*
- * @param bool $onlyTimeSensitive
- * @return \OCP\BackgroundJob\IJob|null
* @since 7.0.0 - In 24.0.0 parameter $onlyTimeSensitive got added
*/
public function getNext(bool $onlyTimeSensitive = false): ?IJob;
/**
- * @param int $id
- * @return \OCP\BackgroundJob\IJob|null
* @since 7.0.0
*/
- public function getById($id);
+ public function getById(int $id): ?IJob;
/**
- * @param int $id
- * @return array|null
* @since 23.0.0
*/
public function getDetailsById(int $id): ?array;
@@ -108,40 +114,34 @@ interface IJobList {
/**
* set the job that was last ran to the current time
*
- * @param \OCP\BackgroundJob\IJob $job
* @since 7.0.0
*/
- public function setLastJob(IJob $job);
+ public function setLastJob(IJob $job): void;
/**
* Remove the reservation for a job
*
- * @param IJob $job
* @since 9.1.0
*/
- public function unlockJob(IJob $job);
+ public function unlockJob(IJob $job): void;
/**
* set the lastRun of $job to now
*
- * @param IJob $job
* @since 7.0.0
*/
- public function setLastRun(IJob $job);
+ public function setLastRun(IJob $job): void;
/**
* set the run duration of $job
*
- * @param IJob $job
- * @param $timeTaken
* @since 12.0.0
*/
- public function setExecutionTime(IJob $job, $timeTaken);
+ public function setExecutionTime(IJob $job, int $timeTaken): void;
/**
* Reset the $job so it executes on the next trigger
*
- * @param IJob $job
* @since 23.0.0
*/
public function resetBackgroundJob(IJob $job): void;
diff --git a/lib/public/BackgroundJob/Job.php b/lib/public/BackgroundJob/Job.php
index 5b20ac82684..d60fb5905c9 100644
--- a/lib/public/BackgroundJob/Job.php
+++ b/lib/public/BackgroundJob/Job.php
@@ -28,6 +28,7 @@ namespace OCP\BackgroundJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\ILogger;
+use Psr\Log\LoggerInterface;
/**
* Base class for background jobs
@@ -38,18 +39,10 @@ use OCP\ILogger;
* @since 15.0.0
*/
abstract class Job implements IJob {
-
- /** @var int $id */
- protected $id;
-
- /** @var int $lastRun */
- protected $lastRun;
-
- /** @var mixed $argument */
+ protected int $id = 0;
+ protected int $lastRun = 0;
protected $argument;
-
- /** @var ITimeFactory */
- protected $time;
+ protected ITimeFactory $time;
/**
* @since 15.0.0
@@ -68,10 +61,16 @@ abstract class Job implements IJob {
* @since 15.0.0
*/
public function execute(IJobList $jobList, ILogger $logger = null) {
+ $this->start($jobList);
+ }
+
+ /**
+ * @inheritdoc
+ * @since 25.0.0
+ */
+ public function start(IJobList $jobList): void {
$jobList->setLastRun($this);
- if ($logger === null) {
- $logger = \OC::$server->getLogger();
- }
+ $logger = \OCP\Server::get(LoggerInterface::class);
try {
$jobStartTime = $this->time->getTime();
@@ -83,9 +82,9 @@ abstract class Job implements IJob {
$jobList->setExecutionTime($this, $timeTaken);
} catch (\Exception $e) {
if ($logger) {
- $logger->logException($e, [
+ $logger->error('Error while running background job (class: ' . get_class($this) . ', arguments: ' . print_r($this->argument, true) . ')', [
'app' => 'core',
- 'message' => 'Error while running background job (class: ' . get_class($this) . ', arguments: ' . print_r($this->argument, true) . ')'
+ 'exception' => $e,
]);
}
}
diff --git a/lib/public/BackgroundJob/QueuedJob.php b/lib/public/BackgroundJob/QueuedJob.php
index e7e6e9a2939..b9c4d693b8f 100644
--- a/lib/public/BackgroundJob/QueuedJob.php
+++ b/lib/public/BackgroundJob/QueuedJob.php
@@ -35,15 +35,26 @@ use OCP\ILogger;
abstract class QueuedJob extends Job {
/**
- * run the job, then remove it from the joblist
+ * Run the job, then remove it from the joblist
*
* @param IJobList $jobList
* @param ILogger|null $logger
*
* @since 15.0.0
+ * @deprecated since 25.0.0 Use start() instead. This method will be removed
+ * with the ILogger interface
*/
final public function execute($jobList, ILogger $logger = null) {
+ $this->start($jobList);
+ }
+
+ /**
+ * Run the job, then remove it from the joblist
+ *
+ * @since 25.0.0
+ */
+ final public function start(IJobList $jobList): void {
$jobList->remove($this, $this->argument);
- parent::execute($jobList, $logger);
+ parent::start($jobList);
}
}
diff --git a/lib/public/BackgroundJob/TimedJob.php b/lib/public/BackgroundJob/TimedJob.php
index 579486f6fbf..9d6b599c21b 100644
--- a/lib/public/BackgroundJob/TimedJob.php
+++ b/lib/public/BackgroundJob/TimedJob.php
@@ -36,13 +36,11 @@ use OCP\ILogger;
* @since 15.0.0
*/
abstract class TimedJob extends Job {
- /** @var int */
- protected $interval = 0;
- /** @var int */
- protected $timeSensitivity = IJob::TIME_SENSITIVE;
+ protected int $interval = 0;
+ protected int $timeSensitivity = IJob::TIME_SENSITIVE;
/**
- * set the interval for the job
+ * Set the interval for the job
*
* @param int $seconds the time to pass between two runs of the same job in seconds
*
@@ -89,10 +87,20 @@ abstract class TimedJob extends Job {
* @param ILogger|null $logger
*
* @since 15.0.0
+ * @deprecated since 25.0.0 Use start() instead
*/
final public function execute($jobList, ILogger $logger = null) {
+ $this->start($jobList);
+ }
+
+ /**
+ * Run the job if the last run is is more than the interval ago
+ *
+ * @since 25.0.0
+ */
+ final public function start(IJobList $jobList): void {
if (($this->time->getTime() - $this->lastRun) > $this->interval) {
- parent::execute($jobList, $logger);
+ parent::start($jobList);
}
}
}
diff --git a/lib/public/Cache/CappedMemoryCache.php b/lib/public/Cache/CappedMemoryCache.php
new file mode 100644
index 00000000000..6699600d42c
--- /dev/null
+++ b/lib/public/Cache/CappedMemoryCache.php
@@ -0,0 +1,160 @@
+<?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/>
+ *
+ */
+namespace OCP\Cache;
+
+use OCP\ICache;
+
+/**
+ * In-memory cache with a capacity limit to keep memory usage in check
+ *
+ * Uses a simple FIFO expiry mechanism
+ *
+ * @since 25.0.0
+ * @template T
+ */
+class CappedMemoryCache implements ICache, \ArrayAccess {
+ private int $capacity;
+ /** @var T[] */
+ private array $cache = [];
+
+ /**
+ * @inheritdoc
+ * @since 25.0.0
+ */
+ public function __construct(int $capacity = 512) {
+ $this->capacity = $capacity;
+ }
+
+ /**
+ * @inheritdoc
+ * @since 25.0.0
+ */
+ public function hasKey($key): bool {
+ return isset($this->cache[$key]);
+ }
+
+ /**
+ * @return ?T
+ * @since 25.0.0
+ */
+ public function get($key) {
+ return $this->cache[$key] ?? null;
+ }
+
+ /**
+ * @inheritdoc
+ * @param string $key
+ * @param T $value
+ * @param int $ttl
+ * @since 25.0.0
+ * @return bool
+ */
+ public function set($key, $value, $ttl = 0): bool {
+ if (is_null($key)) {
+ $this->cache[] = $value;
+ } else {
+ $this->cache[$key] = $value;
+ }
+ $this->garbageCollect();
+ return true;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function remove($key): bool {
+ unset($this->cache[$key]);
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ * @since 25.0.0
+ */
+ public function clear($prefix = ''): bool {
+ $this->cache = [];
+ return true;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function offsetExists($offset): bool {
+ return $this->hasKey($offset);
+ }
+
+ /**
+ * @inheritdoc
+ * @return T
+ * @since 25.0.0
+ */
+ #[\ReturnTypeWillChange]
+ public function &offsetGet($offset) {
+ return $this->cache[$offset];
+ }
+
+ /**
+ * @inheritdoc
+ * @param string $offset
+ * @param T $value
+ * @since 25.0.0
+ */
+ public function offsetSet($offset, $value): void {
+ $this->set($offset, $value);
+ }
+
+ /**
+ * @inheritdoc
+ * @since 25.0.0
+ */
+ public function offsetUnset($offset): void {
+ $this->remove($offset);
+ }
+
+ /**
+ * @return T[]
+ * @since 25.0.0
+ */
+ public function getData(): array {
+ return $this->cache;
+ }
+
+
+ /**
+ * @since 25.0.0
+ */
+ private function garbageCollect(): void {
+ while (count($this->cache) > $this->capacity) {
+ reset($this->cache);
+ $key = key($this->cache);
+ $this->remove($key);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ * @since 25.0.0
+ */
+ public static function isAvailable(): bool {
+ return true;
+ }
+}
diff --git a/lib/public/Calendar/ICreateFromString.php b/lib/public/Calendar/ICreateFromString.php
index 343405e8ab6..8c4bdd44041 100644
--- a/lib/public/Calendar/ICreateFromString.php
+++ b/lib/public/Calendar/ICreateFromString.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* @copyright 2021 Anna Larch <anna.larch@gmx.net>
*
@@ -38,4 +40,11 @@ interface ICreateFromString extends ICalendar {
* @throws CalendarException
*/
public function createFromString(string $name, string $calendarData): void;
+
+ /**
+ * @since 25.0.0
+ *
+ * @throws CalendarException
+ */
+ public function handleIMipMessage(string $name, string $calendarData): void;
}
diff --git a/lib/public/Calendar/IManager.php b/lib/public/Calendar/IManager.php
index 7f0eec80910..dd65917d12b 100644
--- a/lib/public/Calendar/IManager.php
+++ b/lib/public/Calendar/IManager.php
@@ -156,4 +156,18 @@ interface IManager {
* @since 23.0.0
*/
public function newQuery(string $principalUri) : ICalendarQuery;
+
+ /**
+ * Handle a iMip REPLY message
+ *
+ * @since 25.0.0
+ */
+ public function handleIMipReply(string $principalUri, string $sender, string $recipient, string $calendarData): bool;
+
+ /**
+ * Handle a iMip CANCEL message
+ *
+ * @since 25.0.0
+ */
+ public function handleIMipCancel(string $principalUri, string $sender, ?string $replyTo, string $recipient, string $calendarData): bool;
}
diff --git a/lib/public/Collaboration/Reference/IReference.php b/lib/public/Collaboration/Reference/IReference.php
new file mode 100644
index 00000000000..0155ae86dd8
--- /dev/null
+++ b/lib/public/Collaboration/Reference/IReference.php
@@ -0,0 +1,130 @@
+<?php
+
+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/>.
+ */
+
+namespace OCP\Collaboration\Reference;
+
+use JsonSerializable;
+
+/**
+ * @since 25.0.0
+ */
+interface IReference extends JsonSerializable {
+
+ /**
+ * @since 25.0.0
+ */
+ public function getId(): string;
+
+ /**
+ * Accessible flag indicates if the user has access to the provided reference
+ *
+ * @since 25.0.0
+ */
+ public function setAccessible(bool $accessible): void;
+
+ /**
+ * Accessible flag indicates if the user has access to the provided reference
+ *
+ * @since 25.0.0
+ */
+ public function getAccessible(): bool;
+
+ /**
+ * @since 25.0.0
+ */
+ public function setTitle(string $title): void;
+
+ /**
+ * @since 25.0.0
+ */
+ public function getTitle(): string;
+
+ /**
+ * @since 25.0.0
+ */
+ public function setDescription(?string $description): void;
+
+ /**
+ * @since 25.0.0
+ */
+ public function getDescription(): ?string;
+
+ /**
+ * @since 25.0.0
+ */
+ public function setImageUrl(?string $imageUrl): void;
+
+ /**
+ * @since 25.0.0
+ */
+ public function getImageUrl(): ?string;
+
+ /**
+ * @since 25.0.0
+ */
+ public function setImageContentType(?string $contentType): void;
+
+ /**
+ * @since 25.0.0
+ */
+ public function getImageContentType(): ?string;
+
+ /**
+ * @since 25.0.0
+ */
+ public function setUrl(?string $url): void;
+
+ /**
+ * @since 25.0.0
+ */
+ public function getUrl(): ?string;
+
+ /**
+ * Set the reference specific rich object representation
+ *
+ * @since 25.0.0
+ */
+ public function setRichObject(string $type, ?array $richObject): void;
+
+ /**
+ * Returns the type of the reference specific rich object
+ *
+ * @since 25.0.0
+ */
+ public function getRichObjectType(): string;
+
+ /**
+ * Returns the reference specific rich object representation
+ *
+ * @since 25.0.0
+ */
+ public function getRichObject(): array;
+
+ /**
+ * Returns the opengraph rich object representation
+ *
+ * @since 25.0.0
+ */
+ public function getOpenGraphObject(): array;
+}
diff --git a/lib/public/Collaboration/Reference/IReferenceManager.php b/lib/public/Collaboration/Reference/IReferenceManager.php
new file mode 100644
index 00000000000..487e243c7ed
--- /dev/null
+++ b/lib/public/Collaboration/Reference/IReferenceManager.php
@@ -0,0 +1,70 @@
+<?php
+
+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/>.
+ */
+
+namespace OCP\Collaboration\Reference;
+
+/**
+ * @since 25.0.0
+ */
+interface IReferenceManager {
+ /**
+ * Return all reference identifiers within a string as an array
+ *
+ * @return string[] Array of found references (urls)
+ * @since 25.0.0
+ */
+ public function extractReferences(string $text): array;
+
+ /**
+ * Resolve a given reference id to its metadata with all available providers
+ *
+ * This method has a fallback to always provide the open graph metadata,
+ * but may still return null in case this is disabled or the fetching fails
+ *
+ * @since 25.0.0
+ */
+ public function resolveReference(string $referenceId): ?IReference;
+
+ /**
+ * Get a reference by its cache key
+ *
+ * @since 25.0.0
+ */
+ public function getReferenceByCacheKey(string $cacheKey): ?IReference;
+
+ /**
+ * Explicitly get a reference from the cache to avoid heavy fetches for cases
+ * the cache can then be filled with a separate request from the frontend
+ *
+ * @since 25.0.0
+ */
+ public function getReferenceFromCache(string $referenceId): ?IReference;
+
+ /**
+ * Invalidate all cache entries with a prefix or just one if the cache key is provided
+ *
+ * @since 25.0.0
+ */
+ public function invalidateCache(string $cachePrefix, ?string $cacheKey = null): void;
+}
diff --git a/lib/public/Collaboration/Reference/IReferenceProvider.php b/lib/public/Collaboration/Reference/IReferenceProvider.php
new file mode 100644
index 00000000000..100374b78b3
--- /dev/null
+++ b/lib/public/Collaboration/Reference/IReferenceProvider.php
@@ -0,0 +1,63 @@
+<?php
+
+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/>.
+ */
+
+namespace OCP\Collaboration\Reference;
+
+/**
+ * @since 25.0.0
+ */
+interface IReferenceProvider {
+ /**
+ * Validate that a given reference identifier matches the current provider
+ *
+ * @since 25.0.0
+ */
+ public function matchReference(string $referenceText): bool;
+
+ /**
+ * Return a reference with its metadata for a given reference identifier
+ *
+ * @since 25.0.0
+ */
+ public function resolveReference(string $referenceText): ?IReference;
+
+ /**
+ * Return true if the reference metadata can be globally cached
+ *
+ * @since 25.0.0
+ */
+ public function getCachePrefix(string $referenceId): string;
+
+ /**
+ * Return a custom cache key to be used for caching the metadata
+ * This could be for example the current user id if the reference
+ * access permissions are different for each user
+ *
+ * Should return null, if the cache is only related to the
+ * reference id and has no further dependency
+ *
+ * @since 25.0.0
+ */
+ public function getCacheKey(string $referenceId): ?string;
+}
diff --git a/lib/public/Color.php b/lib/public/Color.php
new file mode 100644
index 00000000000..e2cabd9c2fc
--- /dev/null
+++ b/lib/public/Color.php
@@ -0,0 +1,142 @@
+<?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/>.
+ *
+ */
+namespace OCP;
+
+/**
+ * Simple RGB color container
+ * @since 25.0.0
+ */
+class Color {
+ private int $r;
+ private int $g;
+ private int $b;
+
+ /**
+ * @since 25.0.0
+ */
+ public function __construct($r, $g, $b) {
+ $this->r = $r;
+ $this->g = $g;
+ $this->b = $b;
+ }
+
+ /**
+ * Returns the red color component of this color as an int from 0 to 255
+ *
+ * @since 25.0.0
+ */
+ public function red(): int {
+ return $this->r;
+ }
+
+ /**
+ * Returns the red color component of this color as a float from 0 to 1
+ *
+ * @since 25.0.0
+ */
+ public function redF(): float {
+ return $this->r / 255;
+ }
+
+ /**
+ * Returns the green color component of this color as an int from 0 to 255
+ *
+ * @since 25.0.0
+ */
+ public function green(): int {
+ return $this->g;
+ }
+
+ /**
+ * Returns the green color component of this color as a float from 0 to 1
+ *
+ * @since 25.0.0
+ */
+ public function greenF(): float {
+ return $this->g / 255;
+ }
+
+ /**
+ * Returns the green blue component of this color as an int from 0 to 255
+ *
+ * @since 25.0.0
+ */
+ public function blue(): int {
+ return $this->b;
+ }
+
+ /**
+ * Returns the blue color component of this color as a float from 0 to 1
+ *
+ * @since 25.0.0
+ */
+ public function blueF(): float {
+ return $this->g / 255;
+ }
+
+ /**
+ * Returns the name of the color in the format "#RRGGBB"; i.e. a "#" character followed by three two-digit hexadecimal numbers.
+ *
+ * @since 25.0.0
+ */
+ public function name(): string {
+ return sprintf("#%02x%02x%02x", $this->r, $this->g, $this->b);
+ }
+
+ /**
+ * Mix two colors
+ *
+ * @param int $steps the number of intermediate colors that should be generated for the palette
+ * @param Color $color1 the first color
+ * @param Color $color2 the second color
+ * @return list<Color>
+ * @since 25.0.0
+ */
+ public static function mixPalette(int $steps, Color $color1, Color $color2): array {
+ $palette = [$color1];
+ $step = self::stepCalc($steps, [$color1, $color2]);
+ for ($i = 1; $i < $steps; $i++) {
+ $r = intval($color1->red() + ($step[0] * $i));
+ $g = intval($color1->green() + ($step[1] * $i));
+ $b = intval($color1->blue() + ($step[2] * $i));
+ $palette[] = new Color($r, $g, $b);
+ }
+ return $palette;
+ }
+
+ /**
+ * Calculate steps between two Colors
+ * @param int $steps start color
+ * @param Color[] $ends end color
+ * @return array{0: int, 1: int, 2: int} [r,g,b] steps for each color to go from $steps to $ends
+ * @since 25.0.0
+ */
+ private static function stepCalc(int $steps, array $ends): array {
+ $step = [];
+ $step[0] = ($ends[1]->red() - $ends[0]->red()) / $steps;
+ $step[1] = ($ends[1]->green() - $ends[0]->green()) / $steps;
+ $step[2] = ($ends[1]->blue() - $ends[0]->blue()) / $steps;
+ return $step;
+ }
+}
diff --git a/lib/public/Comments/IComment.php b/lib/public/Comments/IComment.php
index 44d294bb07c..eb696fa5f06 100644
--- a/lib/public/Comments/IComment.php
+++ b/lib/public/Comments/IComment.php
@@ -230,11 +230,11 @@ interface IComment {
/**
* sets the date of the most recent child
*
- * @param \DateTime $dateTime
+ * @param \DateTime|null $dateTime
* @return IComment
* @since 9.0.0
*/
- public function setLatestChildDateTime(\DateTime $dateTime);
+ public function setLatestChildDateTime(?\DateTime $dateTime = null);
/**
* returns the object type the comment is attached to
diff --git a/lib/public/Comments/ICommentsManager.php b/lib/public/Comments/ICommentsManager.php
index 814ca3e8f9c..da9e4d76a38 100644
--- a/lib/public/Comments/ICommentsManager.php
+++ b/lib/public/Comments/ICommentsManager.php
@@ -488,9 +488,9 @@ interface ICommentsManager {
* Only will delete the message related with the object.
*
* @param string $objectType the object type (e.g. 'files')
- * @param string $objectId e.g. the file id
+ * @param string $objectId e.g. the file id, leave empty to expire on all objects of this type
* @return boolean true if at least one row was deleted
* @since 25.0.0
*/
- public function deleteMessageExpiredAtObject(string $objectType, string $objectId): bool;
+ public function deleteCommentsExpiredAtObject(string $objectType, string $objectId = ''): bool;
}
diff --git a/lib/public/DB/QueryBuilder/IExpressionBuilder.php b/lib/public/DB/QueryBuilder/IExpressionBuilder.php
index 8f7cd10dee5..53dc1fa5a7f 100644
--- a/lib/public/DB/QueryBuilder/IExpressionBuilder.php
+++ b/lib/public/DB/QueryBuilder/IExpressionBuilder.php
@@ -107,7 +107,7 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
@@ -115,7 +115,7 @@ interface IExpressionBuilder {
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function comparison($x, string $operator, $y, $type = null): IQueryFunction;
+ public function comparison($x, string $operator, $y, $type = null): string;
/**
* Creates an equality comparison expression with the given arguments.
@@ -132,14 +132,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function eq($x, $y, $type = null): IQueryFunction;
+ public function eq($x, $y, $type = null): string;
/**
* Creates a non equality comparison expression with the given arguments.
@@ -155,14 +155,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function neq($x, $y, $type = null): IQueryFunction;
+ public function neq($x, $y, $type = null): string;
/**
* Creates a lower-than comparison expression with the given arguments.
@@ -178,14 +178,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function lt($x, $y, $type = null): IQueryFunction;
+ public function lt($x, $y, $type = null): string;
/**
* Creates a lower-than-equal comparison expression with the given arguments.
@@ -201,14 +201,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function lte($x, $y, $type = null): IQueryFunction;
+ public function lte($x, $y, $type = null): string;
/**
* Creates a greater-than comparison expression with the given arguments.
@@ -224,14 +224,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function gt($x, $y, $type = null): IQueryFunction;
+ public function gt($x, $y, $type = null): string;
/**
* Creates a greater-than-equal comparison expression with the given arguments.
@@ -247,38 +247,38 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function gte($x, $y, $type = null): IQueryFunction;
+ public function gte($x, $y, $type = null): string;
/**
* Creates an IS NULL expression with the given arguments.
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be restricted by IS NULL.
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0
*
* @psalm-taint-sink sql $x
*/
- public function isNull($x): IQueryFunction;
+ public function isNull($x): string;
/**
* Creates an IS NOT NULL expression with the given arguments.
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be restricted by IS NOT NULL.
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0
*
* @psalm-taint-sink sql $x
*/
- public function isNotNull($x): IQueryFunction;
+ public function isNotNull($x): string;
/**
* Creates a LIKE() comparison expression with the given arguments.
@@ -288,14 +288,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function like($x, $y, $type = null): IQueryFunction;
+ public function like($x, $y, $type = null): string;
/**
* Creates a NOT LIKE() comparison expression with the given arguments.
@@ -305,14 +305,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function notLike($x, $y, $type = null): IQueryFunction;
+ public function notLike($x, $y, $type = null): string;
/**
* Creates a ILIKE() comparison expression with the given arguments.
@@ -322,14 +322,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function iLike($x, $y, $type = null): IQueryFunction;
+ public function iLike($x, $y, $type = null): string;
/**
* Creates a IN () comparison expression with the given arguments.
@@ -339,14 +339,14 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function in($x, $y, $type = null): IQueryFunction;
+ public function in($x, $y, $type = null): string;
/**
* Creates a NOT IN () comparison expression with the given arguments.
@@ -356,36 +356,36 @@ interface IExpressionBuilder {
* @param mixed|null $type one of the IQueryBuilder::PARAM_* constants
* required when comparing text fields for oci compatibility
*
- * @return IQueryFunction
+ * @return string
* @since 8.2.0 - Parameter $type was added in 9.0.0
*
* @psalm-taint-sink sql $x
* @psalm-taint-sink sql $y
* @psalm-taint-sink sql $type
*/
- public function notIn($x, $y, $type = null): IQueryFunction;
+ public function notIn($x, $y, $type = null): string;
/**
* Creates a $x = '' statement, because Oracle needs a different check
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison.
- * @return IQueryFunction
+ * @return string
* @since 13.0.0
*
* @psalm-taint-sink sql $x
*/
- public function emptyString($x): IQueryFunction;
+ public function emptyString($x): string;
/**
* Creates a `$x <> ''` statement, because Oracle needs a different check
*
* @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison.
- * @return IQueryFunction
+ * @return string
* @since 13.0.0
*
* @psalm-taint-sink sql $x
*/
- public function nonEmptyString($x): IQueryFunction;
+ public function nonEmptyString($x): string;
/**
diff --git a/lib/public/DB/QueryBuilder/IFunctionBuilder.php b/lib/public/DB/QueryBuilder/IFunctionBuilder.php
index 811e8d06aaf..d4edc8ea9f8 100644
--- a/lib/public/DB/QueryBuilder/IFunctionBuilder.php
+++ b/lib/public/DB/QueryBuilder/IFunctionBuilder.php
@@ -188,16 +188,4 @@ interface IFunctionBuilder {
* @since 18.0.0
*/
public function least($x, $y): IQueryFunction;
-
- /**
- * Takes the minimum of multiple values
- *
- * If you want to get the minimum value of all rows in a column, use `min` instead
- *
- * @param array<array{"when": string|ILiteral|IParameter|IQueryFunction, "then": string|ILiteral|IParameter|IQueryFunction}> $whens
- * @param string|ILiteral|IParameter|IQueryFunction $else
- * @return IQueryFunction
- * @since 18.0.0
- */
- public function case(array $whens, $else): IQueryFunction;
}
diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php
index 446e9a00b4c..218b7d8cb2d 100644
--- a/lib/public/DB/QueryBuilder/IQueryBuilder.php
+++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php
@@ -503,7 +503,7 @@ interface IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
* @since 8.2.0
@@ -528,7 +528,7 @@ interface IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
* @since 8.2.0
@@ -553,7 +553,7 @@ interface IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
* @since 8.2.0
@@ -578,7 +578,7 @@ interface IQueryBuilder {
* @param string $fromAlias The alias that points to a from clause.
* @param string $join The table name to join.
* @param string $alias The alias of the join table.
- * @param string|IQueryFunction|ICompositeExpression|null $condition The condition for the join.
+ * @param string|ICompositeExpression|null $condition The condition for the join.
*
* @return $this This QueryBuilder instance.
* @since 8.2.0
diff --git a/lib/public/Federation/Events/TrustedServerRemovedEvent.php b/lib/public/Federation/Events/TrustedServerRemovedEvent.php
new file mode 100644
index 00000000000..785991c1554
--- /dev/null
+++ b/lib/public/Federation/Events/TrustedServerRemovedEvent.php
@@ -0,0 +1,48 @@
+<?php
+
+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/>.
+ *
+ */
+namespace OCP\Federation\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * @since 25.0.0
+ */
+class TrustedServerRemovedEvent extends Event {
+ private string $urlHash;
+
+ /**
+ * @since 25.0.0
+ */
+ public function __construct(string $urlHash) {
+ parent::__construct();
+ $this->urlHash = $urlHash;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function getUrlHash(): string {
+ return $this->urlHash;
+ }
+}
diff --git a/lib/public/Files/Cache/ICache.php b/lib/public/Files/Cache/ICache.php
index e27f4207f1e..37e71f3ac79 100644
--- a/lib/public/Files/Cache/ICache.php
+++ b/lib/public/Files/Cache/ICache.php
@@ -243,7 +243,7 @@ interface ICache {
* use the one with the highest id gives the best result with the background scanner, since that is most
* likely the folder where we stopped scanning previously
*
- * @return string|bool the path of the folder or false when no folder matched
+ * @return string|false the path of the folder or false when no folder matched
* @since 9.0.0
*/
public function getIncomplete();
diff --git a/lib/public/Files/DavUtil.php b/lib/public/Files/DavUtil.php
new file mode 100644
index 00000000000..343f3c2ac0f
--- /dev/null
+++ b/lib/public/Files/DavUtil.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
+ *
+ * @author Arthur Schiwon <blizzz@owncloud.com>
+ * @author Bart Visscher <bartv@thisnet.nl>
+ * @author Jakob Sack <mail@jakobsack.de>
+ * @author Jörn Friedrich Dreyer <jfd@butonic.de>
+ * @author Klaas Freitag <freitag@owncloud.com>
+ * @author Markus Goetz <markus@woboq.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Vincent Petry <pvince81@owncloud.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/>
+ *
+ */
+
+namespace OCP\Files;
+
+/**
+ * This class provides different helper functions related to WebDAV protocol
+ *
+ * @since 25.0.0
+ */
+class DavUtil {
+ /**
+ * Compute the fileId to use for dav responses
+ *
+ * @param int $id Id of the file returned by FileInfo::getId
+ * @since 25.0.0
+ */
+ public static function getDavFileId(int $id): string {
+ $instanceId = \OC_Util::getInstanceId();
+ $id = sprintf('%08d', $id);
+ return $id . $instanceId;
+ }
+
+ /**
+ * Compute the format needed for returning permissions for dav
+ *
+ * @since 25.0.0
+ */
+ public static function getDavPermissions(FileInfo $info): string {
+ $p = '';
+ if ($info->isShared()) {
+ $p .= 'S';
+ }
+ if ($info->isShareable()) {
+ $p .= 'R';
+ }
+ if ($info->isMounted()) {
+ $p .= 'M';
+ }
+ if ($info->isReadable()) {
+ $p .= 'G';
+ }
+ if ($info->isDeletable()) {
+ $p .= 'D';
+ }
+ if ($info->isUpdateable()) {
+ $p .= 'NV'; // Renameable, Moveable
+ }
+ if ($info->getType() === FileInfo::TYPE_FILE) {
+ if ($info->isUpdateable()) {
+ $p .= 'W';
+ }
+ } else {
+ if ($info->isCreatable()) {
+ $p .= 'CK';
+ }
+ }
+ return $p;
+ }
+}
diff --git a/lib/public/Files/Events/BeforeDirectFileDownloadEvent.php b/lib/public/Files/Events/BeforeDirectFileDownloadEvent.php
new file mode 100644
index 00000000000..a32c95c6408
--- /dev/null
+++ b/lib/public/Files/Events/BeforeDirectFileDownloadEvent.php
@@ -0,0 +1,84 @@
+<?php
+
+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/>.
+ *
+ */
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * This event is triggered when a user tries to download a file
+ * directly.
+ *
+ * @since 25.0.0
+ */
+class BeforeDirectFileDownloadEvent extends Event {
+ private string $path;
+ private bool $successful = true;
+ private ?string $errorMessage = null;
+
+ /**
+ * @since 25.0.0
+ */
+ public function __construct(string $path) {
+ parent::__construct();
+ $this->path = $path;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function getPath(): string {
+ return $this->path;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function isSuccessful(): bool {
+ return $this->successful;
+ }
+
+ /**
+ * Set if the event was successful
+ *
+ * @since 25.0.0
+ */
+ public function setSuccessful(bool $successful): void {
+ $this->successful = $successful;
+ }
+
+ /**
+ * Get the error message, if any
+ * @since 25.0.0
+ */
+ public function getErrorMessage(): ?string {
+ return $this->errorMessage;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function setErrorMessage(string $errorMessage): void {
+ $this->errorMessage = $errorMessage;
+ }
+}
diff --git a/lib/public/Files/Events/BeforeZipCreatedEvent.php b/lib/public/Files/Events/BeforeZipCreatedEvent.php
new file mode 100644
index 00000000000..18f41a42899
--- /dev/null
+++ b/lib/public/Files/Events/BeforeZipCreatedEvent.php
@@ -0,0 +1,91 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * @since 25.0.0
+ */
+class BeforeZipCreatedEvent extends Event {
+ private string $directory;
+ private array $files;
+ private bool $successful = true;
+ private ?string $errorMessage = null;
+
+ /**
+ * @since 25.0.0
+ */
+ public function __construct(string $directory, array $files) {
+ parent::__construct();
+ $this->directory = $directory;
+ $this->files = $files;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function getDirectory(): string {
+ return $this->directory;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function getFiles(): array {
+ return $this->files;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function isSuccessful(): bool {
+ return $this->successful;
+ }
+
+ /**
+ * Set if the event was successful
+ *
+ * @since 25.0.0
+ */
+ public function setSuccessful(bool $successful): void {
+ $this->successful = $successful;
+ }
+
+ /**
+ * Get the error message, if any
+ * @since 25.0.0
+ */
+ public function getErrorMessage(): ?string {
+ return $this->errorMessage;
+ }
+
+ /**
+ * @since 25.0.0
+ */
+ public function setErrorMessage(string $errorMessage): void {
+ $this->errorMessage = $errorMessage;
+ }
+}
diff --git a/lib/public/Files/Mount/ISystemMountPoint.php b/lib/public/Files/Mount/ISystemMountPoint.php
new file mode 100644
index 00000000000..a090a84947b
--- /dev/null
+++ b/lib/public/Files/Mount/ISystemMountPoint.php
@@ -0,0 +1,34 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OCP\Files\Mount;
+
+/**
+ * Mark a mountpoint as containing system data, meaning that the data is not user specific
+ *
+ * Example use case is signaling to the encryption wrapper that system-wide keys should be used for a mountpoint
+ *
+ * @since 25.0.0
+ */
+interface ISystemMountPoint extends IMountPoint {
+}
diff --git a/lib/public/Files/SimpleFS/ISimpleFile.php b/lib/public/Files/SimpleFS/ISimpleFile.php
index 8f1921cb7cb..34cd128d449 100644
--- a/lib/public/Files/SimpleFS/ISimpleFile.php
+++ b/lib/public/Files/SimpleFS/ISimpleFile.php
@@ -41,44 +41,39 @@ interface ISimpleFile {
/**
* Get the name
*
- * @return string
* @since 11.0.0
*/
- public function getName();
+ public function getName(): string;
/**
* Get the size in bytes
*
- * @return int
* @since 11.0.0
*/
- public function getSize();
+ public function getSize(): int;
/**
* Get the ETag
*
- * @return string
* @since 11.0.0
*/
- public function getETag();
+ public function getETag(): string;
/**
* Get the last modification time
*
- * @return int
* @since 11.0.0
*/
- public function getMTime();
+ public function getMTime(): int;
/**
* Get the content
*
* @throws NotPermittedException
* @throws NotFoundException
- * @return string
* @since 11.0.0
*/
- public function getContent();
+ public function getContent(): string;
/**
* Overwrite the file
@@ -88,7 +83,7 @@ interface ISimpleFile {
* @throws NotFoundException
* @since 11.0.0
*/
- public function putContent($data);
+ public function putContent($data): void;
/**
* Delete the file
@@ -96,15 +91,14 @@ interface ISimpleFile {
* @throws NotPermittedException
* @since 11.0.0
*/
- public function delete();
+ public function delete(): void;
/**
* Get the MimeType
*
- * @return string
* @since 11.0.0
*/
- public function getMimeType();
+ public function getMimeType(): string;
/**
* @since 24.0.0
diff --git a/lib/public/Files/SimpleFS/ISimpleFolder.php b/lib/public/Files/SimpleFS/ISimpleFolder.php
index 0159c41760b..3c8e6e88ab3 100644
--- a/lib/public/Files/SimpleFS/ISimpleFolder.php
+++ b/lib/public/Files/SimpleFS/ISimpleFolder.php
@@ -38,7 +38,7 @@ interface ISimpleFolder {
* @return ISimpleFile[]
* @since 11.0.0
*/
- public function getDirectoryListing();
+ public function getDirectoryListing(): array;
/**
* Check if a file with $name exists
@@ -47,28 +47,24 @@ interface ISimpleFolder {
* @return bool
* @since 11.0.0
*/
- public function fileExists($name);
+ public function fileExists(string $name): bool;
/**
* Get the file named $name from the folder
*
- * @param string $name
- * @return ISimpleFile
* @throws NotFoundException
* @since 11.0.0
*/
- public function getFile($name);
+ public function getFile(string $name): ISimpleFile;
/**
* Creates a new file with $name in the folder
*
- * @param string $name
* @param string|resource|null $content @since 19.0.0
- * @return ISimpleFile
* @throws NotPermittedException
* @since 11.0.0
*/
- public function newFile($name, $content = null);
+ public function newFile(string $name, $content = null): ISimpleFile;
/**
* Remove the folder and all the files in it
@@ -76,13 +72,12 @@ interface ISimpleFolder {
* @throws NotPermittedException
* @since 11.0.0
*/
- public function delete();
+ public function delete(): void;
/**
* Get the folder name
*
- * @return string
* @since 11.0.0
*/
- public function getName();
+ public function getName(): string;
}
diff --git a/lib/public/Files/SimpleFS/ISimpleRoot.php b/lib/public/Files/SimpleFS/ISimpleRoot.php
index fd590b66b31..31c3efe76dd 100644
--- a/lib/public/Files/SimpleFS/ISimpleRoot.php
+++ b/lib/public/Files/SimpleFS/ISimpleRoot.php
@@ -35,8 +35,6 @@ interface ISimpleRoot {
/**
* Get the folder with name $name
*
- * @param string $name
- * @return ISimpleFolder
* @throws NotFoundException
* @throws \RuntimeException
* @since 11.0.0
@@ -56,8 +54,6 @@ interface ISimpleRoot {
/**
* Create a new folder named $name
*
- * @param string $name
- * @return ISimpleFolder
* @throws NotPermittedException
* @throws \RuntimeException
* @since 11.0.0
diff --git a/lib/public/Files/SimpleFS/InMemoryFile.php b/lib/public/Files/SimpleFS/InMemoryFile.php
index 590cb43e1d6..393449d4f1f 100644
--- a/lib/public/Files/SimpleFS/InMemoryFile.php
+++ b/lib/public/Files/SimpleFS/InMemoryFile.php
@@ -36,17 +36,13 @@ use OCP\Files\NotPermittedException;
class InMemoryFile implements ISimpleFile {
/**
* Holds the file name.
- *
- * @var string
*/
- private $name;
+ private string $name;
/**
* Holds the file contents.
- *
- * @var string
*/
- private $contents;
+ private string $contents;
/**
* InMemoryFile constructor.
@@ -64,7 +60,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function getName() {
+ public function getName(): string {
return $this->name;
}
@@ -72,7 +68,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function getSize() {
+ public function getSize(): int {
return strlen($this->contents);
}
@@ -80,7 +76,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function getETag() {
+ public function getETag(): string {
return '';
}
@@ -88,7 +84,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function getMTime() {
+ public function getMTime(): int {
return time();
}
@@ -96,7 +92,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function getContent() {
+ public function getContent(): string {
return $this->contents;
}
@@ -104,7 +100,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function putContent($data) {
+ public function putContent($data): void {
$this->contents = $data;
}
@@ -113,7 +109,7 @@ class InMemoryFile implements ISimpleFile {
*
* @since 16.0.0
*/
- public function delete() {
+ public function delete(): void {
// unimplemented for in memory files
}
@@ -121,7 +117,7 @@ class InMemoryFile implements ISimpleFile {
* @inheritdoc
* @since 16.0.0
*/
- public function getMimeType() {
+ public function getMimeType(): string {
$fileInfo = new \finfo(FILEINFO_MIME_TYPE);
return $fileInfo->buffer($this->contents);
}
diff --git a/lib/public/IAvatar.php b/lib/public/IAvatar.php
index 218ef258250..d05a12e1dbf 100644
--- a/lib/public/IAvatar.php
+++ b/lib/public/IAvatar.php
@@ -36,66 +36,70 @@ use OCP\Files\SimpleFS\ISimpleFile;
interface IAvatar {
/**
- * get the users avatar
+ * Get the users avatar
+ *
* @param int $size size in px of the avatar, avatars are square, defaults to 64, -1 can be used to not scale the image
* @return false|\OCP\IImage containing the avatar or false if there's no image
* @since 6.0.0 - size of -1 was added in 9.0.0
*/
- public function get($size = 64);
+ public function get(int $size = 64);
/**
* Check if an avatar exists for the user
*
- * @return bool
* @since 8.1.0
*/
- public function exists();
+ public function exists(): bool;
/**
* Check if the avatar of a user is a custom uploaded one
*
- * @return bool
* @since 14.0.0
*/
public function isCustomAvatar(): bool;
/**
- * sets the users avatar
+ * Sets the users avatar
+ *
* @param \OCP\IImage|resource|string $data An image object, imagedata or path to set a new avatar
* @throws \Exception if the provided file is not a jpg or png image
* @throws \Exception if the provided image is not valid
* @throws \OC\NotSquareException if the image is not square
- * @return void
* @since 6.0.0
*/
- public function set($data);
+ public function set($data): void;
/**
- * remove the users avatar
- * @return void
+ * Remove the user's avatar
+ *
+ * @param bool $silent Whether removing the avatar should trigger a change
* @since 6.0.0
*/
- public function remove();
+ public function remove(bool $silent = false): void;
/**
* Get the file of the avatar
- * @param int $size -1 can be used to not scale the image
- * @return ISimpleFile
+ *
+ * @param int $size The desired image size. -1 can be used to not scale the image
* @throws NotFoundException
* @since 9.0.0
*/
- public function getFile($size);
+ public function getFile(int $size): ISimpleFile;
/**
- * @param string $text
- * @return Color Object containting r g b int in the range [0, 255]
+ * Get the avatar background color
+ *
* @since 14.0.0
*/
- public function avatarBackgroundColor(string $text);
+ public function avatarBackgroundColor(string $hash): Color;
/**
- * Handle a changed user
+ * Updates the display name if changed.
+ *
+ * @param string $feature The changed feature
+ * @param mixed $oldValue The previous value
+ * @param mixed $newValue The new value
* @since 13.0.0
*/
- public function userChanged($feature, $oldValue, $newValue);
+ public function userChanged(string $feature, $oldValue, $newValue): void;
}
diff --git a/lib/public/IAvatarManager.php b/lib/public/IAvatarManager.php
index 573e109f003..15894550d10 100644
--- a/lib/public/IAvatarManager.php
+++ b/lib/public/IAvatarManager.php
@@ -37,15 +37,14 @@ namespace OCP;
interface IAvatarManager {
/**
- * return a user specific instance of \OCP\IAvatar
+ * Return a user specific instance of \OCP\IAvatar
* @see IAvatar
- * @param string $user the ownCloud user id
- * @return IAvatar
+ * @param string $userId the Nextcloud user id
* @throws \Exception In case the username is potentially dangerous
* @throws \OCP\Files\NotFoundException In case there is no user folder yet
* @since 6.0.0
*/
- public function getAvatar(string $user) : IAvatar;
+ public function getAvatar(string $userId): IAvatar;
/**
* Returns a guest user avatar instance.
diff --git a/lib/public/IBinaryFinder.php b/lib/public/IBinaryFinder.php
new file mode 100644
index 00000000000..028c1f4d0a7
--- /dev/null
+++ b/lib/public/IBinaryFinder.php
@@ -0,0 +1,41 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OCP;
+
+/**
+ * Service that find the binary path for a program.
+ *
+ * This interface should be injected via depency injection and must
+ * not be implemented in applications.
+ *
+ * @since 25.0.0
+ */
+interface IBinaryFinder {
+ /**
+ * Try to find a program
+ *
+ * @return false|string
+ * @since 25.0.0
+ */
+ public function findBinaryPath(string $program);
+}
diff --git a/lib/public/IEventSource.php b/lib/public/IEventSource.php
index 85f09837125..879b365cc77 100644
--- a/lib/public/IEventSource.php
+++ b/lib/public/IEventSource.php
@@ -35,7 +35,7 @@ interface IEventSource {
/**
* send a message to the client
*
- * @param string $type
+ * @param string $type One of success, notice, error, failure and done. Used in core/js/update.js
* @param mixed $data
*
* if only one parameter is given, a typeless message will be send with that parameter as data
diff --git a/lib/public/ISession.php b/lib/public/ISession.php
index 2709e09d4ca..12cd716ec3f 100644
--- a/lib/public/ISession.php
+++ b/lib/public/ISession.php
@@ -84,6 +84,14 @@ interface ISession {
public function clear();
/**
+ * Reopen a session for writing again
+ *
+ * @return bool true if the session was actually reopened, otherwise false
+ * @since 25.0.0
+ */
+ public function reopen(): bool;
+
+ /**
* Close the session and release the lock
* @since 7.0.0
*/
diff --git a/lib/public/IURLGenerator.php b/lib/public/IURLGenerator.php
index 580536b8b5f..808ba66c862 100644
--- a/lib/public/IURLGenerator.php
+++ b/lib/public/IURLGenerator.php
@@ -35,6 +35,16 @@ namespace OCP;
* @since 6.0.0
*/
interface IURLGenerator {
+
+ /**
+ * Regex for matching http(s) urls
+ *
+ * This is a copy of the frontend regex in core/src/OCP/comments.js, make sure to adjust both when changing
+ *
+ * @since 25.0.0
+ */
+ public const URL_REGEX = '/(\s|\n|^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|\n|$)/mi';
+
/**
* Returns the URL for a route
* @param string $routeName the name of the route
diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php
index 77e2fc21a22..af0d5f08809 100644
--- a/lib/public/IUserManager.php
+++ b/lib/public/IUserManager.php
@@ -85,6 +85,15 @@ interface IUserManager {
public function get($uid);
/**
+ * Get the display name of a user
+ *
+ * @param string $uid
+ * @return string|null
+ * @since 25.0.0
+ */
+ public function getDisplayName(string $uid): ?string;
+
+ /**
* check if a user exists
*
* @param string $uid
diff --git a/lib/public/Migration/IOutput.php b/lib/public/Migration/IOutput.php
index 2dba50ab2c6..212b5d927f8 100644
--- a/lib/public/Migration/IOutput.php
+++ b/lib/public/Migration/IOutput.php
@@ -32,18 +32,21 @@ interface IOutput {
/**
* @param string $message
+ * @return void
* @since 9.1.0
*/
public function info($message);
/**
* @param string $message
+ * @return void
* @since 9.1.0
*/
public function warning($message);
/**
* @param int $max
+ * @return void
* @since 9.1.0
*/
public function startProgress($max = 0);
@@ -51,12 +54,13 @@ interface IOutput {
/**
* @param int $step
* @param string $description
+ * @return void
* @since 9.1.0
*/
public function advance($step = 1, $description = '');
/**
- * @param int $max
+ * @return void
* @since 9.1.0
*/
public function finishProgress();
diff --git a/lib/public/Security/Bruteforce/IThrottler.php b/lib/public/Security/Bruteforce/IThrottler.php
new file mode 100644
index 00000000000..6f492d6c59d
--- /dev/null
+++ b/lib/public/Security/Bruteforce/IThrottler.php
@@ -0,0 +1,126 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 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/>.
+ *
+ */
+
+namespace OCP\Security\Bruteforce;
+
+/**
+ * Class Throttler implements the bruteforce protection for security actions in
+ * Nextcloud.
+ *
+ * It is working by logging invalid login attempts to the database and slowing
+ * down all login attempts from the same subnet. The max delay is 30 seconds and
+ * the starting delay are 200 milliseconds. (after the first failed login)
+ *
+ * This is based on Paragonie's AirBrake for Airship CMS. You can find the original
+ * code at https://github.com/paragonie/airship/blob/7e5bad7e3c0fbbf324c11f963fd1f80e59762606/src/Engine/Security/AirBrake.php
+ *
+ * @package OC\Security\Bruteforce
+ * @since 25.0.0
+ */
+interface IThrottler {
+ /**
+ * @since 25.0.0
+ */
+ public const MAX_DELAY = 25;
+
+ /**
+ * @since 25.0.0
+ */
+ public const MAX_DELAY_MS = 25000; // in milliseconds
+
+ /**
+ * @since 25.0.0
+ */
+ public const MAX_ATTEMPTS = 10;
+
+ /**
+ * Register a failed attempt to bruteforce a security control
+ *
+ * @param string $action
+ * @param string $ip
+ * @param array $metadata Optional metadata logged to the database
+ * @since 25.0.0
+ */
+ public function registerAttempt(string $action, string $ip, array $metadata = []): void;
+
+ /**
+ * Get the throttling delay (in milliseconds)
+ *
+ * @param string $ip
+ * @param string $action optionally filter by action
+ * @param float $maxAgeHours
+ * @return int
+ * @since 25.0.0
+ */
+ public function getAttempts(string $ip, string $action = '', float $maxAgeHours = 12): int;
+
+ /**
+ * Get the throttling delay (in milliseconds)
+ *
+ * @param string $ip
+ * @param string $action optionally filter by action
+ * @return int
+ * @since 25.0.0
+ */
+ public function getDelay(string $ip, string $action = ''): int;
+
+ /**
+ * Reset the throttling delay for an IP address, action and metadata
+ *
+ * @param string $ip
+ * @param string $action
+ * @param array $metadata
+ * @since 25.0.0
+ */
+ public function resetDelay(string $ip, string $action, array $metadata): void;
+
+ /**
+ * Reset the throttling delay for an IP address
+ *
+ * @param string $ip
+ * @since 25.0.0
+ */
+ public function resetDelayForIP(string $ip): void;
+
+ /**
+ * Will sleep for the defined amount of time
+ *
+ * @param string $ip
+ * @param string $action optionally filter by action
+ * @return int the time spent sleeping
+ * @since 25.0.0
+ */
+ public function sleepDelay(string $ip, string $action = ''): int;
+
+ /**
+ * Will sleep for the defined amount of time unless maximum was reached in the last 30 minutes
+ * In this case a "429 Too Many Request" exception is thrown
+ *
+ * @param string $ip
+ * @param string $action optionally filter by action
+ * @return int the time spent sleeping
+ * @throws MaxDelayReached when reached the maximum
+ * @since 25.0.0
+ */
+ public function sleepDelayOrThrowOnMax(string $ip, string $action = ''): int;
+}
diff --git a/lib/public/Share/IAttributes.php b/lib/public/Share/IAttributes.php
new file mode 100644
index 00000000000..6e4cee08b12
--- /dev/null
+++ b/lib/public/Share/IAttributes.php
@@ -0,0 +1,68 @@
+<?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/>
+ *
+ */
+namespace OCP\Share;
+
+/**
+ * Interface IAttributes
+ *
+ * @package OCP\Share
+ * @since 25.0.0
+ */
+interface IAttributes {
+
+ /**
+ * Sets an attribute enabled/disabled. If the key did not exist before it will be created.
+ *
+ * @param string $scope scope
+ * @param string $key key
+ * @param bool $enabled enabled
+ * @return IAttributes The modified object
+ * @since 25.0.0
+ */
+ public function setAttribute($scope, $key, $enabled);
+
+ /**
+ * Returns if attribute is enabled/disabled for given scope id and key.
+ * If attribute does not exist, returns null
+ *
+ * @param string $scope scope
+ * @param string $key key
+ * @return bool|null
+ * @since 25.0.0
+ */
+ public function getAttribute($scope, $key);
+
+ /**
+ * Formats the IAttributes object to array with the following format:
+ * [
+ * 0 => [
+ * "scope" => <string>,
+ * "key" => <string>,
+ * "enabled" => <bool>
+ * ],
+ * ...
+ * ]
+ *
+ * @return array formatted IAttributes
+ * @since 25.0.0
+ */
+ public function toArray();
+}
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index f207ca87a2c..0810acc673a 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -135,10 +135,11 @@ interface IManager {
* @param string $userId
* @param Folder $node
* @param bool $reshares
+ * @param bool $shallow Whether the method should stop at the first level, or look into sub-folders.
* @return IShare[][] [$fileId => IShare[], ...]
* @since 11.0.0
*/
- public function getSharesInFolder($userId, Folder $node, $reshares = false);
+ public function getSharesInFolder($userId, Folder $node, $reshares = false, $shallow = true);
/**
* Get shares shared by (initiated) by the provided user.
diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php
index 1d3cf9bbbdf..5a825552e26 100644
--- a/lib/public/Share/IShare.php
+++ b/lib/public/Share/IShare.php
@@ -36,7 +36,9 @@ use OCP\Files\NotFoundException;
use OCP\Share\Exceptions\IllegalIDChangeException;
/**
- * Interface IShare
+ * This interface allows to represent a share object.
+ *
+ * This interface must not be implemented in your application.
*
* @since 9.0.0
*/
@@ -300,7 +302,7 @@ interface IShare {
* See \OCP\Constants::PERMISSION_*
*
* @param int $permissions
- * @return \OCP\Share\IShare The modified object
+ * @return IShare The modified object
* @since 9.0.0
*/
public function setPermissions($permissions);
@@ -315,6 +317,31 @@ interface IShare {
public function getPermissions();
/**
+ * Create share attributes object
+ *
+ * @since 25.0.0
+ * @return IAttributes
+ */
+ public function newAttributes(): IAttributes;
+
+ /**
+ * Set share attributes
+ *
+ * @param ?IAttributes $attributes
+ * @since 25.0.0
+ * @return IShare The modified object
+ */
+ public function setAttributes(?IAttributes $attributes);
+
+ /**
+ * Get share attributes
+ *
+ * @since 25.0.0
+ * @return ?IAttributes
+ */
+ public function getAttributes(): ?IAttributes;
+
+ /**
* Set the accepted status
* See self::STATUS_*
*
diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php
index 6af513360fe..c549592d6f6 100644
--- a/lib/public/Share/IShareProvider.php
+++ b/lib/public/Share/IShareProvider.php
@@ -123,10 +123,11 @@ interface IShareProvider {
* @param string $userId
* @param Folder $node
* @param bool $reshares Also get the shares where $user is the owner instead of just the shares where $user is the initiator
+ * @param bool $shallow Whether the method should stop at the first level, or look into sub-folders.
* @return \OCP\Share\IShare[][]
* @since 11.0.0
*/
- public function getSharesInFolder($userId, Folder $node, $reshares);
+ public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true);
/**
* Get all shares by the given user
diff --git a/lib/public/User/Events/UserChangedEvent.php b/lib/public/User/Events/UserChangedEvent.php
index 3a40f8c3f11..f48dd3914e6 100644
--- a/lib/public/User/Events/UserChangedEvent.php
+++ b/lib/public/User/Events/UserChangedEvent.php
@@ -32,16 +32,10 @@ use OCP\IUser;
* @since 18.0.0
*/
class UserChangedEvent extends Event {
-
- /** @var IUser */
- private $user;
-
- /** @var string */
- private $feature;
-
+ private IUser $user;
+ private string $feature;
/** @var mixed */
private $value;
-
/** @var mixed */
private $oldValue;
diff --git a/lib/public/UserStatus/IUserStatus.php b/lib/public/UserStatus/IUserStatus.php
index bf743dea08d..8803b328ad5 100644
--- a/lib/public/UserStatus/IUserStatus.php
+++ b/lib/public/UserStatus/IUserStatus.php
@@ -65,6 +65,18 @@ interface IUserStatus {
public const INVISIBLE = 'invisible';
/**
+ * @var string
+ * @since 25.0.0
+ */
+ public const MESSAGE_CALL = 'call';
+
+ /**
+ * @var string
+ * @since 25.0.0
+ */
+ public const MESSAGE_AVAILABILITY = 'availability';
+
+ /**
* Get the user this status is connected to
*
* @return string
diff --git a/lib/public/Util.php b/lib/public/Util.php
index e5bb2a955ae..6cd3eaa7f85 100644
--- a/lib/public/Util.php
+++ b/lib/public/Util.php
@@ -48,6 +48,7 @@ namespace OCP;
use OC\AppScriptDependency;
use OC\AppScriptSort;
+use bantu\IniGetWrapper\IniGetWrapper;
/**
* This class provides different helper functions to make the life of a developer easier
@@ -604,4 +605,27 @@ class Util {
}
return $temp;
}
+
+ /**
+ * Check if a function is enabled in the php configuration
+ *
+ * @since 25.0.0
+ */
+ public static function isFunctionEnabled(string $functionName): bool {
+ if (!function_exists($functionName)) {
+ return false;
+ }
+ $ini = \OCP\Server::get(IniGetWrapper::class);
+ $disabled = explode(',', $ini->get('disable_functions') ?: '');
+ $disabled = array_map('trim', $disabled);
+ if (in_array($functionName, $disabled)) {
+ return false;
+ }
+ $disabled = explode(',', $ini->get('suhosin.executor.func.blacklist') ?: '');
+ $disabled = array_map('trim', $disabled);
+ if (in_array($functionName, $disabled)) {
+ return false;
+ }
+ return true;
+ }
}