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+ * @return list<string>
55+ */
56+ abstract protected function getMagicStrings (): array ;
57+
58+ abstract protected function getImagickFormatHint (): string ;
59+
4160 /**
4261 * {@inheritDoc}
4362 */
@@ -87,12 +106,25 @@ public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
87106 * @param int $maxY
88107 *
89108 * @return \Imagick
109+ *
110+ * @throws \Exception
90111 */
91112 private function getResizedPreview ($ tmpPath , $ maxX , $ maxY ) {
92113 $ bp = new Imagick ();
93114
115+ if (!$ this ->isMagicStringSupported ($ tmpPath )) {
116+ throw new \Exception ('Invalid image type: magic string not recognized ' );
117+ }
118+
119+ // Validate mime type
120+ $ bp ->pingImage ($ this ->getImagickFormatHint () . ': ' . $ tmpPath . '[0] ' );
121+ $ mimeType = $ bp ->getImageMimeType ();
122+ if (!preg_match ($ this ->getAllowedMimeTypes (), $ mimeType )) {
123+ throw new \Exception ('File mime type does not match the preview provider: ' . $ mimeType );
124+ }
125+
94126 // Layer 0 contains either the bitmap or a flat representation of all vector layers
95- $ bp ->readImage ($ tmpPath . '[0] ' );
127+ $ bp ->readImage ($ this -> getImagickFormatHint () . ' : ' . $ tmpPath . '[0] ' );
96128
97129 $ bp = $ this ->resize ($ bp , $ maxX , $ maxY );
98130
@@ -101,6 +133,22 @@ private function getResizedPreview($tmpPath, $maxX, $maxY) {
101133 return $ bp ;
102134 }
103135
136+ private function isMagicStringSupported (string $ filepath ): bool {
137+ $ signatures = $ this ->getMagicStrings ();
138+ if (empty ($ signatures )) {
139+ return true ;
140+ }
141+ $ length = array_reduce ($ signatures , static fn (int $ carry , string $ signature ) => max ($ carry , strlen ($ signature )), 0 );
142+ $ firstBytes = file_get_contents ($ filepath , false , null , 0 , $ length );
143+ foreach ($ signatures as $ signature ) {
144+ if (str_starts_with ($ firstBytes , $ signature )) {
145+ return true ;
146+ }
147+ }
148+
149+ return false ;
150+ }
151+
104152 /**
105153 * Returns a resized \Imagick object
106154 *
0 commit comments