Safe SVG - Version 2.0.3

Version Description

  • 2022-09-01 =
  • Added: More robust PHP testing (props @iamdharmesh, @faisal-alvi via #71, #73).
  • Fixed: Addressed PHPCS errors (props @iamdharmesh, @faisal-alvi via #73).
Download this release

Release Info

Developer 10up
Plugin Icon 128x128 Safe SVG
Version 2.0.3
Comparing to
See all releases

Code changes from version 2.0.2 to 2.0.3

includes/safe-svg-attributes.php CHANGED
@@ -1,6 +1,13 @@
1
  <?php
 
 
 
 
 
2
 
3
-
 
 
4
  class safe_svg_attributes extends \enshrined\svgSanitize\data\AllowedAttributes {
5
 
6
  /**
@@ -15,4 +22,4 @@ class safe_svg_attributes extends \enshrined\svgSanitize\data\AllowedAttributes
15
  */
16
  return apply_filters( 'svg_allowed_attributes', parent::getAttributes() );
17
  }
18
- }
1
  <?php
2
+ /**
3
+ * Safe SVG allowed attributes.
4
+ *
5
+ * @package safe-svg
6
+ */
7
 
8
+ /**
9
+ * SVG Allowed Attributes lass.
10
+ */
11
  class safe_svg_attributes extends \enshrined\svgSanitize\data\AllowedAttributes {
12
 
13
  /**
22
  */
23
  return apply_filters( 'svg_allowed_attributes', parent::getAttributes() );
24
  }
25
+ }
includes/safe-svg-tags.php CHANGED
@@ -1,6 +1,13 @@
1
  <?php
 
 
 
 
 
2
 
3
-
 
 
4
  class safe_svg_tags extends \enshrined\svgSanitize\data\AllowedTags {
5
 
6
  /**
@@ -15,4 +22,4 @@ class safe_svg_tags extends \enshrined\svgSanitize\data\AllowedTags {
15
  */
16
  return apply_filters( 'svg_allowed_tags', parent::getTags() );
17
  }
18
- }
1
  <?php
2
+ /**
3
+ * Safe SVG allowed tags
4
+ *
5
+ * @package safe-svg
6
+ */
7
 
8
+ /**
9
+ * SVG Allowed Tags class.
10
+ */
11
  class safe_svg_tags extends \enshrined\svgSanitize\data\AllowedTags {
12
 
13
  /**
22
  */
23
  return apply_filters( 'svg_allowed_tags', parent::getTags() );
24
  }
25
+ }
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: 10up, enshrined
3
  Tags: svg, sanitize, upload, sanitise, security, svg upload, image, vector, file, graphic, media, mime
4
  Requires at least: 4.7
5
  Tested up to: 6.0
6
- Stable tag: 2.0.2
7
  Requires PHP: 7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -66,6 +66,10 @@ They take one argument that must be returned. See below for examples:
66
 
67
  == Changelog ==
68
 
 
 
 
 
69
  = 2.0.2 - 2022-06-27 =
