diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2025-02-06 16:13:27 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-06 16:13:27 +0100 |
commit | 93c72f5675f391fb016f8f9aefc429c7bb0d459b (patch) | |
tree | fec3d61626fbd281136e76ddbc45505aaf08b540 | |
parent | e71e58e06e4c3783e579de2a1cf04a8f201b24e9 (diff) | |
parent | 1e30936b78697c5a474c10537fa45e5cdce342e5 (diff) | |
download | nextcloud-server-93c72f5675f391fb016f8f9aefc429c7bb0d459b.tar.gz nextcloud-server-93c72f5675f391fb016f8f9aefc429c7bb0d459b.zip |
Merge pull request #50660 from nextcloud/fix/mime-int
fix: make sure we process mime extensions as string
-rw-r--r-- | build/psalm-baseline.xml | 6 | ||||
-rw-r--r-- | core/Command/Maintenance/Mimetype/GenerateMimetypeFileBuilder.php | 4 | ||||
-rw-r--r-- | core/Command/Maintenance/Mimetype/UpdateDB.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Type/Detection.php | 15 | ||||
-rw-r--r-- | lib/public/Files/IMimeTypeDetector.php | 6 | ||||
-rw-r--r-- | lib/public/Files/IMimeTypeLoader.php | 10 | ||||
-rw-r--r-- | tests/lib/Files/Type/DetectionTest.php | 35 |
7 files changed, 70 insertions, 10 deletions
diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 488daa10621..2824f99f79d 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1235,12 +1235,6 @@ <code><![CDATA[$this->timeFactory->getTime()]]></code> </InvalidScalarArgument> </file> - <file src="core/Command/Maintenance/Mimetype/UpdateDB.php"> - <UndefinedInterfaceMethod> - <code><![CDATA[getAllMappings]]></code> - <code><![CDATA[updateFilecache]]></code> - </UndefinedInterfaceMethod> - </file> <file src="core/Command/Preview/Repair.php"> <UndefinedInterfaceMethod> <code><![CDATA[section]]></code> diff --git a/core/Command/Maintenance/Mimetype/GenerateMimetypeFileBuilder.php b/core/Command/Maintenance/Mimetype/GenerateMimetypeFileBuilder.php index 283809a9031..5b598d20672 100644 --- a/core/Command/Maintenance/Mimetype/GenerateMimetypeFileBuilder.php +++ b/core/Command/Maintenance/Mimetype/GenerateMimetypeFileBuilder.php @@ -18,6 +18,10 @@ class GenerateMimetypeFileBuilder { public function generateFile(array $aliases): string { // Remove comments $aliases = array_filter($aliases, static function ($key) { + // Single digit extensions will be treated as integers + // Let's make sure they are strings + // https://github.com/nextcloud/server/issues/42902 + $key = (string)$key; return !($key === '' || $key[0] === '_'); }, ARRAY_FILTER_USE_KEY); diff --git a/core/Command/Maintenance/Mimetype/UpdateDB.php b/core/Command/Maintenance/Mimetype/UpdateDB.php index 9ba535ef658..4467e89eb32 100644 --- a/core/Command/Maintenance/Mimetype/UpdateDB.php +++ b/core/Command/Maintenance/Mimetype/UpdateDB.php @@ -45,6 +45,10 @@ class UpdateDB extends Command { $totalNewMimetypes = 0; foreach ($mappings as $ext => $mimetypes) { + // Single digit extensions will be treated as integers + // Let's make sure they are strings + // https://github.com/nextcloud/server/issues/42902 + $ext = (string)$ext; if ($ext[0] === '_') { // comment continue; diff --git a/lib/private/Files/Type/Detection.php b/lib/private/Files/Type/Detection.php index b1e4c098e54..3676a9b736c 100644 --- a/lib/private/Files/Type/Detection.php +++ b/lib/private/Files/Type/Detection.php @@ -23,6 +23,7 @@ class Detection implements IMimeTypeDetector { private const CUSTOM_MIMETYPEMAPPING = 'mimetypemapping.json'; private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json'; + /** @var array<string, list{string, string|null}> */ protected array $mimetypes = []; protected array $secureMimeTypes = []; @@ -52,6 +53,8 @@ class Detection implements IMimeTypeDetector { public function registerType(string $extension, string $mimetype, ?string $secureMimeType = null): void { + // Make sure the extension is a string + // https://github.com/nextcloud/server/issues/42902 $this->mimetypes[$extension] = [$mimetype, $secureMimeType]; $this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype; } @@ -66,13 +69,17 @@ class Detection implements IMimeTypeDetector { * @param array $types */ public function registerTypeArray(array $types): void { - $this->mimetypes = array_merge($this->mimetypes, $types); + // Register the types, + foreach ($types as $extension => $mimeType) { + $this->registerType((string)$extension, $mimeType[0], $mimeType[1] ?? null); + } // Update the alternative mimetypes to avoid having to look them up each time. foreach ($this->mimetypes as $extension => $mimeType) { - if (str_starts_with($extension, '_comment')) { + if (str_starts_with((string)$extension, '_comment')) { continue; } + $this->secureMimeTypes[$mimeType[0]] = $mimeType[1] ?? $mimeType[0]; if (isset($mimeType[1])) { $this->secureMimeTypes[$mimeType[1]] = $mimeType[1]; @@ -133,7 +140,7 @@ class Detection implements IMimeTypeDetector { } /** - * @return array + * @return array<string, list{string, string|null}> */ public function getAllMappings(): array { $this->loadMappings(); @@ -163,7 +170,7 @@ class Detection implements IMimeTypeDetector { $extension = strrchr($fileName, '.'); if ($extension !== false) { $extension = strtolower($extension); - $extension = substr($extension, 1); //remove leading . + $extension = substr($extension, 1); // remove leading . return $this->mimetypes[$extension][0] ?? 'application/octet-stream'; } } diff --git a/lib/public/Files/IMimeTypeDetector.php b/lib/public/Files/IMimeTypeDetector.php index 1c683cdd4b9..6f3e498c203 100644 --- a/lib/public/Files/IMimeTypeDetector.php +++ b/lib/public/Files/IMimeTypeDetector.php @@ -73,4 +73,10 @@ interface IMimeTypeDetector { * @since 28.0.0 */ public function getAllAliases(): array; + + /** + * @return array<string, list{string, string|null}> + * @since 32.0.0 + */ + public function getAllMappings(): array; } diff --git a/lib/public/Files/IMimeTypeLoader.php b/lib/public/Files/IMimeTypeLoader.php index 44261527d53..77c59fb2c0a 100644 --- a/lib/public/Files/IMimeTypeLoader.php +++ b/lib/public/Files/IMimeTypeLoader.php @@ -47,4 +47,14 @@ interface IMimeTypeLoader { * @since 8.2.0 */ public function reset(): void; + + /** + * Update filecache mimetype based on file extension + * + * @param string $ext + * @param int $mimeTypeId + * @return int + * @since 32.0.0 + */ + public function updateFilecache(string $ext, int $mimeTypeId): int; } diff --git a/tests/lib/Files/Type/DetectionTest.php b/tests/lib/Files/Type/DetectionTest.php index dcbb455efc9..a11a59bed1e 100644 --- a/tests/lib/Files/Type/DetectionTest.php +++ b/tests/lib/Files/Type/DetectionTest.php @@ -100,6 +100,41 @@ class DetectionTest extends \Test\TestCase { $this->assertEquals($expected, $result); } + public function dataMimeTypeCustom(): array { + return [ + ['123', 'foobar/123'], + ['a123', 'foobar/123'], + ['bar', 'foobar/bar'], + ]; + } + + /** + * @dataProvider dataMimeTypeCustom + * + * @param string $ext + * @param string $mime + */ + public function testDetectMimeTypeCustom(string $ext, string $mime): void { + $confDir = sys_get_temp_dir(); + file_put_contents($confDir . '/mimetypemapping.dist.json', json_encode([])); + + /** @var IURLGenerator $urlGenerator */ + $urlGenerator = $this->getMockBuilder(IURLGenerator::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var LoggerInterface $logger */ + $logger = $this->createMock(LoggerInterface::class); + + // Create new mapping file + file_put_contents($confDir . '/mimetypemapping.dist.json', json_encode([$ext => [$mime]])); + + $detection = new Detection($urlGenerator, $logger, $confDir, $confDir); + $mappings = $detection->getAllMappings(); + $this->assertArrayHasKey($ext, $mappings); + $this->assertEquals($mime, $detection->detectPath('foo.' . $ext)); + } + public function dataGetSecureMimeType(): array { return [ ['image/svg+xml', 'text/plain'], |