]> BookStack Code Mirror - bookstack/blob - app/Util/WebSafeMimeSniffer.php
6861add724dbf2bf1ca6a0a34bd8ae4109b66ded
[bookstack] / app / Util / WebSafeMimeSniffer.php
1 <?php
2
3 namespace BookStack\Util;
4
5 use finfo;
6
7 /**
8  * Helper class to sniff out the mime-type of content resulting in
9  * a mime-type that's relatively safe to serve to a browser.
10  */
11 class WebSafeMimeSniffer
12 {
13     /**
14      * @var string[]
15      */
16     protected $safeMimes = [
17         'application/json',
18         'application/octet-stream',
19         'application/pdf',
20         'audio/aac',
21         'audio/midi',
22         'audio/mpeg',
23         'audio/ogg',
24         'audio/opus',
25         'audio/wav',
26         'audio/webm',
27         'image/apng',
28         'image/bmp',
29         'image/jpeg',
30         'image/png',
31         'image/gif',
32         'image/webp',
33         'image/avif',
34         'image/heic',
35         'text/css',
36         'text/csv',
37         'text/javascript',
38         'text/json',
39         'text/plain',
40         'video/x-msvideo',
41         'video/mp4',
42         'video/mpeg',
43         'video/ogg',
44         'video/webm',
45         'video/vp9',
46         'video/h264',
47         'video/av1',
48     ];
49
50     /**
51      * Sniff the mime-type from the given file content while running the result
52      * through an allow-list to ensure a web-safe result.
53      * Takes the content as a reference since the value may be quite large.
54      */
55     public function sniff(string &$content): string
56     {
57         $fInfo = new finfo(FILEINFO_MIME_TYPE);
58         $mime = $fInfo->buffer($content) ?: 'application/octet-stream';
59
60         if (in_array($mime, $this->safeMimes)) {
61             return $mime;
62         }
63
64         [$category] = explode('/', $mime, 2);
65         if ($category === 'text') {
66             return 'text/plain';
67         }
68
69         return 'application/octet-stream';
70     }
71 }