Passed
Push — master ( b4729c...919a8d )
by Roeland
25:37 queued 13:57
created
lib/private/Files/Type/Detection.php 1 patch
Indentation   +342 added lines, -342 removed lines patch added patch discarded remove patch
@@ -53,346 +53,346 @@
 block discarded – undo
53 53
  * @package OC\Files\Type
54 54
  */
55 55
 class Detection implements IMimeTypeDetector {
56
-	private const CUSTOM_MIMETYPEMAPPING = 'mimetypemapping.json';
57
-	private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json';
58
-
59
-	protected $mimetypes = [];
60
-	protected $secureMimeTypes = [];
61
-
62
-	protected $mimetypeIcons = [];
63
-	/** @var string[] */
64
-	protected $mimeTypeAlias = [];
65
-
66
-	/** @var IURLGenerator */
67
-	private $urlGenerator;
68
-
69
-	/** @var ILogger */
70
-	private $logger;
71
-
72
-	/** @var string */
73
-	private $customConfigDir;
74
-
75
-	/** @var string */
76
-	private $defaultConfigDir;
77
-
78
-	/**
79
-	 * @param IURLGenerator $urlGenerator
80
-	 * @param ILogger $logger
81
-	 * @param string $customConfigDir
82
-	 * @param string $defaultConfigDir
83
-	 */
84
-	public function __construct(IURLGenerator $urlGenerator,
85
-								ILogger $logger,
86
-								string $customConfigDir,
87
-								string $defaultConfigDir) {
88
-		$this->urlGenerator = $urlGenerator;
89
-		$this->logger = $logger;
90
-		$this->customConfigDir = $customConfigDir;
91
-		$this->defaultConfigDir = $defaultConfigDir;
92
-	}
93
-
94
-	/**
95
-	 * Add an extension -> mimetype mapping
96
-	 *
97
-	 * $mimetype is the assumed correct mime type
98
-	 * The optional $secureMimeType is an alternative to send to send
99
-	 * to avoid potential XSS.
100
-	 *
101
-	 * @param string $extension
102
-	 * @param string $mimetype
103
-	 * @param string|null $secureMimeType
104
-	 */
105
-	public function registerType(string $extension,
106
-								 string $mimetype,
107
-								 ?string $secureMimeType = null): void {
108
-		$this->mimetypes[$extension] = [$mimetype, $secureMimeType];
109
-		$this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype;
110
-	}
111
-
112
-	/**
113
-	 * Add an array of extension -> mimetype mappings
114
-	 *
115
-	 * The mimetype value is in itself an array where the first index is
116
-	 * the assumed correct mimetype and the second is either a secure alternative
117
-	 * or null if the correct is considered secure.
118
-	 *
119
-	 * @param array $types
120
-	 */
121
-	public function registerTypeArray(array $types): void {
122
-		$this->mimetypes = array_merge($this->mimetypes, $types);
123
-
124
-		// Update the alternative mimetypes to avoid having to look them up each time.
125
-		foreach ($this->mimetypes as $extension => $mimeType) {
126
-			if (strpos($extension, '_comment') === 0) {
127
-				continue;
128
-			}
129
-			$this->secureMimeTypes[$mimeType[0]] = $mimeType[1] ?? $mimeType[0];
130
-			if (isset($mimeType[1])) {
131
-				$this->secureMimeTypes[$mimeType[1]] = $mimeType[1];
132
-			}
133
-		}
134
-	}
135
-
136
-	private function loadCustomDefinitions(string $fileName, array $definitions): array {
137
-		if (file_exists($this->customConfigDir . '/' . $fileName)) {
138
-			$custom = json_decode(file_get_contents($this->customConfigDir . '/' . $fileName), true);
139
-			if (json_last_error() === JSON_ERROR_NONE) {
140
-				$definitions = array_merge($definitions, $custom);
141
-			} else {
142
-				$this->logger->warning('Failed to parse ' . $fileName . ': ' . json_last_error_msg());
143
-			}
144
-		}
145
-		return $definitions;
146
-	}
147
-
148
-	/**
149
-	 * Add the mimetype aliases if they are not yet present
150
-	 */
151
-	private function loadAliases(): void {
152
-		if (!empty($this->mimeTypeAlias)) {
153
-			return;
154
-		}
155
-
156
-		$this->mimeTypeAlias = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypealiases.dist.json'), true);
157
-		$this->mimeTypeAlias = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEALIASES, $this->mimeTypeAlias);
158
-	}
159
-
160
-	/**
161
-	 * @return string[]
162
-	 */
163
-	public function getAllAliases(): array {
164
-		$this->loadAliases();
165
-		return $this->mimeTypeAlias;
166
-	}
167
-
168
-	public function getOnlyDefaultAliases(): array {
169
-		$this->loadMappings();
170
-		$this->mimeTypeAlias = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypealiases.dist.json'), true);
171
-		return $this->mimeTypeAlias;
172
-	}
173
-
174
-	/**
175
-	 * Add mimetype mappings if they are not yet present
176
-	 */
177
-	private function loadMappings(): void {
178
-		if (!empty($this->mimetypes)) {
179
-			return;
180
-		}
181
-
182
-		$mimetypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true);
183
-		$mimetypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEMAPPING, $mimetypeMapping);
184
-
185
-		$this->registerTypeArray($mimetypeMapping);
186
-	}
187
-
188
-	/**
189
-	 * @return array
190
-	 */
191
-	public function getAllMappings(): array {
192
-		$this->loadMappings();
193
-		return $this->mimetypes;
194
-	}
195
-
196
-	/**
197
-	 * detect mimetype only based on filename, content of file is not used
198
-	 *
199
-	 * @param string $path
200
-	 * @return string
201
-	 */
202
-	public function detectPath($path): string {
203
-		$this->loadMappings();
204
-
205
-		$fileName = basename($path);
206
-
207
-		// remove leading dot on hidden files with a file extension
208
-		$fileName = ltrim($fileName, '.');
209
-
210
-		// note: leading dot doesn't qualify as extension
211
-		if (strpos($fileName, '.') > 0) {
212
-
213
-			// remove versioning extension: name.v1508946057 and transfer extension: name.ocTransferId2057600214.part
214
-			$fileName = preg_replace('!((\.v\d+)|((\.ocTransferId\d+)?\.part))$!', '', $fileName);
215
-
216
-			//try to guess the type by the file extension
217
-			$extension = strrchr($fileName, '.');
218
-			if ($extension !== false) {
219
-				$extension = strtolower($extension);
220
-				$extension = substr($extension, 1); //remove leading .
221
-				return $this->mimetypes[$extension][0] ?? 'application/octet-stream';
222
-			}
223
-		}
224
-
225
-		return 'application/octet-stream';
226
-	}
227
-
228
-	/**
229
-	 * detect mimetype only based on the content of file
230
-	 * @param string $path
231
-	 * @return string
232
-	 * @since 18.0.0
233
-	 */
234
-	public function detectContent(string $path): string {
235
-		$this->loadMappings();
236
-
237
-		if (@is_dir($path)) {
238
-			// directories are easy
239
-			return 'httpd/unix-directory';
240
-		}
241
-
242
-		if (function_exists('finfo_open')
243
-			&& function_exists('finfo_file')
244
-			&& $finfo = finfo_open(FILEINFO_MIME)) {
245
-			$info = @finfo_file($finfo, $path);
246
-			finfo_close($finfo);
247
-			if ($info) {
248
-				$info = strtolower($info);
249
-				$mimeType = strpos($info, ';') !== false ? substr($info, 0, strpos($info, ';')) : $info;
250
-				$mimeType = $this->getSecureMimeType($mimeType);
251
-				if ($mimeType !== 'application/octet-stream') {
252
-					return $mimeType;
253
-				}
254
-			}
255
-		}
256
-
257
-		if (strpos($path, '://') !== false && strpos($path, 'file://') === 0) {
258
-			// Is the file wrapped in a stream?
259
-			return 'application/octet-stream';
260
-		}
261
-
262
-		if (function_exists('mime_content_type')) {
263
-			// use mime magic extension if available
264
-			$mimeType = mime_content_type($path);
265
-			if ($mimeType !== false) {
266
-				$mimeType = $this->getSecureMimeType($mimeType);
267
-				if ($mimeType !== 'application/octet-stream') {
268
-					return $mimeType;
269
-				}
270
-			}
271
-		}
272
-
273
-		if (\OC_Helper::canExecute('file')) {
274
-			// it looks like we have a 'file' command,
275
-			// lets see if it does have mime support
276
-			$path = escapeshellarg($path);
277
-			$fp = popen("test -f $path && file -b --mime-type $path", 'r');
278
-			$mimeType = fgets($fp);
279
-			pclose($fp);
280
-
281
-			if ($mimeType !== false) {
282
-				//trim the newline
283
-				$mimeType = trim($mimeType);
284
-				$mimeType = $this->getSecureMimeType($mimeType);
285
-				if ($mimeType !== 'application/octet-stream') {
286
-					return $mimeType;
287
-				}
288
-			}
289
-		}
290
-		return 'application/octet-stream';
291
-	}
292
-
293
-	/**
294
-	 * detect mimetype based on both filename and content
295
-	 *
296
-	 * @param string $path
297
-	 * @return string
298
-	 */
299
-	public function detect($path): string {
300
-		$mimeType = $this->detectPath($path);
301
-
302
-		if ($mimeType !== 'application/octet-stream') {
303
-			return $mimeType;
304
-		}
305
-
306
-		return $this->detectContent($path);
307
-	}
308
-
309
-	/**
310
-	 * detect mimetype based on the content of a string
311
-	 *
312
-	 * @param string $data
313
-	 * @return string
314
-	 */
315
-	public function detectString($data): string {
316
-		if (function_exists('finfo_open') && function_exists('finfo_file')) {
317
-			$finfo = finfo_open(FILEINFO_MIME);
318
-			$info = finfo_buffer($finfo, $data);
319
-			return strpos($info, ';') !== false ? substr($info, 0, strpos($info, ';')) : $info;
320
-		}
321
-
322
-		$tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
323
-		$fh = fopen($tmpFile, 'wb');
324
-		fwrite($fh, $data, 8024);
325
-		fclose($fh);
326
-		$mime = $this->detect($tmpFile);
327
-		unset($tmpFile);
328
-		return $mime;
329
-	}
330
-
331
-	/**
332
-	 * Get a secure mimetype that won't expose potential XSS.
333
-	 *
334
-	 * @param string $mimeType
335
-	 * @return string
336
-	 */
337
-	public function getSecureMimeType($mimeType): string {
338
-		$this->loadMappings();
339
-
340
-		return $this->secureMimeTypes[$mimeType] ?? 'application/octet-stream';
341
-	}
342
-
343
-	/**
344
-	 * Get path to the icon of a file type
345
-	 * @param string $mimetype the MIME type
346
-	 * @return string the url
347
-	 */
348
-	public function mimeTypeIcon($mimetype): string {
349
-		$this->loadAliases();
350
-
351
-		while (isset($this->mimeTypeAlias[$mimetype])) {
352
-			$mimetype = $this->mimeTypeAlias[$mimetype];
353
-		}
354
-		if (isset($this->mimetypeIcons[$mimetype])) {
355
-			return $this->mimetypeIcons[$mimetype];
356
-		}
357
-
358
-		// Replace slash and backslash with a minus
359
-		$icon = str_replace(['/', '\\'], '-', $mimetype);
360
-
361
-		// Is it a dir?
362
-		if ($mimetype === 'dir') {
363
-			$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder.svg');
364
-			return $this->mimetypeIcons[$mimetype];
365
-		}
366
-		if ($mimetype === 'dir-shared') {
367
-			$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-shared.svg');
368
-			return $this->mimetypeIcons[$mimetype];
369
-		}
370
-		if ($mimetype === 'dir-external') {
371
-			$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-external.svg');
372
-			return $this->mimetypeIcons[$mimetype];
373
-		}
374
-
375
-		// Icon exists?
376
-		try {
377
-			$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $icon . '.svg');
378
-			return $this->mimetypeIcons[$mimetype];
379
-		} catch (\RuntimeException $e) {
380
-			// Specified image not found
381
-		}
382
-
383
-		// Try only the first part of the filetype
384
-
385
-		if (strpos($icon, '-')) {
386
-			$mimePart = substr($icon, 0, strpos($icon, '-'));
387
-			try {
388
-				$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $mimePart . '.svg');
389
-				return $this->mimetypeIcons[$mimetype];
390
-			} catch (\RuntimeException $e) {
391
-				// Image for the first part of the mimetype not found
392
-			}
393
-		}
394
-
395
-		$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/file.svg');
396
-		return $this->mimetypeIcons[$mimetype];
397
-	}
56
+    private const CUSTOM_MIMETYPEMAPPING = 'mimetypemapping.json';
57
+    private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json';
58
+
59
+    protected $mimetypes = [];
60
+    protected $secureMimeTypes = [];
61
+
62
+    protected $mimetypeIcons = [];
63
+    /** @var string[] */
64
+    protected $mimeTypeAlias = [];
65
+
66
+    /** @var IURLGenerator */
67
+    private $urlGenerator;
68
+
69
+    /** @var ILogger */
70
+    private $logger;
71
+
72
+    /** @var string */
73
+    private $customConfigDir;
74
+
75
+    /** @var string */
76
+    private $defaultConfigDir;
77
+
78
+    /**
79
+     * @param IURLGenerator $urlGenerator
80
+     * @param ILogger $logger
81
+     * @param string $customConfigDir
82
+     * @param string $defaultConfigDir
83
+     */
84
+    public function __construct(IURLGenerator $urlGenerator,
85
+                                ILogger $logger,
86
+                                string $customConfigDir,
87
+                                string $defaultConfigDir) {
88
+        $this->urlGenerator = $urlGenerator;
89
+        $this->logger = $logger;
90
+        $this->customConfigDir = $customConfigDir;
91
+        $this->defaultConfigDir = $defaultConfigDir;
92
+    }
93
+
94
+    /**
95
+     * Add an extension -> mimetype mapping
96
+     *
97
+     * $mimetype is the assumed correct mime type
98
+     * The optional $secureMimeType is an alternative to send to send
99
+     * to avoid potential XSS.
100
+     *
101
+     * @param string $extension
102
+     * @param string $mimetype
103
+     * @param string|null $secureMimeType
104
+     */
105
+    public function registerType(string $extension,
106
+                                    string $mimetype,
107
+                                 ?string $secureMimeType = null): void {
108
+        $this->mimetypes[$extension] = [$mimetype, $secureMimeType];
109
+        $this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype;
110
+    }
111
+
112
+    /**
113
+     * Add an array of extension -> mimetype mappings
114
+     *
115
+     * The mimetype value is in itself an array where the first index is
116
+     * the assumed correct mimetype and the second is either a secure alternative
117
+     * or null if the correct is considered secure.
118
+     *
119
+     * @param array $types
120
+     */
121
+    public function registerTypeArray(array $types): void {
122
+        $this->mimetypes = array_merge($this->mimetypes, $types);
123
+
124
+        // Update the alternative mimetypes to avoid having to look them up each time.
125
+        foreach ($this->mimetypes as $extension => $mimeType) {
126
+            if (strpos($extension, '_comment') === 0) {
127
+                continue;
128
+            }
129
+            $this->secureMimeTypes[$mimeType[0]] = $mimeType[1] ?? $mimeType[0];
130
+            if (isset($mimeType[1])) {
131
+                $this->secureMimeTypes[$mimeType[1]] = $mimeType[1];
132
+            }
133
+        }
134
+    }
135
+
136
+    private function loadCustomDefinitions(string $fileName, array $definitions): array {
137
+        if (file_exists($this->customConfigDir . '/' . $fileName)) {
138
+            $custom = json_decode(file_get_contents($this->customConfigDir . '/' . $fileName), true);
139
+            if (json_last_error() === JSON_ERROR_NONE) {
140
+                $definitions = array_merge($definitions, $custom);
141
+            } else {
142
+                $this->logger->warning('Failed to parse ' . $fileName . ': ' . json_last_error_msg());
143
+            }
144
+        }
145
+        return $definitions;
146
+    }
147
+
148
+    /**
149
+     * Add the mimetype aliases if they are not yet present
150
+     */
151
+    private function loadAliases(): void {
152
+        if (!empty($this->mimeTypeAlias)) {
153
+            return;
154
+        }
155
+
156
+        $this->mimeTypeAlias = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypealiases.dist.json'), true);
157
+        $this->mimeTypeAlias = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEALIASES, $this->mimeTypeAlias);
158
+    }
159
+
160
+    /**
161
+     * @return string[]
162
+     */
163
+    public function getAllAliases(): array {
164
+        $this->loadAliases();
165
+        return $this->mimeTypeAlias;
166
+    }
167
+
168
+    public function getOnlyDefaultAliases(): array {
169
+        $this->loadMappings();
170
+        $this->mimeTypeAlias = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypealiases.dist.json'), true);
171
+        return $this->mimeTypeAlias;
172
+    }
173
+
174
+    /**
175
+     * Add mimetype mappings if they are not yet present
176
+     */
177
+    private function loadMappings(): void {
178
+        if (!empty($this->mimetypes)) {
179
+            return;
180
+        }
181
+
182
+        $mimetypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true);
183
+        $mimetypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEMAPPING, $mimetypeMapping);
184
+
185
+        $this->registerTypeArray($mimetypeMapping);
186
+    }
187
+
188
+    /**
189
+     * @return array
190
+     */
191
+    public function getAllMappings(): array {
192
+        $this->loadMappings();
193
+        return $this->mimetypes;
194
+    }
195
+
196
+    /**
197
+     * detect mimetype only based on filename, content of file is not used
198
+     *
199
+     * @param string $path
200
+     * @return string
201
+     */
202
+    public function detectPath($path): string {
203
+        $this->loadMappings();
204
+
205
+        $fileName = basename($path);
206
+
207
+        // remove leading dot on hidden files with a file extension
208
+        $fileName = ltrim($fileName, '.');
209
+
210
+        // note: leading dot doesn't qualify as extension
211
+        if (strpos($fileName, '.') > 0) {
212
+
213
+            // remove versioning extension: name.v1508946057 and transfer extension: name.ocTransferId2057600214.part
214
+            $fileName = preg_replace('!((\.v\d+)|((\.ocTransferId\d+)?\.part))$!', '', $fileName);
215
+
216
+            //try to guess the type by the file extension
217
+            $extension = strrchr($fileName, '.');
218
+            if ($extension !== false) {
219
+                $extension = strtolower($extension);
220
+                $extension = substr($extension, 1); //remove leading .
221
+                return $this->mimetypes[$extension][0] ?? 'application/octet-stream';
222
+            }
223
+        }
224
+
225
+        return 'application/octet-stream';
226
+    }
227
+
228
+    /**
229
+     * detect mimetype only based on the content of file
230
+     * @param string $path
231
+     * @return string
232
+     * @since 18.0.0
233
+     */
234
+    public function detectContent(string $path): string {
235
+        $this->loadMappings();
236
+
237
+        if (@is_dir($path)) {
238
+            // directories are easy
239
+            return 'httpd/unix-directory';
240
+        }
241
+
242
+        if (function_exists('finfo_open')
243
+            && function_exists('finfo_file')
244
+            && $finfo = finfo_open(FILEINFO_MIME)) {
245
+            $info = @finfo_file($finfo, $path);
246
+            finfo_close($finfo);
247
+            if ($info) {
248
+                $info = strtolower($info);
249
+                $mimeType = strpos($info, ';') !== false ? substr($info, 0, strpos($info, ';')) : $info;
250
+                $mimeType = $this->getSecureMimeType($mimeType);
251
+                if ($mimeType !== 'application/octet-stream') {
252
+                    return $mimeType;
253
+                }
254
+            }
255
+        }
256
+
257
+        if (strpos($path, '://') !== false && strpos($path, 'file://') === 0) {
258
+            // Is the file wrapped in a stream?
259
+            return 'application/octet-stream';
260
+        }
261
+
262
+        if (function_exists('mime_content_type')) {
263
+            // use mime magic extension if available
264
+            $mimeType = mime_content_type($path);
265
+            if ($mimeType !== false) {
266
+                $mimeType = $this->getSecureMimeType($mimeType);
267
+                if ($mimeType !== 'application/octet-stream') {
268
+                    return $mimeType;
269
+                }
270
+            }
271
+        }
272
+
273
+        if (\OC_Helper::canExecute('file')) {
274
+            // it looks like we have a 'file' command,
275
+            // lets see if it does have mime support
276
+            $path = escapeshellarg($path);
277
+            $fp = popen("test -f $path && file -b --mime-type $path", 'r');
278
+            $mimeType = fgets($fp);
279
+            pclose($fp);
280
+
281
+            if ($mimeType !== false) {
282
+                //trim the newline
283
+                $mimeType = trim($mimeType);
284
+                $mimeType = $this->getSecureMimeType($mimeType);
285
+                if ($mimeType !== 'application/octet-stream') {
286
+                    return $mimeType;
287
+                }
288
+            }
289
+        }
290
+        return 'application/octet-stream';
291
+    }
292
+
293
+    /**
294
+     * detect mimetype based on both filename and content
295
+     *
296
+     * @param string $path
297
+     * @return string
298
+     */
299
+    public function detect($path): string {
300
+        $mimeType = $this->detectPath($path);
301
+
302
+        if ($mimeType !== 'application/octet-stream') {
303
+            return $mimeType;
304
+        }
305
+
306
+        return $this->detectContent($path);
307
+    }
308
+
309
+    /**
310
+     * detect mimetype based on the content of a string
311
+     *
312
+     * @param string $data
313
+     * @return string
314
+     */
315
+    public function detectString($data): string {
316
+        if (function_exists('finfo_open') && function_exists('finfo_file')) {
317
+            $finfo = finfo_open(FILEINFO_MIME);
318
+            $info = finfo_buffer($finfo, $data);
319
+            return strpos($info, ';') !== false ? substr($info, 0, strpos($info, ';')) : $info;
320
+        }
321
+
322
+        $tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
323
+        $fh = fopen($tmpFile, 'wb');
324
+        fwrite($fh, $data, 8024);
325
+        fclose($fh);
326
+        $mime = $this->detect($tmpFile);
327
+        unset($tmpFile);
328
+        return $mime;
329
+    }
330
+
331
+    /**
332
+     * Get a secure mimetype that won't expose potential XSS.
333
+     *
334
+     * @param string $mimeType
335
+     * @return string
336
+     */
337
+    public function getSecureMimeType($mimeType): string {
338
+        $this->loadMappings();
339
+
340
+        return $this->secureMimeTypes[$mimeType] ?? 'application/octet-stream';
341
+    }
342
+
343
+    /**
344
+     * Get path to the icon of a file type
345
+     * @param string $mimetype the MIME type
346
+     * @return string the url
347
+     */
348
+    public function mimeTypeIcon($mimetype): string {
349
+        $this->loadAliases();
350
+
351
+        while (isset($this->mimeTypeAlias[$mimetype])) {
352
+            $mimetype = $this->mimeTypeAlias[$mimetype];
353
+        }
354
+        if (isset($this->mimetypeIcons[$mimetype])) {
355
+            return $this->mimetypeIcons[$mimetype];
356
+        }
357
+
358
+        // Replace slash and backslash with a minus
359
+        $icon = str_replace(['/', '\\'], '-', $mimetype);
360
+
361
+        // Is it a dir?
362
+        if ($mimetype === 'dir') {
363
+            $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder.svg');
364
+            return $this->mimetypeIcons[$mimetype];
365
+        }
366
+        if ($mimetype === 'dir-shared') {
367
+            $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-shared.svg');
368
+            return $this->mimetypeIcons[$mimetype];
369
+        }
370
+        if ($mimetype === 'dir-external') {
371
+            $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-external.svg');
372
+            return $this->mimetypeIcons[$mimetype];
373
+        }
374
+
375
+        // Icon exists?
376
+        try {
377
+            $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $icon . '.svg');
378
+            return $this->mimetypeIcons[$mimetype];
379
+        } catch (\RuntimeException $e) {
380
+            // Specified image not found
381
+        }
382
+
383
+        // Try only the first part of the filetype
384
+
385
+        if (strpos($icon, '-')) {
386
+            $mimePart = substr($icon, 0, strpos($icon, '-'));
387
+            try {
388
+                $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $mimePart . '.svg');
389
+                return $this->mimetypeIcons[$mimetype];
390
+            } catch (\RuntimeException $e) {
391
+                // Image for the first part of the mimetype not found
392
+            }
393
+        }
394
+
395
+        $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/file.svg');
396
+        return $this->mimetypeIcons[$mimetype];
397
+    }
398 398
 }
Please login to merge, or discard this patch.