summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/l10n/fi.js2
-rw-r--r--lib/l10n/fi.json2
-rw-r--r--lib/l10n/hu.js2
-rw-r--r--lib/l10n/hu.json2
-rw-r--r--lib/l10n/uk.js7
-rw-r--r--lib/l10n/uk.json7
-rw-r--r--lib/l10n/zh_TW.js2
-rw-r--r--lib/l10n/zh_TW.json2
-rw-r--r--lib/private/AppFramework/App.php22
-rw-r--r--lib/private/AppFramework/Bootstrap/Coordinator.php22
-rw-r--r--lib/private/AppFramework/Http/Request.php18
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenMapper.php27
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php55
-rw-r--r--lib/private/Collaboration/Reference/File/FileReferenceProvider.php8
-rw-r--r--lib/private/Config.php7
-rw-r--r--lib/private/DB/BacktraceDebugStack.php1
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php38
-rw-r--r--lib/private/Files/Config/UserMountCache.php12
-rw-r--r--lib/private/Files/Mount/Manager.php9
-rw-r--r--lib/private/Files/Mount/MountPoint.php24
-rw-r--r--lib/private/Files/Node/File.php2
-rw-r--r--lib/private/Files/Node/Folder.php8
-rw-r--r--lib/private/Files/Node/Node.php56
-rw-r--r--lib/private/Files/Node/Root.php4
-rw-r--r--lib/private/Files/SetupManager.php39
-rw-r--r--lib/private/Files/View.php17
-rw-r--r--lib/private/Preview/IMagickSupport.php40
-rw-r--r--lib/private/PreviewManager.php14
-rw-r--r--lib/private/Route/CachingRouter.php27
-rw-r--r--lib/private/Route/Router.php39
-rw-r--r--lib/private/Server.php22
-rw-r--r--lib/private/TemplateLayout.php4
-rw-r--r--lib/private/legacy/OC_App.php16
-rw-r--r--lib/public/AppFramework/Controller.php3
-rw-r--r--lib/public/Files/Mount/IMountPoint.php4
37 files changed, 427 insertions, 139 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 69d1f92c98c..62f66dca67b 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -1392,6 +1392,7 @@ return array(
'OC\\Preview\\Generator' => $baseDir . '/lib/private/Preview/Generator.php',
'OC\\Preview\\GeneratorHelper' => $baseDir . '/lib/private/Preview/GeneratorHelper.php',
'OC\\Preview\\HEIC' => $baseDir . '/lib/private/Preview/HEIC.php',
+ 'OC\\Preview\\IMagickSupport' => $baseDir . '/lib/private/Preview/IMagickSupport.php',
'OC\\Preview\\Illustrator' => $baseDir . '/lib/private/Preview/Illustrator.php',
'OC\\Preview\\Image' => $baseDir . '/lib/private/Preview/Image.php',
'OC\\Preview\\Imaginary' => $baseDir . '/lib/private/Preview/Imaginary.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 1191a3bfa53..33d63a26e3e 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -1425,6 +1425,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Preview\\Generator' => __DIR__ . '/../../..' . '/lib/private/Preview/Generator.php',
'OC\\Preview\\GeneratorHelper' => __DIR__ . '/../../..' . '/lib/private/Preview/GeneratorHelper.php',
'OC\\Preview\\HEIC' => __DIR__ . '/../../..' . '/lib/private/Preview/HEIC.php',
+ 'OC\\Preview\\IMagickSupport' => __DIR__ . '/../../..' . '/lib/private/Preview/IMagickSupport.php',
'OC\\Preview\\Illustrator' => __DIR__ . '/../../..' . '/lib/private/Preview/Illustrator.php',
'OC\\Preview\\Image' => __DIR__ . '/../../..' . '/lib/private/Preview/Image.php',
'OC\\Preview\\Imaginary' => __DIR__ . '/../../..' . '/lib/private/Preview/Imaginary.php',
diff --git a/lib/l10n/fi.js b/lib/l10n/fi.js
index f724b77763d..23134d43402 100644
--- a/lib/l10n/fi.js
+++ b/lib/l10n/fi.js
@@ -135,6 +135,7 @@ OC.L10N.register(
"%1$s shared »%2$s« with you." : "%1$s jakoi kohteen »%2$s« kanssasi.",
"Click the button below to open it." : "Napsauta alla olevaa painiketta avataksesi sen.",
"The requested share does not exist anymore" : "Pyydettyä jakoa ei ole enää olemassa",
+ "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Käyttäjää ei luotu, koska käyttäjäraja on tullut täyteen. Tarkista ilmoitukset saadaksesi lisätietoja.",
"Could not find category \"%s\"" : "Luokkaa \"%s\" ei löytynyt",
"Sunday" : "sunnuntai",
"Monday" : "maanantai",
@@ -184,6 +185,7 @@ OC.L10N.register(
"A valid password must be provided" : "Anna kelvollinen salasana",
"The username is already being used" : "Käyttäjätunnus on jo käytössä",
"Could not create user" : "Ei voitu luoda käyttäjää",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\", välilyönnit ja \"_.@-'\"",
"A valid username must be provided" : "Anna kelvollinen käyttäjätunnus",
"Username contains whitespace at the beginning or at the end" : "Käyttäjätunnus sisältää tyhjätilaa joko alussa tai lopussa",
"Username must not consist of dots only" : "Käyttäjänimi ei voi koostua vain pisteistä",
diff --git a/lib/l10n/fi.json b/lib/l10n/fi.json
index ee534d2856b..1f028ceb86e 100644
--- a/lib/l10n/fi.json
+++ b/lib/l10n/fi.json
@@ -133,6 +133,7 @@
"%1$s shared »%2$s« with you." : "%1$s jakoi kohteen »%2$s« kanssasi.",
"Click the button below to open it." : "Napsauta alla olevaa painiketta avataksesi sen.",
"The requested share does not exist anymore" : "Pyydettyä jakoa ei ole enää olemassa",
+ "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Käyttäjää ei luotu, koska käyttäjäraja on tullut täyteen. Tarkista ilmoitukset saadaksesi lisätietoja.",
"Could not find category \"%s\"" : "Luokkaa \"%s\" ei löytynyt",
"Sunday" : "sunnuntai",
"Monday" : "maanantai",
@@ -182,6 +183,7 @@
"A valid password must be provided" : "Anna kelvollinen salasana",
"The username is already being used" : "Käyttäjätunnus on jo käytössä",
"Could not create user" : "Ei voitu luoda käyttäjää",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\", välilyönnit ja \"_.@-'\"",
"A valid username must be provided" : "Anna kelvollinen käyttäjätunnus",
"Username contains whitespace at the beginning or at the end" : "Käyttäjätunnus sisältää tyhjätilaa joko alussa tai lopussa",
"Username must not consist of dots only" : "Käyttäjänimi ei voi koostua vain pisteistä",
diff --git a/lib/l10n/hu.js b/lib/l10n/hu.js
index 06770c1f1b0..9fb6d495087 100644
--- a/lib/l10n/hu.js
+++ b/lib/l10n/hu.js
@@ -114,7 +114,7 @@ OC.L10N.register(
"Profile picture" : "Profilkép",
"About" : "Névjegy",
"Full name" : "Teljes név",
- "Headline" : "Főcím",
+ "Headline" : "Címsor",
"Organisation" : "Szervezet",
"Role" : "Szerepkör",
"Unknown user" : "Ismeretlen felhasználó",
diff --git a/lib/l10n/hu.json b/lib/l10n/hu.json
index 2b5dfb58ec6..a36249b02f6 100644
--- a/lib/l10n/hu.json
+++ b/lib/l10n/hu.json
@@ -112,7 +112,7 @@
"Profile picture" : "Profilkép",
"About" : "Névjegy",
"Full name" : "Teljes név",
- "Headline" : "Főcím",
+ "Headline" : "Címsor",
"Organisation" : "Szervezet",
"Role" : "Szerepkör",
"Unknown user" : "Ismeretlen felhasználó",
diff --git a/lib/l10n/uk.js b/lib/l10n/uk.js
index 6b290c350f5..5679eb51661 100644
--- a/lib/l10n/uk.js
+++ b/lib/l10n/uk.js
@@ -56,6 +56,7 @@ OC.L10N.register(
"Invalid image" : "Недійсне зображення",
"Avatar image is not square" : "Зображення аватара не квадратне",
"View profile" : "Перегляд профілю",
+ "Local time: %s" : "Місцевий час: %s",
"today" : "сьогодні",
"tomorrow" : "завтра",
"yesterday" : "вчора",
@@ -100,6 +101,7 @@ OC.L10N.register(
"Users" : "Користувачі",
"Email" : "Електронна пошта",
"Mail %s" : "Пошта %s",
+ "View %s on the fediverse" : "Переглянути %s у Fediverse",
"Phone" : "Телефон",
"Call %s" : "Телефонуйте %s",
"Twitter" : "Twitter",
@@ -150,7 +152,8 @@ OC.L10N.register(
"%1$s shared »%2$s« with you" : "%1$s надано доступ до \"%2$s\"",
"%1$s shared »%2$s« with you." : "%1$s надано доступ до \"%2$s\".",
"Click the button below to open it." : "Щоб відкрити файл, натисніть кнопку нижче.",
- "The requested share does not exist anymore" : "Запитувана частка більше не існує",
+ "The requested share does not exist anymore" : "Запитуваний спільний ресурс більше недоступний",
+ "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Користувача не створено, оскільки досягнуто обмеження на кількість користувачів. Перевірте сповіщення для докладної інформації.",
"Could not find category \"%s\"" : "Не вдалося знайти категорію \"%s\"",
"Sunday" : "Неділя",
"Monday" : "Понеділок",
@@ -200,6 +203,7 @@ OC.L10N.register(
"A valid password must be provided" : "Потрібно задати вірний пароль",
"The username is already being used" : "Ім'я користувача вже використовується",
"Could not create user" : "Не вдалося створити користувача",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Лише такі символи дозволено у імені користувача: \"a-z\", \"A-Z\", \"0-9\", пробіл та \"_.@-'\"",
"A valid username must be provided" : "Потрібно задати вірне ім'я користувача",
"Username contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу в початку або в кінці",
"Username must not consist of dots only" : "Ім'я користувача не повинно складатися лише з крапок",
@@ -262,6 +266,7 @@ OC.L10N.register(
"%s enter the database username." : "%s введіть ім'я користувача бази даних.",
"%s enter the database name." : "%s введіть назву бази даних.",
"%s you may not use dots in the database name" : "%s не можна використовувати крапки в назві бази даних",
+ "The user limit has been reached and the user was not created. Check your notifications to learn more." : "Досягнуто обмеження на кількість користувачів, користувача не було створено. Перевірте сповіщення для докладної інформації.",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Тільки такі символи допускаються в імені користувача: \"a-z\", \"A-Z\", \"0-9\", і \"_.@-'\""
},
"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);");
diff --git a/lib/l10n/uk.json b/lib/l10n/uk.json
index 2bb32fd83e3..7a0854d23eb 100644
--- a/lib/l10n/uk.json
+++ b/lib/l10n/uk.json
@@ -54,6 +54,7 @@
"Invalid image" : "Недійсне зображення",
"Avatar image is not square" : "Зображення аватара не квадратне",
"View profile" : "Перегляд профілю",
+ "Local time: %s" : "Місцевий час: %s",
"today" : "сьогодні",
"tomorrow" : "завтра",
"yesterday" : "вчора",
@@ -98,6 +99,7 @@
"Users" : "Користувачі",
"Email" : "Електронна пошта",
"Mail %s" : "Пошта %s",
+ "View %s on the fediverse" : "Переглянути %s у Fediverse",
"Phone" : "Телефон",
"Call %s" : "Телефонуйте %s",
"Twitter" : "Twitter",
@@ -148,7 +150,8 @@
"%1$s shared »%2$s« with you" : "%1$s надано доступ до \"%2$s\"",
"%1$s shared »%2$s« with you." : "%1$s надано доступ до \"%2$s\".",
"Click the button below to open it." : "Щоб відкрити файл, натисніть кнопку нижче.",
- "The requested share does not exist anymore" : "Запитувана частка більше не існує",
+ "The requested share does not exist anymore" : "Запитуваний спільний ресурс більше недоступний",
+ "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Користувача не створено, оскільки досягнуто обмеження на кількість користувачів. Перевірте сповіщення для докладної інформації.",
"Could not find category \"%s\"" : "Не вдалося знайти категорію \"%s\"",
"Sunday" : "Неділя",
"Monday" : "Понеділок",
@@ -198,6 +201,7 @@
"A valid password must be provided" : "Потрібно задати вірний пароль",
"The username is already being used" : "Ім'я користувача вже використовується",
"Could not create user" : "Не вдалося створити користувача",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Лише такі символи дозволено у імені користувача: \"a-z\", \"A-Z\", \"0-9\", пробіл та \"_.@-'\"",
"A valid username must be provided" : "Потрібно задати вірне ім'я користувача",
"Username contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу в початку або в кінці",
"Username must not consist of dots only" : "Ім'я користувача не повинно складатися лише з крапок",
@@ -260,6 +264,7 @@
"%s enter the database username." : "%s введіть ім'я користувача бази даних.",
"%s enter the database name." : "%s введіть назву бази даних.",
"%s you may not use dots in the database name" : "%s не можна використовувати крапки в назві бази даних",
+ "The user limit has been reached and the user was not created. Check your notifications to learn more." : "Досягнуто обмеження на кількість користувачів, користувача не було створено. Перевірте сповіщення для докладної інформації.",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Тільки такі символи допускаються в імені користувача: \"a-z\", \"A-Z\", \"0-9\", і \"_.@-'\""
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"
} \ No newline at end of file
diff --git a/lib/l10n/zh_TW.js b/lib/l10n/zh_TW.js
index 6124af85631..7e3c03ad5a8 100644
--- a/lib/l10n/zh_TW.js
+++ b/lib/l10n/zh_TW.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Invalid image" : "無效的圖片",
"Avatar image is not square" : "頭像不是正方形",
"View profile" : "檢視個人檔案",
+ "Local time: %s" : "本機時間:%s",
"today" : "今天",
"tomorrow" : "明天",
"yesterday" : "昨天",
@@ -204,6 +205,7 @@ OC.L10N.register(
"A valid password must be provided" : "須提供有效的密碼",
"The username is already being used" : "這個使用者名稱已經有人使用了",
"Could not create user" : "無法建立使用者",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "使用者名稱僅允許以下字元:\"a-z\"、\"A-Z\"、\"0-9\"、空格與 \"_.@-'\"",
"A valid username must be provided" : "必須提供一個有效的用戶名",
"Username contains whitespace at the beginning or at the end" : "用戶名的開頭或結尾有空白",
"Username must not consist of dots only" : "使用者名稱不能只包含小數點",
diff --git a/lib/l10n/zh_TW.json b/lib/l10n/zh_TW.json
index c9a8f17835d..743e5d90ffd 100644
--- a/lib/l10n/zh_TW.json
+++ b/lib/l10n/zh_TW.json
@@ -55,6 +55,7 @@
"Invalid image" : "無效的圖片",
"Avatar image is not square" : "頭像不是正方形",
"View profile" : "檢視個人檔案",
+ "Local time: %s" : "本機時間:%s",
"today" : "今天",
"tomorrow" : "明天",
"yesterday" : "昨天",
@@ -202,6 +203,7 @@
"A valid password must be provided" : "須提供有效的密碼",
"The username is already being used" : "這個使用者名稱已經有人使用了",
"Could not create user" : "無法建立使用者",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "使用者名稱僅允許以下字元:\"a-z\"、\"A-Z\"、\"0-9\"、空格與 \"_.@-'\"",
"A valid username must be provided" : "必須提供一個有效的用戶名",
"Username contains whitespace at the beginning or at the end" : "用戶名的開頭或結尾有空白",
"Username must not consist of dots only" : "使用者名稱不能只包含小數點",
diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php
index d2ef7da9e46..abf8a08a44b 100644
--- a/lib/private/AppFramework/App.php
+++ b/lib/private/AppFramework/App.php
@@ -34,7 +34,6 @@ namespace OC\AppFramework;
use OC\AppFramework\DependencyInjection\DIContainer;
use OC\AppFramework\Http\Dispatcher;
use OC\AppFramework\Http\Request;
-use OC\Diagnostics\EventLogger;
use OCP\Profiler\IProfiler;
use OC\Profiler\RoutingDataCollector;
use OCP\AppFramework\QueryException;
@@ -43,7 +42,6 @@ use OCP\AppFramework\Http\ICallbackResponse;
use OCP\AppFramework\Http\IOutput;
use OCP\Diagnostics\IEventLogger;
use OCP\HintException;
-use OCP\IConfig;
use OCP\IRequest;
/**
@@ -120,7 +118,7 @@ class App {
public static function main(string $controllerName, string $methodName, DIContainer $container, array $urlParams = null) {
/** @var IProfiler $profiler */
$profiler = $container->get(IProfiler::class);
- $config = $container->get(IConfig::class);
+ $eventLogger = $container->get(IEventLogger::class);
// Disable profiler on the profiler UI
$profiler->setEnabled($profiler->isEnabled() && !is_null($urlParams) && isset($urlParams['_route']) && !str_starts_with($urlParams['_route'], 'profiler.'));
if ($profiler->isEnabled()) {
@@ -128,6 +126,8 @@ class App {
$profiler->add(new RoutingDataCollector($container['AppName'], $controllerName, $methodName));
}
+ $eventLogger->start('app:controller:params', 'Gather controller parameters');
+
if (!is_null($urlParams)) {
/** @var Request $request */
$request = $container->get(IRequest::class);
@@ -139,6 +139,10 @@ class App {
}
$appName = $container['AppName'];
+ $eventLogger->end('app:controller:params');
+
+ $eventLogger->start('app:controller:load', 'Load app controller');
+
// first try $controllerName then go for \OCA\AppName\Controller\$controllerName
try {
$controller = $container->get($controllerName);
@@ -158,10 +162,18 @@ class App {
$controller = $container->query($controllerName);
}
+ $eventLogger->end('app:controller:load');
+
+ $eventLogger->start('app:controller:dispatcher', 'Initialize dispatcher and pre-middleware');
+
// initialize the dispatcher and run all the middleware before the controller
/** @var Dispatcher $dispatcher */
$dispatcher = $container['Dispatcher'];
+ $eventLogger->end('app:controller:dispatcher');
+
+ $eventLogger->start('app:controller:run', 'Run app controller');
+
[
$httpHeaders,
$responseHeaders,
@@ -170,11 +182,11 @@ class App {
$response
] = $dispatcher->dispatch($controller, $methodName);
+ $eventLogger->end('app:controller:run');
+
$io = $container[IOutput::class];
if ($profiler->isEnabled()) {
- /** @var EventLogger $eventLogger */
- $eventLogger = $container->get(IEventLogger::class);
$eventLogger->end('runtime');
$profile = $profiler->collect($container->get(IRequest::class), $response);
$profiler->saveProfile($profile);
diff --git a/lib/private/AppFramework/Bootstrap/Coordinator.php b/lib/private/AppFramework/Bootstrap/Coordinator.php
index ff04196fef6..f41b734a25b 100644
--- a/lib/private/AppFramework/Bootstrap/Coordinator.php
+++ b/lib/private/AppFramework/Bootstrap/Coordinator.php
@@ -98,11 +98,14 @@ class Coordinator {
* @param string[] $appIds
*/
private function registerApps(array $appIds): void {
+ $this->eventLogger->start('bootstrap:register_apps', '');
if ($this->registrationContext === null) {
$this->registrationContext = new RegistrationContext($this->logger);
}
$apps = [];
foreach ($appIds as $appId) {
+ $this->eventLogger->start("bootstrap:register_app:$appId", "Register $appId");
+ $this->eventLogger->start("bootstrap:register_app:$appId:autoloader", "Setup autoloader for $appId");
/*
* First, we have to enable the app's autoloader
*
@@ -114,36 +117,43 @@ class Coordinator {
continue;
}
OC_App::registerAutoloading($appId, $path);
+ $this->eventLogger->end("bootstrap:register_app:$appId:autoloader");
/*
- * Next we check if there is an application class and it implements
+ * Next we check if there is an application class, and it implements
* the \OCP\AppFramework\Bootstrap\IBootstrap interface
*/
$appNameSpace = App::buildAppNamespace($appId);
$applicationClassName = $appNameSpace . '\\AppInfo\\Application';
try {
if (class_exists($applicationClassName) && in_array(IBootstrap::class, class_implements($applicationClassName), true)) {
+ $this->eventLogger->start("bootstrap:register_app:$appId:application", "Load `Application` instance for $appId");
try {
/** @var IBootstrap|App $application */
$apps[$appId] = $application = $this->serverContainer->query($applicationClassName);
} catch (QueryException $e) {
// Weird, but ok
+ $this->eventLogger->end("bootstrap:register_app:$appId");
continue;
}
+ $this->eventLogger->end("bootstrap:register_app:$appId:application");
- $this->eventLogger->start('bootstrap:register_app_' . $appId, '');
+ $this->eventLogger->start("bootstrap:register_app:$appId:register", "`Application::register` for $appId");
$application->register($this->registrationContext->for($appId));
- $this->eventLogger->end('bootstrap:register_app_' . $appId);
+ $this->eventLogger->end("bootstrap:register_app:$appId:register");
}
} catch (Throwable $e) {
$this->logger->emergency('Error during app service registration: ' . $e->getMessage(), [
'exception' => $e,
'app' => $appId,
]);
+ $this->eventLogger->end("bootstrap:register_app:$appId");
continue;
}
+ $this->eventLogger->end("bootstrap:register_app:$appId");
}
+ $this->eventLogger->start('bootstrap:register_apps:apply', 'Apply all the registered service by apps');
/**
* Now that all register methods have been called, we can delegate the registrations
* to the actual services
@@ -153,6 +163,8 @@ class Coordinator {
$this->registrationContext->delegateDashboardPanelRegistrations($this->dashboardManager);
$this->registrationContext->delegateEventListenerRegistrations($this->eventDispatcher);
$this->registrationContext->delegateContainerRegistrations($apps);
+ $this->eventLogger->end('bootstrap:register_apps:apply');
+ $this->eventLogger->end('bootstrap:register_apps');
}
public function getRegistrationContext(): ?RegistrationContext {
@@ -178,7 +190,7 @@ class Coordinator {
* the instance was already created for register, but any other
* (legacy) code will now do their magic via the constructor.
*/
- $this->eventLogger->start('bootstrap:boot_app_' . $appId, '');
+ $this->eventLogger->start('bootstrap:boot_app:' . $appId, "Call `Application::boot` for $appId");
try {
/** @var App $application */
$application = $this->serverContainer->query($applicationClassName);
@@ -196,7 +208,7 @@ class Coordinator {
'exception' => $e,
]);
}
- $this->eventLogger->end('bootstrap:boot_app_' . $appId);
+ $this->eventLogger->end('bootstrap:boot_app:' . $appId);
}
public function isBootable(string $appId) {
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index ac162f6565e..1f32d6c5461 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -260,6 +260,9 @@ class Request implements \ArrayAccess, \Countable, IRequest {
: null;
case 'parameters':
case 'params':
+ if ($this->isPutStreamContent()) {
+ return $this->items['parameters'];
+ }
return $this->getContent();
default:
return isset($this[$name])
@@ -391,12 +394,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*/
protected function getContent() {
// If the content can't be parsed into an array then return a stream resource.
- if ($this->method === 'PUT'
- && $this->getHeader('Content-Length') !== '0'
- && $this->getHeader('Content-Length') !== ''
- && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
- && strpos($this->getHeader('Content-Type'), 'application/json') === false
- ) {
+ if ($this->isPutStreamContent()) {
if ($this->content === false) {
throw new \LogicException(
'"put" can only be accessed once if not '
@@ -411,6 +409,14 @@ class Request implements \ArrayAccess, \Countable, IRequest {
}
}
+ private function isPutStreamContent(): bool {
+ return $this->method === 'PUT'
+ && $this->getHeader('Content-Length') !== '0'
+ && $this->getHeader('Content-Length') !== ''
+ && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
+ && strpos($this->getHeader('Content-Type'), 'application/json') === false;
+ }
+
/**
* Attempt to decode the content and populate parameters
*/
diff --git a/lib/private/Authentication/Token/PublicKeyTokenMapper.php b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
index 7b11ef8adf3..8feb275b3b7 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenMapper.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
@@ -229,4 +229,31 @@ class PublicKeyTokenMapper extends QBMapper {
);
$update->executeStatement();
}
+
+ public function updateHashesForUser(string $userId, string $passwordHash): void {
+ $qb = $this->db->getQueryBuilder();
+ $update = $qb->update($this->getTableName())
+ ->set('password_hash', $qb->createNamedParameter($passwordHash))
+ ->where(
+ $qb->expr()->eq('uid', $qb->createNamedParameter($userId))
+ );
+ $update->executeStatement();
+ }
+
+ public function getFirstTokenForUser(string $userId): ?PublicKeyToken {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('uid', $qb->createNamedParameter($userId)))
+ ->setMaxResults(1)
+ ->orderBy('id');
+ $result = $qb->executeQuery();
+
+ $data = $result->fetch();
+ $result->closeCursor();
+ if ($data === false) {
+ return null;
+ }
+ return PublicKeyToken::fromRow($data);
+ }
}
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
index c8adec24b31..84708065070 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
@@ -46,6 +46,8 @@ use OCP\Security\IHasher;
use Psr\Log\LoggerInterface;
class PublicKeyTokenProvider implements IProvider {
+ public const TOKEN_MIN_LENGTH = 22;
+
use TTransactional;
/** @var PublicKeyTokenMapper */
@@ -98,13 +100,33 @@ class PublicKeyTokenProvider implements IProvider {
string $name,
int $type = IToken::TEMPORARY_TOKEN,
int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ if (strlen($token) < self::TOKEN_MIN_LENGTH) {
+ $exception = new InvalidTokenException('Token is too short, minimum of ' . self::TOKEN_MIN_LENGTH . ' characters is required, ' . strlen($token) . ' characters given');
+ $this->logger->error('Invalid token provided when generating new token', ['exception' => $exception]);
+ throw $exception;
+ }
+
if (mb_strlen($name) > 128) {
$name = mb_substr($name, 0, 120) . '…';
}
+ // We need to check against one old token to see if there is a password
+ // hash that we can reuse for detecting outdated passwords
+ $randomOldToken = $this->mapper->getFirstTokenForUser($uid);
+ $oldTokenMatches = $randomOldToken && $this->hasher->verify(sha1($password) . $password, $randomOldToken->getPasswordHash());
+
$dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);
+
+ if ($oldTokenMatches) {
+ $dbToken->setPasswordHash($randomOldToken->getPasswordHash());
+ }
+
$this->mapper->insert($dbToken);
+ if (!$oldTokenMatches && $password !== null) {
+ $this->updatePasswords($uid, $password);
+ }
+
// Add the token to the cache
$this->cache[$dbToken->getToken()] = $dbToken;
@@ -112,6 +134,27 @@ class PublicKeyTokenProvider implements IProvider {
}
public function getToken(string $tokenId): IToken {
+ /**
+ * Token length: 72
+ * @see \OC\Core\Controller\ClientFlowLoginController::generateAppPassword
+ * @see \OC\Core\Controller\AppPasswordController::getAppPassword
+ * @see \OC\Core\Command\User\AddAppPassword::execute
+ * @see \OC\Core\Service\LoginFlowV2Service::flowDone
+ * @see \OCA\Talk\MatterbridgeManager::generatePassword
+ * @see \OCA\Preferred_Providers\Controller\PasswordController::generateAppPassword
+ * @see \OCA\GlobalSiteSelector\TokenHandler::generateAppPassword
+ *
+ * Token length: 22-256 - https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length
+ * @see \OC\User\Session::createSessionToken
+ *
+ * Token length: 29
+ * @see \OCA\Settings\Controller\AuthSettingsController::generateRandomDeviceToken
+ * @see \OCA\Registration\Service\RegistrationService::generateAppPassword
+ */
+ if (strlen($tokenId) < self::TOKEN_MIN_LENGTH) {
+ throw new InvalidTokenException('Token is too short for a generated token, should be the password during basic auth');
+ }
+
$tokenHash = $this->hashToken($tokenId);
if (isset($this->cache[$tokenHash])) {
@@ -122,7 +165,7 @@ class PublicKeyTokenProvider implements IProvider {
$token = $this->cache[$tokenHash];
} else {
try {
- $token = $this->mapper->getToken($this->hashToken($tokenId));
+ $token = $this->mapper->getToken($tokenHash);
$this->cache[$token->getToken()] = $token;
} catch (DoesNotExistException $ex) {
try {
@@ -289,10 +332,11 @@ class PublicKeyTokenProvider implements IProvider {
// Update the password for all tokens
$tokens = $this->mapper->getTokenByUser($token->getUID());
+ $hashedPassword = $this->hashPassword($password);
foreach ($tokens as $t) {
$publicKey = $t->getPublicKey();
$t->setPassword($this->encryptPassword($password, $publicKey));
- $t->setPasswordHash($this->hashPassword($password));
+ $t->setPasswordHash($hashedPassword);
$this->updateToken($t);
}
}
@@ -481,6 +525,13 @@ class PublicKeyTokenProvider implements IProvider {
$this->updateToken($t);
}
}
+
+ // If password hashes are different we update them all to be equal so
+ // that the next execution only needs to verify once
+ if (count($hashNeedsUpdate) > 1) {
+ $newPasswordHash = $this->hashPassword($password);
+ $this->mapper->updateHashesForUser($uid, $newPasswordHash);
+ }
}
private function logOpensslError() {
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
index 4e6c7ea623f..95e49cdf860 100644
--- a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
+++ b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php
@@ -62,21 +62,21 @@ class FileReferenceProvider implements IReferenceProvider {
}
private function getFilesAppLinkId(string $referenceText): ?int {
- $start = $this->urlGenerator->getAbsoluteURL('/apps/files');
- $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/files');
+ $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);
+ 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);
+ parse_str($parts['query'] ?? '', $query);
$fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId;
$fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId;
}
diff --git a/lib/private/Config.php b/lib/private/Config.php
index ba3b8c6fe4d..7308a3769df 100644
--- a/lib/private/Config.php
+++ b/lib/private/Config.php
@@ -285,6 +285,13 @@ class Config {
'This can usually be fixed by giving the webserver write access to the config directory.');
}
+ // Never write file back if disk space should be too low
+ $df = disk_free_space($this->configDir);
+ $size = strlen($content) + 10240;
+ if ($df !== false && (int)$df < $size) {
+ throw new \Exception($this->configDir . " does not have enough space for writing the config file! Not writing it back!");
+ }
+
// Try to acquire a file lock
if (!flock($filePointer, LOCK_EX)) {
throw new \Exception(sprintf('Could not acquire an exclusive lock on the config file %s', $this->configFilePath));
diff --git a/lib/private/DB/BacktraceDebugStack.php b/lib/private/DB/BacktraceDebugStack.php
index be37e5a35da..6a19be89225 100644
--- a/lib/private/DB/BacktraceDebugStack.php
+++ b/lib/private/DB/BacktraceDebugStack.php
@@ -30,5 +30,6 @@ class BacktraceDebugStack extends DebugStack {
parent::startQuery($sql, $params, $types);
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$this->queries[$this->currentQuery]['backtrace'] = $backtrace;
+ $this->queries[$this->currentQuery]['start'] = $this->start;
}
}
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index 0e08d9d0e83..ae6481e45bb 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -26,6 +26,7 @@ namespace OC\Files\Config;
use OC\Hooks\Emitter;
use OC\Hooks\EmitterTrait;
+use OCP\Diagnostics\IEventLogger;
use OCP\Files\Config\IHomeMountProvider;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Config\IMountProviderCollection;
@@ -65,13 +66,29 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
/** @var callable[] */
private $mountFilters = [];
+ private IEventLogger $eventLogger;
+
/**
* @param \OCP\Files\Storage\IStorageFactory $loader
* @param IUserMountCache $mountCache
*/
- public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) {
+ public function __construct(
+ IStorageFactory $loader,
+ IUserMountCache $mountCache,
+ IEventLogger $eventLogger
+ ) {
$this->loader = $loader;
$this->mountCache = $mountCache;
+ $this->eventLogger = $eventLogger;
+ }
+
+ private function getMountsFromProvider(IMountProvider $provider, IUser $user, IStorageFactory $loader): array {
+ $class = str_replace('\\', '_', get_class($provider));
+ $uid = $user->getUID();
+ $this->eventLogger->start('fs:setup:provider:' . $class, "Getting mounts from $class for $uid");
+ $mounts = $provider->getMountsForUser($user, $loader) ?? [];
+ $this->eventLogger->end('fs:setup:provider:' . $class);
+ return $mounts;
}
/**
@@ -82,11 +99,8 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
private function getUserMountsForProviders(IUser $user, array $providers): array {
$loader = $this->loader;
$mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
- return $provider->getMountsForUser($user, $loader);
+ return $this->getMountsFromProvider($provider, $user, $loader);
}, $providers);
- $mounts = array_filter($mounts, function ($result) {
- return is_array($result);
- });
$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
return array_merge($mounts, $providerMounts);
}, []);
@@ -121,24 +135,22 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
});
foreach ($firstProviders as $provider) {
- $mounts = $provider->getMountsForUser($user, $this->loader);
- if (is_array($mounts)) {
- $firstMounts = array_merge($firstMounts, $mounts);
- }
+ $mounts = $this->getMountsFromProvider($provider, $user, $this->loader);
+ $firstMounts = array_merge($firstMounts, $mounts);
}
$firstMounts = $this->filterMounts($user, $firstMounts);
array_walk($firstMounts, [$mountManager, 'addMount']);
$lateMounts = [];
foreach ($lastProviders as $provider) {
- $mounts = $provider->getMountsForUser($user, $this->loader);
- if (is_array($mounts)) {
- $lateMounts = array_merge($lateMounts, $mounts);
- }
+ $mounts = $this->getMountsFromProvider($provider, $user, $this->loader);
+ $lateMounts = array_merge($lateMounts, $mounts);
}
$lateMounts = $this->filterMounts($user, $lateMounts);
+ $this->eventLogger->start("fs:setup:add-mounts", "Add mounts to the filesystem");
array_walk($lateMounts, [$mountManager, 'addMount']);
+ $this->eventLogger->end("fs:setup:add-mounts");
return array_merge($lateMounts, $firstMounts);
}
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index 3540b563742..fe677c5ea52 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -31,6 +31,7 @@ namespace OC\Files\Config;
use OCP\Cache\CappedMemoryCache;
use OCA\Files_Sharing\SharedMount;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Diagnostics\IEventLogger;
use OCP\Files\Config\ICachedMountFileInfo;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IUserMountCache;
@@ -56,19 +57,27 @@ class UserMountCache implements IUserMountCache {
private LoggerInterface $logger;
/** @var CappedMemoryCache<array> */
private CappedMemoryCache $cacheInfoCache;
+ private IEventLogger $eventLogger;
/**
* UserMountCache constructor.
*/
- public function __construct(IDBConnection $connection, IUserManager $userManager, LoggerInterface $logger) {
+ public function __construct(
+ IDBConnection $connection,
+ IUserManager $userManager,
+ LoggerInterface $logger,
+ IEventLogger $eventLogger
+ ) {
$this->connection = $connection;
$this->userManager = $userManager;
$this->logger = $logger;
+ $this->eventLogger = $eventLogger;
$this->cacheInfoCache = new CappedMemoryCache();
$this->mountsForUsers = new CappedMemoryCache();
}
public function registerMounts(IUser $user, array $mounts, array $mountProviderClasses = null) {
+ $this->eventLogger->start('fs:setup:user:register', 'Registering mounts for user');
// filter out non-proper storages coming from unit tests
$mounts = array_filter($mounts, function (IMountPoint $mount) {
return $mount instanceof SharedMount || ($mount->getStorage() && $mount->getStorage()->getCache());
@@ -134,6 +143,7 @@ class UserMountCache implements IUserMountCache {
foreach ($changedMounts as $mount) {
$this->updateCachedMount($mount);
}
+ $this->eventLogger->end('fs:setup:user:register');
}
/**
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 9ba0e504058..805cce658a6 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -184,8 +184,13 @@ class Manager implements IMountManager {
* @return IMountPoint[]
*/
public function findByNumericId(int $id): array {
- $storageId = \OC\Files\Cache\Storage::getStorageId($id);
- return $this->findByStorageId($storageId);
+ $result = [];
+ foreach ($this->mounts as $mount) {
+ if ($mount->getNumericStorageId() === $id) {
+ $result[] = $mount;
+ }
+ }
+ return $result;
}
/**
diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php
index 49f7e560ad3..20e08120080 100644
--- a/lib/private/Files/Mount/MountPoint.php
+++ b/lib/private/Files/Mount/MountPoint.php
@@ -44,6 +44,7 @@ class MountPoint implements IMountPoint {
protected $storage = null;
protected $class;
protected $storageId;
+ protected $numericStorageId = null;
protected $rootId = null;
/**
@@ -195,19 +196,15 @@ class MountPoint implements IMountPoint {
}
/**
- * @return string
+ * @return string|null
*/
public function getStorageId() {
if (!$this->storageId) {
- if (is_null($this->storage)) {
- $storage = $this->createStorage(); //FIXME: start using exceptions
- if (is_null($storage)) {
- return null;
- }
-
- $this->storage = $storage;
+ $storage = $this->getStorage();
+ if (is_null($storage)) {
+ return null;
}
- $this->storageId = $this->storage->getId();
+ $this->storageId = $storage->getId();
if (strlen($this->storageId) > 64) {
$this->storageId = md5($this->storageId);
}
@@ -219,7 +216,14 @@ class MountPoint implements IMountPoint {
* @return int
*/
public function getNumericStorageId() {
- return $this->getStorage()->getStorageCache()->getNumericId();
+ if (is_null($this->numericStorageId)) {
+ $storage = $this->getStorage();
+ if (is_null($storage)) {
+ return -1;
+ }
+ $this->numericStorageId = $storage->getStorageCache()->getNumericId();
+ }
+ return $this->numericStorageId;
}
/**
diff --git a/lib/private/Files/Node/File.php b/lib/private/Files/Node/File.php
index d8a6741dc6e..475930b361a 100644
--- a/lib/private/Files/Node/File.php
+++ b/lib/private/Files/Node/File.php
@@ -37,7 +37,7 @@ class File extends Node implements \OCP\Files\File {
* Creates a Folder that represents a non-existing path
*
* @param string $path path
- * @return string non-existing node class
+ * @return NonExistingFile non-existing node
*/
protected function createNonExistingNode($path) {
return new NonExistingFile($this->root, $this->view, $path);
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index bf9ae3c148d..90aed642a2d 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -54,7 +54,7 @@ class Folder extends Node implements \OCP\Files\Folder {
* Creates a Folder that represents a non-existing path
*
* @param string $path path
- * @return string non-existing node class
+ * @return NonExistingFolder non-existing node
*/
protected function createNonExistingNode($path) {
return new NonExistingFolder($this->root, $this->view, $path);
@@ -98,7 +98,7 @@ class Folder extends Node implements \OCP\Files\Folder {
* @throws \OCP\Files\NotFoundException
*/
public function getDirectoryListing() {
- $folderContent = $this->view->getDirectoryContent($this->path, '', $this->getFileInfo());
+ $folderContent = $this->view->getDirectoryContent($this->path, '', $this->getFileInfo(false));
return array_map(function (FileInfo $info) {
if ($info->getMimetype() === FileInfo::MIMETYPE_FOLDER) {
@@ -114,7 +114,7 @@ class Folder extends Node implements \OCP\Files\Folder {
* @param FileInfo $info
* @return File|Folder
*/
- protected function createNode($path, FileInfo $info = null) {
+ protected function createNode($path, FileInfo $info = null, bool $infoHasSubMountsIncluded = true) {
if (is_null($info)) {
$isDir = $this->view->is_dir($path);
} else {
@@ -122,7 +122,7 @@ class Folder extends Node implements \OCP\Files\Folder {
}
$parent = dirname($path) === $this->getPath() ? $this : null;
if ($isDir) {
- return new Folder($this->root, $this->view, $path, $info, $parent);
+ return new Folder($this->root, $this->view, $path, $info, $parent, $infoHasSubMountsIncluded);
} else {
return new File($this->root, $this->view, $path, $info, $parent);
}
diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php
index 6c4e0b0f908..2f88cc3a15a 100644
--- a/lib/private/Files/Node/Node.php
+++ b/lib/private/Files/Node/Node.php
@@ -56,35 +56,35 @@ class Node implements \OCP\Files\Node {
*/
protected $path;
- /**
- * @var \OCP\Files\FileInfo
- */
- protected $fileInfo;
+ protected ?FileInfo $fileInfo;
/**
* @var Node|null
*/
protected $parent;
+ private bool $infoHasSubMountsIncluded;
+
/**
* @param \OC\Files\View $view
* @param \OCP\Files\IRootFolder $root
* @param string $path
* @param FileInfo $fileInfo
*/
- public function __construct($root, $view, $path, $fileInfo = null, ?Node $parent = null) {
+ public function __construct($root, $view, $path, $fileInfo = null, ?Node $parent = null, bool $infoHasSubMountsIncluded = true) {
$this->view = $view;
$this->root = $root;
$this->path = $path;
$this->fileInfo = $fileInfo;
$this->parent = $parent;
+ $this->infoHasSubMountsIncluded = $infoHasSubMountsIncluded;
}
/**
* Creates a Node of the same type that represents a non-existing path
*
* @param string $path path
- * @return string non-existing node class
+ * @return Node non-existing node
* @throws \Exception
*/
protected function createNonExistingNode($path) {
@@ -98,17 +98,23 @@ class Node implements \OCP\Files\Node {
* @throws InvalidPathException
* @throws NotFoundException
*/
- public function getFileInfo() {
+ public function getFileInfo(bool $includeMountPoint = true) {
if (!$this->fileInfo) {
if (!Filesystem::isValidPath($this->path)) {
throw new InvalidPathException();
}
- $fileInfo = $this->view->getFileInfo($this->path);
+ $fileInfo = $this->view->getFileInfo($this->path, $includeMountPoint);
+ $this->infoHasSubMountsIncluded = $includeMountPoint;
if ($fileInfo instanceof FileInfo) {
$this->fileInfo = $fileInfo;
} else {
throw new NotFoundException();
}
+ } elseif ($includeMountPoint && !$this->infoHasSubMountsIncluded && $this instanceof Folder) {
+ if ($this->fileInfo instanceof \OC\Files\FileInfo) {
+ $this->view->addSubMounts($this->fileInfo);
+ }
+ $this->infoHasSubMountsIncluded = true;
}
return $this->fileInfo;
}
@@ -179,7 +185,7 @@ class Node implements \OCP\Files\Node {
* @return string
*/
public function getInternalPath() {
- return $this->getFileInfo()->getInternalPath();
+ return $this->getFileInfo(false)->getInternalPath();
}
/**
@@ -188,7 +194,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function getId() {
- return $this->getFileInfo()->getId();
+ return $this->getFileInfo(false)->getId() ?? -1;
}
/**
@@ -232,7 +238,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function getPermissions() {
- return $this->getFileInfo()->getPermissions();
+ return $this->getFileInfo(false)->getPermissions();
}
/**
@@ -241,7 +247,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function isReadable() {
- return $this->getFileInfo()->isReadable();
+ return $this->getFileInfo(false)->isReadable();
}
/**
@@ -250,7 +256,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function isUpdateable() {
- return $this->getFileInfo()->isUpdateable();
+ return $this->getFileInfo(false)->isUpdateable();
}
/**
@@ -259,7 +265,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function isDeletable() {
- return $this->getFileInfo()->isDeletable();
+ return $this->getFileInfo(false)->isDeletable();
}
/**
@@ -268,7 +274,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function isShareable() {
- return $this->getFileInfo()->isShareable();
+ return $this->getFileInfo(false)->isShareable();
}
/**
@@ -277,7 +283,7 @@ class Node implements \OCP\Files\Node {
* @throws NotFoundException
*/
public function isCreatable() {
- return $this->getFileInfo()->isCreatable();
+ return $this->getFileInfo(false)->isCreatable();
}
/**
@@ -328,42 +334,42 @@ class Node implements \OCP\Files\Node {
}
public function isMounted() {
- return $this->getFileInfo()->isMounted();
+ return $this->getFileInfo(false)->isMounted();
}
public function isShared() {
- return $this->getFileInfo()->isShared();
+ return $this->getFileInfo(false)->isShared();
}
public function getMimeType() {
- return $this->getFileInfo()->getMimetype();
+ return $this->getFileInfo(false)->getMimetype();
}
public function getMimePart() {
- return $this->getFileInfo()->getMimePart();
+ return $this->getFileInfo(false)->getMimePart();
}
public function getType() {
- return $this->getFileInfo()->getType();
+ return $this->getFileInfo(false)->getType();
}
public function isEncrypted() {
- return $this->getFileInfo()->isEncrypted();
+ return $this->getFileInfo(false)->isEncrypted();
}
public function getMountPoint() {
- return $this->getFileInfo()->getMountPoint();
+ return $this->getFileInfo(false)->getMountPoint();
}
public function getOwner() {
- return $this->getFileInfo()->getOwner();
+ return $this->getFileInfo(false)->getOwner();
}
public function getChecksum() {
}
public function getExtension(): string {
- return $this->getFileInfo()->getExtension();
+ return $this->getFileInfo(false)->getExtension();
}
/**
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index 8d0a65d2a68..29cdbb987c3 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -202,9 +202,9 @@ class Root extends Folder implements IRootFolder {
$path = $this->normalizePath($path);
if ($this->isValidPath($path)) {
$fullPath = $this->getFullPath($path);
- $fileInfo = $this->view->getFileInfo($fullPath);
+ $fileInfo = $this->view->getFileInfo($fullPath, false);
if ($fileInfo) {
- return $this->createNode($fullPath, $fileInfo);
+ return $this->createNode($fullPath, $fileInfo, false);
} else {
throw new NotFoundException($path);
}
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 979e4ce966a..4cbd0328d76 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -212,6 +212,8 @@ class SetupManager {
}
$this->setupUsersComplete[] = $user->getUID();
+ $this->eventLogger->start('fs:setup:user:full', 'Setup full filesystem for user');
+
if (!isset($this->setupUserMountProviders[$user->getUID()])) {
$this->setupUserMountProviders[$user->getUID()] = [];
}
@@ -226,6 +228,7 @@ class SetupManager {
});
});
$this->afterUserFullySetup($user, $previouslySetupProviders);
+ $this->eventLogger->end('fs:setup:user:full');
}
/**
@@ -237,6 +240,8 @@ class SetupManager {
}
$this->setupUsers[] = $user->getUID();
+ $this->eventLogger->start('fs:setup:user:onetime', 'Onetime filesystem for user');
+
$this->setupBuiltinWrappers();
$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
@@ -250,14 +255,18 @@ class SetupManager {
Filesystem::initInternal($userDir);
if ($this->lockdownManager->canAccessFilesystem()) {
+ $this->eventLogger->start('fs:setup:user:home', 'Setup home filesystem for user');
// home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
$homeMount = $this->mountProviderCollection->getHomeMountForUser($user);
$this->mountManager->addMount($homeMount);
if ($homeMount->getStorageRootId() === -1) {
+ $this->eventLogger->start('fs:setup:user:home:scan', 'Scan home filesystem for user');
$homeMount->getStorage()->mkdir('');
$homeMount->getStorage()->getScanner()->scan('');
+ $this->eventLogger->end('fs:setup:user:home:scan');
}
+ $this->eventLogger->end('fs:setup:user:home');
} else {
$this->mountManager->addMount(new MountPoint(
new NullStorage([]),
@@ -271,12 +280,15 @@ class SetupManager {
}
$this->listenForNewMountProviders();
+
+ $this->eventLogger->end('fs:setup:user:onetime');
}
/**
* Final housekeeping after a user has been fully setup
*/
private function afterUserFullySetup(IUser $user, array $previouslySetupProviders): void {
+ $this->eventLogger->start('fs:setup:user:full:post', 'Housekeeping after user is setup');
$userRoot = '/' . $user->getUID() . '/';
$mounts = $this->mountManager->getAll();
$mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
@@ -296,6 +308,7 @@ class SetupManager {
$this->cache->set($user->getUID(), true, $cacheDuration);
$this->fullSetupRequired[$user->getUID()] = false;
}
+ $this->eventLogger->end('fs:setup:user:full:post');
}
/**
@@ -312,17 +325,17 @@ class SetupManager {
$this->oneTimeUserSetup($user);
}
- $this->eventLogger->start('setup_fs', 'Setup filesystem');
-
if ($this->lockdownManager->canAccessFilesystem()) {
$mountCallback();
}
+ $this->eventLogger->start('fs:setup:user:post-init-mountpoint', 'post_initMountPoints legacy hook');
\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
+ $this->eventLogger->end('fs:setup:user:post-init-mountpoint');
$userDir = '/' . $user->getUID() . '/files';
+ $this->eventLogger->start('fs:setup:user:setup-hook', 'setup legacy hook');
OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
-
- $this->eventLogger->end('setup_fs');
+ $this->eventLogger->end('fs:setup:user:setup-hook');
}
/**
@@ -335,7 +348,7 @@ class SetupManager {
}
$this->rootSetup = true;
- $this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
+ $this->eventLogger->start('fs:setup:root', 'Setup root filesystem');
$this->setupBuiltinWrappers();
@@ -344,7 +357,7 @@ class SetupManager {
$this->mountManager->addMount($rootMountProvider);
}
- $this->eventLogger->end('setup_root_fs');
+ $this->eventLogger->end('fs:setup:root');
}
/**
@@ -413,6 +426,9 @@ class SetupManager {
$this->oneTimeUserSetup($user);
}
+ $this->eventLogger->start('fs:setup:user:path', "Setup $path filesystem for user");
+ $this->eventLogger->start('fs:setup:user:path:find', "Find mountpoint for $path");
+
$mounts = [];
if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
$currentProviders[] = $cachedMount->getMountProvider();
@@ -421,13 +437,16 @@ class SetupManager {
$mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]);
} else {
$this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
+ $this->eventLogger->end('fs:setup:user:path:find');
$this->setupForUser($user);
+ $this->eventLogger->end('fs:setup:user:path');
return;
}
}
if ($includeChildren) {
$subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
+ $this->eventLogger->end('fs:setup:user:path:find');
$needsFullSetup = array_reduce($subCachedMounts, function (bool $needsFullSetup, ICachedMountInfo $cachedMountInfo) {
return $needsFullSetup || $cachedMountInfo->getMountProvider() === '';
@@ -436,6 +455,7 @@ class SetupManager {
if ($needsFullSetup) {
$this->logger->debug("mount has no provider set, performing full setup");
$this->setupForUser($user);
+ $this->eventLogger->end('fs:setup:user:path');
return;
} else {
foreach ($subCachedMounts as $cachedMount) {
@@ -446,6 +466,8 @@ class SetupManager {
}
}
}
+ } else {
+ $this->eventLogger->end('fs:setup:user:path:find');
}
if (count($mounts)) {
@@ -456,6 +478,7 @@ class SetupManager {
} elseif (!$this->isSetupStarted($user)) {
$this->oneTimeUserSetup($user);
}
+ $this->eventLogger->end('fs:setup:user:path');
}
private function fullSetupRequired(IUser $user): bool {
@@ -488,6 +511,8 @@ class SetupManager {
return;
}
+ $this->eventLogger->start('fs:setup:user:providers', "Setup filesystem for " . implode(', ', $providers));
+
// home providers are always used
$providers = array_filter($providers, function (string $provider) {
return !is_subclass_of($provider, IHomeMountProvider::class);
@@ -504,6 +529,7 @@ class SetupManager {
if (!$this->isSetupStarted($user)) {
$this->oneTimeUserSetup($user);
}
+ $this->eventLogger->end('fs:setup:user:providers');
return;
} else {
$this->setupUserMountProviders[$user->getUID()] = array_merge($setupProviders, $providers);
@@ -514,6 +540,7 @@ class SetupManager {
$this->setupForUserWith($user, function () use ($mounts) {
array_walk($mounts, [$this->mountManager, 'addMount']);
});
+ $this->eventLogger->end('fs:setup:user:providers');
}
public function tearDown() {
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index f79a992c773..456f804ee56 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -1412,11 +1412,7 @@ class View {
if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
//add the sizes of other mount points to the folder
$extOnly = ($includeMountPoints === 'ext');
- $mounts = Filesystem::getMountManager()->findIn($path);
- $info->setSubMounts(array_filter($mounts, function (IMountPoint $mount) use ($extOnly) {
- $subStorage = $mount->getStorage();
- return !($extOnly && $subStorage instanceof \OCA\Files_Sharing\SharedStorage);
- }));
+ $this->addSubMounts($info, $extOnly);
}
}
@@ -1429,6 +1425,17 @@ class View {
}
/**
+ * Extend a FileInfo that was previously requested with `$includeMountPoints = false` to include the sub mounts
+ */
+ public function addSubMounts(FileInfo $info, $extOnly = false): void {
+ $mounts = Filesystem::getMountManager()->findIn($info->getPath());
+ $info->setSubMounts(array_filter($mounts, function (IMountPoint $mount) use ($extOnly) {
+ $subStorage = $mount->getStorage();
+ return !($extOnly && $subStorage instanceof \OCA\Files_Sharing\SharedStorage);
+ }));
+ }
+
+ /**
* get the content of a directory
*
* @param string $directory path under datadirectory
diff --git a/lib/private/Preview/IMagickSupport.php b/lib/private/Preview/IMagickSupport.php
new file mode 100644
index 00000000000..e22ae93ab94
--- /dev/null
+++ b/lib/private/Preview/IMagickSupport.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace OC\Preview;
+
+use OCP\ICache;
+use OCP\ICacheFactory;
+
+class IMagickSupport {
+ private ICache $cache;
+ private ?\Imagick $imagick;
+
+ public function __construct(ICacheFactory $cacheFactory) {
+ $this->cache = $cacheFactory->createLocal('imagick');
+
+ if (extension_loaded('imagick')) {
+ $this->imagick = new \Imagick();
+ } else {
+ $this->imagick = null;
+ }
+ }
+
+ public function hasExtension(): bool {
+ return !is_null($this->imagick);
+ }
+
+ public function supportsFormat(string $format): bool {
+ if (is_null($this->imagick)) {
+ return false;
+ }
+
+ $cached = $this->cache->get($format);
+ if (!is_null($cached)) {
+ return $cached;
+ }
+
+ $formatSupported = count($this->imagick->queryFormats($format)) === 1;
+ $this->cache->set($format, $cached);
+ return $formatSupported;
+ }
+}
diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php
index 367f0c1c057..dd6b6ba8ee1 100644
--- a/lib/private/PreviewManager.php
+++ b/lib/private/PreviewManager.php
@@ -33,6 +33,7 @@ namespace OC;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\Preview\Generator;
use OC\Preview\GeneratorHelper;
+use OC\Preview\IMagickSupport;
use OCP\AppFramework\QueryException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
@@ -73,6 +74,7 @@ class PreviewManager implements IPreview {
private array $loadedBootstrapProviders = [];
private IServerContainer $container;
private IBinaryFinder $binaryFinder;
+ private IMagickSupport $imagickSupport;
public function __construct(
IConfig $config,
@@ -84,7 +86,8 @@ class PreviewManager implements IPreview {
?string $userId,
Coordinator $bootstrapCoordinator,
IServerContainer $container,
- IBinaryFinder $binaryFinder
+ IBinaryFinder $binaryFinder,
+ IMagickSupport $imagickSupport
) {
$this->config = $config;
$this->rootFolder = $rootFolder;
@@ -96,6 +99,7 @@ class PreviewManager implements IPreview {
$this->bootstrapCoordinator = $bootstrapCoordinator;
$this->container = $container;
$this->binaryFinder = $binaryFinder;
+ $this->imagickSupport = $imagickSupport;
}
/**
@@ -368,9 +372,7 @@ class PreviewManager implements IPreview {
$this->registerCoreProvider(Preview\Imaginary::class, Preview\Imaginary::supportedMimeTypes());
// SVG, Office and Bitmap require imagick
- if (extension_loaded('imagick')) {
- $checkImagick = new \Imagick();
-
+ if ($this->imagickSupport->hasExtension()) {
$imagickProviders = [
'SVG' => ['mimetype' => '/image\/svg\+xml/', 'class' => Preview\SVG::class],
'TIFF' => ['mimetype' => '/image\/tiff/', 'class' => Preview\TIFF::class],
@@ -390,12 +392,12 @@ class PreviewManager implements IPreview {
continue;
}
- if (count($checkImagick->queryFormats($queryFormat)) === 1) {
+ if ($this->imagickSupport->supportsFormat($queryFormat)) {
$this->registerCoreProvider($class, $provider['mimetype']);
}
}
- if (count($checkImagick->queryFormats('PDF')) === 1) {
+ if ($this->imagickSupport->supportsFormat('PDF')) {
// Office requires openoffice or libreoffice
$officeBinary = $this->config->getSystemValue('preview_libreoffice_path', null);
if (!is_string($officeBinary)) {
diff --git a/lib/private/Route/CachingRouter.php b/lib/private/Route/CachingRouter.php
index f65060e710b..69fb3c986c9 100644
--- a/lib/private/Route/CachingRouter.php
+++ b/lib/private/Route/CachingRouter.php
@@ -24,20 +24,27 @@
*/
namespace OC\Route;
+use OCP\Diagnostics\IEventLogger;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+use OCP\IRequest;
+use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
class CachingRouter extends Router {
- /**
- * @var \OCP\ICache
- */
- protected $cache;
+ protected ICache $cache;
- /**
- * @param \OCP\ICache $cache
- */
- public function __construct($cache, LoggerInterface $logger) {
- $this->cache = $cache;
- parent::__construct($logger);
+ public function __construct(
+ ICacheFactory $cacheFactory,
+ LoggerInterface $logger,
+ IRequest $request,
+ IConfig $config,
+ IEventLogger $eventLogger,
+ ContainerInterface $container
+ ) {
+ $this->cache = $cacheFactory->createLocal('route');
+ parent::__construct($logger, $request, $config, $eventLogger, $container);
}
/**
diff --git a/lib/private/Route/Router.php b/lib/private/Route/Router.php
index 7e1acd49800..e2a092d861e 100644
--- a/lib/private/Route/Router.php
+++ b/lib/private/Route/Router.php
@@ -34,8 +34,12 @@ namespace OC\Route;
use OC\AppFramework\Routing\RouteParser;
use OCP\AppFramework\App;
+use OCP\Diagnostics\IEventLogger;
+use OCP\IConfig;
+use OCP\IRequest;
use OCP\Route\IRouter;
use OCP\Util;
+use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
@@ -64,11 +68,21 @@ class Router implements IRouter {
protected LoggerInterface $logger;
/** @var RequestContext */
protected $context;
-
- public function __construct(LoggerInterface $logger) {
+ private IEventLogger $eventLogger;
+ private IConfig $config;
+ private ContainerInterface $container;
+
+ public function __construct(
+ LoggerInterface $logger,
+ IRequest $request,
+ IConfig $config,
+ IEventLogger $eventLogger,
+ ContainerInterface $container
+ ) {
$this->logger = $logger;
+ $this->config = $config;
$baseUrl = \OC::$WEBROOT;
- if (!(\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
+ if (!($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
$baseUrl .= '/index.php';
}
if (!\OC::$CLI && isset($_SERVER['REQUEST_METHOD'])) {
@@ -76,12 +90,13 @@ class Router implements IRouter {
} else {
$method = 'GET';
}
- $request = \OC::$server->getRequest();
$host = $request->getServerHost();
$schema = $request->getServerProtocol();
$this->context = new RequestContext($baseUrl, $method, $host, $schema);
// TODO cache
$this->root = $this->getCollection('root');
+ $this->eventLogger = $eventLogger;
+ $this->container = $container;
}
/**
@@ -134,7 +149,7 @@ class Router implements IRouter {
$routingFiles = [];
}
}
- \OC::$server->getEventLogger()->start('loadroutes' . $requestedApp, 'Loading Routes');
+ $this->eventLogger->start('route:load:' . $requestedApp, 'Loading Routes for ' . $requestedApp);
foreach ($routingFiles as $app => $file) {
if (!isset($this->loadedApps[$app])) {
if (!\OC_App::isAppLoaded($app)) {
@@ -170,7 +185,7 @@ class Router implements IRouter {
$collection->addPrefix('/ocs');
$this->root->addCollection($collection);
}
- \OC::$server->getEventLogger()->end('loadroutes' . $requestedApp);
+ $this->eventLogger->end('route:load:' . $requestedApp);
}
/**
@@ -231,6 +246,7 @@ class Router implements IRouter {
* @return array
*/
public function findMatchingRoute(string $url): array {
+ $this->eventLogger->start('route:match', 'Match route');
if (substr($url, 0, 6) === '/apps/') {
// empty string / 'apps' / $app / rest of the route
[, , $app,] = explode('/', $url, 4);
@@ -249,7 +265,7 @@ class Router implements IRouter {
$this->loadRoutes('settings');
} elseif (substr($url, 0, 6) === '/core/') {
\OC::$REQUESTEDAPP = $url;
- if (!\OC::$server->getConfig()->getSystemValueBool('maintenance') && !Util::needUpgrade()) {
+ if (!$this->config->getSystemValueBool('maintenance') && !Util::needUpgrade()) {
\OC_App::loadApps();
}
$this->loadRoutes('core');
@@ -276,6 +292,7 @@ class Router implements IRouter {
}
}
+ $this->eventLogger->end('route:match');
return $parameters;
}
@@ -289,7 +306,7 @@ class Router implements IRouter {
public function match($url) {
$parameters = $this->findMatchingRoute($url);
- \OC::$server->getEventLogger()->start('run_route', 'Run route');
+ $this->eventLogger->start('route:run', 'Run route');
if (isset($parameters['caller'])) {
$caller = $parameters['caller'];
unset($parameters['caller']);
@@ -303,13 +320,15 @@ class Router implements IRouter {
}
unset($parameters['action']);
unset($parameters['caller']);
+ $this->eventLogger->start('route:run:call', 'Run callable route');
call_user_func($action, $parameters);
+ $this->eventLogger->end('route:run:call');
} elseif (isset($parameters['file'])) {
include $parameters['file'];
} else {
throw new \Exception('no action available');
}
- \OC::$server->getEventLogger()->end('run_route');
+ $this->eventLogger->end('route:run');
}
/**
@@ -434,7 +453,7 @@ class Router implements IRouter {
$applicationClassName = $appNameSpace . '\\AppInfo\\Application';
if (class_exists($applicationClassName)) {
- $application = \OC::$server->query($applicationClassName);
+ $application = $this->container->get($applicationClassName);
} else {
$application = new App($appName);
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index bd33cdf58bd..35f63686457 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -86,6 +86,7 @@ use OC\EventDispatcher\SymfonyAdapter;
use OC\Federation\CloudFederationFactory;
use OC\Federation\CloudFederationProviderManager;
use OC\Federation\CloudIdManager;
+use OC\Files\Config\MountProviderCollection;
use OC\Files\Config\UserMountCache;
use OC\Files\Config\UserMountCacheListener;
use OC\Files\Lock\LockManager;
@@ -126,9 +127,11 @@ use OC\Metadata\MetadataManager;
use OC\Notification\Manager;
use OC\OCS\DiscoveryService;
use OC\Preview\GeneratorHelper;
+use OC\Preview\IMagickSupport;
use OC\Remote\Api\ApiFactory;
use OC\Remote\InstanceFactory;
use OC\RichObjectStrings\Validator;
+use OC\Route\CachingRouter;
use OC\Route\Router;
use OC\Security\Bruteforce\Throttler;
use OC\Security\CertificateManager;
@@ -336,7 +339,8 @@ class Server extends ServerContainer implements IServerContainer {
$c->get(ISession::class)->get('user_id'),
$c->get(Coordinator::class),
$c->get(IServerContainer::class),
- $c->get(IBinaryFinder::class)
+ $c->get(IBinaryFinder::class),
+ $c->get(IMagickSupport::class)
);
});
/** @deprecated 19.0.0 */
@@ -819,11 +823,10 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(Router::class, function (Server $c) {
$cacheFactory = $c->get(ICacheFactory::class);
- $logger = $c->get(LoggerInterface::class);
if ($cacheFactory->isLocalCacheAvailable()) {
- $router = new \OC\Route\CachingRouter($cacheFactory->createLocal('route'), $logger);
+ $router = $c->resolve(CachingRouter::class);
} else {
- $router = new \OC\Route\Router($logger);
+ $router = $c->resolve(Router::class);
}
return $router;
});
@@ -946,11 +949,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerDeprecatedAlias('DateTimeFormatter', IDateTimeFormatter::class);
$this->registerService(IUserMountCache::class, function (ContainerInterface $c) {
- $mountCache = new UserMountCache(
- $c->get(IDBConnection::class),
- $c->get(IUserManager::class),
- $c->get(LoggerInterface::class)
- );
+ $mountCache = $c->get(UserMountCache::class);
$listener = new UserMountCacheListener($mountCache);
$listener->listen($c->get(IUserManager::class));
return $mountCache;
@@ -959,9 +958,10 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerDeprecatedAlias('UserMountCache', IUserMountCache::class);
$this->registerService(IMountProviderCollection::class, function (ContainerInterface $c) {
- $loader = \OC\Files\Filesystem::getLoader();
+ $loader = $c->get(IStorageFactory::class);
$mountCache = $c->get(IUserMountCache::class);
- $manager = new \OC\Files\Config\MountProviderCollection($loader, $mountCache);
+ $eventLogger = $c->get(IEventLogger::class);
+ $manager = new MountProviderCollection($loader, $mountCache, $eventLogger);
// builtin providers
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 5a4cd32e5df..d127443944f 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -130,7 +130,7 @@ class TemplateLayout extends \OC_Template {
$navigation = $this->navigationManager->getAll();
$this->assign('navigation', $navigation);
$settingsNavigation = $this->navigationManager->getAll('settings');
- $this->assign('settingsnavigation', $settingsNavigation);
+ $this->initialState->provideInitialState('core', 'settingsNavEntries', $settingsNavigation);
foreach ($navigation as $entry) {
if ($entry['active']) {
@@ -268,7 +268,7 @@ class TemplateLayout extends \OC_Template {
$this->assign('cssfiles', []);
$this->assign('printcssfiles', []);
- $this->assign('versionHash', self::$versionHash);
+ $this->initialState->provideInitialState('core', 'versionHash', self::$versionHash);
foreach ($cssFiles as $info) {
$web = $info[1];
$file = $info[2];
diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php
index c4c2f089767..7f51d81d21b 100644
--- a/lib/private/legacy/OC_App.php
+++ b/lib/private/legacy/OC_App.php
@@ -158,12 +158,17 @@ class OC_App {
* @param string $app
* @throws Exception
*/
- public static function loadApp(string $app) {
+ public static function loadApp(string $app): void {
+ if (isset(self::$loadedApps[$app])) {
+ return;
+ }
self::$loadedApps[$app] = true;
$appPath = self::getAppPath($app);
if ($appPath === false) {
return;
}
+ $eventLogger = \OC::$server->get(\OCP\Diagnostics\IEventLogger::class);
+ $eventLogger->start("bootstrap:load_app:$app", "Load $app");
// in case someone calls loadApp() directly
self::registerAutoloading($app, $appPath);
@@ -174,12 +179,12 @@ class OC_App {
$hasAppPhpFile = is_file($appPath . '/appinfo/app.php');
- \OC::$server->getEventLogger()->start('bootstrap:load_app_' . $app, 'Load app: ' . $app);
if ($isBootable && $hasAppPhpFile) {
\OC::$server->getLogger()->error('/appinfo/app.php is not loaded when \OCP\AppFramework\Bootstrap\IBootstrap on the application class is used. Migrate everything from app.php to the Application class.', [
'app' => $app,
]);
} elseif ($hasAppPhpFile) {
+ $eventLogger->start("bootstrap:load_app:$app:app.php", "Load legacy app.php app $app");
\OC::$server->getLogger()->debug('/appinfo/app.php is deprecated, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead.', [
'app' => $app,
]);
@@ -202,11 +207,12 @@ class OC_App {
]);
}
}
+ $eventLogger->end("bootstrap:load_app:$app:app.php");
}
- \OC::$server->getEventLogger()->end('bootstrap:load_app_' . $app);
$coordinator->bootApp($app);
+ $eventLogger->start("bootstrap:load_app:$app:info", "Load info.xml for $app and register any services defined in it");
$info = self::getAppInfo($app);
if (!empty($info['activity']['filters'])) {
foreach ($info['activity']['filters'] as $filter) {
@@ -261,6 +267,10 @@ class OC_App {
}
}
}
+
+ $eventLogger->end("bootstrap:load_app:$app:info");
+
+ $eventLogger->end("bootstrap:load_app:$app");
}
/**
diff --git a/lib/public/AppFramework/Controller.php b/lib/public/AppFramework/Controller.php
index 89cfd2e55fc..e8500d5ae1a 100644
--- a/lib/public/AppFramework/Controller.php
+++ b/lib/public/AppFramework/Controller.php
@@ -91,6 +91,9 @@ abstract class Controller {
if ($data->getLastModified() !== null) {
$response->setLastModified($data->getLastModified());
}
+ if ($data->isThrottled()) {
+ $response->throttle($data->getThrottleMetadata());
+ }
return $response;
}
diff --git a/lib/public/Files/Mount/IMountPoint.php b/lib/public/Files/Mount/IMountPoint.php
index b8e7ec9118f..1272550d737 100644
--- a/lib/public/Files/Mount/IMountPoint.php
+++ b/lib/public/Files/Mount/IMountPoint.php
@@ -55,7 +55,7 @@ interface IMountPoint {
/**
* Get the id of the storages
*
- * @return string
+ * @return string|null
* @since 8.0.0
*/
public function getStorageId();
@@ -63,7 +63,7 @@ interface IMountPoint {
/**
* Get the id of the storages
*
- * @return int
+ * @return int|null
* @since 9.1.0
*/
public function getNumericStorageId();