From 781784553889601d02553931aed8ff1fde95640b Mon Sep 17 00:00:00 2001
From: Carl Schwan <carl@carlschwan.eu>
Date: Mon, 4 Apr 2022 23:15:00 +0200
Subject: Add a metadata service to store file metadata

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
---
 lib/composer/composer/InstalledVersions.php    |   4 +-
 lib/composer/composer/LICENSE                  |   2 -
 lib/composer/composer/autoload_classmap.php    |  11 ++-
 lib/composer/composer/autoload_namespaces.php  |   2 +-
 lib/composer/composer/autoload_psr4.php        |   2 +-
 lib/composer/composer/autoload_real.php        |  25 +++++-
 lib/composer/composer/autoload_static.php      |   9 +++
 lib/composer/composer/installed.php            |   4 +-
 lib/private/Files/ObjectStore/NoopScanner.php  |   2 +-
 lib/private/Metadata/Capabilities.php          |  44 +++++++++++
 lib/private/Metadata/FileEventListener.php     |  84 ++++++++++++++++++++
 lib/private/Metadata/FileMetadata.php          |  43 ++++++++++
 lib/private/Metadata/FileMetadataMapper.php    | 105 +++++++++++++++++++++++++
 lib/private/Metadata/IMetadataManager.php      |  35 +++++++++
 lib/private/Metadata/IMetadataProvider.php     |  41 ++++++++++
 lib/private/Metadata/MetadataManager.php       | 100 +++++++++++++++++++++++
 lib/private/Metadata/Provider/ExifProvider.php |  51 ++++++++++++
 lib/private/Server.php                         |  12 ++-
 lib/public/AppFramework/Db/Entity.php          |   4 +
 lib/public/AppFramework/Db/QBMapper.php        |   2 +
 lib/public/DB/QueryBuilder/IQueryBuilder.php   |   5 ++
 lib/public/DB/Types.php                        |   6 ++
 22 files changed, 576 insertions(+), 17 deletions(-)
 create mode 100644 lib/private/Metadata/Capabilities.php
 create mode 100644 lib/private/Metadata/FileEventListener.php
 create mode 100644 lib/private/Metadata/FileMetadata.php
 create mode 100644 lib/private/Metadata/FileMetadataMapper.php
 create mode 100644 lib/private/Metadata/IMetadataManager.php
 create mode 100644 lib/private/Metadata/IMetadataProvider.php
 create mode 100644 lib/private/Metadata/MetadataManager.php
 create mode 100644 lib/private/Metadata/Provider/ExifProvider.php

(limited to 'lib')

