3838 */
3939abstract class Bitmap extends ProviderV2 {
4040
41+ /**
42+ * List of MIME types that this preview provider is allowed to process.
43+ *
44+ * These should correspond to the MIME types *identified* by Imagemagick
45+ * for files to be processed by this provider. These do / will not
46+ * necessarily need to match the MIME types stored in the database
47+ * (which are identified by IMimeTypeDetector).
48+ *
49+ * @return string Regular expression
50+ */
51+ abstract protected function getAllowedMimeTypes (): string ;
52+
53+
54+ /**
55+ * @return list<string>
56+ */
57+ abstract protected function getMagicStrings (): array ;
58+
59+ abstract protected function getImagickFormatHint (): string ;
60+
4161 /**
4262 * {@inheritDoc}
4363 */
@@ -91,8 +111,19 @@ public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
91111 private function getResizedPreview ($ tmpPath , $ maxX , $ maxY ) {
92112 $ bp = new Imagick ();
93113
114+ if (!$ this ->isMagicStringSupported ($ tmpPath )) {
115+ throw new \Exception ('Invalid image type: magic string not recognized ' );
116+ }
117+
118+ // Validate mime type
119+ $ bp ->pingImage ($ this ->getImagickFormatHint () . ': ' . $ tmpPath . '[0] ' );
120+ $ mimeType = $ bp ->getImageMimeType ();
121+ if (!preg_match ($ this ->getAllowedMimeTypes (), $ mimeType )) {
122+ throw new \Exception ('File mime type does not match the preview provider: ' . $ mimeType );
123+ }
124+
94125 // Layer 0 contains either the bitmap or a flat representation of all vector layers
95- $ bp ->readImage ($ tmpPath . '[0] ' );
126+ $ bp ->readImage ($ this -> getImagickFormatHint () . ' : ' . $ tmpPath . '[0] ' );
96127
97128 $ bp = $ this ->resize ($ bp , $ maxX , $ maxY );
98129
@@ -101,6 +132,22 @@ private function getResizedPreview($tmpPath, $maxX, $maxY) {
101132 return $ bp ;
102133 }
103134
135+ private function isMagicStringSupported (string $ filepath ): bool {
136+ $ signatures = $ this ->getMagicStrings ();
137+ if (empty ($ signatures )) {
138+ return true ;
139+ }
140+ $ length = array_reduce ($ signatures , static fn (int $ carry , string $ signature ) => max ($ carry , strlen ($ signature )), 0 );
141+ $ firstBytes = file_get_contents ($ filepath , false , null , 0 , $ length );
142+ foreach ($ signatures as $ signature ) {
143+ if (str_starts_with ($ firstBytes , $ signature )) {
144+ return true ;
145+ }
146+ }
147+
148+ return false ;
149+ }
150+
104151 /**
105152 * Returns a resized \Imagick object
106153 *
0 commit comments