Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/blocksy-companion-pro/framework/features/svg.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 +
3 + namespace Blocksy;
4 +
5 + class SvgHandling {
6 + public function __construct() {
7 + add_filter(
8 + 'wp_handle_upload_prefilter',
9 + function ($file) {
10 + $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
11 +
12 + if ('svg' !== $extension) {
13 + return $file;
14 + }
15 +
16 + if (! apply_filters('blocksy:svg:should_sanitize', true)) {
17 + return $file;
18 + }
19 +
20 + $svg_content = file_get_contents($file['tmp_name']);
21 +
22 + $trimmed_content = trim($svg_content);
23 +
24 + if (
25 + strpos($trimmed_content, '<?xml') !== 0
26 + &&
27 + strpos($trimmed_content, '<svg') !== 0
28 + ) {
29 + $file['error'] = __('This file does not appear to be a valid SVG file.', 'blocksy-companion');
30 + return $file;
31 + }
32 +
33 + if (
34 + stripos($svg_content, '<?php') !== false
35 + ||
36 + stripos($svg_content, '<?=') !== false
37 + ) {
38 + $file['error'] = __('SVG files cannot contain PHP code.', 'blocksy-companion');
39 + return $file;
40 + }
41 +
42 + $sanitized_content = $this->cleanup_svg($svg_content);
43 +
44 + file_put_contents($file['tmp_name'], $sanitized_content);
45 +
46 + return $file;
47 + }
48 + );
49 +
50 + add_filter(
51 + 'wp_get_attachment_metadata',
52 + [$this, 'filter_get_attachment_metadata'],
53 + 10, 2
54 + );
55 +
56 + add_filter(
57 + 'wp_update_attachment_metadata',
58 + [$this, 'filter_get_attachment_metadata'],
59 + 10, 2
60 + );
61 +
62 + add_filter(
63 + 'wp_get_attachment_image_src',
64 + function ($image, $attachment_id, $size, $icon) {
65 + if (! isset($attachment_id)) {
66 + return $image;
67 + }
68 +
69 + $mime = get_post_mime_type($attachment_id);
70 +
71 + if (
72 + 'image/svg+xml' === $mime
73 + &&
74 + $image[1] === 1
75 + &&
76 + $image[2] === 1
77 + ) {
78 + $dimensions = $this->get_dimensions_for($attachment_id);
79 +
80 + $image[2] = $dimensions['height'];
81 + $image[1] = $dimensions['width'];
82 + }
83 +
84 + return $image;
85 + },
86 + 10, 4
87 + );
88 +
89 + $should_add_filter = true;
90 +
91 + // Avoid adding the filter during image cropping to prevent issues with SVGs.
92 + // WP can't locate editor for SVGs so it throws an error.
93 + if (
94 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
95 + isset($_REQUEST['action'])
96 + &&
97 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
98 + $_REQUEST['action'] === 'crop-image'
99 + ) {
100 + $should_add_filter = false;
101 + }
102 +
103 + if ($should_add_filter) {
104 + add_filter('upload_mimes', [$this, 'upload_mimes']);
105 + add_filter('wp_check_filetype_and_ext', [$this, 'wp_check_filetype_and_ext'], 75, 4);
106 + }
107 + }
108 +
109 + public function wp_check_filetype_and_ext($data = null, $file = null, $filename = null, $mimes = null) {
110 + $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
111 +
112 + // Only accept files with .svg as the final extension
113 + // Reject files like test.svg.php, test.svg.jpg, etc.
114 + if ($extension === 'svg') {
115 + $data['type'] = 'image/svg+xml';
116 + $data['ext'] = 'svg';
117 + }
118 +
119 + return $data;
120 + }
121 +
122 + public function upload_mimes($mimes) {
123 + $mimes['svg'] = 'image/svg+xml';
124 + return $mimes;
125 + }
126 +
127 + public function filter_get_attachment_metadata($data, $attachment_id) {
128 + $mime = get_post_mime_type($attachment_id);
129 +
130 + if (
131 + 'image/svg+xml' === $mime
132 + &&
133 + is_array($data)
134 + &&
135 + (
136 + ! isset($data['width'])
137 + ||
138 + ! isset($data['height'])
139 + )
140 + ) {
141 + $dimensions = $this->get_dimensions_for($attachment_id);
142 +
143 + $data['width'] = $dimensions['width'];
144 + $data['height'] = $dimensions['height'];
145 + }
146 +
147 + return $data;
148 + }
149 +
150 + public function get_dimensions_for($attachment_id) {
151 + $height = 100;
152 + $width = 100;
153 +
154 + $maybe_file = get_attached_file($attachment_id);
155 +
156 + if ($maybe_file) {
157 + $dimensions = $this->svg_dimensions($maybe_file);
158 +
159 + if ($dimensions) {
160 + $height = round($dimensions['height']);
161 + $width = round($dimensions['width']);
162 + }
163 + }
164 +
165 + return [
166 + 'height' => $height,
167 + 'width' => $width
168 + ];
169 + }
170 +
171 + public function svg_dimensions($svg) {
172 + if (
173 + ! preg_match('/.svg$/', $svg)
174 + ||
175 + ! file_exists($svg)
176 + ) {
177 + return null;
178 + }
179 +
180 + $svg = file_get_contents($svg);
181 +
182 + $attributes = new \stdClass();
183 +
184 + if ($svg && function_exists('simplexml_load_string')) {
185 + $svg = @simplexml_load_string($svg);
186 +
187 + if ($svg) {
188 + foreach ($svg->attributes() as $key => $value) {
189 + $attributes->{$key} = strval($value);
190 + }
191 + }
192 + }
193 +
194 + if (
195 + ! isset($attributes->width)
196 + &&
197 + $svg
198 + &&
199 + function_exists('xml_parser_create')
200 + ) {
201 + $xml = xml_parser_create('UTF-8');
202 +
203 + $svgData = new \stdClass();
204 +
205 + xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, false);
206 + xml_set_element_handler(
207 + $xml,
208 + function ($parser, $name, $attrs) use (&$svgData) {
209 + if ($name === 'SVG') {
210 + if (isset($attrs['WIDTH'])) {
211 + $attrs['width'] = $attrs['WIDTH'];
212 + }
213 +
214 + if (isset($attrs['HEIGHT'])) {
215 + $attrs['height'] = $attrs['HEIGHT'];
216 + }
217 +
218 + if (isset($attrs['VIEWBOX'])) {
219 + $attrs['viewBox'] = $attrs['VIEWBOX'];
220 + }
221 +
222 + foreach ($attrs as $key => $value) {
223 + $svgData->{$key} = $value;
224 + }
225 + }
226 + },
227 + function ($parser, $tag) {
228 + }
229 + );
230 +
231 + if (xml_parse($xml, $svg, true)) {
232 + $attributes = $svgData;
233 + }
234 +
235 + xml_parser_free($xml);
236 + }
237 +
238 + $width = 0;
239 + $height = 0;
240 +
241 + if (empty($attributes)) {
242 + return false;
243 + }
244 +
245 + if (
246 + isset($attributes->width, $attributes->height)
247 + &&
248 + is_numeric($attributes->width)
249 + &&
250 + is_numeric($attributes->height)
251 + ) {
252 + $width = floatval($attributes->width);
253 + $height = floatval($attributes->height);
254 + } elseif (isset($attributes->viewBox)) {
255 + $sizes = explode(' ', $attributes->viewBox);
256 +
257 + if (isset($sizes[2], $sizes[3])) {
258 + $width = floatval($sizes[2]);
259 + $height = floatval($sizes[3]);
260 + }
261 + } else {
262 + return false;
263 + }
264 +
265 + return [
266 + 'width' => $width,
267 + 'height' => $height,
268 + 'orientation' => ($width > $height) ? 'landscape' : 'portrait'
269 + ];
270 + }
271 +
272 + public function cleanup_svg($content) {
273 + $base_path = BLOCKSY_PATH . 'vendor/svg-sanitizer/src';
274 +
275 + require_once($base_path . '/data/AttributeInterface.php');
276 + require_once($base_path . '/data/TagInterface.php');
277 + require_once($base_path . '/data/AllowedAttributes.php');
278 + require_once($base_path . '/data/AllowedTags.php');
279 + require_once($base_path . '/data/XPath.php');
280 + require_once($base_path . '/ElementReference/Resolver.php');
281 + require_once($base_path . '/ElementReference/Subject.php');
282 + require_once($base_path . '/ElementReference/Usage.php');
283 + require_once($base_path . '/Exceptions/NestingException.php');
284 + require_once($base_path . '/Helper.php');
285 + require_once($base_path . '/Sanitizer.php');
286 +
287 + $sanitizer = new \blocksy\enshrined\svgSanitize\Sanitizer();
288 +
289 + // Remove <?xml tag from the SVG content to avoid html5
290 + // validation issues when embedding SVGs inline.
291 + $sanitizer->removeXMLTag(true);
292 +
293 + return $sanitizer->sanitize($content);
294 + }
295 + }
296 +
297 +