diff --git a/lib/composer/composer/InstalledVersions.php b/lib/composer/composer/InstalledVersions.php
index d50e0c9fcc4..fc50a9f8622 100644
--- a/lib/composer/composer/InstalledVersions.php
+++ b/lib/composer/composer/InstalledVersions.php
@@ -264,7 +264,7 @@ class InstalledVersions
         if (null === self::$installed) {
             // only require the installed.php file if this file is loaded from its dumped location,
             // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
-            if (substr(__DIR__, -8, 1) !== 'C') {
+            if (substr(__DIR__, -8, 1) !== 'C' && is_file(__DIR__ . '/installed.php')) {
                 self::$installed = include __DIR__ . '/installed.php';
             } else {
                 self::$installed = array();
@@ -337,7 +337,7 @@ class InstalledVersions
         if (null === self::$installed) {
             // only require the installed.php file if this file is loaded from its dumped location,
             // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
-            if (substr(__DIR__, -8, 1) !== 'C') {
+            if (substr(__DIR__, -8, 1) !== 'C' && is_file(__DIR__ . '/installed.php')) {
                 self::$installed = require __DIR__ . '/installed.php';
             } else {
                 self::$installed = array();
diff --git a/lib/composer/composer/LICENSE b/lib/composer/composer/LICENSE
index f27399a042d..62ecfd8d004 100644
--- a/lib/composer/composer/LICENSE
+++ b/lib/composer/composer/LICENSE
@@ -1,4 +1,3 @@
-
 Copyright (c) Nils Adermann, Jordi Boggiano
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -18,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
-
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index acc0f6bf2ad..be40cd4c607 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -2,7 +2,7 @@
 
 // autoload_classmap.php @generated by Composer
 
-$vendorDir = dirname(__DIR__);
+$vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
@@ -1021,6 +1021,7 @@ return array(
     'OC\\Core\\Migrations\\Version23000Date20211203110726' => $baseDir . '/core/Migrations/Version23000Date20211203110726.php',
     'OC\\Core\\Migrations\\Version23000Date20211213203940' => $baseDir . '/core/Migrations/Version23000Date20211213203940.php',
     'OC\\Core\\Migrations\\Version240000Date20220202150027' => $baseDir . '/core/Migrations/Version240000Date20220202150027.php',
+    'OC\\Core\\Migrations\\Version240000Date20220404230027' => $baseDir . '/core/Migrations/Version240000Date20220404230027.php',
     'OC\\Core\\Migrations\\Version24000Date20211210141942' => $baseDir . '/core/Migrations/Version24000Date20211210141942.php',
     'OC\\Core\\Migrations\\Version24000Date20211213081506' => $baseDir . '/core/Migrations/Version24000Date20211213081506.php',
     'OC\\Core\\Migrations\\Version24000Date20211213081604' => $baseDir . '/core/Migrations/Version24000Date20211213081604.php',
@@ -1302,6 +1303,14 @@ return array(
     'OC\\Memcache\\ProfilerWrapperCache' => $baseDir . '/lib/private/Memcache/ProfilerWrapperCache.php',
     'OC\\Memcache\\Redis' => $baseDir . '/lib/private/Memcache/Redis.php',
     'OC\\MemoryInfo' => $baseDir . '/lib/private/MemoryInfo.php',
+    'OC\\Metadata\\Capabilities' => $baseDir . '/lib/private/Metadata/Capabilities.php',
+    'OC\\Metadata\\FileEventListener' => $baseDir . '/lib/private/Metadata/FileEventListener.php',
+    'OC\\Metadata\\FileMetadata' => $baseDir . '/lib/private/Metadata/FileMetadata.php',
+    'OC\\Metadata\\FileMetadataMapper' => $baseDir . '/lib/private/Metadata/FileMetadataMapper.php',
+    'OC\\Metadata\\IMetadataManager' => $baseDir . '/lib/private/Metadata/IMetadataManager.php',
+    'OC\\Metadata\\IMetadataProvider' => $baseDir . '/lib/private/Metadata/IMetadataProvider.php',
+    'OC\\Metadata\\MetadataManager' => $baseDir . '/lib/private/Metadata/MetadataManager.php',
+    'OC\\Metadata\\Provider\\ExifProvider' => $baseDir . '/lib/private/Metadata/Provider/ExifProvider.php',
     'OC\\Migration\\BackgroundRepair' => $baseDir . '/lib/private/Migration/BackgroundRepair.php',
     'OC\\Migration\\ConsoleOutput' => $baseDir . '/lib/private/Migration/ConsoleOutput.php',
     'OC\\Migration\\SimpleOutput' => $baseDir . '/lib/private/Migration/SimpleOutput.php',
diff --git a/lib/composer/composer/autoload_namespaces.php b/lib/composer/composer/autoload_namespaces.php
index f1ae7a0ffec..4a9c20beed0 100644
--- a/lib/composer/composer/autoload_namespaces.php
+++ b/lib/composer/composer/autoload_namespaces.php
@@ -2,7 +2,7 @@
 
 // autoload_namespaces.php @generated by Composer
 
-$vendorDir = dirname(__DIR__);
+$vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
diff --git a/lib/composer/composer/autoload_psr4.php b/lib/composer/composer/autoload_psr4.php
index 74e48cf69ae..b641d9c6a03 100644
--- a/lib/composer/composer/autoload_psr4.php
+++ b/lib/composer/composer/autoload_psr4.php
@@ -2,7 +2,7 @@
 
 // autoload_psr4.php @generated by Composer
 
-$vendorDir = dirname(__DIR__);
+$vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
diff --git a/lib/composer/composer/autoload_real.php b/lib/composer/composer/autoload_real.php
index 4b1ab7678ec..a5748c7a891 100644
--- a/lib/composer/composer/autoload_real.php
+++ b/lib/composer/composer/autoload_real.php
@@ -23,11 +23,30 @@ class ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c
         }
 
         spl_autoload_register(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader'), true, true);
-        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
         spl_autoload_unregister(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader'));
 
-        require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader)();
+        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+        if ($useStaticLoader) {
+            require __DIR__ . '/autoload_static.php';
+
+            call_user_func(\Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader));
+        } else {
+            $map = require __DIR__ . '/autoload_namespaces.php';
+            foreach ($map as $namespace => $path) {
+                $loader->set($namespace, $path);
+            }
+
+            $map = require __DIR__ . '/autoload_psr4.php';
+            foreach ($map as $namespace => $path) {
+                $loader->setPsr4($namespace, $path);
+            }
+
+            $classMap = require __DIR__ . '/autoload_classmap.php';
+            if ($classMap) {
+                $loader->addClassMap($classMap);
+            }
+        }
 
         $loader->register(true);
 
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 09e8d3a627e..7e778d73b83 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -1050,6 +1050,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OC\\Core\\Migrations\\Version23000Date20211203110726' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20211203110726.php',
         'OC\\Core\\Migrations\\Version23000Date20211213203940' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20211213203940.php',
         'OC\\Core\\Migrations\\Version240000Date20220202150027' => __DIR__ . '/../../..' . '/core/Migrations/Version240000Date20220202150027.php',
+        'OC\\Core\\Migrations\\Version240000Date20220404230027' => __DIR__ . '/../../..' . '/core/Migrations/Version240000Date20220404230027.php',
         'OC\\Core\\Migrations\\Version24000Date20211210141942' => __DIR__ . '/../../..' . '/core/Migrations/Version24000Date20211210141942.php',
         'OC\\Core\\Migrations\\Version24000Date20211213081506' => __DIR__ . '/../../..' . '/core/Migrations/Version24000Date20211213081506.php',
         'OC\\Core\\Migrations\\Version24000Date20211213081604' => __DIR__ . '/../../..' . '/core/Migrations/Version24000Date20211213081604.php',
@@ -1331,6 +1332,14 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OC\\Memcache\\ProfilerWrapperCache' => __DIR__ . '/../../..' . '/lib/private/Memcache/ProfilerWrapperCache.php',
         'OC\\Memcache\\Redis' => __DIR__ . '/../../..' . '/lib/private/Memcache/Redis.php',
         'OC\\MemoryInfo' => __DIR__ . '/../../..' . '/lib/private/MemoryInfo.php',
+        'OC\\Metadata\\Capabilities' => __DIR__ . '/../../..' . '/lib/private/Metadata/Capabilities.php',
+        'OC\\Metadata\\FileEventListener' => __DIR__ . '/../../..' . '/lib/private/Metadata/FileEventListener.php',
+        'OC\\Metadata\\FileMetadata' => __DIR__ . '/../../..' . '/lib/private/Metadata/FileMetadata.php',
+        'OC\\Metadata\\FileMetadataMapper' => __DIR__ . '/../../..' . '/lib/private/Metadata/FileMetadataMapper.php',
+        'OC\\Metadata\\IMetadataManager' => __DIR__ . '/../../..' . '/lib/private/Metadata/IMetadataManager.php',
+        'OC\\Metadata\\IMetadataProvider' => __DIR__ . '/../../..' . '/lib/private/Metadata/IMetadataProvider.php',
+        'OC\\Metadata\\MetadataManager' => __DIR__ . '/../../..' . '/lib/private/Metadata/MetadataManager.php',
+        'OC\\Metadata\\Provider\\ExifProvider' => __DIR__ . '/../../..' . '/lib/private/Metadata/Provider/ExifProvider.php',
         'OC\\Migration\\BackgroundRepair' => __DIR__ . '/../../..' . '/lib/private/Migration/BackgroundRepair.php',
         'OC\\Migration\\ConsoleOutput' => __DIR__ . '/../../..' . '/lib/private/Migration/ConsoleOutput.php',
         'OC\\Migration\\SimpleOutput' => __DIR__ . '/../../..' . '/lib/private/Migration/SimpleOutput.php',
diff --git a/lib/composer/composer/installed.php b/lib/composer/composer/installed.php
index f12a8e00dbe..67a1ddfbd8c 100644
--- a/lib/composer/composer/installed.php
+++ b/lib/composer/composer/installed.php
@@ -5,7 +5,7 @@
         'type' => 'library',
         'install_path' => __DIR__ . '/../../../',
         'aliases' => array(),
-        'reference' => '1225189f74d06606aafc4150d07584b90cea50dd',
+        'reference' => '42c7886f80c7a5e767b192d07474114dd0848b16',
         'name' => '__root__',
         'dev' => false,
     ),
@@ -16,7 +16,7 @@
             'type' => 'library',
             'install_path' => __DIR__ . '/../../../',
             'aliases' => array(),
-            'reference' => '1225189f74d06606aafc4150d07584b90cea50dd',
+            'reference' => '42c7886f80c7a5e767b192d07474114dd0848b16',
             'dev_requirement' => false,
         ),
     ),
diff --git a/lib/private/Files/ObjectStore/NoopScanner.php b/lib/private/Files/ObjectStore/NoopScanner.php
index 42e212271d5..3b8cbdb18bb 100644
--- a/lib/private/Files/ObjectStore/NoopScanner.php
+++ b/lib/private/Files/ObjectStore/NoopScanner.php
@@ -31,7 +31,7 @@ use OC\Files\Storage\Storage;
 
 class NoopScanner extends Scanner {
 	public function __construct(Storage $storage) {
-		//we don't need the storage, so do nothing here
+		// we don't need the storage, so do nothing here
 	}
 
 	/**
diff --git a/lib/private/Metadata/Capabilities.php b/lib/private/Metadata/Capabilities.php
new file mode 100644
index 00000000000..2fa0006f581
--- /dev/null
+++ b/lib/private/Metadata/Capabilities.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OCP\Capabilities\IPublicCapability;
+use OCP\IConfig;
+
+class Capabilities implements IPublicCapability {
+	private IMetadataManager $manager;
+	private IConfig $config;
+
+	public function __construct(IMetadataManager $manager, IConfig $config) {
+		$this->manager = $manager;
+		$this->config = $config;
+	}
+
+	public function getCapabilities() {
+		if ($this->config->getSystemValueBool('enable_file_metadata', true)) {
+			return ['metadataAvailable' => $this->manager->getCapabilities()];
+		}
+
+		return [];
+	}
+}
diff --git a/lib/private/Metadata/FileEventListener.php b/lib/private/Metadata/FileEventListener.php
new file mode 100644
index 00000000000..fdec891c6e2
--- /dev/null
+++ b/lib/private/Metadata/FileEventListener.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OC\Files\Filesystem;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Events\Node\NodeDeletedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\Files\Events\NodeRemovedFromCache;
+use OCP\Files\File;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\Files\FileInfo;
+
+class FileEventListener implements IEventListener {
+	private IMetadataManager $manager;
+
+	public function __construct(IMetadataManager $manager) {
+		$this->manager = $manager;
+	}
+
+	private function shouldExtractMetadata(Node $node): bool {
+		try {
+			if ($node->getMimetype() === 'httpd/unix-directory') {
+				return false;
+			}
+		} catch (NotFoundException $e) {
+			return false;
+		}
+		if ($node->getSize(false) <= 0) {
+			return false;
+		}
+
+		$path = $node->getPath();
+		// TODO make this more dynamic, we have the same issue in other places
+		return !str_starts_with($path, 'appdata_') && !str_starts_with($path, 'files_versions/') && !str_starts_with($path, 'files_trashbin/');
+	}
+
+	public function handle(Event $event): void {
+		if ($event instanceof NodeRemovedFromCache) {
+			$view = Filesystem::getView();
+			$info = $view->getFileInfo($event->getPath());
+			if ($info && $info->getType() === FileInfo::TYPE_FILE) {
+				$this->manager->clearMetadata($info->getId());
+			}
+		}
+
+		if ($event instanceof NodeDeletedEvent) {
+			$node = $event->getNode();
+			if ($this->shouldExtractMetadata($node)) {
+				/** @var File $node */
+				$this->manager->clearMetadata($event->getNode()->getId());
+			}
+		}
+
+		if ($event instanceof NodeWrittenEvent) {
+			$node = $event->getNode();
+			if ($this->shouldExtractMetadata($node)) {
+				/** @var File $node */
+				$this->manager->generateMetadata($event->getNode(), false);
+			}
+		}
+	}
+}
diff --git a/lib/private/Metadata/FileMetadata.php b/lib/private/Metadata/FileMetadata.php
new file mode 100644
index 00000000000..c53f5d7f619
--- /dev/null
+++ b/lib/private/Metadata/FileMetadata.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OCP\AppFramework\Db\Entity;
+use OCP\DB\Types;
+
+/**
+ * @method string getGroupName()
+ * @method void setGroupName(string $groupName)
+ * @method string getMetadata()
+ * @method void setMetadata(array $metadata)
+ * @see OC\Core\Migrations\Version240000Date20220404230027
+ */
+class FileMetadata extends Entity {
+	protected ?string $groupName = null;
+	protected ?array $metadata = null;
+
+	public function __construct() {
+		$this->addType('groupName', 'string');
+		$this->addType('metadata', Types::JSON);
+	}
+}
diff --git a/lib/private/Metadata/FileMetadataMapper.php b/lib/private/Metadata/FileMetadataMapper.php
new file mode 100644
index 00000000000..53f750ae540
--- /dev/null
+++ b/lib/private/Metadata/FileMetadataMapper.php
@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\Exception;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class FileMetadataMapper extends QBMapper {
+	public function __construct(IDBConnection $db) {
+		parent::__construct($db, 'file_metadata', FileMetadata::class);
+	}
+
+	/**
+	 * @return FileMetadata[]
+	 * @throws Exception
+	 */
+	public function findForFile(int $fileId): array {
+		$qb = $this->db->getQueryBuilder();
+		$qb->select('*')
+			->from($this->getTableName())
+			->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+
+		return $this->findEntities($qb);
+	}
+
+	/**
+	 * @throws DoesNotExistException
+	 * @throws MultipleObjectsReturnedException
+	 * @throws Exception
+	 */
+	public function findForGroupForFile(int $fileId, string $groupName): FileMetadata {
+		$qb = $this->db->getQueryBuilder();
+		$qb->select('*')
+			->from($this->getTableName())
+			->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT_ARRAY)))
+			->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, IQueryBuilder::PARAM_STR)));
+
+		return $this->findEntity($qb);
+	}
+
+	/**
+	 * @return array<int, FileMetadata>
+	 * @throws Exception
+	 */
+	public function findForGroupForFiles(array $fileIds, string $groupName): array {
+		$qb = $this->db->getQueryBuilder();
+		$qb->select('*')
+			->from($this->getTableName())
+			->where($qb->expr()->in('id', $qb->createParameter('fileIds')))
+			->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, IQueryBuilder::PARAM_STR)));
+
+		$metadata = [];
+		foreach (array_chunk($fileIds, 1000) as $fileIdsChunk) {
+			$qb->setParameter('fileIds', $fileIdsChunk, IQueryBuilder::PARAM_INT_ARRAY);
+			/** @var FileMetadata[] $rawEntities */
+			$rawEntities = $this->findEntities($qb);
+			foreach ($rawEntities as $entity) {
+				$metadata[$entity->getId()] = $entity;
+			}
+		}
+
+		foreach ($fileIds as $id) {
+			if (isset($metadata[$id])) {
+				continue;
+			}
+			$empty = new FileMetadata();
+			$empty->setMetadata([]);
+			$empty->setGroupName($groupName);
+			$empty->setId($id);
+			$metadata[$id] = $empty;
+		}
+		return $metadata;
+	}
+
+	public function clear(int $fileId): void {
+		$qb = $this->db->getQueryBuilder();
+		$qb->delete($this->getTableName())
+			->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+
+		$qb->executeStatement();
+	}
+}
diff --git a/lib/private/Metadata/IMetadataManager.php b/lib/private/Metadata/IMetadataManager.php
new file mode 100644
index 00000000000..d2d37f15c25
--- /dev/null
+++ b/lib/private/Metadata/IMetadataManager.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OC\Metadata;
+
+use OCP\Files\File;
+
+/**
+ * Interface to manage additional metadata for files
+ */
+interface IMetadataManager {
+	/**
+	 * @param class-string<IMetadataProvider> $className
+	 */
+	public function registerProvider(string $className): void;
+
+	/**
+	 * Generate the metadata for one file
+	 */
+	public function generateMetadata(File $file, bool $checkExisting = false): void;
+
+	/**
+	 * Clear the metadata for one file
+	 */
+	public function clearMetadata(int $fileId): void;
+
+	/** @return array<int, FileMetadata> */
+	public function fetchMetadataFor(string $group, array $fileIds): array;
+
+	/**
+	 * Get the capabilites as an array of mimetype regex to the type provided
+	 */
+	public function getCapabilities(): array;
+}
diff --git a/lib/private/Metadata/IMetadataProvider.php b/lib/private/Metadata/IMetadataProvider.php
new file mode 100644
index 00000000000..7cbe102a538
--- /dev/null
+++ b/lib/private/Metadata/IMetadataProvider.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace OC\Metadata;
+
+use OCP\Files\File;
+
+/**
+ * Interface for the metadata providers. If you want an application to provide
+ * some metadata, you can use this to store them.
+ */
+interface IMetadataProvider {
+	/**
+	 * The list of groups that this metadata provider is able to provide.
+	 *
+	 * @return string[]
+	 */
+	public static function groupsProvided(): array;
+
+	/**
+	 * Check if the metadata provider is available. A metadata provider might be
+	 * unavailable due to a php extension not being installed.
+	 */
+	public static function isAvailable(): bool;
+
+	/**
+	 * Get the mimetypes supported as a regex.
+	 */
+	public static function getMimetypesSupported(): string;
+
+	/**
+	 * Execute the extraction on the specified file. The metadata should be
+	 * grouped by metadata
+	 *
+	 * Each group should be json serializable and the string representation
+	 * shouldn't be longer than 4000 characters.
+	 *
+	 * @param File $file The file to extract the metadata from
+	 * @param array<string, FileMetadata> An array containing all the metadata fetched.
+	 */
+	public function execute(File $file): array;
+}
diff --git a/lib/private/Metadata/MetadataManager.php b/lib/private/Metadata/MetadataManager.php
new file mode 100644
index 00000000000..69e9cb3c852
--- /dev/null
+++ b/lib/private/Metadata/MetadataManager.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OC\Metadata\Provider\ExifProvider;
+use OCP\Files\File;
+use OCP\IConfig;
+use Psr\Log\LoggerInterface;
+
+class MetadataManager implements IMetadataManager {
+	/** @var array<string, IMetadataProvider> */
+	private array $providers;
+	private array $providerClasses;
+	private FileMetadataMapper $fileMetadataMapper;
+	private IConfig $config;
+	private LoggerInterface $logger;
+
+	public function __construct(
+		FileMetadataMapper $fileMetadataMapper,
+		IConfig $config,
+		LoggerInterface $logger
+	) {
+		$this->providers = [];
+		$this->providerClasses = [];
+		$this->fileMetadataMapper = $fileMetadataMapper;
+		$this->config = $config;
+		$this->logger = $logger;
+
+		// TODO move to another place, where?
+		$this->registerProvider(ExifProvider::class);
+	}
+
+	/**
+	 * @param class-string<IMetadataProvider> $className
+	 */
+	public function registerProvider(string $className):void {
+		if (in_array($className, $this->providerClasses)) {
+			return;
+		}
+
+		if (call_user_func([$className, 'isAvailable'])) {
+			$this->providers[call_user_func([$className, 'getMimetypesSupported'])] = \OC::$server->get($className);
+		}
+	}
+
+	public function generateMetadata(File $file, bool $checkExisting = false): void {
+		$existingMetadataGroups = [];
+
+		if ($checkExisting) {
+			$existingMetadata = $this->fileMetadataMapper->findForFile($file->getId());
+			foreach ($existingMetadata as $metadata) {
+				$existingMetadataGroups[] = $metadata->getGroupName();
+			}
+		}
+
+		foreach ($this->providers as $supportedMimetype => $provider) {
+			if (preg_match($supportedMimetype, $file->getMimeType())) {
+				if (count(array_diff($provider::groupsProvided(), $existingMetadataGroups)) > 0) {
+					$metaDataGroup = $provider->execute($file);
+					foreach ($metaDataGroup as $group => $metadata) {
+						$this->fileMetadataMapper->insertOrUpdate($metadata);
+					}
+				}
+			}
+		}
+	}
+
+	public function clearMetadata(int $fileId): void {
+		$this->fileMetadataMapper->clear($fileId);
+	}
+
+	public function fetchMetadataFor(string $group, array $fileIds): array {
+		return $this->fileMetadataMapper->findForGroupForFiles($fileIds, $group);
+	}
+
+	public function getCapabilities(): array {
+		$capabilities = [];
+		foreach ($this->providers as $supportedMimetype => $provider) {
+			$capabilities[$supportedMimetype] = $provider::groupsProvided();
+		}
+		return $capabilities;
+	}
+}
diff --git a/lib/private/Metadata/Provider/ExifProvider.php b/lib/private/Metadata/Provider/ExifProvider.php
new file mode 100644
index 00000000000..91c858f6794
--- /dev/null
+++ b/lib/private/Metadata/Provider/ExifProvider.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace OC\Metadata\Provider;
+
+use OC\Metadata\FileMetadata;
+use OC\Metadata\IMetadataProvider;
+use OCP\Files\File;
+
+class ExifProvider implements IMetadataProvider {
+	public static function groupsProvided(): array {
+		return ['size'];
+	}
+
+	public static function isAvailable(): bool {
+		return extension_loaded('exif');
+	}
+
+	public function execute(File $file): array {
+		$fileDescriptor = $file->fopen('rb');
+		$data = @exif_read_data($fileDescriptor, 'ANY_TAG', true);
+
+		$size = new FileMetadata();
+		$size->setGroupName('size');
+		$size->setId($file->getId());
+		$size->setMetadata([]);
+
+		if (!$data) {
+			return [
+				'size' => $size,
+			];
+		}
+
+		if (array_key_exists('COMPUTED', $data)
+			&& array_key_exists('Width', $data['COMPUTED'])
+			&& array_key_exists('Height', $data['COMPUTED'])
+		) {
+			$size->setMetadata([
+				'width' => $data['COMPUTED']['Width'],
+				'height' => $data['COMPUTED']['Height'],
+			]);
+		}
+
+		return [
+			'size' => $size,
+		];
+	}
+
+	public static function getMimetypesSupported(): string {
+		return '/image\/.*/';
+	}
+}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 7817d1beafe..e9d673d3746 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -122,6 +122,9 @@ use OC\Log\PsrLoggerAdapter;
 use OC\Mail\Mailer;
 use OC\Memcache\ArrayCache;
 use OC\Memcache\Factory;