70
  * **Added:** Dependency security scanning (props [@jeffpaul](https://github.com/jeffpaul) via [#60](https://github.com/10up/safe-svg/pull/60)).
71
  * **Added:** End-to-end testing with Cypress (props [@iamdharmesh](https://github.com/iamdharmesh) via [#64](https://github.com/10up/safe-svg/pull/64)).
3
  Tags: svg, sanitize, upload, sanitise, security, svg upload, image, vector, file, graphic, media, mime
4
  Requires at least: 4.7
5
  Tested up to: 6.0
6
+ Stable tag: 2.0.3
7
  Requires PHP: 7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
66
 
67
  == Changelog ==
68
 
69
+ = 2.0.3 - 2022-09-01 =
70
+ * **Added:** More robust PHP testing (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#71](https://github.com/10up/safe-svg/pull/71), [#73](https://github.com/10up/safe-svg/pull/73)).
71
+ * **Fixed:** Addressed PHPCS errors (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#73](https://github.com/10up/safe-svg/pull/73)).
72
+
73
  = 2.0.2 - 2022-06-27 =
74
  * **Added:** Dependency security scanning (props [@jeffpaul](https://github.com/jeffpaul) via [#60](https://github.com/10up/safe-svg/pull/60)).
75
  * **Added:** End-to-end testing with Cypress (props [@iamdharmesh](https://github.com/iamdharmesh) via [#64](https://github.com/10up/safe-svg/pull/64)).
safe-svg.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
- /*
3
  * Plugin Name: Safe SVG
4
  * Plugin URI: https://wordpress.org/plugins/safe-svg/
5
  * Description: Enable SVG uploads and sanitize them to stop XML/SVG vulnerabilities in your WordPress website
6
- * Version: 2.0.2
7
  * Requires at least: 4.7
8
  * Requires PHP: 7.0
9
  * Author: 10up
@@ -12,9 +12,15 @@
12
  * License URI: https://www.gnu.org/licenses/gpl-2.0.html
13
  * Text Domain: safe-svg
14
  * Domain Path: /languages
 
 
15
  */
16
 
17
- defined( 'ABSPATH' ) or die( 'Really?' );
 
 
 
 
18
 
19
  // Try and include our autoloader.
20
  if ( is_readable( __DIR__ . '/vendor/autoload.php' ) ) {
@@ -48,519 +54,532 @@ require 'includes/safe-svg-attributes.php';
48
 
49
  if ( ! class_exists( 'safe_svg' ) ) {
50
 
51
- /**
52
- * Class safe_svg
53
- */
54
- Class safe_svg {
55
-
56
- /**
57
- * The sanitizer
58
- *
59
- * @var \enshrined\svgSanitize\Sanitizer
60
- */
61
- protected $sanitizer;
62
-
63
- /**
64
- * Set up the class
65
- */
66
- function __construct() {
67
- $this->sanitizer = new enshrined\svgSanitize\Sanitizer();
68
- $this->sanitizer->minify( true );
69
-
70
- add_filter( 'upload_mimes', array( $this, 'allow_svg' ) );
71
- add_filter( 'wp_handle_upload_prefilter', array( $this, 'check_for_svg' ) );
72
- add_filter( 'wp_check_filetype_and_ext', array( $this, 'fix_mime_type_svg' ), 75, 4 );
73
- add_filter( 'wp_prepare_attachment_for_js', array( $this, 'fix_admin_preview' ), 10, 3 );
74
- add_filter( 'wp_get_attachment_image_src', array( $this, 'one_pixel_fix' ), 10, 4 );
75
- add_filter( 'admin_post_thumbnail_html', array( $this, 'featured_image_fix' ), 10, 3 );
76
- add_action( 'admin_enqueue_scripts', array( $this, 'load_custom_admin_style' ) );
77
- add_action( 'get_image_tag', array( $this, 'get_image_tag_override' ), 10, 6 );
78
- add_filter( 'wp_generate_attachment_metadata', array( $this, 'skip_svg_regeneration' ), 10, 2 );
79
- add_filter( 'wp_get_attachment_metadata', array( $this, 'metadata_error_fix' ), 10, 2 );
80
- add_filter( 'wp_calculate_image_srcset_meta', array( $this, 'disable_srcset' ), 10, 4 );
81
- }
82
-
83
- /**
84
- * Allow SVG Uploads
85
- *
86
- * @param $mimes
87
- *
88
- * @return mixed
89
- */
90
- public function allow_svg( $mimes ) {
91
- $mimes['svg'] = 'image/svg+xml';
92
- $mimes['svgz'] = 'image/svg+xml';
93
-
94
- return $mimes;
95
- }
96
-
97
- /**
98
- * Fixes the issue in WordPress 4.7.1 being unable to correctly identify SVGs
99
- *
100
- * @thanks @lewiscowles
101
- *
102
- * @param null $data
103
- * @param null $file
104
- * @param null $filename
105
- * @param null $mimes
106
- *
107
- * @return null
108
- */
109
- public function fix_mime_type_svg( $data = null, $file = null, $filename = null, $mimes = null ) {
110
- $ext = isset( $data['ext'] ) ? $data['ext'] : '';
111
- if ( strlen( $ext ) < 1 ) {
112
- $exploded = explode( '.', $filename );
113
- $ext = strtolower( end( $exploded ) );
114
- }
115
- if ( $ext === 'svg' ) {
116
- $data['type'] = 'image/svg+xml';
117
- $data['ext'] = 'svg';
118
- } elseif ( $ext === 'svgz' ) {
119
- $data['type'] = 'image/svg+xml';
120
- $data['ext'] = 'svgz';
121
- }
122
-
123
- return $data;
124
- }
125
-
126
- /**
127
- * Check if the file is an SVG, if so handle appropriately
128
- *
129
- * @param $file
130
- *
131
- * @return mixed
132
- */
133
- public function check_for_svg( $file ) {
134
-
135
- // Ensure we have a proper file path before processing
136
- if ( ! isset( $file['tmp_name'] ) ) {
137
- return $file;
138
- }
139
-
140
- $file_name = isset( $file['name'] ) ? $file['name'] : '';
141
- $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file_name );
142
- $type = ! empty( $wp_filetype['type'] ) ? $wp_filetype['type'] : '';
143
-
144
- if ( $type === 'image/svg+xml' ) {
145
- if ( ! $this->sanitize( $file['tmp_name'] ) ) {
146
- $file['error'] = __( "Sorry, this file couldn't be sanitized so for security reasons wasn't uploaded",
147
- 'safe-svg' );
148
- }
149
- }
150
-
151
- return $file;
152
- }
153
-
154
- /**
155
- * Sanitize the SVG
156
- *
157
- * @param $file
158
- *
159
- * @return bool|int
160
- */
161
- protected function sanitize( $file ) {
162
- $dirty = file_get_contents( $file );
163
-
164
- // Is the SVG gzipped? If so we try and decode the string
165
- if ( $is_zipped = $this->is_gzipped( $dirty ) ) {
166
- $dirty = gzdecode( $dirty );
167
-
168
- // If decoding fails, bail as we're not secure
169
- if ( $dirty === false ) {
170
- return false;
171
- }
172
- }
173
-
174
- /**
175
- * Load extra filters to allow devs to access the safe tags and attrs by themselves.
176
- */
177
- $this->sanitizer->setAllowedTags( new safe_svg_tags() );
178
- $this->sanitizer->setAllowedAttrs( new safe_svg_attributes() );
179
-
180
- $clean = $this->sanitizer->sanitize( $dirty );
181
-
182
- if ( $clean === false ) {
183
- return false;
184
- }
185
-
186
- // If we were gzipped, we need to re-zip
187
- if ( $is_zipped ) {
188
- $clean = gzencode( $clean );
189
- }
190
-
191
- file_put_contents( $file, $clean );
192
-
193
- return true;
194
- }
195
-
196
- /**
197
- * Check if the contents are gzipped
198
- *
199
- * @see http://www.gzip.org/zlib/rfc-gzip.html#member-format
200
- *
201
- * @param $contents
202
- *
203
- * @return bool
204
- */
205
- protected function is_gzipped( $contents ) {
206
- if ( function_exists( 'mb_strpos' ) ) {
207
- return 0 === mb_strpos( $contents, "\x1f" . "\x8b" . "\x08" );
208
- } else {
209
- return 0 === strpos( $contents, "\x1f" . "\x8b" . "\x08" );
210
- }
211
- }
212
-
213
- /**
214
- * Filters the attachment data prepared for JavaScript to add the sizes array to the response
215
- *
216
- * @param array $response Array of prepared attachment data.
217
- * @param int|object $attachment Attachment ID or object.
218
- * @param array $meta Array of attachment meta data.
219
- *
220
- * @return array
221
- */
222
- public function fix_admin_preview( $response, $attachment, $meta ) {
223
-
224
- if ( $response['mime'] == 'image/svg+xml' ) {
225
- $dimensions = $this->svg_dimensions( get_attached_file( $attachment->ID ) );
226
-
227
- if ( $dimensions ) {
228
- $response = array_merge( $response, $dimensions );
229
- }
230
-
231
- $possible_sizes = apply_filters( 'image_size_names_choose', array(
232
- 'full' => __( 'Full Size' ),
233
- 'thumbnail' => __( 'Thumbnail' ),
234
- 'medium' => __( 'Medium' ),
235
- 'large' => __( 'Large' ),
236
- ) );
237
-
238
- $sizes = array();
239
-
240
- foreach ( $possible_sizes as $size => $label ) {
241
- $default_height = 2000;
242
- $default_width = 2000;
243
-
244
- if ( 'full' === $size && $dimensions ) {
245
- $default_height = $dimensions['height'];
246
- $default_width = $dimensions['width'];
247
- }
248
-
249
- $sizes[ $size ] = array(
250
- 'height' => get_option( "{$size}_size_w", $default_height ),
251
- 'width' => get_option( "{$size}_size_h", $default_width ),
252
- 'url' => $response['url'],
253
- 'orientation' => 'portrait',
254
- );
255
- }
256
-
257
- $response['sizes'] = $sizes;
258
- $response['icon'] = $response['url'];
259
- }
260
-
261
- return $response;
262
- }
263
-
264
- /**
265
- * Filters the image src result.
266
- * If the image size doesn't exist, set a default size of 100 for width and height
267
- *
268
- * @param array|false $image Either array with src, width & height, icon src, or false.
269
- * @param int $attachment_id Image attachment ID.
270
- * @param string|array $size Size of image. Image size or array of width and height values
271
- * (in that order). Default 'thumbnail'.
272
- * @param bool $icon Whether the image should be treated as an icon. Default false.
273
- *
274
- * @return array
275
- */
276
- public function one_pixel_fix( $image, $attachment_id, $size, $icon ) {
277
- if ( get_post_mime_type( $attachment_id ) === 'image/svg+xml' ) {
278
- $dimensions = $this->svg_dimensions( get_attached_file( $attachment_id ) );
279
-
280
- if ( $dimensions ) {
281
- $image[1] = $dimensions['width'];
282
- $image[2] = $dimensions['height'];
283
- } else {
284
- $image[1] = 100;
285
- $image[2] = 100;
286
- }
287
- }
288
-
289
- return $image;
290
- }
291
-
292
- /**
293
- * If the featured image is an SVG we wrap it in an SVG class so we can apply our CSS fix.
294
- *
295
- * @param string $content Admin post thumbnail HTML markup.
296
- * @param int $post_id Post ID.
297
- * @param int $thumbnail_id Thumbnail ID.
298
- *
299
- * @return string
300
- */
301
- public function featured_image_fix( $content, $post_id, $thumbnail_id ) {
302
- $mime = get_post_mime_type( $thumbnail_id );
303
-
304
- if ( 'image/svg+xml' === $mime ) {
305
- $content = sprintf( '<span class="svg">%s</span>', $content );
306
- }
307
-
308
- return $content;
309
- }
310
-
311
- /**
312
- * Load our custom CSS sheet.
313
- */
314
- function load_custom_admin_style() {
315
- wp_enqueue_style( 'safe-svg-css', plugins_url( 'assets/safe-svg.css', __FILE__ ), array() );
316
- }
317
-
318
- /**
319
- * Override the default height and width string on an SVG
320
- *
321
- * @param string $html HTML content for the image.
322
- * @param int $id Attachment ID.
323
- * @param string $alt Alternate text.
324
- * @param string $title Attachment title.
325
- * @param string $align Part of the class name for aligning the image.
326
- * @param string|array $size Size of image. Image size or array of width and height values (in that order).
327
- * Default 'medium'.
328
- *
329
- * @return mixed
330
- */
331
- function get_image_tag_override( $html, $id, $alt, $title, $align, $size ) {
332
- $mime = get_post_mime_type( $id );
333
-
334
- if ( 'image/svg+xml' === $mime ) {
335
- if ( is_array( $size ) ) {
336
- $width = $size[0];
337
- $height = $size[1];
338
- } elseif ( 'full' == $size && $dimensions = $this->svg_dimensions( get_attached_file( $id ) ) ) {
339
- $width = $dimensions['width'];
340
- $height = $dimensions['height'];
341
- } else {
342
- $width = get_option( "{$size}_size_w", false );
343
- $height = get_option( "{$size}_size_h", false );
344
- }
345
-
346
- if ( $height && $width ) {
347
- $html = str_replace( 'width="1" ', sprintf( 'width="%s" ', $width ), $html );
348
- $html = str_replace( 'height="1" ', sprintf( 'height="%s" ', $height ), $html );
349
- } else {
350
- $html = str_replace( 'width="1" ', '', $html );
351
- $html = str_replace( 'height="1" ', '', $html );
352
- }
353
-
354
- $html = str_replace( '/>', ' role="img" />', $html );
355
- }
356
-
357
- return $html;
358
- }
359
-
360
- /**
361
- * Skip regenerating SVGs
362
- *
363
- * @param int $attachment_id Attachment Id to process.
364
- * @param string $file Filepath of the Attached image.
365
- *
366
- * @return mixed Metadata for attachment.
367
- */
368
- function skip_svg_regeneration( $metadata, $attachment_id ) {
369
- $mime = get_post_mime_type( $attachment_id );
370
- if ( 'image/svg+xml' === $mime ) {
371
- $additional_image_sizes = wp_get_additional_image_sizes();
372
- $svg_path = get_attached_file( $attachment_id );
373
- $upload_dir = wp_upload_dir();
374
- // get the path relative to /uploads/ - found no better way:
375
- $relative_path = str_replace( trailingslashit( $upload_dir['basedir'] ), '', $svg_path );
376
- $filename = basename( $svg_path );
377
-
378
- $dimensions = $this->svg_dimensions( $svg_path );
379
-
380
- if ( ! $dimensions ) {
381
- return $metadata;
382
- }
383
-
384
- $metadata = array(
385
- 'width' => intval( $dimensions['width'] ),
386
- 'height' => intval( $dimensions['height'] ),
387
- 'file' => $relative_path
388
- );
389
-
390
- // Might come handy to create the sizes array too - But it's not needed for this workaround! Always links to original svg-file => Hey, it's a vector graphic! ;)
391
- $sizes = array();
392
- foreach ( get_intermediate_image_sizes() as $s ) {
393
- $sizes[ $s ] = array( 'width' => '', 'height' => '', 'crop' => false );
394
-
395
- if ( isset( $additional_image_sizes[ $s ]['width'] ) ) {
396
- // For theme-added sizes
397
- $sizes[ $s ]['width'] = intval( $additional_image_sizes[ $s ]['width'] );
398
- } else {
399
- // For default sizes set in options
400
- $sizes[ $s ]['width'] = get_option( "{$s}_size_w" );
401
- }
402
-
403
- if ( isset( $additional_image_sizes[ $s ]['height'] ) ) {
404
- // For theme-added sizes
405
- $sizes[ $s ]['height'] = intval( $additional_image_sizes[ $s ]['height'] );
406
- } else {
407
- // For default sizes set in options
408
- $sizes[ $s ]['height'] = get_option( "{$s}_size_h" );
409
- }
410
-
411
- if ( isset( $additional_image_sizes[ $s ]['crop'] ) ) {
412
- // For theme-added sizes
413
- $sizes[ $s ]['crop'] = intval( $additional_image_sizes[ $s ]['crop'] );
414
- } else {
415
- // For default sizes set in options
416
- $sizes[ $s ]['crop'] = get_option( "{$s}_crop" );
417
- }
418
-
419
- $sizes[ $s ]['file'] = $filename;
420
- $sizes[ $s ]['mime-type'] = $mime;
421
- }
422
- $metadata['sizes'] = $sizes;
423
- }
424
-
425
- return $metadata;
426
- }
427
-
428
- /**
429
- * Filters the attachment meta data.
430
- *
431
- * @param array|bool $data Array of meta data for the given attachment, or false
432
- * if the object does not exist.
433
- * @param int $post_id Attachment ID.
434
- */
435
- function metadata_error_fix( $data, $post_id ) {
436
-
437
- // If it's a WP_Error regenerate metadata and save it
438
- if ( is_wp_error( $data ) ) {
439
- $data = wp_generate_attachment_metadata( $post_id, get_attached_file( $post_id ) );
440
- wp_update_attachment_metadata( $post_id, $data );
441
- }
442
-
443
- return $data;
444
- }
445
-
446
- /**
447
- * Get SVG size from the width/height or viewport.
448
- *
449
- * @param string|false $svg The file path to where the SVG file should be, false otherwise.
450
- *
451
- * @return array|bool
452
- */
453
- protected function svg_dimensions( $svg ) {
454
- $svg = @simplexml_load_file( $svg );
455
- $width = 0;
456
- $height = 0;
457
- if ( $svg ) {
458
- $attributes = $svg->attributes();
459
-
460
- if ( isset( $attributes->viewBox ) ) {
461
- $sizes = explode( ' ', $attributes->viewBox );
462
- if ( isset( $sizes[2], $sizes[3] ) ) {
463
- $viewbox_width = floatval( $sizes[2] );
464
- $viewbox_height = floatval( $sizes[3] );
465
- }
466
- }
467
-
468
- if ( isset( $attributes->width, $attributes->height ) && is_numeric( (float) $attributes->width ) && is_numeric( (float) $attributes->height ) && ! $this->str_ends_with( (string) $attributes->width, '%' ) && ! $this->str_ends_with( (string) $attributes->height, '%' ) ) {
469
- $attr_width = floatval( $attributes->width );
470
- $attr_height = floatval( $attributes->height );
471
- }
472
-
473
- /**
474
- * Decide which attributes of the SVG we use first for image tag dimensions.
475
- *
476
- * We default to using the parameters in the viewbox attribute but
477
- * that can be overridden using this filter if you'd prefer to use
478
- * the width and height attributes.
479
- *
480
- * @hook safe_svg_use_width_height_attributes
481
- *
482
- * @param {bool} $false If the width & height attributes should be used first. Default false.
483
- * @param {string} $svg The file path to the SVG.
484
- *
485
- * @return {bool} If we should use the width & height attributes first or not.
486
- */
487
- $use_width_height = (bool) apply_filters( 'safe_svg_use_width_height_attributes', false, $svg );
488
-
489
- if ( $use_width_height ) {
490
- if ( isset( $attr_width, $attr_height ) ) {
491
- $width = $attr_width;
492
- $height = $attr_height;
493
- } elseif ( isset( $viewbox_width, $viewbox_height ) ) {
494
- $width = $viewbox_width;
495
- $height = $viewbox_height;
496
- }
497
- } else {
498
- if ( isset( $viewbox_width, $viewbox_height ) ) {
499
- $width = $viewbox_width;
500
- $height = $viewbox_height;
501
- } elseif ( isset( $attr_width, $attr_height ) ) {
502
- $width = $attr_width;
503
- $height = $attr_height;
504
- }
505
- }
506
-
507
- if ( ! $width && ! $height ) {
508
- return false;
509
- }
510
- }
511
-
512
- return array(
513
- 'width' => $width,
514
- 'height' => $height,
515
- 'orientation' => ( $width > $height ) ? 'landscape' : 'portrait'
516
- );
517
- }
518
-
519
- /**
520
- * Disable the creation of srcset on SVG images.
521
- *
522
- * @param array $image_meta The image meta data.
523
- * @param int[] $size_array {
524
- * An array of requested width and height values.
525
- *
526
- * @type int $0 The width in pixels.
527
- * @type int $1 The height in pixels.
528
- * }
529
- * @param string $image_src The 'src' of the image.
530
- * @param int $attachment_id The image attachment ID.
531
- */
532
- public function disable_srcset( $image_meta, $size_array, $image_src, $attachment_id ) {
533
- if ( $attachment_id && 'image/svg+xml' === get_post_mime_type( $attachment_id ) ) {
534
- $image_meta['sizes'] = array();
535
- }
536
-
537
- return $image_meta;
538
- }
539
-
540
- /**
541
- * Polyfill for `str_ends_with()` function added in PHP 8.0.
542
- *
543
- * Performs a case-sensitive check indicating if
544
- * the haystack ends with needle.
545
- *
546
- * @param string $haystack The string to search in.
547
- * @param string $needle The substring to search for in the `$haystack`.
548
- * @return bool True if `$haystack` ends with `$needle`, otherwise false.
549
- */
550
- protected function str_ends_with( $haystack, $needle ) {
551
- if ( function_exists( 'str_ends_with' ) ) {
552
- return str_ends_with( $haystack, $needle );
553
- }
554
-
555
- if ( '' === $haystack && '' !== $needle ) {
556
- return false;
557
- }
558
-
559
- $len = strlen( $needle );
560
- return 0 === substr_compare( $haystack, $needle, -$len, $len );
561
- }
562
-
563
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
564
  }
565
 
566
  $safe_svg = new safe_svg();
1
  <?php
2
+ /**
3
  * Plugin Name: Safe SVG
4
  * Plugin URI: https://wordpress.org/plugins/safe-svg/
5
  * Description: Enable SVG uploads and sanitize them to stop XML/SVG vulnerabilities in your WordPress website
6
+ * Version: 2.0.3
7
  * Requires at least: 4.7
8
  * Requires PHP: 7.0
9
  * Author: 10up
12
  * License URI: https://www.gnu.org/licenses/gpl-2.0.html
13
  * Text Domain: safe-svg
14
  * Domain Path: /languages
15
+ *
16
+ * @package safe-svg
17
  */
18
 
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit; // Exit if accessed directly.
21
+ }
22
+
23
+ define( 'SAFE_SVG_VERSION', '2.0.3' );
24
 
25
  // Try and include our autoloader.
26
  if ( is_readable( __DIR__ . '/vendor/autoload.php' ) ) {
54
 
55
  if ( ! class_exists( 'safe_svg' ) ) {
56
 
57
+ /**
58
+ * Class safe_svg
59
+ */
60
+ class safe_svg {
61
+
62
+ /**
63
+ * The sanitizer
64
+ *
65
+ * @var \enshrined\svgSanitize\Sanitizer
66
+ */
67
+ protected $sanitizer;
68
+
69
+ /**
70
+ * Set up the class
71
+ */
72
+ public function __construct() {
73
+ $this->sanitizer = new enshrined\svgSanitize\Sanitizer();
74
+ $this->sanitizer->minify( true );
75
+
76
+ add_filter( 'upload_mimes', array( $this, 'allow_svg' ) );
77
+ add_filter( 'wp_handle_upload_prefilter', array( $this, 'check_for_svg' ) );
78
+ add_filter( 'wp_check_filetype_and_ext', array( $this, 'fix_mime_type_svg' ), 75, 4 );
79
+ add_filter( 'wp_prepare_attachment_for_js', array( $this, 'fix_admin_preview' ), 10, 3 );
80
+ add_filter( 'wp_get_attachment_image_src', array( $this, 'one_pixel_fix' ), 10, 4 );
81
+ add_filter( 'admin_post_thumbnail_html', array( $this, 'featured_image_fix' ), 10, 3 );
82
+ add_action( 'admin_enqueue_scripts', array( $this, 'load_custom_admin_style' ) );
83
+ add_action( 'get_image_tag', array( $this, 'get_image_tag_override' ), 10, 6 );
84
+ add_filter( 'wp_generate_attachment_metadata', array( $this, 'skip_svg_regeneration' ), 10, 2 );
85
+ add_filter( 'wp_get_attachment_metadata', array( $this, 'metadata_error_fix' ), 10, 2 );
86
+ add_filter( 'wp_calculate_image_srcset_meta', array( $this, 'disable_srcset' ), 10, 4 );
87
+ }
88
+
89
+ /**
90
+ * Allow SVG Uploads
91
+ *
92
+ * @param array $mimes Mime types keyed by the file extension regex corresponding to those types.
93
+ *
94
+ * @return mixed
95
+ */
96
+ public function allow_svg( $mimes ) {
97
+ $mimes['svg'] = 'image/svg+xml';
98
+ $mimes['svgz'] = 'image/svg+xml';
99
+
100
+ return $mimes;
101
+ }
102
+
103
+ /**
104
+ * Fixes the issue in WordPress 4.7.1 being unable to correctly identify SVGs
105
+ *
106
+ * @thanks @lewiscowles
107
+ *
108
+ * @param array $data Values for the extension, mime type, and corrected filename.
109
+ * @param string $file Full path to the file.
110
+ * @param string $filename The name of the file.
111
+ * @param string[] $mimes Array of mime types keyed by their file extension regex.
112
+ *
113
+ * @return null
114
+ */
115
+ public function fix_mime_type_svg( $data = null, $file = null, $filename = null, $mimes = null ) {
116
+ $ext = isset( $data['ext'] ) ? $data['ext'] : '';
117
+ if ( strlen( $ext ) < 1 ) {
118
+ $exploded = explode( '.', $filename );
119
+ $ext = strtolower( end( $exploded ) );
120
+ }
121
+ if ( 'svg' === $ext ) {
122
+ $data['type'] = 'image/svg+xml';
123
+ $data['ext'] = 'svg';
124
+ } elseif ( 'svgz' === $ext ) {
125
+ $data['type'] = 'image/svg+xml';
126
+ $data['ext'] = 'svgz';
127
+ }
128
+
129
+ return $data;
130
+ }
131
+
132
+ /**
133
+ * Check if the file is an SVG, if so handle appropriately
134
+ *
135
+ * @param array $file An array of data for a single file.
136
+ *
137
+ * @return mixed
138
+ */
139
+ public function check_for_svg( $file ) {
140
+
141
+ // Ensure we have a proper file path before processing
142
+ if ( ! isset( $file['tmp_name'] ) ) {
143
+ return $file;
144
+ }
145
+
146
+ $file_name = isset( $file['name'] ) ? $file['name'] : '';
147
+ $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file_name );
148
+ $type = ! empty( $wp_filetype['type'] ) ? $wp_filetype['type'] : '';
149
+
150
+ if ( 'image/svg+xml' === $type ) {
151
+ if ( ! $this->sanitize( $file['tmp_name'] ) ) {
152
+ $file['error'] = __(
153
+ "Sorry, this file couldn't be sanitized so for security reasons wasn't uploaded",
154
+ 'safe-svg'
155
+ );
156
+ }
157
+ }
158
+
159
+ return $file;
160
+ }
161
+
162
+ /**
163
+ * Sanitize the SVG
164
+ *
165
+ * @param string $file Temp file path.
166
+ *
167
+ * @return bool|int
168
+ */
169
+ protected function sanitize( $file ) {
170
+ $dirty = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
171
+
172
+ // Is the SVG gzipped? If so we try and decode the string
173
+ $is_zipped = $this->is_gzipped( $dirty );
174
+ if ( $is_zipped ) {
175
+ $dirty = gzdecode( $dirty );
176
+
177
+ // If decoding fails, bail as we're not secure
178
+ if ( false === $dirty ) {
179
+ return false;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Load extra filters to allow devs to access the safe tags and attrs by themselves.
185
+ */
186
+ $this->sanitizer->setAllowedTags( new safe_svg_tags() );
187
+ $this->sanitizer->setAllowedAttrs( new safe_svg_attributes() );
188
+
189
+ $clean = $this->sanitizer->sanitize( $dirty );
190
+
191
+ if ( false === $clean ) {
192
+ return false;
193
+ }
194
+
195
+ // If we were gzipped, we need to re-zip
196
+ if ( $is_zipped ) {
197
+ $clean = gzencode( $clean );
198
+ }
199
+
200
+ file_put_contents( $file, $clean ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
201
+
202
+ return true;
203
+ }
204
+
205
+ /**
206
+ * Check if the contents are gzipped
207
+ *
208
+ * @see http://www.gzip.org/zlib/rfc-gzip.html#member-format
209
+ *
210
+ * @param string $contents Content to check.
211
+ *
212
+ * @return bool
213
+ */
214
+ protected function is_gzipped( $contents ) {
215
+ // phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found
216
+ if ( function_exists( 'mb_strpos' ) ) {
217
+ return 0 === mb_strpos( $contents, "\x1f" . "\x8b" . "\x08" );
218
+ } else {
219
+ return 0 === strpos( $contents, "\x1f" . "\x8b" . "\x08" );
220
+ }
221
+ // phpcs:enable
222
+ }
223
+
224
+ /**
225
+ * Filters the attachment data prepared for JavaScript to add the sizes array to the response
226
+ *
227
+ * @param array $response Array of prepared attachment data.
228
+ * @param int|object $attachment Attachment ID or object.
229
+ * @param array $meta Array of attachment meta data.
230
+ *
231
+ * @return array
232
+ */
233
+ public function fix_admin_preview( $response, $attachment, $meta ) {
234
+
235
+ if ( 'image/svg+xml' === $response['mime'] ) {
236
+ $dimensions = $this->svg_dimensions( get_attached_file( $attachment->ID ) );
237
+
238
+ if ( $dimensions ) {
239
+ $response = array_merge( $response, $dimensions );
240
+ }
241
+
242
+ $possible_sizes = apply_filters(
243
+ 'image_size_names_choose',
244
+ array(
245
+ 'full' => __( 'Full Size' ),
246
+ 'thumbnail' => __( 'Thumbnail' ),
247
+ 'medium' => __( 'Medium' ),
248
+ 'large' => __( 'Large' ),
249
+ )
250
+ );
251
+
252
+ $sizes = array();
253
+
254
+ foreach ( $possible_sizes as $size => $label ) {
255
+ $default_height = 2000;
256
+ $default_width = 2000;
257
+
258
+ if ( 'full' === $size && $dimensions ) {
259
+ $default_height = $dimensions['height'];
260
+ $default_width = $dimensions['width'];
261
+ }
262
+
263
+ $sizes[ $size ] = array(
264
+ 'height' => get_option( "{$size}_size_w", $default_height ),
265
+ 'width' => get_option( "{$size}_size_h", $default_width ),
266
+ 'url' => $response['url'],
267
+ 'orientation' => 'portrait',
268
+ );
269
+ }
270
+
271
+ $response['sizes'] = $sizes;
272
+ $response['icon'] = $response['url'];
273
+ }
274
+
275
+ return $response;
276
+ }
277
+
278
+ /**
279
+ * Filters the image src result.
280
+ * If the image size doesn't exist, set a default size of 100 for width and height
281
+ *
282
+ * @param array|false $image Either array with src, width & height, icon src, or false.
283
+ * @param int $attachment_id Image attachment ID.
284
+ * @param string|array $size Size of image. Image size or array of width and height values
285
+ * (in that order). Default 'thumbnail'.
286
+ * @param bool $icon Whether the image should be treated as an icon. Default false.
287
+ *
288
+ * @return array
289
+ */
290
+ public function one_pixel_fix( $image, $attachment_id, $size, $icon ) {
291
+ if ( get_post_mime_type( $attachment_id ) === 'image/svg+xml' ) {
292
+ $dimensions = $this->svg_dimensions( get_attached_file( $attachment_id ) );
293
+
294
+ if ( $dimensions ) {
295
+ $image[1] = $dimensions['width'];
296
+ $image[2] = $dimensions['height'];
297
+ } else {
298
+ $image[1] = 100;
299
+ $image[2] = 100;
300
+ }
301
+ }
302
+
303
+ return $image;
304
+ }
305
+
306
+ /**
307
+ * If the featured image is an SVG we wrap it in an SVG class so we can apply our CSS fix.
308
+ *
309
+ * @param string $content Admin post thumbnail HTML markup.
310
+ * @param int $post_id Post ID.
311
+ * @param int $thumbnail_id Thumbnail ID.
312
+ *
313
+ * @return string
314
+ */
315
+ public function featured_image_fix( $content, $post_id, $thumbnail_id ) {
316
+ $mime = get_post_mime_type( $thumbnail_id );
317
+
318
+ if ( 'image/svg+xml' === $mime ) {
319
+ $content = sprintf( '<span class="svg">%s</span>', $content );
320
+ }
321
+
322
+ return $content;
323
+ }
324
+
325
+ /**
326
+ * Load our custom CSS sheet.
327
+ */
328
+ public function load_custom_admin_style() {
329
+ wp_enqueue_style( 'safe-svg-css', plugins_url( 'assets/safe-svg.css', __FILE__ ), array(), SAFE_SVG_VERSION );
330
+ }
331
+
332
+ /**
333
+ * Override the default height and width string on an SVG
334
+ *
335
+ * @param string $html HTML content for the image.
336
+ * @param int $id Attachment ID.
337
+ * @param string $alt Alternate text.
338
+ * @param string $title Attachment title.
339
+ * @param string $align Part of the class name for aligning the image.
340
+ * @param string|array $size Size of image. Image size or array of width and height values (in that order).
341
+ * Default 'medium'.
342
+ *
343
+ * @return mixed
344
+ */
345
+ public function get_image_tag_override( $html, $id, $alt, $title, $align, $size ) {
346
+ $mime = get_post_mime_type( $id );
347
+
348
+ if ( 'image/svg+xml' === $mime ) {
349
+ if ( is_array( $size ) ) {
350
+ $width = $size[0];
351
+ $height = $size[1];
352
+ // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.Found, Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
353
+ } elseif ( 'full' === $size && $dimensions = $this->svg_dimensions( get_attached_file( $id ) ) ) {
354
+ $width = $dimensions['width'];
355
+ $height = $dimensions['height'];
356
+ } else {
357
+ $width = get_option( "{$size}_size_w", false );
358
+ $height = get_option( "{$size}_size_h", false );
359
+ }
360
+
361
+ if ( $height && $width ) {
362
+ $html = str_replace( 'width="1" ', sprintf( 'width="%s" ', $width ), $html );
363
+ $html = str_replace( 'height="1" ', sprintf( 'height="%s" ', $height ), $html );
364
+ } else {
365
+ $html = str_replace( 'width="1" ', '', $html );
366
+ $html = str_replace( 'height="1" ', '', $html );
367
+ }
368
+
369
+ $html = str_replace( '/>', ' role="img" />', $html );
370
+ }
371
+
372
+ return $html;
373
+ }
374
+
375
+ /**
376
+ * Skip regenerating SVGs
377
+ *
378
+ * @param array $metadata An array of attachment meta data.
379
+ * @param int $attachment_id Attachment Id to process.
380
+ *
381
+ * @return mixed Metadata for attachment.
382
+ */
383
+ public function skip_svg_regeneration( $metadata, $attachment_id ) {
384
+ $mime = get_post_mime_type( $attachment_id );
385
+ if ( 'image/svg+xml' === $mime ) {
386
+ $additional_image_sizes = wp_get_additional_image_sizes();
387
+ $svg_path = get_attached_file( $attachment_id );
388
+ $upload_dir = wp_upload_dir();
389
+ // get the path relative to /uploads/ - found no better way:
390
+ $relative_path = str_replace( trailingslashit( $upload_dir['basedir'] ), '', $svg_path );
391
+ $filename = basename( $svg_path );
392
+
393
+ $dimensions = $this->svg_dimensions( $svg_path );
394
+
395
+ if ( ! $dimensions ) {
396
+ return $metadata;
397
+ }
398
+
399
+ $metadata = array(
400
+ 'width' => intval( $dimensions['width'] ),
401
+ 'height' => intval( $dimensions['height'] ),
402
+ 'file' => $relative_path,
403
+ );
404
+
405
+ // Might come handy to create the sizes array too - But it's not needed for this workaround! Always links to original svg-file => Hey, it's a vector graphic! ;)
406
+ $sizes = array();
407
+ foreach ( get_intermediate_image_sizes() as $s ) {
408
+ $sizes[ $s ] = array(
409
+ 'width' => '',
410
+ 'height' => '',
411
+ 'crop' => false,
412
+ );
413
+
414
+ if ( isset( $additional_image_sizes[ $s ]['width'] ) ) {
415
+ // For theme-added sizes
416
+ $sizes[ $s ]['width'] = intval( $additional_image_sizes[ $s ]['width'] );
417
+ } else {
418
+ // For default sizes set in options
419
+ $sizes[ $s ]['width'] = get_option( "{$s}_size_w" );
420
+ }
421
+
422
+ if ( isset( $additional_image_sizes[ $s ]['height'] ) ) {
423
+ // For theme-added sizes
424
+ $sizes[ $s ]['height'] = intval( $additional_image_sizes[ $s ]['height'] );
425
+ } else {
426
+ // For default sizes set in options
427
+ $sizes[ $s ]['height'] = get_option( "{$s}_size_h" );
428
+ }
429
+
430
+ if ( isset( $additional_image_sizes[ $s ]['crop'] ) ) {
431
+ // For theme-added sizes
432
+ $sizes[ $s ]['crop'] = intval( $additional_image_sizes[ $s ]['crop'] );
433
+ } else {
434
+ // For default sizes set in options
435
+ $sizes[ $s ]['crop'] = get_option( "{$s}_crop" );
436
+ }
437
+
438
+ $sizes[ $s ]['file'] = $filename;
439
+ $sizes[ $s ]['mime-type'] = $mime;
440
+ }
441
+ $metadata['sizes'] = $sizes;
442
+ }
443
+
444
+ return $metadata;
445
+ }
446
+
447
+ /**
448
+ * Filters the attachment meta data.
449
+ *
450
+ * @param array|bool $data Array of meta data for the given attachment, or false
451
+ * if the object does not exist.
452
+ * @param int $post_id Attachment ID.
453
+ */
454
+ public function metadata_error_fix( $data, $post_id ) {
455
+
456
+ // If it's a WP_Error regenerate metadata and save it
457
+ if ( is_wp_error( $data ) ) {
458
+ $data = wp_generate_attachment_metadata( $post_id, get_attached_file( $post_id ) );
459
+ wp_update_attachment_metadata( $post_id, $data );
460
+ }
461
+
462
+ return $data;
463
+ }
464
+
465
+ /**
466
+ * Get SVG size from the width/height or viewport.
467
+ *
468
+ * @param string|false $svg The file path to where the SVG file should be, false otherwise.
469
+ *
470
+ * @return array|bool
471
+ */
472
+ protected function svg_dimensions( $svg ) {
473
+ $svg = @simplexml_load_file( $svg ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
474
+ $width = 0;
475
+ $height = 0;
476
+ if ( $svg ) {
477
+ $attributes = $svg->attributes();
478
+
479
+ if ( isset( $attributes->viewBox ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
480
+ $sizes = explode( ' ', $attributes->viewBox ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
481
+ if ( isset( $sizes[2], $sizes[3] ) ) {
482
+ $viewbox_width = floatval( $sizes[2] );
483
+ $viewbox_height = floatval( $sizes[3] );
484
+ }
485
+ }
486
+
487
+ if ( isset( $attributes->width, $attributes->height ) && is_numeric( (float) $attributes->width ) && is_numeric( (float) $attributes->height ) && ! $this->str_ends_with( (string) $attributes->width, '%' ) && ! $this->str_ends_with( (string) $attributes->height, '%' ) ) {
488
+ $attr_width = floatval( $attributes->width );
489
+ $attr_height = floatval( $attributes->height );
490
+ }
491
+
492
+ /**
493
+ * Decide which attributes of the SVG we use first for image tag dimensions.
494
+ *
495
+ * We default to using the parameters in the viewbox attribute but
496
+ * that can be overridden using this filter if you'd prefer to use
497
+ * the width and height attributes.
498
+ *
499
+ * @hook safe_svg_use_width_height_attributes
500
+ *
501
+ * @param {bool} $false If the width & height attributes should be used first. Default false.
502
+ * @param {string} $svg The file path to the SVG.
503
+ *
504
+ * @return {bool} If we should use the width & height attributes first or not.
505
+ */
506
+ $use_width_height = (bool) apply_filters( 'safe_svg_use_width_height_attributes', false, $svg );
507
+
508
+ if ( $use_width_height ) {
509
+ if ( isset( $attr_width, $attr_height ) ) {
510
+ $width = $attr_width;
511
+ $height = $attr_height;
512
+ } elseif ( isset( $viewbox_width, $viewbox_height ) ) {
513
+ $width = $viewbox_width;
514
+ $height = $viewbox_height;
515
+ }
516
+ } else {
517
+ if ( isset( $viewbox_width, $viewbox_height ) ) {
518
+ $width = $viewbox_width;
519
+ $height = $viewbox_height;
520
+ } elseif ( isset( $attr_width, $attr_height ) ) {
521
+ $width = $attr_width;
522
+ $height = $attr_height;
523
+ }
524
+ }
525
+
526
+ if ( ! $width && ! $height ) {
527
+ return false;
528
+ }
529
+ }
530
+
531
+ return array(
532
+ 'width' => $width,
533
+ 'height' => $height,
534
+ 'orientation' => ( $width > $height ) ? 'landscape' : 'portrait',
535
+ );
536
+ }
537
+
538
+ /**
539
+ * Disable the creation of srcset on SVG images.
540
+ *
541
+ * @param array $image_meta The image meta data.
542
+ * @param int[] $size_array {
543
+ * An array of requested width and height values.
544
+ *
545
+ * @type int $0 The width in pixels.
546
+ * @type int $1 The height in pixels.
547
+ * }
548
+ * @param string $image_src The 'src' of the image.
549
+ * @param int $attachment_id The image attachment ID.
550
+ */
551
+ public function disable_srcset( $image_meta, $size_array, $image_src, $attachment_id ) {
552
+ if ( $attachment_id && 'image/svg+xml' === get_post_mime_type( $attachment_id ) ) {
553
+ $image_meta['sizes'] = array();
554
+ }
555
+
556
+ return $image_meta;
557
+ }
558
+
559
+ /**
560
+ * Polyfill for `str_ends_with()` function added in PHP 8.0.
561
+ *
562
+ * Performs a case-sensitive check indicating if
563
+ * the haystack ends with needle.
564
+ *
565
+ * @param string $haystack The string to search in.
566
+ * @param string $needle The substring to search for in the `$haystack`.
567
+ * @return bool True if `$haystack` ends with `$needle`, otherwise false.
568
+ */
569
+ protected function str_ends_with( $haystack, $needle ) {
570
+ if ( function_exists( 'str_ends_with' ) ) {
571
+ return str_ends_with( $haystack, $needle );
572
+ }
573
+
574
+ if ( '' === $haystack && '' !== $needle ) {
575
+ return false;
576
+ }
577
+
578
+ $len = strlen( $needle );
579
+ return 0 === substr_compare( $haystack, $needle, -$len, $len );
580
+ }
581
+
582
+ }
583
  }
584
 
585
  $safe_svg = new safe_svg();
vendor/autoload.php CHANGED
@@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) {
9
 
10
  require_once __DIR__ . '/composer/autoload_real.php';
11
 
12
- return ComposerAutoloaderInite6369ee01de87c9996b1c2a1cd9470c9::getLoader();
9
 
10
  require_once __DIR__ . '/composer/autoload_real.php';
11
 
12
+ return ComposerAutoloaderInitd232799cacabaae996af1a3db5d0e23d::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInite6369ee01de87c9996b1c2a1cd9470c9
6
  {
7
  private static $loader;
8
 
@@ -24,12 +24,12 @@ class ComposerAutoloaderInite6369ee01de87c9996b1c2a1cd9470c9
24
 
25
  require __DIR__ . '/platform_check.php';
26
 
27
- spl_autoload_register(array('ComposerAutoloaderInite6369ee01de87c9996b1c2a1cd9470c9', 'loadClassLoader'), true, true);
28
  self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
29
- spl_autoload_unregister(array('ComposerAutoloaderInite6369ee01de87c9996b1c2a1cd9470c9', 'loadClassLoader'));
30
 
31
  require __DIR__ . '/autoload_static.php';
32
- call_user_func(\Composer\Autoload\ComposerStaticInite6369ee01de87c9996b1c2a1cd9470c9::getInitializer($loader));
33
 
34
  $loader->register(true);
35
 
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitd232799cacabaae996af1a3db5d0e23d
6
  {
7
  private static $loader;
8
 
24
 
25
  require __DIR__ . '/platform_check.php';
26
 
27
+ spl_autoload_register(array('ComposerAutoloaderInitd232799cacabaae996af1a3db5d0e23d', 'loadClassLoader'), true, true);
28
  self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
29
+ spl_autoload_unregister(array('ComposerAutoloaderInitd232799cacabaae996af1a3db5d0e23d', 'loadClassLoader'));
30
 
31
  require __DIR__ . '/autoload_static.php';
32
+ call_user_func(\Composer\Autoload\ComposerStaticInitd232799cacabaae996af1a3db5d0e23d::getInitializer($loader));
33
 
34
  $loader->register(true);
35
 
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInite6369ee01de87c9996b1c2a1cd9470c9
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'e' =>
@@ -27,9 +27,9 @@ class ComposerStaticInite6369ee01de87c9996b1c2a1cd9470c9
27
  public static function getInitializer(ClassLoader $loader)
28
  {
29
  return \Closure::bind(function () use ($loader) {
30
- $loader->prefixLengthsPsr4 = ComposerStaticInite6369ee01de87c9996b1c2a1cd9470c9::$prefixLengthsPsr4;
31
- $loader->prefixDirsPsr4 = ComposerStaticInite6369ee01de87c9996b1c2a1cd9470c9::$prefixDirsPsr4;
32
- $loader->classMap = ComposerStaticInite6369ee01de87c9996b1c2a1cd9470c9::$classMap;
33
 
34
  }, null, ClassLoader::class);
35
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitd232799cacabaae996af1a3db5d0e23d
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'e' =>
27
  public static function getInitializer(ClassLoader $loader)
28
  {
29
  return \Closure::bind(function () use ($loader) {
30
+ $loader->prefixLengthsPsr4 = ComposerStaticInitd232799cacabaae996af1a3db5d0e23d::$prefixLengthsPsr4;
31
+ $loader->prefixDirsPsr4 = ComposerStaticInitd232799cacabaae996af1a3db5d0e23d::$prefixDirsPsr4;
32
+ $loader->classMap = ComposerStaticInitd232799cacabaae996af1a3db5d0e23d::$classMap;
33
 
34
  }, null, ClassLoader::class);
35
  }
vendor/composer/installed.json CHANGED
@@ -49,6 +49,6 @@
49
  "install-path": "../enshrined/svg-sanitize"
50
  }
51
  ],
52
- "dev": true,
53
  "dev-package-names": []
54
  }
49
  "install-path": "../enshrined/svg-sanitize"
50
  }
51
  ],
52
+ "dev": false,
53
  "dev-package-names": []
54
  }
vendor/composer/installed.php CHANGED
@@ -1,19 +1,19 @@
1
  <?php return array(
2
  'root' => array(
3
  'name' => 'darylldoyle/safe-svg',
4
- 'pretty_version' => '2.0.2',
5
- 'version' => '2.0.2.0',
6
- 'reference' => 'c603e4b5592ac46c71c846d6e81924f1a9f0a761',
7
  'type' => 'wordpress-plugin',
8
  'install_path' => __DIR__ . '/../../',
9
  'aliases' => array(),
10
- 'dev' => true,
11
  ),
12
  'versions' => array(
13
  'darylldoyle/safe-svg' => array(
14
- 'pretty_version' => '2.0.2',
15
- 'version' => '2.0.2.0',
16
- 'reference' => 'c603e4b5592ac46c71c846d6e81924f1a9f0a761',
17
  'type' => 'wordpress-plugin',
18
  'install_path' => __DIR__ . '/../../',
19
  'aliases' => array(),
1
  <?php return array(
2
  'root' => array(
3
  'name' => 'darylldoyle/safe-svg',
4
+ 'pretty_version' => '2.0.3',
5
+ 'version' => '2.0.3.0',
6
+ 'reference' => '1e016108a721af56ed50e54bb1cc2dfe3ec62750',
7
  'type' => 'wordpress-plugin',
8
  'install_path' => __DIR__ . '/../../',
9
  'aliases' => array(),
10
+ 'dev' => false,
11
  ),
12
  'versions' => array(
13
  'darylldoyle/safe-svg' => array(
14
+ 'pretty_version' => '2.0.3',
15
+ 'version' => '2.0.3.0',
16
+ 'reference' => '1e016108a721af56ed50e54bb1cc2dfe3ec62750',
17
  'type' => 'wordpress-plugin',
18
  'install_path' => __DIR__ . '/../../',
19
  'aliases' => array(),