PluginProbe
Elementor Website Builder – more than just a page builder / 3.4.7
Elementor Website Builder – more than just a page builder v3.4.7
4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 All 455 releases
← All changes | core/files/assets/svg/svg-handler.php +620 -103 4.3.1 → 3.4.7 View file →
@@ -1,34 +1,25 @@
1 1 <?php
2 2 namespace Elementor\Core\Files\Assets\Svg;
3 3
4 4 use Elementor\Core\Files\Assets\Files_Upload_Handler;
5 -use Elementor\Core\Files\File_Types\Svg;
6 -use Elementor\Core\Files\Uploads_Manager;
7 -use Elementor\Plugin;
8 5
9 6 if ( ! defined( 'ABSPATH' ) ) {
10 7 exit; // Exit if accessed directly.
11 8 }
12 9
13 -/**
14 - * SVG Handler
15 - *
16 - * @deprecated 3.5.0 Use `Elementor\Core\Files\File_Types\Svg` instead, accessed by calling: `Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );`
17 - */
18 10 class Svg_Handler extends Files_Upload_Handler {
19 -
20 11 /**
21 12 * Inline svg attachment meta key
22 - *
23 - * @deprecated 3.5.0
24 13 */
25 14 const META_KEY = '_elementor_inline_svg';
26 15
16 + const SCRIPT_REGEX = '/(?:\w+script|data):/xi';
17 +
27 18 /**
28 - * @deprecated 3.5.0
19 + * @var \DOMDocument
29 20 */
30 - const SCRIPT_REGEX = '/(?:\w+script|data):/xi';
21 + private $svg_dom = null;
31 22
32 23 /**
33 24 * Attachment ID.
34 25 *
@@ -33,146 +24,592 @@
33 24 * Attachment ID.
34 25 *
35 26 * Holds the current attachment ID.
36 27 *
37 - * @deprecated 3.5.0
38 - *
39 28 * @var int
40 29 */
41 30 private $attachment_id;
42 31
43 - /**
44 - * @deprecated 3.5.0
45 - */
46 32 public static function get_name() {
47 33 return 'svg-handler';
48 34 }
49 35
50 36 /**
51 - * Get meta
52 - *
53 - * @deprecated 3.5.0
54 - *
37 + * get_meta
55 38 * @return mixed
56 39 */
57 40 protected function get_meta() {
58 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0' );
59 -
60 41 return get_post_meta( $this->attachment_id, self::META_KEY, true );
61 42 }
62 43
63 44 /**
64 - * Update meta
65 - *
66 - * @deprecated 3.5.0
67 - *
45 + * update_meta
68 46 * @param $meta
69 47 */
70 48 protected function update_meta( $meta ) {
71 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0' );
72 -
73 49 update_post_meta( $this->attachment_id, self::META_KEY, $meta );
74 50 }
75 51
76 52 /**
77 - * Delete meta
78 - *
79 - * @deprecated 3.5.0
53 + * delete_meta
80 54 */
81 55 protected function delete_meta() {
82 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0' );
83 -
84 56 delete_post_meta( $this->attachment_id, self::META_KEY );
85 57 }
86 58
87 - /**
88 - * Get mime type
89 - *
90 - * @deprecated 3.5.0
91 - */
92 59 public function get_mime_type() {
93 60 return 'image/svg+xml';
94 61 }
95 62
96 - /**
97 - * Get file type
98 - *
99 - * @deprecated 3.5.0
100 - */
101 63 public function get_file_type() {
102 64 return 'svg';
103 65 }
104 66
105 67 /**
106 - * Delete meta cache
107 - *
108 - * @deprecated 3.5.0 Use `Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' )->delete_meta_cache()` instead.
68 + * delete_meta_cache
109 69 */
110 70 public function delete_meta_cache() {
111 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Plugin::$instance->uploads_manager->get_file_type_handlers( \'svg\' )->delete_meta_cache()' );
71 + delete_post_meta_by_key( self::META_KEY );
72 + }
112 73
113 - /** @var Svg $svg_handler */
114 - $svg_handler = Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );
115 -
116 - $svg_handler->delete_meta_cache();
74 + /**
75 + * read_from_file
76 + * @return bool|string
77 + */
78 + public function read_from_file() {
79 + return file_get_contents( get_attached_file( $this->attachment_id ) );
117 80 }
118 81
119 82 /**
120 - * Get inline svg
121 - *
122 - * @deprecated 3.5.0 Use `Elementor\Core\Files\File_Types\Svg::get_inline_svg()` instead.
123 - *
83 + * get_inline_svg
124 84 * @param $attachment_id
125 85 *
126 86 * @return bool|mixed|string
127 87 */
128 88 public static function get_inline_svg( $attachment_id ) {
129 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Elementor\Core\Files\File_Types\Svg::get_inline_svg()' );
89 + $svg = get_post_meta( $attachment_id, self::META_KEY, true );
130 90
131 - return Svg::get_inline_svg( $attachment_id );
91 + if ( ! empty( $svg ) ) {
92 + return $svg;
93 + }
94 +
95 + $attachment_file = get_attached_file( $attachment_id );
96 +
97 + if ( ! $attachment_file ) {
98 + return '';
99 + }
100 +
101 + $svg = file_get_contents( $attachment_file );
102 +
103 + if ( ! empty( $svg ) ) {
104 + update_post_meta( $attachment_id, self::META_KEY, $svg );
105 + }
106 +
107 + return $svg;
132 108 }
133 109
134 110 /**
135 - * Sanitize svg
111 + * decode_svg
112 + * @param $content
136 113 *
137 - * @deprecated 3.5.0 Use `Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' )->delete_meta_cache()->sanitize_svg()` instead.
114 + * @return string
115 + */
116 + private function decode_svg( $content ) {
117 + return gzdecode( $content );
118 + }
119 +
120 + /**
121 + * encode_svg
122 + * @param $content
138 123 *
124 + * @return string
125 + */
126 + private function encode_svg( $content ) {
127 + return gzencode( $content );
128 + }
129 +
130 + /**
131 + * sanitize_svg
139 132 * @param $filename
140 133 *
141 134 * @return bool
142 135 */
143 136 public function sanitize_svg( $filename ) {
144 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Plugin::$instance->uploads_manager->get_file_type_handlers( \'svg\' )->delete_meta_cache()->sanitize_svg()' );
137 + $original_content = file_get_contents( $filename );
138 + $is_encoded = $this->is_encoded( $original_content );
145 139
146 - /** @var Svg $svg_handler */
147 - $svg_handler = Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );
140 + if ( $is_encoded ) {
141 + $decoded = $this->decode_svg( $original_content );
142 + if ( false === $decoded ) {
143 + return false;
144 + }
145 + $original_content = $decoded;
146 + }
148 147
149 - return $svg_handler->sanitize_svg( $filename );
148 + $valid_svg = $this->sanitizer( $original_content );
149 +
150 + if ( false === $valid_svg ) {
151 + return false;
152 + }
153 +
154 + // If we were gzipped, we need to re-zip
155 + if ( $is_encoded ) {
156 + $valid_svg = $this->encode_svg( $valid_svg );
157 + }
158 + file_put_contents( $filename, $valid_svg );
159 +
160 + return true;
150 161 }
151 162
152 163 /**
153 - * Sanitizer
164 + * Check if the contents are gzipped
165 + * @see http://www.gzip.org/zlib/rfc-gzip.html#member-format
154 166 *
155 - * @deprecated 3.5.0 Use `Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' )->sanitizer()` instead.
167 + * @param $contents
168 + * @return bool
169 + */
170 + private function is_encoded( $contents ) {
171 + $needle = "\x1f\x8b\x08";
172 + if ( function_exists( 'mb_strpos' ) ) {
173 + return 0 === mb_strpos( $contents, $needle );
174 + } else {
175 + return 0 === strpos( $contents, $needle );
176 + }
177 + }
178 +
179 + /**
180 + * is_allowed_tag
181 + * @param $element
156 182 *
183 + * @return bool
184 + */
185 + private function is_allowed_tag( $element ) {
186 + static $allowed_tags = false;
187 + if ( false === $allowed_tags ) {
188 + $allowed_tags = $this->get_allowed_elements();
189 + }
190 +
191 + $tag_name = $element->tagName; // phpcs:ignore -- php DomDocument
192 +
193 + if ( ! in_array( strtolower( $tag_name ), $allowed_tags ) ) {
194 + $this->remove_element( $element );
195 + return false;
196 + }
197 +
198 + return true;
199 + }
200 +
201 + private function remove_element( $element ) {
202 + $element->parentNode->removeChild( $element ); // phpcs:ignore -- php DomDocument
203 + }
204 +
205 + /**
206 + * is_a_attribute
207 + * @param $name
208 + * @param $check
209 + *
210 + * @return bool
211 + */
212 + private function is_a_attribute( $name, $check ) {
213 + return 0 === strpos( $name, $check . '-' );
214 + }
215 +
216 + /**
217 + * is_remote_value
218 + * @param $value
219 + *
220 + * @return string
221 + */
222 + private function is_remote_value( $value ) {
223 + $value = trim( preg_replace( '/[^ -~]/xu', '', $value ) );
224 + $wrapped_in_url = preg_match( '~^url\(\s*[\'"]\s*(.*)\s*[\'"]\s*\)$~xi', $value, $match );
225 + if ( ! $wrapped_in_url ) {
226 + return false;
227 + }
228 +
229 + $value = trim( $match[1], '\'"' );
230 + return preg_match( '~^((https?|ftp|file):)?//~xi', $value );
231 + }
232 +
233 + /**
234 + * has_js_value
235 + * @param $value
236 + *
237 + * @return false|int
238 + */
239 + private function has_js_value( $value ) {
240 + return preg_match( '/base64|data|(?:java)?script|alert\(|window\.|document/i', $value );
241 + }
242 +
243 + /**
244 + * get_allowed_attributes
245 + * @return array
246 + */
247 + private function get_allowed_attributes() {
248 + $allowed_attributes = [
249 + 'class',
250 + 'clip-path',
251 + 'clip-rule',
252 + 'fill',
253 + 'fill-opacity',
254 + 'fill-rule',
255 + 'filter',
256 + 'id',
257 + 'mask',
258 + 'opacity',
259 + 'stroke',
260 + 'stroke-dasharray',
261 + 'stroke-dashoffset',
262 + 'stroke-linecap',
263 + 'stroke-linejoin',
264 + 'stroke-miterlimit',
265 + 'stroke-opacity',
266 + 'stroke-width',
267 + 'style',
268 + 'systemlanguage',
269 + 'transform',
270 + 'href',
271 + 'xlink:href',
272 + 'xlink:title',
273 + 'cx',
274 + 'cy',
275 + 'r',
276 + 'requiredfeatures',
277 + 'clippathunits',
278 + 'type',
279 + 'rx',
280 + 'ry',
281 + 'color-interpolation-filters',
282 + 'stddeviation',
283 + 'filterres',
284 + 'filterunits',
285 + 'height',
286 + 'primitiveunits',
287 + 'width',
288 + 'x',
289 + 'y',
290 + 'font-size',
291 + 'display',
292 + 'font-family',
293 + 'font-style',
294 + 'font-weight',
295 + 'text-anchor',
296 + 'marker-end',
297 + 'marker-mid',
298 + 'marker-start',
299 + 'x1',
300 + 'x2',
301 + 'y1',
302 + 'y2',
303 + 'gradienttransform',
304 + 'gradientunits',
305 + 'spreadmethod',
306 + 'markerheight',
307 + 'markerunits',
308 + 'markerwidth',
309 + 'orient',
310 + 'preserveaspectratio',
311 + 'refx',
312 + 'refy',
313 + 'viewbox',
314 + 'maskcontentunits',
315 + 'maskunits',
316 + 'd',
317 + 'patterncontentunits',
318 + 'patterntransform',
319 + 'patternunits',
320 + 'points',
321 + 'fx',
322 + 'fy',
323 + 'offset',
324 + 'stop-color',
325 + 'stop-opacity',
326 + 'xmlns',
327 + 'xmlns:se',
328 + 'xmlns:xlink',
329 + 'xml:space',
330 + 'method',
331 + 'spacing',
332 + 'startoffset',
333 + 'dx',
334 + 'dy',
335 + 'rotate',
336 + 'textlength',
337 + ];
338 +
339 + /**
340 + * Allowed attributes in SVG file.
341 + *
342 + * Filters the list of allowed attributes in SVG files.
343 + *
344 + * Since SVG files can run JS code that may inject malicious code, all attributes
345 + * are removed except the allowed attributes.
346 + *
347 + * This hook can be used to manage allowed SVG attributes. To either add new
348 + * attributes or delete existing attributes. To strengthen or weaken site security.
349 + *
350 + * @param array $allowed_attributes A list of allowed attributes.
351 + */
352 + $allowed_attributes = apply_filters( 'elementor/files/svg/allowed_attributes', $allowed_attributes );
353 +
354 + return $allowed_attributes;
355 + }
356 +
357 + /**
358 + * get_allowed_elements
359 + * @return array
360 + */
361 + private function get_allowed_elements() {
362 + $allowed_elements = [
363 + 'a',
364 + 'circle',
365 + 'clippath',
366 + 'defs',
367 + 'style',
368 + 'desc',
369 + 'ellipse',
370 + 'fegaussianblur',
371 + 'filter',
372 + 'foreignobject',
373 + 'g',
374 + 'image',
375 + 'line',
376 + 'lineargradient',
377 + 'marker',
378 + 'mask',
379 + 'metadata',
380 + 'path',
381 + 'pattern',
382 + 'polygon',
383 + 'polyline',
384 + 'radialgradient',
385 + 'rect',
386 + 'stop',
387 + 'svg',
388 + 'switch',
389 + 'symbol',
390 + 'text',
391 + 'textpath',
392 + 'title',
393 + 'tspan',
394 + 'use',
395 + ];
396 +
397 + /**
398 + * Allowed elements in SVG file.
399 + *
400 + * Filters the list of allowed elements in SVG files.
401 + *
402 + * Since SVG files can run JS code that may inject malicious code, all elements
403 + * are removed except the allowed elements.
404 + *
405 + * This hook can be used to manage SVG elements. To either add new elements or
406 + * delete existing elements. To strengthen or weaken site security.
407 + *
408 + * @param array $allowed_elements A list of allowed elements.
409 + */
410 + $allowed_elements = apply_filters( 'elementor/files/svg/allowed_elements', $allowed_elements );
411 +
412 + return $allowed_elements;
413 + }
414 +
415 + /**
416 + * validate_allowed_attributes
417 + * @param \DOMElement $element
418 + */
419 + private function validate_allowed_attributes( $element ) {
420 + static $allowed_attributes = false;
421 + if ( false === $allowed_attributes ) {
422 + $allowed_attributes = $this->get_allowed_attributes();
423 + }
424 +
425 + for ( $index = $element->attributes->length - 1; $index >= 0; $index-- ) {
426 + // get attribute name
427 + $attr_name = $element->attributes->item( $index )->name;
428 + $attr_name_lowercase = strtolower( $attr_name );
429 + // Remove attribute if not in whitelist
430 + if ( ! in_array( $attr_name_lowercase, $allowed_attributes ) && ! $this->is_a_attribute( $attr_name_lowercase, 'aria' ) && ! $this->is_a_attribute( $attr_name_lowercase, 'data' ) ) {
431 + $element->removeAttribute( $attr_name );
432 + continue;
433 + }
434 +
435 + $attr_value = $element->attributes->item( $index )->value;
436 +
437 + // Remove attribute if it has a remote reference or js or data-URI/base64
438 + if ( ! empty( $attr_value ) && ( $this->is_remote_value( $attr_value ) || $this->has_js_value( $attr_value ) ) ) {
439 + $element->removeAttribute( $attr_name );
440 + continue;
441 + }
442 + }
443 + }
444 +
445 + /**
446 + * strip_xlinks
447 + * @param \DOMElement $element
448 + */
449 + private function strip_xlinks( $element ) {
450 + $xlinks = $element->getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' );
451 +
452 + if ( ! $xlinks ) {
453 + return;
454 + }
455 +
456 + $allowed_links = [
457 + 'data:image/png', // PNG
458 + 'data:image/gif', // GIF
459 + 'data:image/jpg', // JPG
460 + 'data:image/jpe', // JPEG
461 + 'data:image/pjp', // PJPEG
462 + ];
463 + if ( 1 === preg_match( self::SCRIPT_REGEX, $xlinks ) ) {
464 + if ( ! in_array( substr( $xlinks, 0, 14 ), $allowed_links ) ) {
465 + $element->removeAttributeNS( 'http://www.w3.org/1999/xlink', 'href' );
466 + }
467 + }
468 + }
469 +
470 + /**
471 + * validate_use_tag
472 + * @param $element
473 + */
474 + private function validate_use_tag( $element ) {
475 + $xlinks = $element->getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' );
476 + if ( $xlinks && '#' !== substr( $xlinks, 0, 1 ) ) {
477 + $element->parentNode->removeChild( $element ); // phpcs:ignore -- php DomNode
478 + }
479 + }
480 +
481 + /**
482 + * strip_docktype
483 + */
484 + private function strip_doctype() {
485 + foreach ( $this->svg_dom->childNodes as $child ) {
486 + if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) { // phpcs:ignore -- php DomDocument
487 + $child->parentNode->removeChild( $child ); // phpcs:ignore -- php DomDocument
488 + }
489 + }
490 + }
491 +
492 + /**
493 + * sanitize_elements
494 + */
495 + private function sanitize_elements() {
496 + $elements = $this->svg_dom->getElementsByTagName( '*' );
497 + // loop through all elements
498 + // we do this backwards so we don't skip anything if we delete a node
499 + // see comments at: http://php.net/manual/en/class.domnamednodemap.php
500 + for ( $index = $elements->length - 1; $index >= 0; $index-- ) {
501 + /**
502 + * @var \DOMElement $current_element
503 + */
504 + $current_element = $elements->item( $index );
505 + // If the tag isn't in the whitelist, remove it and continue with next iteration
506 + if ( ! $this->is_allowed_tag( $current_element ) ) {
507 + continue;
508 + }
509 +
510 + //validate element attributes
511 + $this->validate_allowed_attributes( $current_element );
512 +
513 + $this->strip_xlinks( $current_element );
514 +
515 + if ( 'use' === strtolower( $current_element->tagName ) ) { // phpcs:ignore -- php DomDocument
516 + $this->validate_use_tag( $current_element );
517 + }
518 + }
519 + }
520 +
521 + /**
522 + * sanitizer
157 523 * @param $content
158 524 *
159 525 * @return bool|string
160 526 */
161 527 public function sanitizer( $content ) {
162 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Plugin::$instance->uploads_manager->get_file_type_handlers( \'svg\' )->sanitizer()' );
528 + // Strip php tags
529 + $content = $this->strip_comments( $content );
530 + $content = $this->strip_php_tags( $content );
163 531
164 - /** @var Svg $svg_handler */
165 - $svg_handler = Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );
532 + // Find the start and end tags so we can cut out miscellaneous garbage.
533 + $start = strpos( $content, '<svg' );
534 + $end = strrpos( $content, '</svg>' );
535 + if ( false === $start || false === $end ) {
536 + return false;
537 + }
166 538
167 - return $svg_handler->sanitizer( $content );
539 + $content = substr( $content, $start, ( $end - $start + 6 ) );
540 +
541 + // If the server's PHP version is 8 or up, make sure to Disable the ability to load external entities
542 + $php_version_under_eight = version_compare( PHP_VERSION, '8.0.0', '<' );
543 + if ( $php_version_under_eight ) {
544 + $libxml_disable_entity_loader = libxml_disable_entity_loader( true ); // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated
545 + }
546 + // Suppress the errors
547 + $libxml_use_internal_errors = libxml_use_internal_errors( true );
548 +
549 + // Create DomDocument instance
550 + $this->svg_dom = new \DOMDocument();
551 + $this->svg_dom->formatOutput = false;
552 + $this->svg_dom->preserveWhiteSpace = false;
553 + $this->svg_dom->strictErrorChecking = false;
554 +
555 + $open_svg = $this->svg_dom->loadXML( $content );
556 + if ( ! $open_svg ) {
557 + return false;
558 + }
559 +
560 + $this->strip_doctype();
561 + $this->sanitize_elements();
562 +
563 + // Export sanitized svg to string
564 + // Using documentElement to strip out <?xml version="1.0" encoding="UTF-8"...
565 + $sanitized = $this->svg_dom->saveXML( $this->svg_dom->documentElement, LIBXML_NOEMPTYTAG );
566 +
567 + // Restore defaults
568 + if ( $php_version_under_eight ) {
569 + libxml_disable_entity_loader( $libxml_disable_entity_loader ); // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated
570 + }
571 + libxml_use_internal_errors( $libxml_use_internal_errors );
572 +
573 + return $sanitized;
168 574 }
169 575
170 576 /**
171 - * Prepare attachment for js
577 + * strip_php_tags
578 + * @param $string
172 579 *
173 - * @deprecated 3.5.0 Use `Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' )->wp_prepare_attachment_for_js()` instead.
580 + * @return string
581 + */
582 + private function strip_php_tags( $string ) {
583 + $string = preg_replace( '/<\?(=|php)(.+?)\?>/i', '', $string );
584 + // Remove XML, ASP, etc.
585 + $string = preg_replace( '/<\?(.*)\?>/Us', '', $string );
586 + $string = preg_replace( '/<\%(.*)\%>/Us', '', $string );
587 +
588 + if ( ( false !== strpos( $string, '<?' ) ) || ( false !== strpos( $string, '<%' ) ) ) {
589 + return '';
590 + }
591 + return $string;
592 + }
593 +
594 + /**
595 + * strip_comments
596 + * @param $string
174 597 *
598 + * @return string
599 + */
600 + private function strip_comments( $string ) {
601 + // Remove comments.
602 + $string = preg_replace( '/<!--(.*)-->/Us', '', $string );
603 + $string = preg_replace( '/\/\*(.*)\*\//Us', '', $string );
604 + if ( ( false !== strpos( $string, '<!--' ) ) || ( false !== strpos( $string, '/*' ) ) ) {
605 + return '';
606 + }
607 + return $string;
608 + }
609 +
610 + /**
611 + * wp_prepare_attachment_for_js
175 612 * @param $attachment_data
176 613 * @param $attachment
177 614 * @param $meta
178 615 *
@@ -178,72 +615,152 @@
178 615 *
179 616 * @return mixed
180 617 */
181 618 public function wp_prepare_attachment_for_js( $attachment_data, $attachment, $meta ) {
182 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Plugin::$instance->uploads_manager->get_file_type_handlers( \'svg\' )->wp_prepare_attachment_for_js()' );
619 + if ( 'image' !== $attachment_data['type'] || 'svg+xml' !== $attachment_data['subtype'] || ! class_exists( 'SimpleXMLElement' ) ) {
620 + return $attachment_data;
621 + }
183 622
184 - /** @var Svg $svg_handler */
185 - $svg_handler = Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );
623 + $svg = self::get_inline_svg( $attachment->ID );
186 624
187 - return $svg_handler->wp_prepare_attachment_for_js( $attachment_data, $attachment, $meta );
625 + if ( ! $svg ) {
626 + return $attachment_data;
627 + }
628 +
629 + try {
630 + $svg = new \SimpleXMLElement( $svg );
631 + } catch ( \Exception $e ) {
632 + return $attachment_data;
633 + }
634 +
635 + $src = $attachment_data['url'];
636 + $width = (int) $svg['width'];
637 + $height = (int) $svg['height'];
638 +
639 + // Media Gallery
640 + $attachment_data['image'] = compact( 'src', 'width', 'height' );
641 + $attachment_data['thumb'] = compact( 'src', 'width', 'height' );
642 +
643 + // Single Details of Image
644 + $attachment_data['sizes']['full'] = [
645 + 'height' => $height,
646 + 'width' => $width,
647 + 'url' => $src,
648 + 'orientation' => $height > $width ? 'portrait' : 'landscape',
649 + ];
650 + return $attachment_data;
188 651 }
189 652
190 653 /**
191 - * Set attachment id
192 - *
193 - * @deprecated 3.5.0
194 - *
654 + * set_attachment_id
195 655 * @param $attachment_id
196 656 *
197 657 * @return int
198 658 */
199 659 public function set_attachment_id( $attachment_id ) {
200 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0' );
201 -
202 660 $this->attachment_id = $attachment_id;
203 661 return $this->attachment_id;
204 662 }
205 663
206 664 /**
207 - * Get attachment id
208 - *
209 - * @deprecated 3.5.0
210 - *
665 + * get_attachment_id
211 666 * @return int
212 667 */
213 668 public function get_attachment_id() {
214 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0' );
215 -
216 669 return $this->attachment_id;
217 670 }
218 671
219 672 /**
220 - * Set svg meta data
221 - *
222 - * @deprecated 3.5.0 Use `Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' )->set_svg_meta_data()` instead.
223 - *
673 + * set_svg_meta_data
224 674 * @return mixed
225 675 */
226 676 public function set_svg_meta_data( $data, $id ) {
227 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Plugin::$instance->uploads_manager->get_file_type_handlers( \'svg\' )->set_svg_meta_data()' );
677 + $attachment = get_post( $id ); // Filter makes sure that the post is an attachment.
678 + $mime_type = $attachment->post_mime_type;
228 679
229 - /** @var Svg $svg_handler */
230 - $svg_handler = Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );
680 + // If the attachment is an svg
681 + if ( 'image/svg+xml' === $mime_type ) {
682 + // If the svg metadata are empty or the width is empty or the height is empty.
683 + // then get the attributes from xml.
684 + if ( empty( $data ) || empty( $data['width'] ) || empty( $data['height'] ) ) {
685 + $xml = simplexml_load_file( get_attached_file( $id ) );
686 + $attr = $xml->attributes();
687 + $view_box = explode( ' ', $attr->viewBox );// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
688 + $data['width'] = isset( $attr->width ) && preg_match( '/\d+/', $attr->width, $value ) ? (int) $value[0] : ( 4 === count( $view_box ) ? (int) $view_box[2] : null );
689 + $data['height'] = isset( $attr->height ) && preg_match( '/\d+/', $attr->height, $value ) ? (int) $value[0] : ( 4 === count( $view_box ) ? (int) $view_box[3] : null );
690 + }
691 + }
231 692
232 - return $svg_handler->set_svg_meta_data( $data, $id );
693 + return $data;
233 694 }
234 695
235 696 /**
236 - * Handle upload prefilter
237 - *
238 - * @deprecated 3.5.0 Use `Elementor\Plugin::$instance->uploads_manager->handle_elementor_wp_media_upload()` instead.
239 - *
697 + * handle_upload_prefilter
240 698 * @param $file
241 699 *
242 700 * @return mixed
243 701 */
244 702 public function handle_upload_prefilter( $file ) {
245 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.5.0', 'Elementor\Plugin::$instance->uploads_manager->handle_elementor_wp_media_upload()' );
703 + if ( ! $this->is_file_should_handled( $file ) ) {
704 + return $file;
705 + }
246 706
247 - return Plugin::$instance->uploads_manager->handle_elementor_wp_media_upload( $file );
707 + $file = parent::handle_upload_prefilter( $file );
708 +
709 + if ( ! $file['error'] && self::file_sanitizer_can_run() && ! $this->sanitize_svg( $file['tmp_name'] ) ) {
710 + $display_type = strtoupper( $this->get_file_type() );
711 +
712 + /* translators: %s: File type. */
713 + $file['error'] = sprintf( esc_html__( 'Invalid %1$s Format, file not uploaded for security reasons', 'elementor' ), $display_type );
714 + }
715 +
716 + return $file;
717 + }
718 +
719 + /**
720 + * @since 3.0.0
721 + * @deprecated 3.0.0 Use Files_Upload_Handler::file_sanitizer_can_run() instead.
722 + */
723 + public function svg_sanitizer_can_run() {
724 + _deprecated_function( __METHOD__, '3.0.0', 'Files_Upload_Handler::file_sanitizer_can_run()' );
725 +
726 + return Files_Upload_Handler::file_sanitizer_can_run();
727 + }
728 +
729 + /**
730 + * @since 3.0.0
731 + * @deprecated 3.0.0
732 + */
733 + public function upload_mimes() {
734 + _deprecated_function( __METHOD__, '3.0.0' );
735 + }
736 +
737 + /**
738 + * @since 3.0.0
739 + * @deprecated 3.0.0
740 + */
741 + public function wp_handle_upload_prefilter() {
742 + _deprecated_function( __METHOD__, '3.0.0' );
743 + }
744 +
745 + /**
746 + * @since 3.0.0
747 + * @deprecated 3.0.0 Use Files_Upload_Handler::is_enabled() instead.
748 + * @see is_enabled()
749 + */
750 + public function is_svg_uploads_enabled() {
751 + _deprecated_function( __METHOD__, '3.0.0', 'Files_Upload_Handler::is_enabled()' );
752 +
753 + return Files_Upload_Handler::is_enabled();
754 + }
755 +
756 + /**
757 + * Svg_Handler constructor.
758 + */
759 + public function __construct() {
760 + parent::__construct();
761 +
762 + add_filter( 'wp_update_attachment_metadata', [ $this, 'set_svg_meta_data' ], 10, 2 );
763 + add_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ], 10, 3 );
764 + add_action( 'elementor/core/files/clear_cache', [ $this, 'delete_meta_cache' ] );
248 765 }
249 766 }