+use OC\Metadata\Capabilities as MetadataCapabilities;
+use OC\Metadata\IMetadataManager;
+use OC\Metadata\MetadataManager;
 use OC\Notification\Manager;
 use OC\OCS\DiscoveryService;
 use OC\Preview\GeneratorHelper;
@@ -151,7 +154,6 @@ use OC\Template\JSCombiner;
 use OCA\Theming\ImageManager;
 use OCA\Theming\ThemingDefaults;
 use OCA\Theming\Util;
-use OCA\WorkflowEngine\Service\Logger;
 use OCP\Accounts\IAccountManager;
 use OCP\App\IAppManager;
 use OCP\Authentication\LoginCredentials\IStore;
@@ -241,15 +243,12 @@ use OCP\SystemTag\ISystemTagManager;
 use OCP\SystemTag\ISystemTagObjectMapper;
 use OCP\Talk\IBroker;
 use OCP\User\Events\BeforePasswordUpdatedEvent;
-use OCP\User\Events\BeforeUserCreatedEvent;
-use OCP\User\Events\BeforeUserDeletedEvent;
 use OCP\User\Events\BeforeUserLoggedInEvent;
 use OCP\User\Events\BeforeUserLoggedInWithCookieEvent;
 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;
@@ -1163,6 +1162,9 @@ class Server extends ServerContainer implements IServerContainer {
 			$manager->registerCapability(function () use ($c) {
 				return $c->get(\OC\Security\Bruteforce\Capabilities::class);
 			});
+			$manager->registerCapability(function () use ($c) {
+				return $c->get(MetadataCapabilities::class);
+			});
 			return $manager;
 		});
 		/** @deprecated 19.0.0 */
