EWWW Image Optimizer - Version 4.7.4

Version Description

  • fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
  • fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
  • fixed: Lazy Load parsing breaking img elements in script blocks
  • fixed: Lazy Load and JS WebP bail when SVGs are wrapped in XML tags
  • fixed: ExactDN mixes x and w srcset descriptors
  • fixed: page parsers (ExactDN, Lazy, JS WebP) still fail to process some img elements that have unquoted src attributes
Download this release

Release Info

Developer nosilver4u
Plugin Icon 128x128 EWWW Image Optimizer
Version 4.7.4
Comparing to
See all releases

Code changes from version 4.7.3 to 4.7.4

changelog.txt CHANGED
@@ -1,3 +1,11 @@
 
 
 
 
 
 
 
 
1
  = 4.7.3 =
2
  * added: disable WebP script block on certain pages by defining EWWW_IMAGE_OPTIMIZER_NO_JS as true
3
  * changed: use SVG inline image placeholder if width and height are known when LQIP is disabled or ExactDN is not available
1
+ = 4.7.4 =
2
+ * fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
3
+ * fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
4
+ * fixed: Lazy Load parsing breaking img elements in script blocks
5
+ * fixed: Lazy Load and JS WebP bail when SVGs are wrapped in XML tags
6
+ * fixed: ExactDN mixes x and w srcset descriptors
7
+ * fixed: page parsers (ExactDN, Lazy, JS WebP) still fail to process some img elements that have unquoted src attributes
8
+
9
  = 4.7.3 =
10
  * added: disable WebP script block on certain pages by defining EWWW_IMAGE_OPTIMIZER_NO_JS as true
11
  * changed: use SVG inline image placeholder if width and height are known when LQIP is disabled or ExactDN is not available
classes/class-ewwwio-alt-webp.php CHANGED
@@ -297,7 +297,7 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
297
  is_feed() ||
298
  is_preview() ||
299
  ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
