@@ -48,15 +48,19 @@ public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
4848 $ svg ->setBackgroundColor (new \ImagickPixel ('transparent ' ));
4949
5050 $ content = stream_get_contents ($ file ->fopen ('r ' ));
51- if (substr ( $ content, 0 , 5 ) !== ' <?xml ' ) {
52- $ content = ' <?xml version="1.0" encoding="UTF-8" standalone="no"?> ' . $ content ;
51+ if ($ content === false ) {
52+ return null ;
5353 }
54-
55- // Do not parse SVG files with references
56- if (preg_match ('/["\s](xlink:)?href\s*=/i ' , $ content )) {
54+ // check if the file can be processed by this provider
55+ if (!$ this ->canBeProcessed ($ content )) {
5756 return null ;
5857 }
5958
59+ $ content = ltrim ($ content );
60+ if (substr ($ content , 0 , 5 ) !== '<?xml ' ) {
61+ $ content = '<?xml version="1.0" encoding="UTF-8" standalone="no"?> ' . $ content ;
62+ }
63+
6064 $ svg ->readImageBlob ($ content );
6165 $ svg ->setImageFormat ('png32 ' );
6266 } catch (\Exception $ e ) {
@@ -78,4 +82,30 @@ public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
7882 }
7983 return null ;
8084 }
85+
86+ /**
87+ * Check if the file can be processed by this provider,
88+ * meaning the SVG is safe to be processed and does not contain any external references.
89+ */
90+ protected function canBeProcessed (string $ content ): bool {
91+ // check for allowed encodings and convert if necessary
92+ $ encoding = mb_detect_encoding ($ content , ['ISO-2022-JP ' , 'UTF-8 ' , 'ISO-8859-1 ' ], true );
93+ if ($ encoding === false ) {
94+ return false ;
95+ } elseif ($ encoding !== 'UTF-8 ' ) {
96+ $ content = mb_convert_encoding ($ content , 'UTF-8 ' , $ encoding );
97+ }
98+
99+ // Strip all non-printable/control characters except newlines/tabs
100+ $ content = preg_replace ('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/ ' , '' , $ content );
101+ if ($ content === null ) {
102+ return false ;
103+ }
104+
105+ // check for any potential external reference (include custom namespace prefix)
106+ if (preg_match ('/["\s \']([a-z_][a-z0-9_.-]*:)?href\s*=/i ' , $ content )) {
107+ return false ;
108+ }
109+ return true ;
110+ }
81111}
0 commit comments