@@ -1433,6 +1435,8 @@ class Server extends ServerContainer implements IServerContainer {
 
 		$this->registerAlias(IBroker::class, Broker::class);
 
+		$this->registerAlias(IMetadataManager::class, MetadataManager::class);
+
 		$this->connectDispatcher();
 	}
 
diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php
index 89e8f69859e..a059e3a27b0 100644
--- a/lib/public/AppFramework/Db/Entity.php
+++ b/lib/public/AppFramework/Db/Entity.php
@@ -120,6 +120,10 @@ abstract class Entity {
 					if (!$args[0] instanceof \DateTime) {
 						$args[0] = new \DateTime($args[0]);
 					}
+				} elseif ($type === 'json') {
+					if (!is_array($args[0])) {
+						$args[0] = json_decode($args[0], true);
+					}
 				} else {
 					settype($args[0], $type);
 				}
diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php
index 5124650bc19..fa753a09dcf 100644
--- a/lib/public/AppFramework/Db/QBMapper.php
+++ b/lib/public/AppFramework/Db/QBMapper.php
@@ -253,6 +253,8 @@ abstract class QBMapper {
 				return IQueryBuilder::PARAM_LOB;
 			case 'datetime':
 				return IQueryBuilder::PARAM_DATE;
+			case 'json':
+				return IQueryBuilder::PARAM_JSON;
 		}
 
 		return IQueryBuilder::PARAM_STR;
diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php
index 76754f7bf41..afca9e372ee 100644
--- a/lib/public/DB/QueryBuilder/IQueryBuilder.php
+++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php
@@ -64,6 +64,11 @@ interface IQueryBuilder {
 	 */
 	public const PARAM_DATE = 'datetime';
 
+	/**
+	 * @since 24.0.0
+	 */
+	public const PARAM_JSON = 'json';
+
 	/**
 	 * @since 9.0.0
 	 */
diff --git a/lib/public/DB/Types.php b/lib/public/DB/Types.php
index 4636ac3389f..31a474b03a0 100644
--- a/lib/public/DB/Types.php
+++ b/lib/public/DB/Types.php
@@ -110,4 +110,10 @@ final class Types {
 	 * @since 21.0.0
 	 */
 	public const TIME = 'time';
+
+	/**
+	 * @var string
+	 * @since 24.0.0
+	 */
+	public const JSON = 'json';
 }
-- 
cgit v1.2.3


From 1c7ecfc54499d866b9913c135c0c7439634d8bb1 Mon Sep 17 00:00:00 2001
From: Carl Schwan <carl@carlschwan.eu>
Date: Wed, 13 Apr 2022 10:52:26 +0200
Subject: Fix an issue with the search backend update

And update autoloader

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
---
 apps/accessibility/composer/autoload.php           |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/admin_audit/composer/autoload.php             |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/cloud_federation_api/composer/autoload.php    |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/comments/composer/autoload.php                |  5 +++++
 apps/comments/composer/composer/autoload_real.php  |  2 +-
 apps/contactsinteraction/composer/autoload.php     |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/dav/lib/Connector/Sabre/FilesPlugin.php       |  6 +++---
 apps/dav/lib/Files/FileSearchBackend.php           | 20 ++++++++---------
 apps/encryption/composer/autoload.php              |  5 +++++
 .../encryption/composer/composer/autoload_real.php |  2 +-
 apps/federatedfilesharing/composer/autoload.php    |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/federation/composer/autoload.php              |  5 +++++
 .../federation/composer/composer/autoload_real.php |  2 +-
 apps/files/composer/autoload.php                   |  5 +++++
 apps/files/composer/composer/autoload_real.php     |  2 +-
 apps/files_sharing/composer/autoload.php           |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/files_trashbin/composer/autoload.php          |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/files_versions/composer/autoload.php          |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/lookup_server_connector/composer/autoload.php |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/oauth2/composer/autoload.php                  |  5 +++++
 apps/oauth2/composer/composer/autoload_real.php    |  2 +-
 apps/provisioning_api/composer/autoload.php        |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/settings/composer/autoload.php                |  5 +++++
 apps/settings/composer/composer/autoload_real.php  |  2 +-
 apps/sharebymail/composer/autoload.php             |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/systemtags/composer/autoload.php              |  5 +++++
 .../systemtags/composer/composer/autoload_real.php |  2 +-
 apps/testing/composer/autoload.php                 |  5 +++++
 apps/testing/composer/composer/autoload_real.php   |  2 +-
 apps/twofactor_backupcodes/composer/autoload.php   |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/updatenotification/composer/autoload.php      |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/user_ldap/composer/autoload.php               |  5 +++++
 apps/user_ldap/composer/composer/autoload_real.php |  2 +-
 apps/user_status/composer/autoload.php             |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 apps/workflowengine/composer/autoload.php          |  5 +++++
 .../composer/composer/autoload_real.php            |  2 +-
 lib/composer/autoload.php                          |  5 +++++
 lib/composer/composer/LICENSE                      |  2 ++
 lib/composer/composer/autoload_classmap.php        |  2 +-
 lib/composer/composer/autoload_namespaces.php      |  2 +-
 lib/composer/composer/autoload_psr4.php            |  2 +-
 lib/composer/composer/autoload_real.php            | 25 +++-------------------
 lib/private/Metadata/MetadataManager.php           |  7 +++++-
 lib/private/Metadata/Provider/ExifProvider.php     |  8 +++++++
 58 files changed, 184 insertions(+), 63 deletions(-)

(limited to 'lib')

diff --git a/apps/accessibility/composer/autoload.php b/apps/accessibility/composer/autoload.php
index f624ded3950..6f896b45abc 100644
--- a/apps/accessibility/composer/autoload.php
+++ b/apps/accessibility/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitAccessibility::getLoader();
diff --git a/apps/accessibility/composer/composer/autoload_real.php b/apps/accessibility/composer/composer/autoload_real.php
index a08983b79fe..8b2b83d3139 100644
--- a/apps/accessibility/composer/composer/autoload_real.php
+++ b/apps/accessibility/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitAccessibility
         spl_autoload_unregister(array('ComposerAutoloaderInitAccessibility', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitAccessibility::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitAccessibility::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/admin_audit/composer/autoload.php b/apps/admin_audit/composer/autoload.php
index 7970e9ebe12..d316fe42c51 100644
--- a/apps/admin_audit/composer/autoload.php
+++ b/apps/admin_audit/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitAdminAudit::getLoader();
diff --git a/apps/admin_audit/composer/composer/autoload_real.php b/apps/admin_audit/composer/composer/autoload_real.php
index ffbbdd4e269..bd7d1f99dd1 100644
--- a/apps/admin_audit/composer/composer/autoload_real.php
+++ b/apps/admin_audit/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitAdminAudit
         spl_autoload_unregister(array('ComposerAutoloaderInitAdminAudit', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitAdminAudit::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitAdminAudit::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/cloud_federation_api/composer/autoload.php b/apps/cloud_federation_api/composer/autoload.php
index fcf0f062846..fc52f01bfaf 100644
--- a/apps/cloud_federation_api/composer/autoload.php
+++ b/apps/cloud_federation_api/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitCloudFederationAPI::getLoader();
diff --git a/apps/cloud_federation_api/composer/composer/autoload_real.php b/apps/cloud_federation_api/composer/composer/autoload_real.php
index 1c7ec9607c2..53093c129e3 100644
--- a/apps/cloud_federation_api/composer/composer/autoload_real.php
+++ b/apps/cloud_federation_api/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitCloudFederationAPI
         spl_autoload_unregister(array('ComposerAutoloaderInitCloudFederationAPI', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitCloudFederationAPI::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitCloudFederationAPI::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/comments/composer/autoload.php b/apps/comments/composer/autoload.php
index c974072d6b7..46d800ddaa8 100644
--- a/apps/comments/composer/autoload.php
+++ b/apps/comments/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitComments::getLoader();
diff --git a/apps/comments/composer/composer/autoload_real.php b/apps/comments/composer/composer/autoload_real.php
index 8668cfb671e..7f9d22ca0a2 100644
--- a/apps/comments/composer/composer/autoload_real.php
+++ b/apps/comments/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitComments
         spl_autoload_unregister(array('ComposerAutoloaderInitComments', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitComments::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitComments::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/contactsinteraction/composer/autoload.php b/apps/contactsinteraction/composer/autoload.php
index 7bf597cd9cd..748e5f45fe9 100644
--- a/apps/contactsinteraction/composer/autoload.php
+++ b/apps/contactsinteraction/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitContactsInteraction::getLoader();
diff --git a/apps/contactsinteraction/composer/composer/autoload_real.php b/apps/contactsinteraction/composer/composer/autoload_real.php
index 8ba09879f54..09f95c83645 100644
--- a/apps/contactsinteraction/composer/composer/autoload_real.php
+++ b/apps/contactsinteraction/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitContactsInteraction
         spl_autoload_unregister(array('ComposerAutoloaderInitContactsInteraction', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitContactsInteraction::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitContactsInteraction::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index 5cc562e0ff8..9c4f912610b 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -444,7 +444,7 @@ class FilesPlugin extends ServerPlugin {
 			if ($this->config->getSystemValueBool('enable_file_metadata', true)) {
 				$propFind->handle(self::FILE_METADATA_SIZE, function () use ($node) {
 					if (!str_starts_with($node->getFileInfo()->getMimetype(), 'image')) {
-						return json_encode([]);
+						return json_encode((object)[]);
 					}
 
 					if ($node->hasMetadata('size')) {
@@ -457,10 +457,10 @@ class FilesPlugin extends ServerPlugin {
 						$sizeMetadata = $metadataManager->fetchMetadataFor('size', [$node->getId()])[$node->getId()];
 
 						// TODO would be nice to display this in the profiler...
-						\OC::$server->get(LoggerInterface::class)->warning('Inefficient fetching of metadata');
+						\OC::$server->get(LoggerInterface::class)->debug('Inefficient fetching of metadata');
 					}
 
-					return json_encode($sizeMetadata->getMetadata());
+					return json_encode((object)$sizeMetadata->getMetadata());
 				});
 			}
 		}
diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php
index 21eb14a29bd..7ee82779849 100644
--- a/apps/dav/lib/Files/FileSearchBackend.php
+++ b/apps/dav/lib/Files/FileSearchBackend.php
@@ -124,16 +124,16 @@ class FileSearchBackend implements ISearchBackend {
 			new SearchPropertyDefinition(FilesPlugin::OWNER_ID_PROPERTYNAME, true, true, false),
 
 			// select only properties
-			new SearchPropertyDefinition('{DAV:}resourcetype', false, true, false),
-			new SearchPropertyDefinition('{DAV:}getcontentlength', false, true, false),
-			new SearchPropertyDefinition(FilesPlugin::CHECKSUMS_PROPERTYNAME, false, true, false),
-			new SearchPropertyDefinition(FilesPlugin::PERMISSIONS_PROPERTYNAME, false, true, false),
-			new SearchPropertyDefinition(FilesPlugin::GETETAG_PROPERTYNAME, false, true, false),
-			new SearchPropertyDefinition(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME, false, true, false),
-			new SearchPropertyDefinition(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME, false, true, false),
-			new SearchPropertyDefinition(FilesPlugin::HAS_PREVIEW_PROPERTYNAME, false, true, false, SearchPropertyDefinition::DATATYPE_BOOLEAN),
-			new SearchPropertyDefinition(FilesPlugin::FILE_METADATA_SIZE, false, true, false, SearchPropertyDefinition::DATATYPE_STRING),
-			new SearchPropertyDefinition(FilesPlugin::FILEID_PROPERTYNAME, false, true, false, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
+			new SearchPropertyDefinition('{DAV:}resourcetype', true, false, false),
+			new SearchPropertyDefinition('{DAV:}getcontentlength', true, false, false),
+			new SearchPropertyDefinition(FilesPlugin::CHECKSUMS_PROPERTYNAME, true, false, false),
+			new SearchPropertyDefinition(FilesPlugin::PERMISSIONS_PROPERTYNAME, true, false, false),
+			new SearchPropertyDefinition(FilesPlugin::GETETAG_PROPERTYNAME, true, false, false),
+			new SearchPropertyDefinition(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME, true, false, false),
+			new SearchPropertyDefinition(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME, true, false, false),
+			new SearchPropertyDefinition(FilesPlugin::HAS_PREVIEW_PROPERTYNAME, true, false, false, SearchPropertyDefinition::DATATYPE_BOOLEAN),
+			new SearchPropertyDefinition(FilesPlugin::FILE_METADATA_SIZE, true, false, false, SearchPropertyDefinition::DATATYPE_STRING),
+			new SearchPropertyDefinition(FilesPlugin::FILEID_PROPERTYNAME, true, false, false, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
 		];
 	}
 
diff --git a/apps/encryption/composer/autoload.php b/apps/encryption/composer/autoload.php
index 52febf19470..593ddde0eb0 100644
--- a/apps/encryption/composer/autoload.php
+++ b/apps/encryption/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitEncryption::getLoader();
diff --git a/apps/encryption/composer/composer/autoload_real.php b/apps/encryption/composer/composer/autoload_real.php
index 35091c9ed4a..aafe8533d3d 100644
--- a/apps/encryption/composer/composer/autoload_real.php
+++ b/apps/encryption/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitEncryption
         spl_autoload_unregister(array('ComposerAutoloaderInitEncryption', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitEncryption::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitEncryption::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/federatedfilesharing/composer/autoload.php b/apps/federatedfilesharing/composer/autoload.php
index 5273607f74a..e839dd1bcdd 100644
--- a/apps/federatedfilesharing/composer/autoload.php
+++ b/apps/federatedfilesharing/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitFederatedFileSharing::getLoader();
diff --git a/apps/federatedfilesharing/composer/composer/autoload_real.php b/apps/federatedfilesharing/composer/composer/autoload_real.php
index 0a8c5bf9588..c6f34ef0a65 100644
--- a/apps/federatedfilesharing/composer/composer/autoload_real.php
+++ b/apps/federatedfilesharing/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFederatedFileSharing
         spl_autoload_unregister(array('ComposerAutoloaderInitFederatedFileSharing', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitFederatedFileSharing::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitFederatedFileSharing::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/federation/composer/autoload.php b/apps/federation/composer/autoload.php
index 45677794dd0..77ae3e1c118 100644
--- a/apps/federation/composer/autoload.php
+++ b/apps/federation/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitFederation::getLoader();
diff --git a/apps/federation/composer/composer/autoload_real.php b/apps/federation/composer/composer/autoload_real.php
index 40dc84ff20a..b3913e0ac70 100644
--- a/apps/federation/composer/composer/autoload_real.php
+++ b/apps/federation/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFederation
         spl_autoload_unregister(array('ComposerAutoloaderInitFederation', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitFederation::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitFederation::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/files/composer/autoload.php b/apps/files/composer/autoload.php
index 3aa13fa515d..cbac9333296 100644
--- a/apps/files/composer/autoload.php
+++ b/apps/files/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitFiles::getLoader();
diff --git a/apps/files/composer/composer/autoload_real.php b/apps/files/composer/composer/autoload_real.php
index 5b2c0e86043..e3e4d9e67ef 100644
--- a/apps/files/composer/composer/autoload_real.php
+++ b/apps/files/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles
         spl_autoload_unregister(array('ComposerAutoloaderInitFiles', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitFiles::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitFiles::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/files_sharing/composer/autoload.php b/apps/files_sharing/composer/autoload.php
index 0aa77c00af9..02b3c10c483 100644
--- a/apps/files_sharing/composer/autoload.php
+++ b/apps/files_sharing/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitFiles_Sharing::getLoader();
diff --git a/apps/files_sharing/composer/composer/autoload_real.php b/apps/files_sharing/composer/composer/autoload_real.php
index 24054045984..64a23094d9d 100644
--- a/apps/files_sharing/composer/composer/autoload_real.php
+++ b/apps/files_sharing/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles_Sharing
         spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Sharing', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitFiles_Sharing::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Sharing::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/files_trashbin/composer/autoload.php b/apps/files_trashbin/composer/autoload.php
index ae6d572163f..4e88a44133f 100644
--- a/apps/files_trashbin/composer/autoload.php
+++ b/apps/files_trashbin/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitFiles_Trashbin::getLoader();
diff --git a/apps/files_trashbin/composer/composer/autoload_real.php b/apps/files_trashbin/composer/composer/autoload_real.php
index b9a42591b0c..0d1aa13ee3c 100644
--- a/apps/files_trashbin/composer/composer/autoload_real.php
+++ b/apps/files_trashbin/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles_Trashbin
         spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Trashbin', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitFiles_Trashbin::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Trashbin::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/files_versions/composer/autoload.php b/apps/files_versions/composer/autoload.php
index 7bb72360fba..f75dc09160c 100644
--- a/apps/files_versions/composer/autoload.php
+++ b/apps/files_versions/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitFiles_Versions::getLoader();
diff --git a/apps/files_versions/composer/composer/autoload_real.php b/apps/files_versions/composer/composer/autoload_real.php
index e9e2ad95149..dad15f0b550 100644
--- a/apps/files_versions/composer/composer/autoload_real.php
+++ b/apps/files_versions/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles_Versions
         spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Versions', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitFiles_Versions::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Versions::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/lookup_server_connector/composer/autoload.php b/apps/lookup_server_connector/composer/autoload.php
index ab8f4ce80ff..521fd3630e4 100644
--- a/apps/lookup_server_connector/composer/autoload.php
+++ b/apps/lookup_server_connector/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitLookupServerConnector::getLoader();
diff --git a/apps/lookup_server_connector/composer/composer/autoload_real.php b/apps/lookup_server_connector/composer/composer/autoload_real.php
index 798f093c6e8..417958ba7f1 100644
--- a/apps/lookup_server_connector/composer/composer/autoload_real.php
+++ b/apps/lookup_server_connector/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitLookupServerConnector
         spl_autoload_unregister(array('ComposerAutoloaderInitLookupServerConnector', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitLookupServerConnector::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitLookupServerConnector::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/oauth2/composer/autoload.php b/apps/oauth2/composer/autoload.php
index 276dedf42c2..c7fd27c188d 100644
--- a/apps/oauth2/composer/autoload.php
+++ b/apps/oauth2/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitOAuth2::getLoader();
diff --git a/apps/oauth2/composer/composer/autoload_real.php b/apps/oauth2/composer/composer/autoload_real.php
index 4d9e729ac26..0253518be84 100644
--- a/apps/oauth2/composer/composer/autoload_real.php
+++ b/apps/oauth2/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitOAuth2
         spl_autoload_unregister(array('ComposerAutoloaderInitOAuth2', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitOAuth2::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitOAuth2::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/provisioning_api/composer/autoload.php b/apps/provisioning_api/composer/autoload.php
index 9734ee42b19..d01dfa2c74b 100644
--- a/apps/provisioning_api/composer/autoload.php
+++ b/apps/provisioning_api/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitProvisioning_API::getLoader();
diff --git a/apps/provisioning_api/composer/composer/autoload_real.php b/apps/provisioning_api/composer/composer/autoload_real.php
index bada942777d..a3b1fdeb247 100644
--- a/apps/provisioning_api/composer/composer/autoload_real.php
+++ b/apps/provisioning_api/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitProvisioning_API
         spl_autoload_unregister(array('ComposerAutoloaderInitProvisioning_API', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitProvisioning_API::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitProvisioning_API::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/settings/composer/autoload.php b/apps/settings/composer/autoload.php
index 04ff46ee987..e7087dceec2 100644
--- a/apps/settings/composer/autoload.php
+++ b/apps/settings/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitSettings::getLoader();
diff --git a/apps/settings/composer/composer/autoload_real.php b/apps/settings/composer/composer/autoload_real.php
index 0e9941ee04d..865e01a7fd9 100644
--- a/apps/settings/composer/composer/autoload_real.php
+++ b/apps/settings/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitSettings
         spl_autoload_unregister(array('ComposerAutoloaderInitSettings', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitSettings::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitSettings::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/sharebymail/composer/autoload.php b/apps/sharebymail/composer/autoload.php
index da43a4ff256..bef284b432f 100644
--- a/apps/sharebymail/composer/autoload.php
+++ b/apps/sharebymail/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitShareByMail::getLoader();
diff --git a/apps/sharebymail/composer/composer/autoload_real.php b/apps/sharebymail/composer/composer/autoload_real.php
index 47a2c20fd5e..cfbfdab1b1e 100644
--- a/apps/sharebymail/composer/composer/autoload_real.php
+++ b/apps/sharebymail/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitShareByMail
         spl_autoload_unregister(array('ComposerAutoloaderInitShareByMail', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitShareByMail::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitShareByMail::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/systemtags/composer/autoload.php b/apps/systemtags/composer/autoload.php
index 30f4cd27d40..5f15d593150 100644
--- a/apps/systemtags/composer/autoload.php
+++ b/apps/systemtags/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitSystemTags::getLoader();
diff --git a/apps/systemtags/composer/composer/autoload_real.php b/apps/systemtags/composer/composer/autoload_real.php
index f9bc1f2eaff..340f7c9e6ed 100644
--- a/apps/systemtags/composer/composer/autoload_real.php
+++ b/apps/systemtags/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitSystemTags
         spl_autoload_unregister(array('ComposerAutoloaderInitSystemTags', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitSystemTags::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitSystemTags::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/testing/composer/autoload.php b/apps/testing/composer/autoload.php
index dc2a7034ffa..1ac43d5c8e9 100644
--- a/apps/testing/composer/autoload.php
+++ b/apps/testing/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitTesting::getLoader();
diff --git a/apps/testing/composer/composer/autoload_real.php b/apps/testing/composer/composer/autoload_real.php
index 805c585644d..0d4fabd66a0 100644
--- a/apps/testing/composer/composer/autoload_real.php
+++ b/apps/testing/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitTesting
         spl_autoload_unregister(array('ComposerAutoloaderInitTesting', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitTesting::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitTesting::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/twofactor_backupcodes/composer/autoload.php b/apps/twofactor_backupcodes/composer/autoload.php
index 03a8800c318..091a9b4fefa 100644
--- a/apps/twofactor_backupcodes/composer/autoload.php
+++ b/apps/twofactor_backupcodes/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitTwoFactorBackupCodes::getLoader();
diff --git a/apps/twofactor_backupcodes/composer/composer/autoload_real.php b/apps/twofactor_backupcodes/composer/composer/autoload_real.php
index 0c6e6b19f33..b063e83100f 100644
--- a/apps/twofactor_backupcodes/composer/composer/autoload_real.php
+++ b/apps/twofactor_backupcodes/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitTwoFactorBackupCodes
         spl_autoload_unregister(array('ComposerAutoloaderInitTwoFactorBackupCodes', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitTwoFactorBackupCodes::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitTwoFactorBackupCodes::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/updatenotification/composer/autoload.php b/apps/updatenotification/composer/autoload.php
index 47cc4d587a5..e715564a5bd 100644
--- a/apps/updatenotification/composer/autoload.php
+++ b/apps/updatenotification/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitUpdateNotification::getLoader();
diff --git a/apps/updatenotification/composer/composer/autoload_real.php b/apps/updatenotification/composer/composer/autoload_real.php
index 89854cd42f4..b7569aff2d1 100644
--- a/apps/updatenotification/composer/composer/autoload_real.php
+++ b/apps/updatenotification/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitUpdateNotification
         spl_autoload_unregister(array('ComposerAutoloaderInitUpdateNotification', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitUpdateNotification::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitUpdateNotification::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/user_ldap/composer/autoload.php b/apps/user_ldap/composer/autoload.php
index 24824c188e5..d1e331c189e 100644
--- a/apps/user_ldap/composer/autoload.php
+++ b/apps/user_ldap/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitUser_LDAP::getLoader();
diff --git a/apps/user_ldap/composer/composer/autoload_real.php b/apps/user_ldap/composer/composer/autoload_real.php
index 0e1a6558e55..6f0c636e7d5 100644
--- a/apps/user_ldap/composer/composer/autoload_real.php
+++ b/apps/user_ldap/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitUser_LDAP
         spl_autoload_unregister(array('ComposerAutoloaderInitUser_LDAP', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitUser_LDAP::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitUser_LDAP::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/user_status/composer/autoload.php b/apps/user_status/composer/autoload.php
index b22563e6f83..a82d4105451 100644
--- a/apps/user_status/composer/autoload.php
+++ b/apps/user_status/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitUserStatus::getLoader();
diff --git a/apps/user_status/composer/composer/autoload_real.php b/apps/user_status/composer/composer/autoload_real.php
index 4ffa4b4201b..205d9780930 100644
--- a/apps/user_status/composer/composer/autoload_real.php
+++ b/apps/user_status/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitUserStatus
         spl_autoload_unregister(array('ComposerAutoloaderInitUserStatus', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitUserStatus::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitUserStatus::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/apps/workflowengine/composer/autoload.php b/apps/workflowengine/composer/autoload.php
index 003e945ff82..74a2777acf2 100644
--- a/apps/workflowengine/composer/autoload.php
+++ b/apps/workflowengine/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInitWorkflowEngine::getLoader();
diff --git a/apps/workflowengine/composer/composer/autoload_real.php b/apps/workflowengine/composer/composer/autoload_real.php
index 8ed8cb2a7b4..cdc2b8a55b4 100644
--- a/apps/workflowengine/composer/composer/autoload_real.php
+++ b/apps/workflowengine/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitWorkflowEngine
         spl_autoload_unregister(array('ComposerAutoloaderInitWorkflowEngine', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        \Composer\Autoload\ComposerStaticInitWorkflowEngine::getInitializer($loader)();
+        call_user_func(\Composer\Autoload\ComposerStaticInitWorkflowEngine::getInitializer($loader));
 
         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
diff --git a/lib/composer/autoload.php b/lib/composer/autoload.php
index 6de0160c0b5..a3d144b1777 100644
--- a/lib/composer/autoload.php
+++ b/lib/composer/autoload.php
@@ -2,6 +2,11 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c::getLoader();
diff --git a/lib/composer/composer/LICENSE b/lib/composer/composer/LICENSE
index 62ecfd8d004..f27399a042d 100644
--- a/lib/composer/composer/LICENSE
+++ b/lib/composer/composer/LICENSE
@@ -1,3 +1,4 @@
+
 Copyright (c) Nils Adermann, Jordi Boggiano
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -17,3 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
+
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index be40cd4c607..685fae9bef1 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -2,7 +2,7 @@
 
 // autoload_classmap.php @generated by Composer
 
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
diff --git a/lib/composer/composer/autoload_namespaces.php b/lib/composer/composer/autoload_namespaces.php
index 4a9c20beed0..f1ae7a0ffec 100644
--- a/lib/composer/composer/autoload_namespaces.php
+++ b/lib/composer/composer/autoload_namespaces.php
@@ -2,7 +2,7 @@
 
 // autoload_namespaces.php @generated by Composer
 
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
diff --git a/lib/composer/composer/autoload_psr4.php b/lib/composer/composer/autoload_psr4.php
index b641d9c6a03..74e48cf69ae 100644
--- a/lib/composer/composer/autoload_psr4.php
+++ b/lib/composer/composer/autoload_psr4.php
@@ -2,7 +2,7 @@
 
 // autoload_psr4.php @generated by Composer
 
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
diff --git a/lib/composer/composer/autoload_real.php b/lib/composer/composer/autoload_real.php
index a5748c7a891..eecff48bcf9 100644
--- a/lib/composer/composer/autoload_real.php
+++ b/lib/composer/composer/autoload_real.php
@@ -23,30 +23,11 @@ class ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c
         }
 
         spl_autoload_register(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader'), true, true);
-        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
         spl_autoload_unregister(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader'));
 
-        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
-        if ($useStaticLoader) {
-            require __DIR__ . '/autoload_static.php';
-
-            call_user_func(\Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader));
-        } else {
-            $map = require __DIR__ . '/autoload_namespaces.php';
-            foreach ($map as $namespace => $path) {
-                $loader->set($namespace, $path);
-            }
-
-            $map = require __DIR__ . '/autoload_psr4.php';
-            foreach ($map as $namespace => $path) {
-                $loader->setPsr4($namespace, $path);
-            }
-
-            $classMap = require __DIR__ . '/autoload_classmap.php';
-            if ($classMap) {
-                $loader->addClassMap($classMap);
-            }
-        }
+        require __DIR__ . '/autoload_static.php';
+        call_user_func(\Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader));
 
         $loader->register(true);
 
diff --git a/lib/private/Metadata/MetadataManager.php b/lib/private/Metadata/MetadataManager.php
index 69e9cb3c852..d1cb896febf 100644
--- a/lib/private/Metadata/MetadataManager.php
+++ b/lib/private/Metadata/MetadataManager.php
@@ -93,7 +93,12 @@ class MetadataManager implements IMetadataManager {
 	public function getCapabilities(): array {
 		$capabilities = [];
 		foreach ($this->providers as $supportedMimetype => $provider) {
-			$capabilities[$supportedMimetype] = $provider::groupsProvided();
+			foreach ($provider::groupsProvided() as $group) {
+				if (isset($capabilities[$group])) {
+					$capabilities[$group][] = $supportedMimetype;
+				}
+				$capabilities[$group] = [$supportedMimetype];
+			}
 		}
 		return $capabilities;
 	}
diff --git a/lib/private/Metadata/Provider/ExifProvider.php b/lib/private/Metadata/Provider/ExifProvider.php
index 91c858f6794..2e1eb1d4208 100644
--- a/lib/private/Metadata/Provider/ExifProvider.php
+++ b/lib/private/Metadata/Provider/ExifProvider.php
@@ -25,6 +25,14 @@ class ExifProvider implements IMetadataProvider {
 		$size->setMetadata([]);
 
 		if (!$data) {
+			$sizeResult = getimagesizefromstring($file->getContent());
+			if ($sizeResult !== false) {
+				$size->setMetadata([
+					'width' => $sizeResult[0],
+					'height' => $sizeResult[1],
+				]);
+			}
+
 			return [
 				'size' => $size,
 			];
-- 
cgit v1.2.3