Skip to content

Commit 6964531

Browse files
Merge pull request #50704 from nextcloud/backport/50660/stable30
[stable30] fix: make sure we process mime extensions as string
2 parents 2af31ab + 86408a5 commit 6964531

File tree

7 files changed

+70
-10
lines changed

7 files changed

+70
-10
lines changed

build/psalm-baseline.xml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,12 +1320,6 @@
13201320
<code><![CDATA[$this->timeFactory->getTime()]]></code>
13211321
</InvalidScalarArgument>
13221322
</file>
1323-
<file src="core/Command/Maintenance/Mimetype/UpdateDB.php">
1324-
<UndefinedInterfaceMethod>
1325-
<code><![CDATA[getAllMappings]]></code>
1326-
<code><![CDATA[updateFilecache]]></code>
1327-
</UndefinedInterfaceMethod>
1328-
</file>
13291323
<file src="core/Command/Preview/Repair.php">
13301324
<UndefinedInterfaceMethod>
13311325
<code><![CDATA[section]]></code>

core/Command/Maintenance/Mimetype/GenerateMimetypeFileBuilder.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ class GenerateMimetypeFileBuilder {
1818
public function generateFile(array $aliases): string {
1919
// Remove comments
2020
$aliases = array_filter($aliases, static function ($key) {
21+
// Single digit extensions will be treated as integers
22+
// Let's make sure they are strings
23+
// https://github.com/nextcloud/server/issues/42902
24+
$key = (string)$key;
2125
return !($key === '' || $key[0] === '_');
2226
}, ARRAY_FILTER_USE_KEY);
2327

core/Command/Maintenance/Mimetype/UpdateDB.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4545
$totalNewMimetypes = 0;
4646

4747
foreach ($mappings as $ext => $mimetypes) {
48+
// Single digit extensions will be treated as integers
49+
// Let's make sure they are strings
50+
// https://github.com/nextcloud/server/issues/42902
51+
$ext = (string)$ext;
4852
if ($ext[0] === '_') {
4953
// comment
5054
continue;

lib/private/Files/Type/Detection.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Detection implements IMimeTypeDetector {
2323
private const CUSTOM_MIMETYPEMAPPING = 'mimetypemapping.json';
2424
private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json';
2525

26+
/** @var array<string, list{string, string|null}> */
2627
protected array $mimetypes = [];
2728
protected array $secureMimeTypes = [];
2829

@@ -52,6 +53,8 @@ public function __construct(
5253
public function registerType(string $extension,
5354
string $mimetype,
5455
?string $secureMimeType = null): void {
56+
// Make sure the extension is a string
57+
// https://github.com/nextcloud/server/issues/42902
5558
$this->mimetypes[$extension] = [$mimetype, $secureMimeType];
5659
$this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype;
5760
}
@@ -66,13 +69,17 @@ public function registerType(string $extension,
6669
* @param array $types
6770
*/
6871
public function registerTypeArray(array $types): void {
69-
$this->mimetypes = array_merge($this->mimetypes, $types);
72+
// Register the types,
73+
foreach ($types as $extension => $mimeType) {
74+
$this->registerType((string)$extension, $mimeType[0], $mimeType[1] ?? null);
75+
}
7076

7177
// Update the alternative mimetypes to avoid having to look them up each time.
7278
foreach ($this->mimetypes as $extension => $mimeType) {
73-
if (str_starts_with($extension, '_comment')) {
79+
if (str_starts_with((string)$extension, '_comment')) {
7480
continue;
7581
}
82+
7683
$this->secureMimeTypes[$mimeType[0]] = $mimeType[1] ?? $mimeType[0];
7784
if (isset($mimeType[1])) {
7885
$this->secureMimeTypes[$mimeType[1]] = $mimeType[1];
@@ -133,7 +140,7 @@ private function loadMappings(): void {
133140
}
134141

135142
/**
136-
* @return array
143+
* @return array<string, list{string, string|null}>
137144
*/
138145
public function getAllMappings(): array {
139146
$this->loadMappings();
@@ -163,7 +170,7 @@ public function detectPath($path): string {
163170
$extension = strrchr($fileName, '.');
164171
if ($extension !== false) {
165172
$extension = strtolower($extension);
166-
$extension = substr($extension, 1); //remove leading .
173+
$extension = substr($extension, 1); // remove leading .
167174
return $this->mimetypes[$extension][0] ?? 'application/octet-stream';
168175
}
169176
}

lib/public/Files/IMimeTypeDetector.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,10 @@ public function mimeTypeIcon($mimeType);
7373
* @since 28.0.0
7474
*/
7575
public function getAllAliases(): array;
76+
77+
/**
78+
* @return array<string, list{string, string|null}>
79+
* @since 32.0.0
80+
*/
81+
public function getAllMappings(): array;
7682
}

lib/public/Files/IMimeTypeLoader.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,14 @@ public function exists(string $mimetype): bool;
4747
* @since 8.2.0
4848
*/
4949
public function reset(): void;
50+
51+
/**
52+
* Update filecache mimetype based on file extension
53+
*
54+
* @param string $ext
55+
* @param int $mimeTypeId
56+
* @return int
57+
* @since 32.0.0
58+
*/
59+
public function updateFilecache(string $ext, int $mimeTypeId): int;
5060
}

tests/lib/Files/Type/DetectionTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,41 @@ public function testDetectString(): void {
100100
$this->assertEquals($expected, $result);
101101
}
102102

103+
public function dataMimeTypeCustom(): array {
104+
return [
105+
['123', 'foobar/123'],
106+
['a123', 'foobar/123'],
107+
['bar', 'foobar/bar'],
108+
];
109+
}
110+
111+
/**
112+
* @dataProvider dataMimeTypeCustom
113+
*
114+
* @param string $ext
115+
* @param string $mime
116+
*/
117+
public function testDetectMimeTypeCustom(string $ext, string $mime): void {
118+
$confDir = sys_get_temp_dir();
119+
file_put_contents($confDir . '/mimetypemapping.dist.json', json_encode([]));
120+
121+
/** @var IURLGenerator $urlGenerator */
122+
$urlGenerator = $this->getMockBuilder(IURLGenerator::class)
123+
->disableOriginalConstructor()
124+
->getMock();
125+
126+
/** @var LoggerInterface $logger */
127+
$logger = $this->createMock(LoggerInterface::class);
128+
129+
// Create new mapping file
130+
file_put_contents($confDir . '/mimetypemapping.dist.json', json_encode([$ext => [$mime]]));
131+
132+
$detection = new Detection($urlGenerator, $logger, $confDir, $confDir);
133+
$mappings = $detection->getAllMappings();
134+
$this->assertArrayHasKey($ext, $mappings);
135+
$this->assertEquals($mime, $detection->detectPath('foo.' . $ext));
136+
}
137+
103138
public function dataGetSecureMimeType(): array {
104139
return [
105140
['image/svg+xml', 'text/plain'],

0 commit comments

Comments
 (0)