diff --git a/lib/private/Files/Type/Detection.php b/lib/private/Files/Type/Detection.php index 6af6ce1a0b1e4..2fa2db71ddcd0 100644 --- a/lib/private/Files/Type/Detection.php +++ b/lib/private/Files/Type/Detection.php @@ -97,7 +97,7 @@ private function loadCustomDefinitions(string $fileName, array $definitions): ar if (file_exists($this->customConfigDir . '/' . $fileName)) { $custom = json_decode(file_get_contents($this->customConfigDir . '/' . $fileName), true); if (json_last_error() === JSON_ERROR_NONE) { - $definitions = array_merge($definitions, $custom); + $definitions = array_replace($definitions, $custom); } else { $this->logger->warning('Failed to parse ' . $fileName . ': ' . json_last_error_msg()); } diff --git a/tests/lib/Files/Type/DetectionTest.php b/tests/lib/Files/Type/DetectionTest.php index c30b21de401d2..6e4a4f4c70c21 100644 --- a/tests/lib/Files/Type/DetectionTest.php +++ b/tests/lib/Files/Type/DetectionTest.php @@ -117,24 +117,72 @@ public static function dataMimeTypeCustom(): array { */ #[\PHPUnit\Framework\Attributes\DataProvider('dataMimeTypeCustom')] 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]])); + $tmpDir = sys_get_temp_dir() . '/nc-detect-' . uniqid('', true); + mkdir($tmpDir, 0700); + + try { + // Create a default / shipped mapping file (dist) + file_put_contents($tmpDir . '/mimetypemapping.dist.json', json_encode([])); + + // Create new custom mapping file that should be picked up by Detection + file_put_contents($tmpDir . '/mimetypemapping.json', json_encode([$ext => [$mime]])); + + /** @var IURLGenerator $urlGenerator */ + $urlGenerator = $this->getMockBuilder(IURLGenerator::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var LoggerInterface $logger */ + $logger = $this->createMock(LoggerInterface::class); + + $detection = new Detection($urlGenerator, $logger, $tmpDir, $tmpDir); + $mappings = $detection->getAllMappings(); + + $this->assertArrayHasKey($ext, $mappings); + $this->assertEquals($mime, $detection->detectPath('foo.' . $ext)); + } finally { + // cleanup + @unlink($tmpDir . '/mimetypemapping.json'); + @unlink($tmpDir . '/mimetypemapping.dist.json'); + @rmdir($tmpDir); + } + } - $detection = new Detection($urlGenerator, $logger, $confDir, $confDir); - $mappings = $detection->getAllMappings(); - $this->assertArrayHasKey($ext, $mappings); - $this->assertEquals($mime, $detection->detectPath('foo.' . $ext)); + public function testDetectMimeTypePreservesLeadingZeroKeys(): void { + $tmpDir = sys_get_temp_dir() . '/nc-detect-' . uniqid(); + mkdir($tmpDir, 0700); + try { + // Create a default / shipped mapping file (dist) + file_put_contents($tmpDir . '/mimetypemapping.dist.json', json_encode([])); + + // Create new custom mapping file with potentially problematic keys + $mappings = [ + '001' => ['application/x-zeroone', null], + '1' => ['application/x-one', null], + ]; + file_put_contents($tmpDir . '/mimetypemapping.json', json_encode($mappings)); + + /** @var IURLGenerator $urlGenerator */ + $urlGenerator = $this->getMockBuilder(IURLGenerator::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var LoggerInterface $logger */ + $logger = $this->createMock(LoggerInterface::class); + + $detection = new Detection($urlGenerator, $logger, $tmpDir, $tmpDir); + $mappings = $detection->getAllMappings(); + + $this->assertArrayHasKey('001', $mappings, 'Expected mapping to contain key "001"'); + $this->assertArrayHasKey('1', $mappings, 'Expected mapping to contain key "1"'); + + $this->assertEquals('application/x-zeroone', $detection->detectPath('foo.001')); + $this->assertEquals('application/x-one', $detection->detectPath('foo.1')); + } finally { + @unlink($tmpDir . '/mimetypemapping.json'); + @unlink($tmpDir . '/mimetypemapping.dist.json'); + @rmdir($tmpDir); + } } public static function dataGetSecureMimeType(): array {