300
- preg_match( '/<\?xml/', $buffer )
301
  ) {
302
  if ( empty( $buffer ) ) {
303
  ewwwio_debug_message( 'empty buffer' );
@@ -323,7 +323,7 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
323
  if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
324
  ewwwio_debug_message( 'rest request' );
325
  }
326
- if ( preg_match( '/<\?xml/', $buffer ) ) {
327
  ewwwio_debug_message( 'not html, xml tag found' );
328
  }
329
  if ( strpos( $buffer, 'amp-boilerplate' ) ) {
@@ -337,7 +337,7 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
337
 
338
  /* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
339
 
340
- $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/', '', $buffer ), false );
341
  if ( ewww_image_optimizer_iterable( $images[0] ) ) {
342
  foreach ( $images[0] as $index => $image ) {
343
  $file = $images['img_url'][ $index ];
@@ -456,7 +456,7 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
456
  } // End foreach().
457
  } // End if().
458
  // Now we will look for any lazy images that don't have a src attribute (this search returns ALL img elements though).
459
- $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/', '', $buffer ), false, false );
460
  if ( ewww_image_optimizer_iterable( $images[0] ) ) {
461
  ewwwio_debug_message( 'parsing images without requiring src' );
462
  foreach ( $images[0] as $index => $image ) {
297
  is_feed() ||
298
  is_preview() ||
299
  ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
300
+ preg_match( '/^<\?xml/', $buffer )
301
  ) {
302
  if ( empty( $buffer ) ) {
303
  ewwwio_debug_message( 'empty buffer' );
323
  if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
324
  ewwwio_debug_message( 'rest request' );
325
  }
326
+ if ( preg_match( '/^<\?xml/', $buffer ) ) {
327
  ewwwio_debug_message( 'not html, xml tag found' );
328
  }
329
  if ( strpos( $buffer, 'amp-boilerplate' ) ) {
337
 
338
  /* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
339
 
340
+ $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false );
341
  if ( ewww_image_optimizer_iterable( $images[0] ) ) {
342
  foreach ( $images[0] as $index => $image ) {
343
  $file = $images['img_url'][ $index ];
456
  } // End foreach().
457
  } // End if().
458
  // Now we will look for any lazy images that don't have a src attribute (this search returns ALL img elements though).
459
+ $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false, false );
460
  if ( ewww_image_optimizer_iterable( $images[0] ) ) {
461
  ewwwio_debug_message( 'parsing images without requiring src' );
462
  foreach ( $images[0] as $index => $image ) {
classes/class-ewwwio-lazy-load.php CHANGED
@@ -109,7 +109,7 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
109
  is_preview() ||
110
  ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
111
  wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ||
112
- preg_match( '/<\?xml/', $buffer )
113
  ) {
114
  if ( empty( $buffer ) ) {
115
  ewwwio_debug_message( 'empty buffer' );
@@ -141,7 +141,7 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
141
  if ( wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ) {
142
  ewwwio_debug_message( 'twentytwenty enqueued' );
143
  }
144
- if ( preg_match( '/<\?xml/', $buffer ) ) {
145
  ewwwio_debug_message( 'not html, xml tag found' );
146
  }
147
  if ( strpos( $buffer, 'amp-boilerplate' ) ) {
@@ -153,7 +153,7 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
153
  $above_the_fold = apply_filters( 'ewww_image_optimizer_lazy_fold', 0 );
154
  $images_processed = 0;
155
 
156
- $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/', '', $buffer ), false );
157
  if ( ! empty( $images[0] ) && ewww_image_optimizer_iterable( $images[0] ) ) {
158
  foreach ( $images[0] as $index => $image ) {
159
  $images_processed++;
@@ -346,7 +346,8 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
346
  }
347
 
348
  // Skip inline data URIs.
349
- if ( strpos( $image, "src='data:image" ) || strpos( $image, 'src="data:image' ) ) {
 
350
  return false;
351
  }
352
  // Ignore 0-size Pinterest schema images.
109
  is_preview() ||
110
  ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
111
  wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ||
112
+ preg_match( '/^<\?xml/', $buffer )
113
  ) {
114
  if ( empty( $buffer ) ) {
115
  ewwwio_debug_message( 'empty buffer' );
141
  if ( wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ) {
142
  ewwwio_debug_message( 'twentytwenty enqueued' );
143
  }
144
+ if ( preg_match( '/^<\?xml/', $buffer ) ) {
145
  ewwwio_debug_message( 'not html, xml tag found' );
146
  }
147
  if ( strpos( $buffer, 'amp-boilerplate' ) ) {
153
  $above_the_fold = apply_filters( 'ewww_image_optimizer_lazy_fold', 0 );
154
  $images_processed = 0;
155
 
156
+ $images = $this->get_images_from_html( preg_replace( '/<(noscript|script).*?\/\1>/s', '', $buffer ), false );
157
  if ( ! empty( $images[0] ) && ewww_image_optimizer_iterable( $images[0] ) ) {
158
  foreach ( $images[0] as $index => $image ) {
159
  $images_processed++;
346
  }
347
 
348
  // Skip inline data URIs.
349
+ $image_src = $this->get_attribute( $image, 'src' );
350
+ if ( false !== strpos( $image_src, 'data:image' ) ) {
351
  return false;
352
  }
353
  // Ignore 0-size Pinterest schema images.
classes/class-ewwwio-page-parser.php CHANGED
@@ -42,41 +42,56 @@ class EWWWIO_Page_Parser {
42
  */
43
  function get_images_from_html( $content, $hyperlinks = true, $src_required = true ) {
44
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
45
- $images = array();
 
46
 
47
  $unquoted_pattern = '';
48
  $search_pattern = '#(?P<img_tag><img\s[^>]*?>)#is';
49
  if ( $hyperlinks ) {
50
- $search_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*["\'](?P<figure_class>[\w\s-]+?)["\'][^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*["\'](?P<link_url>[^\s]+?)["\'][^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'][^>]*?>){1}(?:\s*</a>)?#is';
 
51
  $unquoted_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*(?P<figure_class>[\w-]+)[^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*(?P<link_url>[^"\'][^\s>]+)[^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>){1}(?:\s*</a>)?#is';
52
  } elseif ( $src_required ) {
53
- $search_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'][^>]*?>)#is';
 
54
  $unquoted_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>)#is';
55
  }
56
  if ( preg_match_all( $search_pattern, $content, $images ) ) {
 
57
  foreach ( $images as $key => $unused ) {
58
  // Simplify the output as much as possible.
59
  if ( is_numeric( $key ) && $key > 0 ) {
60
  unset( $images[ $key ] );
61
  }
62
  }
 
63
  }
64
- ewwwio_debug_message( 'trying unquoted pattern' );
65
  if ( $unquoted_pattern && preg_match_all( $unquoted_pattern, $content, $unquoted_images ) ) {
 
66
  foreach ( $unquoted_images as $key => $unused ) {
67
  // Simplify the output as much as possible.
68
  if ( is_numeric( $key ) && $key > 0 ) {
69
  unset( $unquoted_images[ $key ] );
70
  }
71
  }
 
72
  }
 
73
  if ( ! empty( $images ) && ! empty( $unquoted_images ) ) {
 
 
74
  $images = array_merge_recursive( $images, $unquoted_images );
 
75
  if ( ! empty( $images[0] ) && ! empty( $images[1] ) ) {
76
  $images[0] = array_merge( $images[0], $images[1] );
77
  unset( $images[1] );
78
  }
 
 
 
79
  }
 
80
  return $images;
81
  }
82
 
42
  */
43
  function get_images_from_html( $content, $hyperlinks = true, $src_required = true ) {
44
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
45
+ $images = array();
46
+ $unquoted_images = array();
47
 
48
  $unquoted_pattern = '';
49
  $search_pattern = '#(?P<img_tag><img\s[^>]*?>)#is';
50
  if ( $hyperlinks ) {
51
+ ewwwio_debug_message( 'using figure+hyperlink(a) patterns with src required' );
52
+ $search_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*["\'](?P<figure_class>[\w\s-]+?)["\'][^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*["\'](?P<link_url>[^\s]+?)["\'][^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*("|\')(?P<img_url>(?!\4).+?)\4[^>]*?>){1}(?:\s*</a>)?#is';
53
  $unquoted_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*(?P<figure_class>[\w-]+)[^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*(?P<link_url>[^"\'][^\s>]+)[^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>){1}(?:\s*</a>)?#is';
54
  } elseif ( $src_required ) {
55
+ ewwwio_debug_message( 'using plain img pattern, src still required' );
56
+ $search_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*("|\')(?P<img_url>(?!\2).+?)\2[^>]*?>)#is';
57
  $unquoted_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>)#is';
58
  }
59
  if ( preg_match_all( $search_pattern, $content, $images ) ) {
60
+ ewwwio_debug_message( 'found ' . count( $images[0] ) . ' image elements with quoted pattern' );
61
  foreach ( $images as $key => $unused ) {
62
  // Simplify the output as much as possible.
63
  if ( is_numeric( $key ) && $key > 0 ) {
64
  unset( $images[ $key ] );
65
  }
66
  }
67
+ /* ewwwio_debug_message( print_r( $images, true ) ); */
68
  }
69
+ $images = array_filter( $images );
70
  if ( $unquoted_pattern && preg_match_all( $unquoted_pattern, $content, $unquoted_images ) ) {
71
+ ewwwio_debug_message( 'found ' . count( $unquoted_images[0] ) . ' image elements with unquoted pattern' );
72
  foreach ( $unquoted_images as $key => $unused ) {
73
  // Simplify the output as much as possible.
74
  if ( is_numeric( $key ) && $key > 0 ) {
75
  unset( $unquoted_images[ $key ] );
76
  }
77
  }
78
+ /* ewwwio_debug_message( print_r( $unquoted_images, true ) ); */
79
  }
80
+ $unquoted_images = array_filter( $unquoted_images );
81
  if ( ! empty( $images ) && ! empty( $unquoted_images ) ) {
82
+ ewwwio_debug_message( 'both patterns found results, merging' );
83
+ /* ewwwio_debug_message( print_r( $images, true ) ); */
84
  $images = array_merge_recursive( $images, $unquoted_images );
85
+ /* ewwwio_debug_message( print_r( $images, true ) ); */
86
  if ( ! empty( $images[0] ) && ! empty( $images[1] ) ) {
87
  $images[0] = array_merge( $images[0], $images[1] );
88
  unset( $images[1] );
89
  }
90
+ } elseif ( empty( $images ) && ! empty( $unquoted_images ) ) {
91
+ ewwwio_debug_message( 'unquoted results only, subbing in' );
92
+ $images = $unquoted_images;
93
  }
94
+ /* ewwwio_debug_message( print_r( $images, true ) ); */
95
  return $images;
96
  }
97
 
classes/class-exactdn.php CHANGED
@@ -61,7 +61,7 @@ class ExactDN extends EWWWIO_Page_Parser {
61
  * @access public
62
  * @var string $remove_path
63
  */
64
- private $remove_path = '';
65
 
66
  /**
67
  * The ExactDN domain/zone.
@@ -122,7 +122,6 @@ class ExactDN extends EWWWIO_Page_Parser {
122
  // Images in post content and galleries.
123
  add_filter( 'the_content', array( $this, 'filter_the_content' ), 999999 );
124
  // Start an output buffer before any output starts.
125
- /* add_action( 'template_redirect', array( $this, 'buffer_start' ), 2 ); */
126
  add_filter( 'ewww_image_optimizer_filter_page_output', array( $this, 'filter_page_output' ), 5 );
127
 
128
  // Core image retrieval.
@@ -176,7 +175,7 @@ class ExactDN extends EWWWIO_Page_Parser {
176
 
177
  // Configure Autoptimize with our CDN domain.
178
  add_filter( 'autoptimize_filter_cssjs_multidomain', array( $this, 'autoptimize_cdn_url' ) );
179
- if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) ) {
180
  $ao_cdn_url = ewww_image_optimizer_get_option( 'autoptimize_cdn_url' );
181
  if ( empty( $ao_cdn_url ) ) {
182
  ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
@@ -509,6 +508,16 @@ class ExactDN extends EWWWIO_Page_Parser {
509
  return $this->sanitize_domain( get_option( 'ewww_image_optimizer_exactdn_domain' ) );
510
  }
511
 
 
 
 
 
 
 
 
 
 
 
512
  /**
513
  * Get the ExactDN option.
514
  *
@@ -637,13 +646,6 @@ class ExactDN extends EWWWIO_Page_Parser {
637
  return '';
638
  }
639
 
640
- /**
641
- * Starts an output buffer and registers the callback function to do ExactDN url replacement.
642
- */
643
- function buffer_start() {
644
- ob_start( array( $this, 'filter_page_output' ) );
645
- }
646
-
647
  /**
648
  * Identify images in page content, and if images are local (uploaded to the current site), pass through ExactDN.
649
  *
@@ -767,6 +769,18 @@ class ExactDN extends EWWWIO_Page_Parser {
767
  if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) ) {
768
  $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
769
  }
 
 
 
 
 
 
 
 
 
 
 
 
770
  if ( ! $lazy && $lazy_load_src ) {
771
  $placeholder_src = $src;
772
  $placeholder_src_orig = $src;
@@ -1060,7 +1074,7 @@ class ExactDN extends EWWWIO_Page_Parser {
1060
  ewwwio_debug_message( 'checking to see if srcset width already exists' );
1061
  $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
1062
  $new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
1063
- if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) ) {
1064
  ewwwio_debug_message( 'src not in srcset, adding' );
1065
  $this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
1066
  // Replace original tag with modified version.
@@ -1625,8 +1639,12 @@ class ExactDN extends EWWWIO_Page_Parser {
1625
 
1626
  $upload_dir = wp_get_upload_dir();
1627
  $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
 
1628
 
1629
  foreach ( $sources as $i => $source ) {
 
 
 
1630
  if ( ! $this->validate_image_url( $source['url'] ) ) {
1631
  continue;
1632
  }
@@ -1692,6 +1710,10 @@ class ExactDN extends EWWWIO_Page_Parser {
1692
  */
1693
  $multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
1694
  $url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
 
 
 
 
1695
 
1696
  if (
1697
  /** Short-circuit via exactdn_srcset_multipliers filter. */
@@ -1704,7 +1726,7 @@ class ExactDN extends EWWWIO_Page_Parser {
1704
  && isset( $image_meta['width'] ) && isset( $image_meta['height'] ) && isset( $image_meta['file'] )
1705
  /** Verify we have the requested width/height. */
1706
  && isset( $size_array[0] ) && isset( $size_array[1] )
1707
- ) {
1708
 
1709
  $fullwidth = $image_meta['width'];
1710
  $fullheight = $image_meta['height'];
@@ -1736,6 +1758,9 @@ class ExactDN extends EWWWIO_Page_Parser {
1736
  $newwidth = intval( $base * $multiplier );
1737
  if ( 1920 === (int) $multiplier ) {
1738
  $newwidth = 1920;
 
 
 
1739
  }
1740
  if ( $newwidth < 50 ) {
1741
  continue;
@@ -1764,8 +1789,8 @@ class ExactDN extends EWWWIO_Page_Parser {
1764
 
1765
  $newsources[ $newwidth ] = array(
1766
  'url' => $this->generate_url( $url, $args ),
1767
- 'descriptor' => 'w',
1768
- 'value' => $newwidth,
1769
  );
1770
 
1771
  $currentwidths[] = $newwidth;
@@ -2041,9 +2066,13 @@ class ExactDN extends EWWWIO_Page_Parser {
2041
  */
2042
  protected function validate_image_url( $url, $exactdn_is_valid = false ) {
2043
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
 
 
 
 
2044
  $parsed_url = $this->parse_url( $url );
2045
  if ( ! $parsed_url ) {
2046
- ewwwio_debug_message( 'could not parse' );
2047
  return false;
2048
  }
2049
 
61
  * @access public
62
  * @var string $remove_path
63
  */
64
+ public $remove_path = '';
65
 
66
  /**
67
  * The ExactDN domain/zone.
122
  // Images in post content and galleries.
123
  add_filter( 'the_content', array( $this, 'filter_the_content' ), 999999 );
124
  // Start an output buffer before any output starts.
 
125
  add_filter( 'ewww_image_optimizer_filter_page_output', array( $this, 'filter_page_output' ), 5 );
126
 
127
  // Core image retrieval.
175
 
176
  // Configure Autoptimize with our CDN domain.
177
  add_filter( 'autoptimize_filter_cssjs_multidomain', array( $this, 'autoptimize_cdn_url' ) );
178
+ if ( false && defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
179
  $ao_cdn_url = ewww_image_optimizer_get_option( 'autoptimize_cdn_url' );
180
  if ( empty( $ao_cdn_url ) ) {
181
  ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
508
  return $this->sanitize_domain( get_option( 'ewww_image_optimizer_exactdn_domain' ) );
509
  }
510
 
511
+ /**
512
+ * Method to override the ExactDN domain at runtime, use with caution.
513
+ *
514
+ * @param string $domain The ExactDN domain to use instead.
515
+ */
516
+ function set_domain( $domain ) {
517
+ if ( is_string( $domain ) ) {
518
+ $this->exactdn_domain = $domain;
519
+ }
520
+ }
521
  /**
522
  * Get the ExactDN option.
523
  *
646
  return '';
647
  }
648
 
 
 
 
 
 
 
 
649
  /**
650
  * Identify images in page content, and if images are local (uploaded to the current site), pass through ExactDN.
651
  *
769
  if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) ) {
770
  $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
771
  }
772
+ if (
773
+ ! $lazy &&
774
+ strpos( $images['img_tag'][ $index ], ' data-src=' ) &&
775
+ strpos( $images['img_tag'][ $index ], 'lazyload' ) &&
776
+ (
777
+ strpos( $images['img_tag'][ $index ], 'data:image/gif' ) ||
778
+ strpos( $images['img_tag'][ $index ], 'data:image/svg' )
779
+ )
780
+ ) {
781
+ $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
782
+ ewwwio_debug_message( "found ewwwio ll src: $lazy_load_src" );
783
+ }
784
  if ( ! $lazy && $lazy_load_src ) {
785
  $placeholder_src = $src;
786
  $placeholder_src_orig = $src;
1074
  ewwwio_debug_message( 'checking to see if srcset width already exists' );
1075
  $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
1076
  $new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
1077
+ if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $new_srcset_attr ) ) {
1078
  ewwwio_debug_message( 'src not in srcset, adding' );
1079
  $this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
1080
  // Replace original tag with modified version.
1639
 
1640
  $upload_dir = wp_get_upload_dir();
1641
  $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
1642
+ $w_descriptor = true;
1643
 
1644
  foreach ( $sources as $i => $source ) {
1645
+ if ( 'x' === $source['descriptor'] ) {
1646
+ $w_descriptor = false;
1647
+ }
1648
  if ( ! $this->validate_image_url( $source['url'] ) ) {
1649
  continue;
1650
  }
1710
  */
1711
  $multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
1712
  $url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
1713
+ if ( ! $w_descriptor ) {
1714
+ ewwwio_debug_message( 'using x descriptors instead of w' );
1715
+ $multipliers = array_filter( $multipliers, 'is_int' );
1716
+ }
1717
 
1718
  if (
1719
  /** Short-circuit via exactdn_srcset_multipliers filter. */
1726
  && isset( $image_meta['width'] ) && isset( $image_meta['height'] ) && isset( $image_meta['file'] )
1727
  /** Verify we have the requested width/height. */
1728
  && isset( $size_array[0] ) && isset( $size_array[1] )
1729
+ ) {
1730
 
1731
  $fullwidth = $image_meta['width'];
1732
  $fullheight = $image_meta['height'];
1758
  $newwidth = intval( $base * $multiplier );
1759
  if ( 1920 === (int) $multiplier ) {
1760
  $newwidth = 1920;
1761
+ if ( ! $w_descriptor ) {
1762
+ continue;
1763
+ }
1764
  }
1765
  if ( $newwidth < 50 ) {
1766
  continue;
1789
 
1790
  $newsources[ $newwidth ] = array(
1791
  'url' => $this->generate_url( $url, $args ),
1792
+ 'descriptor' => ( $w_descriptor ? 'w' : 'x' ),
1793
+ 'value' => ( $w_descriptor ? $newwidth : $multiplier ),
1794
  );
1795
 
1796
  $currentwidths[] = $newwidth;
2066
  */
2067
  protected function validate_image_url( $url, $exactdn_is_valid = false ) {
2068
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
2069
+ if ( false !== strpos( $url, 'data:image/' ) ) {
2070
+ ewwwio_debug_message( "could not parse data uri: $url" );
2071
+ return false;
2072
+ }
2073
  $parsed_url = $this->parse_url( $url );
2074
  if ( ! $parsed_url ) {
2075
+ ewwwio_debug_message( "could not parse: $url" );
2076
  return false;
2077
  }
2078
 
common.php CHANGED
@@ -22,7 +22,7 @@ if ( ! defined( 'ABSPATH' ) ) {
22
  exit;
23
  }
24
 
25
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '473.0' );
26
 
27
  // Initialize a couple globals.
28
  $ewww_debug = '';
@@ -210,6 +210,12 @@ function ewww_image_optimizer_parser_init() {
210
  $buffer_start = false;
211
  // If ExactDN is enabled.
212
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) && empty( $_GET['exactdn_disable'] ) ) {
 
 
 
 
 
 
213
  $buffer_start = true;
214
  /**
215
  * Page Parsing class for working with HTML content.
22
  exit;
23
  }
24
 
25
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '474.0' );
26
 
27
  // Initialize a couple globals.
28
  $ewww_debug = '';
210
  $buffer_start = false;
211
  // If ExactDN is enabled.
212
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) && empty( $_GET['exactdn_disable'] ) ) {
213
+ if ( ! ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
214
+ // Un-configure Autoptimize CDN domain.
215
+ if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && strpos( ewww_image_optimizer_get_option( 'autoptimize_cdn_url' ), 'exactdn' ) ) {
216
+ ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '' );
217
+ }
218
+ }
219
  $buffer_start = true;
220
  /**
221
  * Page Parsing class for working with HTML content.
ewww-image-optimizer.php CHANGED
@@ -13,7 +13,7 @@ Plugin Name: EWWW Image Optimizer
13
  Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
14
  Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Exactly WWW
16
- Version: 4.7.3
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
13
  Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
14
  Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Exactly WWW
16
+ Version: 4.7.4
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: image, compress, resize, optimize, optimization, lossless, lossy, seo, web
5
  Requires at least: 4.9
6
  Tested up to: 5.2
7
  Requires PHP: 5.6
8
- Stable tag: 4.7.3
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
@@ -174,6 +174,14 @@ http://developer.yahoo.com/performance/rules.html#opt_images
174
  * Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
175
  * If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
176
 
 
 
 
 
 
 
 
 
177
  = 4.7.3 =
178
  * added: disable WebP script block on certain pages by defining EWWW_IMAGE_OPTIMIZER_NO_JS as true
179
  * changed: use SVG inline image placeholder if width and height are known when LQIP is disabled or ExactDN is not available
5
  Requires at least: 4.9
6
  Tested up to: 5.2
7
  Requires PHP: 5.6
8
+ Stable tag: 4.7.4
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
174
  * Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
175
  * If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
176
 
177
+ = 4.7.4 =
178
+ * fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
179
+ * fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
180
+ * fixed: Lazy Load parsing breaking img elements in script blocks
181
+ * fixed: Lazy Load and JS WebP bail when SVGs are wrapped in XML tags
182
+ * fixed: ExactDN mixes x and w srcset descriptors
183
+ * fixed: page parsers (ExactDN, Lazy, JS WebP) still fail to process some img elements that have unquoted src attributes
184
+
185
  = 4.7.3 =
186
  * added: disable WebP script block on certain pages by defining EWWW_IMAGE_OPTIMIZER_NO_JS as true
187
  * changed: use SVG inline image placeholder if width and height are known when LQIP is disabled or ExactDN is not available