EWWW Image Optimizer - Version 5.1.0

Version Description

  • added: WebP-only mode for Bulk Optimizer
  • added: JS WebP Rewriting for pull-mode CDNs via WebP URLS without Force WebP
  • added: JS WebP Rewriting zero-conf for WP Offload Media
  • added: force lossy PNG to WebP conversion with EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP override (set to true)
  • changed: bulk optimizer runs wp_update_attachment_metadata() in separate request to avoid timeouts
  • fixed: WebP warning regarding missing modules displayed even if green WebP test image is working
  • fixed: Nextgen bulk actions not working
  • fixed: unable to regenerate existing thumbnails with Image Regenerate & Select Crop plugin
  • updated: WebP (cwebp) binary to version 1.0.3
  • updated: Pngquant binary to version 2.12.5
  • updated: cwebp requires Mac OS X 10.14
  • updated: FreeBSD 10 is EOL, version 11 is the supported/tested version
Download this release

Release Info

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

Code changes from version 5.0.0 to 5.1.0

aux-optimize.php CHANGED
@@ -31,7 +31,7 @@ function ewww_image_optimizer_aux_images() {
31
  global $eio_debug;
32
  ewww_image_optimizer_options( 'debug-silent' );
33
  $output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
34
- if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
35
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
36
  $output .= "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
37
  }
@@ -157,7 +157,7 @@ function ewww_image_optimizer_aux_images_table() {
157
  </tr>
158
  <?php
159
  $alternate = ! $alternate;
160
- } elseif ( is_file( $file ) ) {
161
  // Retrieve the mimetype of the attachment.
162
  $type = ewww_image_optimizer_quick_mimetype( $file, 'i' );
163
  // Get a human readable filesize.
@@ -815,7 +815,10 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
815
  if ( ewww_image_optimizer_iterable( $backup_sizes ) ) {
816
  foreach ( $backup_sizes as $backup_size => $meta ) {
817
  if ( preg_match( '/resized-/', $backup_size ) ) {
818
- $path = $meta['path'];
 
 
 
819
  $image_size = ewww_image_optimizer_filesize( $path );
820
  if ( ! $image_size ) {
821
  continue;
31
  global $eio_debug;
32
  ewww_image_optimizer_options( 'debug-silent' );
33
  $output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
34
+ if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
35
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
36
  $output .= "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
37
  }
157
  </tr>
158
  <?php
159
  $alternate = ! $alternate;
160
+ } elseif ( ewwwio_is_file( $file ) ) {
161
  // Retrieve the mimetype of the attachment.
162
  $type = ewww_image_optimizer_quick_mimetype( $file, 'i' );
163
  // Get a human readable filesize.
815
  if ( ewww_image_optimizer_iterable( $backup_sizes ) ) {
816
  foreach ( $backup_sizes as $backup_size => $meta ) {
817
  if ( preg_match( '/resized-/', $backup_size ) ) {
818
+ $path = $meta['path'];
819
+ if ( ! ewwwio_is_file( $path ) ) {
820
+ continue;
821
+ }
822
  $image_size = ewww_image_optimizer_filesize( $path );
823
  if ( ! $image_size ) {
824
  continue;
binaries/cwebp-fbsd CHANGED
Binary file
binaries/cwebp-linux CHANGED
Binary file
binaries/cwebp-mac12 DELETED
Binary file
binaries/cwebp-mac14 ADDED
Binary file
binaries/cwebp-mac9 DELETED
Binary file
binaries/cwebp-sol CHANGED
Binary file
binaries/cwebp.exe CHANGED
Binary file
binaries/pngquant-fbsd CHANGED
Binary file
binaries/pngquant-linux CHANGED
Binary file
binaries/pngquant-mac CHANGED
Binary file
binaries/pngquant-sol CHANGED
Binary file
binaries/pngquant.exe CHANGED
Binary file
bulk.php CHANGED
@@ -201,16 +201,32 @@ function ewww_image_optimizer_bulk_head_output() {
201
  </div>
202
  <form class="ewww-bulk-form" style="border: solid 1px #e5e5e5; background: #fff; padding: 10px;">
203
  <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label><?php echo ewwwio_help_link( 'https://docs.ewww.io/article/65-force-re-optimization', '5bb640a7042863158cc711cd' ); ?>
204
- &emsp;<input type="checkbox" id="ewww-force" name="ewww-force"<?php echo ( get_transient( 'ewww_image_optimizer_force_reopt' ) ) ? ' checked' : ''; ?>>
205
  &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?>
206
  &nbsp;<a href="tools.php?page=ewww-image-optimizer-tools"><?php esc_html_e( 'View optimization history.', 'ewww-image-optimizer' ); ?></a>
207
  </p>
 
208
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
209
  <div id="ewww-delay-slider" style="margin: 0 0 15px 10px; max-width:500px"></div>
210
  </form>
211
  <?php
212
  }
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  /**
215
  * Outputs the buttons and scanner status html for the Bulk optimize page.
216
  *
@@ -914,7 +930,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
914
  }
915
  ewww_image_optimizer_debug_log();
916
  if (
917
- ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! is_file( $file_path ) ) &&
918
  (
919
  class_exists( 'WindowsAzureStorageUtil' ) ||
920
  class_exists( 'Amazon_S3_And_CloudFront' ) ||
@@ -1003,9 +1019,9 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1003
  }
1004
  }
1005
  $resize_path = $base_dir . $data['file'];
1006
- if ( ( $remote_file || is_file( $resize_path ) ) && 'application/pdf' === $mime && 'full' === $size ) {
1007
  $attachment_images[ 'pdf-' . $size ] = $resize_path;
1008
- } elseif ( $remote_file || is_file( $resize_path ) ) {
1009
  $attachment_images[ $size ] = $resize_path;
1010
  }
1011
  // Optimize retina image, if it exists.
@@ -1014,7 +1030,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1014
  } else {
1015
  $retina_path = false;
1016
  }
1017
- if ( $retina_path && is_file( $retina_path ) ) {
1018
  ewwwio_debug_message( "found retina via wr2x_get_retina $retina_path" );
1019
  $attachment_images[ $size . '-retina' ] = $retina_path;
1020
  } else {
@@ -1035,7 +1051,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1035
  ewwwio_debug_message( 'checking for original_image' );
1036
  // Meta sizes don't contain a path, so we calculate one.
1037
  $resize_path = trailingslashit( dirname( $file_path ) ) . $meta['original_image'];
1038
- if ( $remote_file || is_file( $resize_path ) ) {
1039
  $attachment_images['original_image'] = $resize_path;
1040
  }
1041
  }
@@ -1047,7 +1063,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1047
  $imagemeta_resize_path = '';
1048
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
1049
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
1050
- if ( is_file( $imagemeta_resize_path ) ) {
1051
  $attachment_images[ 'resized-images-' . $index ] = $imagemeta_resize_path;
1052
  }
1053
  }
@@ -1060,7 +1076,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1060
  $custom_size_path = '';
1061
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
1062
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
1063
- if ( is_file( $custom_size_path ) ) {
1064
  $attachment_images[ 'custom-size-' . $dimensions ] = $custom_size_path;
1065
  }
1066
  }
@@ -1560,7 +1576,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1560
  $output['new_nonce'] = '';
1561
  }
1562
  }
1563
- $batch_image_limit = ( empty( $_REQUEST['ewww_batch_limit'] ) && ! class_exists( 'Amazon_S3_And_CloudFront' ) && ! class_exists( 'S3_Uploads' ) ? 999 : 1 );
1564
  // Get the 'bulk attachments' with a list of IDs remaining.
1565
  $attachments = ewww_image_optimizer_get_queued_attachments( 'media', $batch_image_limit );
1566
  if ( ! empty( $attachments ) && is_array( $attachments ) ) {
@@ -1587,7 +1603,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1587
  $output['completed']++;
1588
  $meta = false;
1589
  // See if the image needs fetching from a CDN.
1590
- if ( ! is_file( $image->file ) ) {
1591
  $meta = wp_get_attachment_metadata( $image->attachment_id );
1592
  $file_path = ewww_image_optimizer_remote_fetch( $image->attachment_id, $meta );
1593
  unset( $meta );
@@ -1640,6 +1656,19 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1640
  array( '%d' )
1641
  );
1642
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1643
  // If this is a full size image and it was converted.
1644
  if ( 'full' === $image->resize && ( false !== $image->increment || false !== $converted ) ) {
1645
  if ( ! $meta || ! is_array( $meta ) ) {
@@ -1675,20 +1704,33 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1675
  // Pull the next image.
1676
  $next_image = new EWWW_Image( $attachment, 'media' );
1677
 
1678
- // When we finish all the sizes, we want to fire off any filters for plugins that might need to take action when an image is updated.
 
1679
  if ( $attachment && (int) $attachment !== (int) $next_image->attachment_id ) {
1680
- wp_update_attachment_metadata( $image->attachment_id, wp_get_attachment_metadata( $image->attachment_id ) );
1681
- /* $meta = apply_filters( 'wp_update_attachment_metadata', wp_get_attachment_metadata( $image->attachment_id ), $image->attachment_id ); */
 
 
 
 
 
1682
  }
 
1683
  // When an image (attachment) is done, pull the next attachment ID off the stack.
1684
  if ( ( 'full' === $next_image->resize || empty( $next_image->resize ) ) && ! empty( $attachment ) && (int) $attachment !== (int) $next_image->attachment_id ) {
 
1685
  ewww_image_optimizer_delete_queued_images( array( $attachment ) );
1686
- $attachment = (int) array_shift( $attachments ); // Pull the first image off the stack.
 
 
 
 
1687
  if ( ! empty( $attachments ) && is_array( $attachments ) ) {
1688
  $attachment = (int) $attachments[0]; // Then grab the next one (if any are left).
1689
  } else {
1690
  $attachment = 0;
1691
  }
 
1692
  $next_image = new EWWW_Image( $attachment, 'media' );
1693
  }
1694
  $image = $next_image;
@@ -1745,6 +1787,23 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1745
  die( ewwwio_json_encode( $output ) );
1746
  }
1747
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1748
  /**
1749
  * Called by javascript to cleanup after ourselves after a bulk operation.
1750
  */
@@ -1773,6 +1832,7 @@ add_action( 'wp_ajax_bulk_scan', 'ewww_image_optimizer_media_scan' );
1773
  add_action( 'wp_ajax_bulk_init', 'ewww_image_optimizer_bulk_initialize' );
1774
  add_action( 'wp_ajax_bulk_filename', 'ewww_image_optimizer_bulk_filename' );
1775
  add_action( 'wp_ajax_bulk_loop', 'ewww_image_optimizer_bulk_loop' );
 
1776
  add_action( 'wp_ajax_bulk_cleanup', 'ewww_image_optimizer_bulk_cleanup' );
1777
  add_action( 'wp_ajax_bulk_quota_update', 'ewww_image_optimizer_bulk_quota_update' );
1778
  add_filter( 'ewww_image_optimizer_count_optimized_queries', 'ewww_image_optimizer_reduce_query_count' );
201
  </div>
202
  <form class="ewww-bulk-form" style="border: solid 1px #e5e5e5; background: #fff; padding: 10px;">
203
  <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label><?php echo ewwwio_help_link( 'https://docs.ewww.io/article/65-force-re-optimization', '5bb640a7042863158cc711cd' ); ?>
204
+ &emsp;<input type="checkbox" id="ewww-force" name="ewww-force"<?php echo ( get_transient( 'ewww_image_optimizer_force_reopt' ) || ! empty( $_REQUEST['ewww_force'] ) ) ? ' checked' : ''; ?>>
205
  &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?>
206
  &nbsp;<a href="tools.php?page=ewww-image-optimizer-tools"><?php esc_html_e( 'View optimization history.', 'ewww-image-optimizer' ); ?></a>
207
  </p>
208
+ <?php ewww_image_optimizer_bulk_webp_only(); ?>
209
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
210
  <div id="ewww-delay-slider" style="margin: 0 0 15px 10px; max-width:500px"></div>
211
  </form>
212
  <?php
213
  }
214
 
215
+ /**
216
+ * Output the control for WebP Only on the Bulk page.
217
+ */
218
+ function ewww_image_optimizer_bulk_webp_only() {
219
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
220
+ return;
221
+ }
222
+ ?>
223
+ <p><label for="ewww-webp-only" style="font-weight: bold"><?php esc_html_e( 'WebP Only', 'ewww-image-optimizer' ); ?></label>
224
+ &emsp;<input type="checkbox" id="ewww-webp-only" name="ewww-webp-only"<?php echo ( ! empty( $_REQUEST['ewww_webp_only'] ) ) ? ' checked' : ''; ?>>
225
+ &nbsp;<?php esc_html_e( 'Skip compression and only attempt WebP conversion.', 'ewww-image-optimizer' ); ?>
226
+ </p>
227
+ <?php
228
+ }
229
+
230
  /**
231
  * Outputs the buttons and scanner status html for the Bulk optimize page.
232
  *
930
  }
931
  ewww_image_optimizer_debug_log();
932
  if (
933
+ ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! ewwwio_is_file( $file_path ) ) &&
934
  (
935
  class_exists( 'WindowsAzureStorageUtil' ) ||
936
  class_exists( 'Amazon_S3_And_CloudFront' ) ||
1019
  }
1020
  }
1021
  $resize_path = $base_dir . $data['file'];
1022
+ if ( ( $remote_file || ewwwio_is_file( $resize_path ) ) && 'application/pdf' === $mime && 'full' === $size ) {
1023
  $attachment_images[ 'pdf-' . $size ] = $resize_path;
1024
+ } elseif ( $remote_file || ewwwio_is_file( $resize_path ) ) {
1025
  $attachment_images[ $size ] = $resize_path;
1026
  }
1027
  // Optimize retina image, if it exists.
1030
  } else {
1031
  $retina_path = false;
1032
  }
1033
+ if ( $retina_path && ewwwio_is_file( $retina_path ) ) {
1034
  ewwwio_debug_message( "found retina via wr2x_get_retina $retina_path" );
1035
  $attachment_images[ $size . '-retina' ] = $retina_path;
1036
  } else {
1051
  ewwwio_debug_message( 'checking for original_image' );
1052
  // Meta sizes don't contain a path, so we calculate one.
1053
  $resize_path = trailingslashit( dirname( $file_path ) ) . $meta['original_image'];
1054
+ if ( $remote_file || ewwwio_is_file( $resize_path ) ) {
1055
  $attachment_images['original_image'] = $resize_path;
1056
  }
1057
  }
1063
  $imagemeta_resize_path = '';
1064
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
1065
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
1066
+ if ( ewwwio_is_file( $imagemeta_resize_path ) ) {
1067
  $attachment_images[ 'resized-images-' . $index ] = $imagemeta_resize_path;
1068
  }
1069
  }
1076
  $custom_size_path = '';
1077
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
1078
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
1079
+ if ( ewwwio_is_file( $custom_size_path ) ) {
1080
  $attachment_images[ 'custom-size-' . $dimensions ] = $custom_size_path;
1081
  }
1082
  }
1576
  $output['new_nonce'] = '';
1577
  }
1578
  }
1579
+ $batch_image_limit = ( empty( $_REQUEST['ewww_batch_limit'] ) && ! class_exists( 'S3_Uploads' ) ? 999 : 1 );
1580
  // Get the 'bulk attachments' with a list of IDs remaining.
1581
  $attachments = ewww_image_optimizer_get_queued_attachments( 'media', $batch_image_limit );
1582
  if ( ! empty( $attachments ) && is_array( $attachments ) ) {
1603
  $output['completed']++;
1604
  $meta = false;
1605
  // See if the image needs fetching from a CDN.
1606
+ if ( ! ewwwio_is_file( $image->file ) ) {
1607
  $meta = wp_get_attachment_metadata( $image->attachment_id );
1608
  $file_path = ewww_image_optimizer_remote_fetch( $image->attachment_id, $meta );
1609
  unset( $meta );
1656
  array( '%d' )
1657
  );
1658
  }
1659
+ // Toggle a pending record if the optimization was webp-only.
1660
+ if ( true === $file && $image->id ) {
1661
+ global $wpdb;
1662
+ $wpdb->update(
1663
+ $wpdb->ewwwio_images,
1664
+ array(
1665
+ 'pending' => 0,
1666
+ ),
1667
+ array(
1668
+ 'id' => $image->id,
1669
+ )
1670
+ );
1671
+ }
1672
  // If this is a full size image and it was converted.
1673
  if ( 'full' === $image->resize && ( false !== $image->increment || false !== $converted ) ) {
1674
  if ( ! $meta || ! is_array( $meta ) ) {
1704
  // Pull the next image.
1705
  $next_image = new EWWW_Image( $attachment, 'media' );
1706
 
1707
+ // When we finish all the sizes, we stop the loop so we can fire off any filters for plugins that might need to take action when an image is updated.
1708
+ // The call to wp_get_attachment_metadata() will be done in a separate AJAX request for better reliability, giving it the full request time to complete.
1709
  if ( $attachment && (int) $attachment !== (int) $next_image->attachment_id ) {
1710
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
1711
+ ewwwio_debug_message( 'saving attachment meta' );
1712
+ wp_update_attachment_metadata( $image->attachment_id, wp_get_attachment_metadata( $image->attachment_id ) );
1713
+ } else {
1714
+ $batch_image_limit = 1;
1715
+ $output['update_meta'] = (int) $attachment;
1716
+ }
1717
  }
1718
+
1719
  // When an image (attachment) is done, pull the next attachment ID off the stack.
1720
  if ( ( 'full' === $next_image->resize || empty( $next_image->resize ) ) && ! empty( $attachment ) && (int) $attachment !== (int) $next_image->attachment_id ) {
1721
+ ewwwio_debug_message( 'grabbing next attachment id' );
1722
  ewww_image_optimizer_delete_queued_images( array( $attachment ) );
1723
+ if ( 1 === count( $attachments ) && 1 === (int) $batch_image_limit ) {
1724
+ $attachments = ewww_image_optimizer_get_queued_attachments( 'media', $batch_image_limit );
1725
+ } else {
1726
+ $attachment = (int) array_shift( $attachments ); // Pull the first image off the stack.
1727
+ }
1728
  if ( ! empty( $attachments ) && is_array( $attachments ) ) {
1729
  $attachment = (int) $attachments[0]; // Then grab the next one (if any are left).
1730
  } else {
1731
  $attachment = 0;
1732
  }
1733
+ ewwwio_debug_message( "next id is $attachment" );
1734
  $next_image = new EWWW_Image( $attachment, 'media' );
1735
  }
1736
  $image = $next_image;
1787
  die( ewwwio_json_encode( $output ) );
1788
  }
1789
 
1790
+ /**
1791
+ * Called via AJAX to trigger any actions by other plugins.
1792
+ */
1793
+ function ewww_image_optimizer_bulk_update_meta() {
1794
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1795
+ // Verify that an authorized user has started the optimizer.
1796
+ $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1797
+ if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1798
+ ewwwio_ob_clean();
1799
+ die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
1800
+ }
1801
+ $attachment_id = (int) $_REQUEST['attachment_id'];
1802
+ ewwwio_debug_message( "saving attachment meta for $attachment_id" );
1803
+ wp_update_attachment_metadata( $attachment_id, wp_get_attachment_metadata( $attachment_id ) );
1804
+ die( ewwwio_json_encode( array( 'success' => 1 ) ) );
1805
+ }
1806
+
1807
  /**
1808
  * Called by javascript to cleanup after ourselves after a bulk operation.
1809
  */
1832
  add_action( 'wp_ajax_bulk_init', 'ewww_image_optimizer_bulk_initialize' );
1833
  add_action( 'wp_ajax_bulk_filename', 'ewww_image_optimizer_bulk_filename' );
1834
  add_action( 'wp_ajax_bulk_loop', 'ewww_image_optimizer_bulk_loop' );
1835
+ add_action( 'wp_ajax_ewww_bulk_update_meta', 'ewww_image_optimizer_bulk_update_meta' );
1836
  add_action( 'wp_ajax_bulk_cleanup', 'ewww_image_optimizer_bulk_cleanup' );
1837
  add_action( 'wp_ajax_bulk_quota_update', 'ewww_image_optimizer_bulk_quota_update' );
1838
  add_filter( 'ewww_image_optimizer_count_optimized_queries', 'ewww_image_optimizer_reduce_query_count' );
changelog.txt CHANGED
@@ -1,3 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 5.0.0 =
2
  * added: use native lazy load attributes to supplement lazy loader and make placeholders more efficient
3
  * added: GCS sub-folder rewriting with ExactDN for cleaner URLs
1
+ = 5.1.0 =
2
+ * added: WebP-only mode for Bulk Optimizer
3
+ * added: JS WebP Rewriting for pull-mode CDNs via WebP URLS without Force WebP
4
+ * added: JS WebP Rewriting zero-conf for WP Offload Media
5
+ * added: force lossy PNG to WebP conversion with EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP override (set to true)
6
+ * changed: bulk optimizer runs wp_update_attachment_metadata() in separate request to avoid timeouts
7
+ * fixed: WebP warning regarding missing modules displayed even if green WebP test image is working
8
+ * fixed: Nextgen bulk actions not working
9
+ * fixed: unable to regenerate existing thumbnails with Image Regenerate & Select Crop plugin
10
+ * updated: WebP (cwebp) binary to version 1.0.3
11
+ * updated: Pngquant binary to version 2.12.5
12
+ * updated: cwebp requires Mac OS X 10.14
13
+ * updated: FreeBSD 10 is EOL, version 11 is the supported/tested version
14
+
15
  = 5.0.0 =
16
  * added: use native lazy load attributes to supplement lazy loader and make placeholders more efficient
17
  * added: GCS sub-folder rewriting with ExactDN for cleaner URLs
classes/class-eio-alt-webp.php CHANGED
@@ -63,12 +63,50 @@ class EIO_Alt_Webp extends EIO_Page_Parser {
63
  ewwwio_debug_message( "home url: $this->home_url" );
64
  $this->relative_home_url = preg_replace( '/https?:/', '', $this->home_url );
65
  ewwwio_debug_message( "relative home url: $this->relative_home_url" );
 
 
 
 
 
66
 
67
  $this->webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
68
  if ( ! is_array( $this->webp_paths ) ) {
69
  $this->webp_paths = array();
70
  }
71
- ewwwio_debug_message( 'forcing any images matching these patterns to webp: ' . implode( ',', $this->webp_paths ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
73
  global $exactdn;
74
  $this->exactdn_domain = $exactdn->get_exactdn_domain();
@@ -699,10 +737,130 @@ class EIO_Alt_Webp extends EIO_Page_Parser {
699
  }
700
 
701
  /**
702
- * Checks if the path is a valid "forced" WebP image.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
  *
704
  * @param string $image The image URL.
705
- * @return bool True if the file matches a forced path, false otherwise.
706
  */
707
  function validate_image_url( $image ) {
708
  ewwwio_debug_message( "webp validation for $image" );
@@ -728,9 +886,8 @@ class EIO_Alt_Webp extends EIO_Page_Parser {
728
  if ( $extension && 'webp' === $extension ) {
729
  return false;
730
  }
731
- if ( $this->parsing_exactdn && false !== strpos( $image, $this->exactdn_domain ) ) {
732
- ewwwio_debug_message( 'exactdn image' );
733
- return true;
734
  }
735
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) && $this->webp_paths ) {
736
  // Check the image for configured CDN paths.
@@ -740,21 +897,12 @@ class EIO_Alt_Webp extends EIO_Page_Parser {
740
  return true;
741
  }
742
  }
 
 
 
 
743
  }
744
- if ( 0 === strpos( $image, $this->relative_home_url ) ) {
745
- $imagepath = str_replace( $this->relative_home_url, ABSPATH, $image );
746
- } elseif ( 0 === strpos( $image, $this->home_url ) ) {
747
- $imagepath = str_replace( $this->home_url, ABSPATH, $image );
748
- } else {
749
- ewwwio_debug_message( 'not a valid local image' );
750
- return false;
751
- }
752
- $path_parts = explode( '?', $imagepath );
753
- if ( is_file( $path_parts[0] . '.webp' ) || is_file( $imagepath . '.webp' ) ) {
754
- ewwwio_debug_message( 'local .webp image found' );
755
- return true;
756
- }
757
- return false;
758
  }
759
 
760
  /**
63
  ewwwio_debug_message( "home url: $this->home_url" );
64
  $this->relative_home_url = preg_replace( '/https?:/', '', $this->home_url );
65
  ewwwio_debug_message( "relative home url: $this->relative_home_url" );
66
+ $upload_dir = wp_upload_dir();
67
+ $this->content_url = trailingslashit( ! empty( $upload_dir['baseurl'] ) ? $upload_dir['baseurl'] : content_url( 'uploads' ) );
68
+ ewwwio_debug_message( "content_url: $this->content_url" );
69
+ $this->home_domain = $this->parse_url( $this->home_url, PHP_URL_HOST );
70
+ ewwwio_debug_message( "home domain: $this->home_domain" );
71
 
72
  $this->webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
73
  if ( ! is_array( $this->webp_paths ) ) {
74
  $this->webp_paths = array();
75
  }
76
+
77
+ // Find the WP Offload Media domain/path.
78
+ if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
79
+ global $as3cf;
80
+ $s3_scheme = $as3cf->get_url_scheme();
81
+ $s3_bucket = $as3cf->get_setting( 'bucket' );
82
+ $s3_region = $as3cf->get_setting( 'region' );
83
+ if ( is_wp_error( $s3_region ) ) {
84
+ $s3_region = '';
85
+ }
86
+ $s3_domain = $as3cf->get_provider()->get_url_domain( $s3_bucket, $s3_region, null, array(), true );
87
+ ewwwio_debug_message( "found S3 domain of $s3_domain with bucket $s3_bucket and region $s3_region" );
88
+ if ( ! empty( $s3_domain ) && $as3cf->get_setting( 'serve-from-s3' ) ) {
89
+ $this->webp_paths[] = $s3_scheme . '://' . $s3_domain . '/';
90
+ $this->s3_active = $s3_domain;
91
+ if ( $as3cf->get_setting( 'enable-object-prefix' ) ) {
92
+ $this->s3_object_prefix = $as3cf->get_setting( 'object-prefix' );
93
+ ewwwio_debug_message( $as3cf->get_setting( 'object-prefix' ) );
94
+ }
95
+ if ( $as3cf->get_setting( 'object-versioning' ) ) {
96
+ $this->s3_object_version = true;
97
+ ewwwio_debug_message( 'object versioning enabled' );
98
+ }
99
+ }
100
+ }
101
+
102
+ foreach ( $this->webp_paths as $webp_path ) {
103
+ $webp_domain = $this->parse_url( $webp_path, PHP_URL_HOST );
104
+ if ( $webp_domain ) {
105
+ $this->webp_domains[] = $webp_domain;
106
+ }
107
+ }
108
+ ewwwio_debug_message( 'checking any images matching these patterns for webp: ' . implode( ',', $this->webp_paths ) );
109
+ ewwwio_debug_message( 'rewriting any images matching these domains to webp: ' . implode( ',', $this->webp_domains ) );
110
  if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
111
  global $exactdn;
112
  $this->exactdn_domain = $exactdn->get_exactdn_domain();
737
  }
738
 
739
  /**
740
+ * Attempts to reverse a CDN URL to a local path to test for file existence.
741
+ *
742
+ * Used for supporting pull-mode CDNs without forcing everything to WebP.
743
+ *
744
+ * @param string $url The image URL to mangle.
745
+ * @return bool True if a local file exists correlating to the CDN URL, false otherwise.
746
+ */
747
+ function cdn_to_local( $url ) {
748
+ ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
749
+ if ( ! is_array( $this->webp_domains ) || ! count( $this->webp_domains ) ) {
750
+ return false;
751
+ }
752
+ foreach ( $this->webp_domains as $webp_domain ) {
753
+ if ( $webp_domain === $this->home_domain ) {
754
+ continue;
755
+ }
756
+ ewwwio_debug_message( "looking for $webp_domain in $url" );
757
+ if (
758
+ ! empty( $this->s3_active ) &&
759
+ false !== strpos( $url, $this->s3_active ) &&
760
+ (
761
+ ( false !== strpos( $this->s3_active, '/' ) ) ||
762
+ ( ! empty( $this->s3_object_prefix ) && false !== strpos( $url, $this->s3_object_prefix ) )
763
+ )
764
+ ) {
765
+ // We will wait until the paths loop to fix this one.
766
+ continue;
767
+ }
768
+ if ( false !== strpos( $url, $webp_domain ) ) {
769
+ $local_url = str_replace( $webp_domain, $this->home_domain, $url );
770
+ ewwwio_debug_message( "found $webp_domain, replaced with $this->home_domain to get $local_url" );
771
+ if ( $this->url_to_path_exists( $local_url ) ) {
772
+ return true;
773
+ }
774
+ }
775
+ }
776
+ foreach ( $this->webp_paths as $webp_path ) {
777
+ if ( false !== strpos( $webp_path, $this->home_domain ) || false === strpos( $webp_path, 'http' ) ) {
778
+ continue;
779
+ }
780
+ ewwwio_debug_message( "looking for $webp_path in $url" );
781
+ if (
782
+ ! empty( $this->s3_active ) &&
783
+ false !== strpos( $url, $this->s3_active ) &&
784
+ ! empty( $this->s3_object_prefix ) &&
785
+ 0 === strpos( $url, $webp_path . $this->s3_object_prefix )
786
+ ) {
787
+ $local_url = str_replace( $webp_path . $this->s3_object_prefix, $this->content_url, $url );
788
+ ewwwio_debug_message( "found $webp_path (and $this->s3_object_prefix), replaced with $this->content_url to get $local_url" );
789
+ if ( $this->url_to_path_exists( $local_url ) ) {
790
+ return true;
791
+ }
792
+ }
793
+ if ( false !== strpos( $url, $webp_path ) ) {
794
+ $local_url = str_replace( $webp_path, $this->content_url, $url );
795
+ ewwwio_debug_message( "found $webp_path, replaced with $this->content_url to get $local_url" );
796
+ if ( $this->url_to_path_exists( $local_url ) ) {
797
+ return true;
798
+ }
799
+ }
800
+ }
801
+ return false;
802
+ }
803
+
804
+ /**
805
+ * Remove S3 object versioning from URL.
806
+ *
807
+ * @param string $url The image URL with a potential version string embedded.
808
+ * @return string The URL without a version string.
809
+ */
810
+ function maybe_strip_object_version( $url ) {
811
+ if ( ! empty( $this->s3_object_version ) ) {
812
+ $possible_version = basename( dirname( $url ) );
813
+ if (
814
+ ! empty( $possible_version ) &&
815
+ 8 === strlen( $possible_version ) &&
816
+ ctype_digit( $possible_version )
817
+ ) {
818
+ $url = str_replace( '/' . $possible_version . '/', '/', $url );
819
+ ewwwio_debug_message( "removed version $possible_version from $url" );
820
+ } elseif (
821
+ ! empty( $possible_version ) &&
822
+ 14 === strlen( $possible_version ) &&
823
+ ctype_digit( $possible_version )
824
+ ) {
825
+ $year = substr( $possible_version, 0, 4 );
826
+ $month = substr( $possible_version, 4, 2 );
827
+ $url = str_replace( '/' . $possible_version . '/', "/$year/$month/", $url );
828
+ ewwwio_debug_message( "removed version $possible_version from $url" );
829
+ }
830
+ }
831
+ return $url;
832
+ }
833
+
834
+ /**
835
+ * Converts a URL to a file-system path and checks if the resulting path exists.
836
+ *
837
+ * @param string $image The image URL to mangle.
838
+ * @return bool True if a local file exists correlating to the URL, false otherwise.
839
+ */
840
+ function url_to_path_exists( $image ) {
841
+ ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
842
+ $image = $this->maybe_strip_object_version( $image );
843
+ if ( 0 === strpos( $image, $this->relative_home_url ) ) {
844
+ $imagepath = str_replace( $this->relative_home_url, ABSPATH, $image );
845
+ } elseif ( 0 === strpos( $image, $this->home_url ) ) {
846
+ $imagepath = str_replace( $this->home_url, ABSPATH, $image );
847
+ } else {
848
+ ewwwio_debug_message( 'not a valid local image' );
849
+ return false;
850
+ }
851
+ $path_parts = explode( '?', $imagepath );
852
+ if ( ewwwio_is_file( $path_parts[0] . '.webp' ) || ewwwio_is_file( $imagepath . '.webp' ) ) {
853
+ ewwwio_debug_message( 'local .webp image found' );
854
+ return true;
855
+ }
856
+ return false;
857
+ }
858
+
859
+ /**
860
+ * Checks if the path is a valid WebP image, on-disk or forced.
861
  *
862
  * @param string $image The image URL.
863
+ * @return bool True if the file exists or matches a forced path, false otherwise.
864
  */
865
  function validate_image_url( $image ) {
866
  ewwwio_debug_message( "webp validation for $image" );
886
  if ( $extension && 'webp' === $extension ) {
887
  return false;
888
  }
889
+ if ( apply_filters( 'ewww_image_optimizer_skip_webp_rewrite', false, $image ) ) {
890
+ return false;
 
891
  }
892
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) && $this->webp_paths ) {
893
  // Check the image for configured CDN paths.
897
  return true;
898
  }
899
  }
900
+ } elseif ( $this->webp_paths && $this->webp_domains ) {
901
+ if ( $this->cdn_to_local( $image ) ) {
902
+ return true;
903
+ }
904
  }
905
+ return $this->url_to_path_exists( $image );
 
 
 
 
 
 
 
 
 
 
 
 
 
906
  }
907
 
908
  /**
classes/class-eio-page-parser.php CHANGED
@@ -194,10 +194,36 @@ if ( ! class_exists( 'EIO_Page_Parser' ) ) {
194
  if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
195
  $width = $max_width_string[1];
196
  }
 
 
 
 
197
  }
198
  return $width;
199
  }
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  /**
202
  * Get an attribute from an HTML element.
203
  *
194
  if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
195
  $width = $max_width_string[1];
196
  }
197
+ } elseif ( $style && preg_match( '#width:\s?(\d+)px#', $style, $width_string ) ) {
198
+ if ( $width_string[1] && ( ! $width || $width_string[1] < $width ) ) {
199
+ $width = $width_string[1];
200
+ }
201
  }
202
  return $width;
203
  }
204
 
205
+ /**
206
+ * Get the height from an image element.
207
+ *
208
+ * @param string $img The full image element.
209
+ * @return string The height found or an empty string.
210
+ */
211
+ public function get_img_height( $img ) {
212
+ $height = $this->get_attribute( $img, 'height' );
213
+ // Then check for an inline max-height directive.
214
+ $style = $this->get_attribute( $img, 'style' );
215
+ if ( $style && preg_match( '#max-height:\s?(\d+)px#', $style, $max_height_string ) ) {
216
+ if ( $max_height_string[1] && ( ! $height || $max_height_string[1] < $height ) ) {
217
+ $height = $max_height_string[1];
218
+ }
219
+ } elseif ( $style && preg_match( '#height:\s?(\d+)px#', $style, $height_string ) ) {
220
+ if ( $height_string[1] && ( ! $height || $height_string[1] < $height ) ) {
221
+ $height = $height_string[1];
222
+ }
223
+ }
224
+ return $height;
225
+ }
226
+
227
  /**
228
  * Get an attribute from an HTML element.
229
  *
classes/class-ewww-image.php CHANGED
@@ -122,7 +122,7 @@ class EWWW_Image {
122
  $ewwwdb = $wpdb;
123
  }
124
  $ewwwdb->flush();
125
- if ( $path && ( is_file( $path ) || ewww_image_optimizer_stream_wrapped( $path ) ) ) {
126
  ewwwio_debug_message( "creating EWWW_Image with $path" );
127
  $new_image = ewww_image_optimizer_find_already_optimized( $path );
128
  if ( ! $new_image ) {
@@ -377,7 +377,7 @@ class EWWW_Image {
377
  ewwwio_debug_message( 'invalid meta for restoration' );
378
  return $meta;
379
  }
380
- if ( ! $this->file || ! is_file( $this->file ) || ! $this->converted || ! is_file( $this->converted ) ) {
381
  ewwwio_debug_message( 'one of the files was not set for restoration (or did not exist)' );
382
  return $meta;
383
  }
@@ -423,7 +423,7 @@ class EWWW_Image {
423
  $size_queried['converted'] = ewww_image_optimizer_absolutize_path( $size_queried['converted'] );
424
 
425
  $new_name = ( empty( $size_queried['converted'] ) ? '' : $size_queried['converted'] );
426
- if ( $new_name && is_file( $size_queried['path'] ) && is_file( $new_name ) ) {
427
  $this->restore_db_path( $size_queried['path'], $new_name, $size_queried['id'] );
428
  $this->replace_url( $new_name, $size_queried['path'] );
429
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
@@ -488,7 +488,7 @@ class EWWW_Image {
488
  ewwwio_debug_message( 'no file provided to convert' );
489
  return false;
490
  }
491
- if ( false === is_file( $file ) ) {
492
  ewwwio_debug_message( "$file is not a file, cannot convert" );
493
  return false;
494
  }
@@ -540,14 +540,14 @@ class EWWW_Image {
540
  }
541
  ewwwio_debug_message( "converted PNG size: $png_size" );
542
  // If the PNG exists, and we didn't end up with an empty file.
543
- if ( ! $check_size && $png_size && is_file( $newfile ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
544
  ewwwio_debug_message( 'JPG to PNG successful' );
545
  // Check to see if the user wants the originals deleted.
546
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
547
  // Delete the original JPG.
548
  unlink( $file );
549
  }
550
- } elseif ( $check_size && is_file( $newfile ) && $png_size < ewww_image_optimizer_filesize( $file ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
551
  ewwwio_debug_message( 'JPG to PNG successful, after comparing size' );
552
  // Check to see if the user wants the originals deleted.
553
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
@@ -556,7 +556,7 @@ class EWWW_Image {
556
  }
557
  } else {
558
  ewwwio_debug_message( 'converted PNG is no good' );
559
- if ( is_file( $newfile ) ) {
560
  unlink( $newfile );
561
  }
562
  return false;
@@ -645,14 +645,14 @@ class EWWW_Image {
645
  }
646
  ewwwio_debug_message( "converted JPG size: $jpg_size" );
647
  // If the new JPG is smaller than the original PNG.
648
- if ( ! $check_size && $jpg_size && is_file( $newfile ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/jpeg' ) {
649
  ewwwio_debug_message( 'JPG to PNG successful' );
650
  // If the user wants originals delted after a conversion.
651
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
652
  // Delete the original PNG.
653
  unlink( $file );
654
  }
655
- } elseif ( $check_size && is_file( $newfile ) && $jpg_size < ewww_image_optimizer_filesize( $file ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/jpeg' ) {
656
  ewwwio_debug_message( 'PNG to JPG successful, after comparing size' );
657
  // If the user wants originals delted after a conversion.
658
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
@@ -660,7 +660,7 @@ class EWWW_Image {
660
  unlink( $file );
661
  }
662
  } else {
663
- if ( is_file( $newfile ) ) {
664
  // Otherwise delete the new JPG.
665
  unlink( $newfile );
666
  }
@@ -701,14 +701,14 @@ class EWWW_Image {
701
  }
702
  ewwwio_debug_message( "converted PNG size: $png_size" );
703
  // If the PNG exists, and we didn't end up with an empty file.
704
- if ( ! $check_size && $png_size && is_file( $newfile ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
705
  ewwwio_debug_message( 'GIF to PNG successful' );
706
  // Check to see if the user wants the originals deleted.
707
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
708
  // Delete the original JPG.
709
  unlink( $file );
710
  }
711
- } elseif ( $check_size && is_file( $newfile ) && $png_size < ewww_image_optimizer_filesize( $file ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
712
  ewwwio_debug_message( 'GIF to PNG successful, after comparing size' );
713
  // Check to see if the user wants the originals deleted.
714
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
@@ -717,7 +717,7 @@ class EWWW_Image {
717
  }
718
  } else {
719
  ewwwio_debug_message( 'converted PNG is no good' );
720
- if ( is_file( $newfile ) ) {
721
  unlink( $newfile );
722
  }
723
  return false;
@@ -742,7 +742,7 @@ class EWWW_Image {
742
  public function unique_filename( $file, $fileext ) {
743
  // Strip the file extension.
744
  $filename = preg_replace( '/\.\w+$/', '', $file );
745
- if ( ! is_file( $filename . $fileext ) ) {
746
  return $filename . $fileext;
747
  }
748
  // Set the increment to 1 ( but allow the user to override it ).
122
  $ewwwdb = $wpdb;
123
  }
124
  $ewwwdb->flush();
125
+ if ( $path && ( ewwwio_is_file( $path ) || ewww_image_optimizer_stream_wrapped( $path ) ) ) {
126
  ewwwio_debug_message( "creating EWWW_Image with $path" );
127
  $new_image = ewww_image_optimizer_find_already_optimized( $path );
128
  if ( ! $new_image ) {
377
  ewwwio_debug_message( 'invalid meta for restoration' );
378
  return $meta;
379
  }
380
+ if ( ! $this->file || ! ewwwio_is_file( $this->file ) || ! $this->converted || ! ewwwio_is_file( $this->converted ) ) {
381
  ewwwio_debug_message( 'one of the files was not set for restoration (or did not exist)' );
382
  return $meta;
383
  }
423
  $size_queried['converted'] = ewww_image_optimizer_absolutize_path( $size_queried['converted'] );
424
 
425
  $new_name = ( empty( $size_queried['converted'] ) ? '' : $size_queried['converted'] );
426
+ if ( $new_name && ewwwio_is_file( $size_queried['path'] ) && ewwwio_is_file( $new_name ) ) {
427
  $this->restore_db_path( $size_queried['path'], $new_name, $size_queried['id'] );
428
  $this->replace_url( $new_name, $size_queried['path'] );
429
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
488
  ewwwio_debug_message( 'no file provided to convert' );
489
  return false;
490
  }
491
+ if ( false === ewwwio_is_file( $file ) ) {
492
  ewwwio_debug_message( "$file is not a file, cannot convert" );
493
  return false;
494
  }
540
  }
541
  ewwwio_debug_message( "converted PNG size: $png_size" );
542
  // If the PNG exists, and we didn't end up with an empty file.
543
+ if ( ! $check_size && $png_size && ewwwio_is_file( $newfile ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
544
  ewwwio_debug_message( 'JPG to PNG successful' );
545
  // Check to see if the user wants the originals deleted.
546
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
547
  // Delete the original JPG.
548
  unlink( $file );
549
  }
550
+ } elseif ( $check_size && ewwwio_is_file( $newfile ) && $png_size < ewww_image_optimizer_filesize( $file ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
551
  ewwwio_debug_message( 'JPG to PNG successful, after comparing size' );
552
  // Check to see if the user wants the originals deleted.
553
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
556
  }
557
  } else {
558
  ewwwio_debug_message( 'converted PNG is no good' );
559
+ if ( ewwwio_is_file( $newfile ) ) {
560
  unlink( $newfile );
561
  }
562
  return false;
645
  }
646
  ewwwio_debug_message( "converted JPG size: $jpg_size" );
647
  // If the new JPG is smaller than the original PNG.
648
+ if ( ! $check_size && $jpg_size && ewwwio_is_file( $newfile ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/jpeg' ) {
649
  ewwwio_debug_message( 'JPG to PNG successful' );
650
  // If the user wants originals delted after a conversion.
651
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
652
  // Delete the original PNG.
653
  unlink( $file );
654
  }
655
+ } elseif ( $check_size && ewwwio_is_file( $newfile ) && $jpg_size < ewww_image_optimizer_filesize( $file ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/jpeg' ) {
656
  ewwwio_debug_message( 'PNG to JPG successful, after comparing size' );
657
  // If the user wants originals delted after a conversion.
658
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
660
  unlink( $file );
661
  }
662
  } else {
663
+ if ( ewwwio_is_file( $newfile ) ) {
664
  // Otherwise delete the new JPG.
665
  unlink( $newfile );
666
  }
701
  }
702
  ewwwio_debug_message( "converted PNG size: $png_size" );
703
  // If the PNG exists, and we didn't end up with an empty file.
704
+ if ( ! $check_size && $png_size && ewwwio_is_file( $newfile ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
705
  ewwwio_debug_message( 'GIF to PNG successful' );
706
  // Check to see if the user wants the originals deleted.
707
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
708
  // Delete the original JPG.
709
  unlink( $file );
710
  }
711
+ } elseif ( $check_size && ewwwio_is_file( $newfile ) && $png_size < ewww_image_optimizer_filesize( $file ) && ewww_image_optimizer_mimetype( $newfile, 'i' ) === 'image/png' ) {
712
  ewwwio_debug_message( 'GIF to PNG successful, after comparing size' );
713
  // Check to see if the user wants the originals deleted.
714
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
717
  }
718
  } else {
719
  ewwwio_debug_message( 'converted PNG is no good' );
720
+ if ( ewwwio_is_file( $newfile ) ) {
721
  unlink( $newfile );
722
  }
723
  return false;
742
  public function unique_filename( $file, $fileext ) {
743
  // Strip the file extension.
744
  $filename = preg_replace( '/\.\w+$/', '', $file );
745
+ if ( ! ewwwio_is_file( $filename . $fileext ) ) {
746
  return $filename . $fileext;
747
  }
748
  // Set the increment to 1 ( but allow the user to override it ).
classes/class-ewww-nextgen.php CHANGED
@@ -663,7 +663,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
663
  <p class="ewww-bulk-info"><?php echo $selected_images_text; ?><br />
664
  <?php esc_html_e( 'Previously optimized images will be skipped by default.', 'ewww-image-optimizer' ); ?></p>
665
  <form id="ewww-bulk-start" class="ewww-bulk-form" method="post" action="">
666
- <input type="submit" class="button-secondary action" value="<?php echo $button_text; ?>" />
667
  </form>
668
  <?php
669
  // If there is a previous bulk operation to resume, give the user the option to reset the resume flag.
@@ -989,22 +989,26 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
989
  function ewww_ngg_bulk_action_handler() {
990
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
991
  // If the requested page is blank, or not a bulk_optimize, do nothing.
992
- if ( empty( $_REQUEST['page'] ) || empty( $_REQUEST['bulkaction'] ) || 'bulk_optimize' !== $_REQUEST['bulkaction'] ) {
993
  return;
994
  }
995
  // If there is no media to optimize, do nothing.
996
  if ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) {
997
  return;
998
  }
999
- // If the requested page does not matche, do nothing.
1000
- if ( 'manage-galleries' !== $_REQUEST['page'] && 'manage-images' !== $_REQUEST['page'] ) {
1001
  return;
1002
  }
1003
 
1004
  $type = 'images';
1005
- if ( 'manage-galleries' === $_REQUEST['page'] ) {
1006
  $type = 'galleries';
1007
  }
 
 
 
 
1008
  wp_redirect(
1009
  add_query_arg(
1010
  array(
663
  <p class="ewww-bulk-info"><?php echo $selected_images_text; ?><br />
664
  <?php esc_html_e( 'Previously optimized images will be skipped by default.', 'ewww-image-optimizer' ); ?></p>
665
  <form id="ewww-bulk-start" class="ewww-bulk-form" method="post" action="">
666
+ <input type="submit" class="button-primary action" value="<?php echo $button_text; ?>" />
667
  </form>
668
  <?php
669
  // If there is a previous bulk operation to resume, give the user the option to reset the resume flag.
989
  function ewww_ngg_bulk_action_handler() {
990
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
991
  // If the requested page is blank, or not a bulk_optimize, do nothing.
992
+ if ( empty( $_REQUEST['nggpage'] ) || empty( $_REQUEST['bulkaction'] ) || 'bulk_optimize' !== $_REQUEST['bulkaction'] ) {
993
  return;
994
  }
995
  // If there is no media to optimize, do nothing.
996
  if ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) {
997
  return;
998
  }
999
+ // If the requested page does not match, do nothing.
1000
+ if ( 'manage-galleries' !== $_REQUEST['nggpage'] && 'manage-images' !== $_REQUEST['nggpage'] ) {
1001
  return;
1002
  }
1003
 
1004
  $type = 'images';
1005
+ if ( 'manage-galleries' === $_REQUEST['nggpage'] ) {
1006
  $type = 'galleries';
1007
  }
1008
+ if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'ngg_bulkgallery' ) ) {
1009
+ ewwwio_ob_clean();
1010
+ wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
1011
+ }
1012
  wp_redirect(
1013
  add_query_arg(
1014
  array(
classes/class-ewwwdb.php CHANGED
@@ -96,9 +96,8 @@ class EwwwDB extends wpdb {
96
  $first = reset( $data );
97
  $fields = '`' . implode( '`, `', array_keys( $first ) ) . '`';
98
  $multi_formats = implode( ',', $multi_formats );
99
- $sql = "INSERT INTO `$table` ($fields) VALUES $multi_formats";
100
  $this->check_current_query = false;
101
- return $this->query( $this->prepare( $sql, $values ) );
102
  }
103
 
104
  }
96
  $first = reset( $data );
97
  $fields = '`' . implode( '`, `', array_keys( $first ) ) . '`';
98
  $multi_formats = implode( ',', $multi_formats );
 
99
  $this->check_current_query = false;
100
+ return $this->query( $this->prepare( "INSERT INTO `$table` ($fields) VALUES $multi_formats", $values ) );
101
  }
102
 
103
  }
classes/class-ewwwio-gd-editor.php CHANGED
@@ -36,7 +36,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
36
  if ( ! $filename ) {
37
  $filename = $this->generate_filename( null, null, $extension );
38
  }
39
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
40
  ewwwio_debug_message( "detected existing file: $filename" );
41
  $current_size = getimagesize( $filename );
42
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -160,7 +160,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
160
  if ( ! $filename ) {
161
  $filename = $this->generate_filename( null, null, $extension );
162
  }
163
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
164
  ewwwio_debug_message( "detected existing file: $filename" );
165
  $current_size = getimagesize( $filename );
166
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -237,7 +237,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
237
  if ( ! $filename ) {
238
  $filename = $this->generate_filename( null, null, $extension );
239
  }
240
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
241
  ewwwio_debug_message( "detected existing file: $filename" );
242
  $current_size = getimagesize( $filename );
243
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -356,7 +356,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
356
  ewwwio_debug_message( 'GIF already altered, leave it alone' );
357
  return parent::_resize( $max_w, $max_h, $crop );
358
  }
359
- if ( ! $this->file || ewww_image_optimizer_stream_wrapped( $this->file ) || 0 === strpos( $this->file, 'http' ) || 0 === strpos( $this->file, 'ftp' ) || ! is_file( $this->file ) ) {
360
  ewwwio_debug_message( 'could not load original file, or remote path detected' );
361
  return parent::_resize( $max_w, $max_h, $crop );
362
  }
@@ -553,7 +553,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
553
  return parent::_save( $image, $filename, $mime_type );
554
  }
555
  global $ewww_preempt_editor;
556
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) && empty( $ewww_preempt_editor ) ) {
557
  ewwwio_debug_message( "detected existing file: $filename" );
558
  $current_size = getimagesize( $filename );
559
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -614,7 +614,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
614
  if ( ! $filename ) {
615
  $filename = $this->generate_filename( null, null, $extension );
616
  }
617
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
618
  ewwwio_debug_message( "detected existing file: $filename" );
619
  $current_size = getimagesize( $filename );
620
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
36
  if ( ! $filename ) {
37
  $filename = $this->generate_filename( null, null, $extension );
38
  }
39
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
40
  ewwwio_debug_message( "detected existing file: $filename" );
41
  $current_size = getimagesize( $filename );
42
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
160
  if ( ! $filename ) {
161
  $filename = $this->generate_filename( null, null, $extension );
162
  }
163
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
164
  ewwwio_debug_message( "detected existing file: $filename" );
165
  $current_size = getimagesize( $filename );
166
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
237
  if ( ! $filename ) {
238
  $filename = $this->generate_filename( null, null, $extension );
239
  }
240
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
241
  ewwwio_debug_message( "detected existing file: $filename" );
242
  $current_size = getimagesize( $filename );
243
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
356
  ewwwio_debug_message( 'GIF already altered, leave it alone' );
357
  return parent::_resize( $max_w, $max_h, $crop );
358
  }
359
+ if ( ! $this->file || ewww_image_optimizer_stream_wrapped( $this->file ) || 0 === strpos( $this->file, 'http' ) || 0 === strpos( $this->file, 'ftp' ) || ! ewwwio_is_file( $this->file ) ) {
360
  ewwwio_debug_message( 'could not load original file, or remote path detected' );
361
  return parent::_resize( $max_w, $max_h, $crop );
362
  }
553
  return parent::_save( $image, $filename, $mime_type );
554
  }
555
  global $ewww_preempt_editor;
556
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) && empty( $ewww_preempt_editor ) ) {
557
  ewwwio_debug_message( "detected existing file: $filename" );
558
  $current_size = getimagesize( $filename );
559
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
614
  if ( ! $filename ) {
615
  $filename = $this->generate_filename( null, null, $extension );
616
  }
617
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
618
  ewwwio_debug_message( "detected existing file: $filename" );
619
  $current_size = getimagesize( $filename );
620
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
classes/class-ewwwio-gmagick-editor.php CHANGED
@@ -34,7 +34,7 @@ if ( class_exists( 'WP_Image_Editor_Gmagick' ) ) {
34
  if ( ! $filename ) {
35
  $filename = $this->generate_filename( null, null, $extension );
36
  }
37
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
38
  ewwwio_debug_message( "detected existing file: $filename" );
39
  $current_size = getimagesize( $filename );
40
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
34
  if ( ! $filename ) {
35
  $filename = $this->generate_filename( null, null, $extension );
36
  }
37
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
38
  ewwwio_debug_message( "detected existing file: $filename" );
39
  $current_size = getimagesize( $filename );
40
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
classes/class-ewwwio-imagick-editor.php CHANGED
@@ -35,7 +35,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
35
  if ( ! $filename ) {
36
  $filename = $this->generate_filename( null, null, $extension );
37
  }
38
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
39
  ewwwio_debug_message( "detected existing file: $filename" );
40
  $current_size = getimagesize( $filename );
41
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -112,7 +112,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
112
  if ( ! $filename ) {
113
  $filename = $this->generate_filename( null, null, $extension );
114
  }
115
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
116
  ewwwio_debug_message( "detected existing file: $filename" );
117
  $current_size = getimagesize( $filename );
118
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -189,7 +189,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
189
  if ( ! $filename ) {
190
  $filename = $this->generate_filename( null, null, $extension );
191
  }
192
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
193
  ewwwio_debug_message( "detected existing file: $filename" );
194
  $current_size = getimagesize( $filename );
195
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -274,7 +274,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
274
  unset( $s3_uploads_image );
275
  return $saved;
276
  }
277
- if ( is_file( $saved['path'] ) && empty( $ewww_preempt_editor ) ) {
278
  $temp_filename = $saved['path'];
279
  ewww_image_optimizer( $temp_filename );
280
  ewwwio_debug_message( "image editor (s3 uploads) saved: $temp_filename" );
@@ -282,10 +282,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
282
  ewwwio_debug_message( "image editor size: $image_size" );
283
  }
284
  $copy_result = copy( $saved['path'], $filename );
285
- if ( is_file( $saved['path'] ) ) {
286
  unlink( $saved['path'] );
287
  }
288
- if ( is_file( $temp_filename ) ) {
289
  unlink( $temp_filename );
290
  }
291
  if ( ! $copy_result ) {
@@ -459,7 +459,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
459
  ewwwio_debug_message( 'GIF already altered, leave it alone' );
460
  $return_parent = true;
461
  }
462
- if ( ! $this->file || ewww_image_optimizer_stream_wrapped( $this->file ) || 0 === strpos( $this->file, 'http' ) || 0 === strpos( $this->file, 'ftp' ) || ! is_file( $this->file ) ) {
463
  ewwwio_debug_message( 'could not load original file, or remote path detected' );
464
  $return_parent = true;
465
  }
@@ -657,7 +657,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
657
  return parent::_save( $image, $filename, $mime_type );
658
  }
659
  global $ewww_preempt_editor;
660
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) && empty( $ewww_preempt_editor ) ) {
661
  ewwwio_debug_message( "detected existing file: $filename" );
662
  $current_size = getimagesize( $filename );
663
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
@@ -718,7 +718,7 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
718
  if ( ! $filename ) {
719
  $filename = $this->generate_filename( null, null, $extension );
720
  }
721
- if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) ) {
722
  ewwwio_debug_message( "detected existing file: $filename" );
723
  $current_size = getimagesize( $filename );
724
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
35
  if ( ! $filename ) {
36
  $filename = $this->generate_filename( null, null, $extension );
37
  }
38
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
39
  ewwwio_debug_message( "detected existing file: $filename" );
40
  $current_size = getimagesize( $filename );
41
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
112
  if ( ! $filename ) {
113
  $filename = $this->generate_filename( null, null, $extension );
114
  }
115
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
116
  ewwwio_debug_message( "detected existing file: $filename" );
117
  $current_size = getimagesize( $filename );
118
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
189
  if ( ! $filename ) {
190
  $filename = $this->generate_filename( null, null, $extension );
191
  }
192
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
193
  ewwwio_debug_message( "detected existing file: $filename" );
194
  $current_size = getimagesize( $filename );
195
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
274
  unset( $s3_uploads_image );
275
  return $saved;
276
  }
277
+ if ( ewwwio_is_file( $saved['path'] ) && empty( $ewww_preempt_editor ) ) {
278
  $temp_filename = $saved['path'];
279
  ewww_image_optimizer( $temp_filename );
280
  ewwwio_debug_message( "image editor (s3 uploads) saved: $temp_filename" );
282
  ewwwio_debug_message( "image editor size: $image_size" );
283
  }
284
  $copy_result = copy( $saved['path'], $filename );
285
+ if ( ewwwio_is_file( $saved['path'] ) ) {
286
  unlink( $saved['path'] );
287
  }
288
+ if ( ewwwio_is_file( $temp_filename ) ) {
289
  unlink( $temp_filename );
290
  }
291
  if ( ! $copy_result ) {
459
  ewwwio_debug_message( 'GIF already altered, leave it alone' );
460
  $return_parent = true;
461
  }
462
+ if ( ! $this->file || ewww_image_optimizer_stream_wrapped( $this->file ) || 0 === strpos( $this->file, 'http' ) || 0 === strpos( $this->file, 'ftp' ) || ! ewwwio_is_file( $this->file ) ) {
463
  ewwwio_debug_message( 'could not load original file, or remote path detected' );
464
  $return_parent = true;
465
  }
657
  return parent::_save( $image, $filename, $mime_type );
658
  }
659
  global $ewww_preempt_editor;
660
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) && empty( $ewww_preempt_editor ) ) {
661
  ewwwio_debug_message( "detected existing file: $filename" );
662
  $current_size = getimagesize( $filename );
663
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
718
  if ( ! $filename ) {
719
  $filename = $this->generate_filename( null, null, $extension );
720
  }
721
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && ewwwio_is_file( $filename ) ) {
722
  ewwwio_debug_message( "detected existing file: $filename" );
723
  $current_size = getimagesize( $filename );
724
  if ( $current_size && (int) $this->size['width'] === (int) $current_size[0] && (int) $this->size['height'] === (int) $current_size[1] ) {
classes/class-ewwwio-install-cloud.php CHANGED
@@ -83,7 +83,7 @@ class EWWWIO_Install_Cloud {
83
  wp_die( esc_html__( 'The plugins folder is not writable, you may install the EWWW Image Optimizer Cloud manually.', 'ewww-image-optimizer' ) );
84
  return;
85
  }
86
- if ( ! is_file( $this->plugin_file ) ) {
87
  if ( is_dir( dirname( $this->plugin_file ) ) ) {
88
  wp_die( esc_html__( 'A partial installation already exists. Please remove it and try again.', 'ewww-image-optimizer' ) );
89
  }
@@ -98,7 +98,7 @@ class EWWWIO_Install_Cloud {
98
  }
99
  }
100
 
101
- if ( is_file( $this->plugin_file ) ) {
102
  $core_active = $this->is_plugin_active( $this->core_plugin_file_rel );
103
  // If not plugin active.
104
  if ( ! $this->is_plugin_active( $this->plugin_file_rel ) ) {
83
  wp_die( esc_html__( 'The plugins folder is not writable, you may install the EWWW Image Optimizer Cloud manually.', 'ewww-image-optimizer' ) );
84
  return;
85
  }
86
+ if ( ! ewwwio_is_file( $this->plugin_file ) ) {
87
  if ( is_dir( dirname( $this->plugin_file ) ) ) {
88
  wp_die( esc_html__( 'A partial installation already exists. Please remove it and try again.', 'ewww-image-optimizer' ) );
89
  }
98
  }
99
  }
100
 
101
+ if ( ewwwio_is_file( $this->plugin_file ) ) {
102
  $core_active = $this->is_plugin_active( $this->core_plugin_file_rel );
103
  // If not plugin active.
104
  if ( ! $this->is_plugin_active( $this->plugin_file_rel ) ) {
classes/class-ewwwio-media-background-process.php CHANGED
@@ -475,7 +475,7 @@ class EWWWIO_Async_Request extends WP_Async_Request {
475
  }
476
  ewww_image_optimizer_hidpi_optimize( $file_path );
477
  ewwwio_debug_message( 'checking for: ' . $file_path . '.processing' );
478
- if ( is_file( $file_path . '.processing' ) ) {
479
  ewwwio_debug_message( 'removing ' . $file_path . '.processing' );
480
  unlink( $file_path . '.processing' );
481
  }
@@ -491,25 +491,28 @@ class EWWWIO_Async_Request extends WP_Async_Request {
491
  * @return string The full file path, reconstructed using the upload folder for WP_CONTENT_DIR
492
  */
493
  public function find_file( $file_path ) {
494
- if ( is_file( $file_path ) ) {
 
 
 
495
  return $file_path;
496
  }
497
  // Retrieve the location of the WordPress upload folder.
498
  $upload_dir = wp_upload_dir();
499
  $upload_path = trailingslashit( $upload_dir['basedir'] );
500
  $file = $upload_path . $file_path;
501
- if ( is_file( $file ) ) {
502
  return $file;
503
  }
504
  $upload_path = trailingslashit( WP_CONTENT_DIR );
505
  $file = $upload_path . $file_path;
506
- if ( is_file( $file ) ) {
507
  return $file;
508
  }
509
  $upload_path .= 'uploads/';
510
 
511
  $file = $upload_path . $file_path;
512
- if ( is_file( $file ) ) {
513
  return $file;
514
  }
515
  return '';
475
  }
476
  ewww_image_optimizer_hidpi_optimize( $file_path );
477
  ewwwio_debug_message( 'checking for: ' . $file_path . '.processing' );
478
+ if ( ewwwio_is_file( $file_path . '.processing' ) ) {
479
  ewwwio_debug_message( 'removing ' . $file_path . '.processing' );
480
  unlink( $file_path . '.processing' );
481
  }
491
  * @return string The full file path, reconstructed using the upload folder for WP_CONTENT_DIR
492
  */
493
  public function find_file( $file_path ) {
494
+ if ( false !== strpos( $file_path, '..' ) ) {
495
+ return false;
496
+ }
497
+ if ( ewwwio_is_file( $file_path ) ) {
498
  return $file_path;
499
  }
500
  // Retrieve the location of the WordPress upload folder.
501
  $upload_dir = wp_upload_dir();
502
  $upload_path = trailingslashit( $upload_dir['basedir'] );
503
  $file = $upload_path . $file_path;
504
+ if ( ewwwio_is_file( $file ) ) {
505
  return $file;
506
  }
507
  $upload_path = trailingslashit( WP_CONTENT_DIR );
508
  $file = $upload_path . $file_path;
509
+ if ( ewwwio_is_file( $file ) ) {
510
  return $file;
511
  }
512
  $upload_path .= 'uploads/';
513
 
514
  $file = $upload_path . $file_path;
515
+ if ( ewwwio_is_file( $file ) ) {
516
  return $file;
517
  }
518
  return '';
classes/class-exactdn.php CHANGED
@@ -399,7 +399,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
399
  $exactdn_activate_error = 'zone setup pending';
400
  }
401
  if ( ! empty( $test_result['response']['code'] ) && 200 !== (int) $test_result['response']['code'] ) {
402
- ewwwio_debug_message( 'received response code: ' . $test_result['response']['code'] );
403
  }
404
  add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
405
  return false;
@@ -603,6 +603,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
603
  }
604
  }
605
  }
 
606
  }
607
 
608
  /**
@@ -821,7 +822,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
821
 
822
  // Find the width and height attributes.
823
  $width = $this->get_img_width( $images['img_tag'][ $index ] );
824
- $height = $this->get_attribute( $images['img_tag'][ $index ], 'height' );
825
  // Falsify them if empty.
826
  $width = $width ? $width : false;
827
  $height = $height ? $height : false;
@@ -1145,32 +1146,8 @@ if ( ! class_exists( 'ExactDN' ) ) {
1145
  $content = $this->filter_prz_thumb( $content );
1146
  }
1147
  if ( $this->filtering_the_page && $this->get_option( 'exactdn_all_the_things' ) ) {
1148
- $this->debug_message( 'rewriting all other wp_content urls' );
1149
- if ( $this->exactdn_domain && $this->upload_domain ) {
1150
- $escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
1151
- $this->debug_message( $escaped_upload_domain );
1152
- if ( ! empty( $this->user_exclusions ) ) {
1153
- $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)?(' . implode( '|', $this->user_exclusions ) . ')#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3$4', $content );
1154
- }
1155
- if ( strpos( $content, '<use ' ) ) {
1156
- // Pre-empt rewriting of files within <use> tags, particularly to prevent security errors for SVGs.
1157
- $content = preg_replace( '#(<use.+?href=["\'])(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)/wp-content/#is', '$1$2//' . $this->upload_domain . '$3/?wpcontent-bypass?/', $content );
1158
- }
1159
- // Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
1160
- $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(htm|html|php|ashx|m4v|mov|wvm|qt|webm|ogv|mp4|m4p|mpg|mpeg|mpv)#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
1161
- $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
1162
- $content = str_replace( 'wp-content/plugins/anti-captcha/', '?wpcontent-bypass?/plugins/anti-captcha', $content );
1163
- if (
1164
- false !== strpos( $this->upload_domain, 'amazonaws.com' ) ||
1165
- false !== strpos( $this->upload_domain, 'digitaloceanspaces.com' ) ||
1166
- false !== strpos( $this->upload_domain, 'storage.googleapis.com' )
1167
- ) {
1168
- $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . $this->remove_path . '/#i', '$1//' . $this->exactdn_domain . '/', $content );
1169
- } else {
1170
- $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1//' . $this->exactdn_domain . '/$2$3/', $content );
1171
- }
1172
- $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
1173
- }
1174
  }
1175
  $this->debug_message( 'done parsing page' );
1176
  $this->filtering_the_content = false;
@@ -1265,6 +1242,44 @@ if ( ! class_exists( 'ExactDN' ) ) {
1265
  return $content;
1266
  }
1267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1268
  /**
1269
  * Allow resizing of images for some admin-ajax requests.
1270
  *
@@ -2396,9 +2411,6 @@ if ( ! class_exists( 'ExactDN' ) ) {
2396
  if ( false !== strpos( $url, 'xmlrpc.php' ) ) {
2397
  return $url;
2398
  }
2399
- if ( strpos( $url, 'wp-content/plugins/anti-captcha/' ) ) {
2400
- return $url;
2401
- }
2402
  /**
2403
  * Allow specific URLs to avoid going through ExactDN.
2404
  *
@@ -2443,7 +2455,13 @@ if ( ! class_exists( 'ExactDN' ) ) {
2443
 
2444
  global $wp_version;
2445
  // If a resource doesn't have a version string, we add one to help with cache-busting.
2446
- if ( ( empty( $parsed_url['query'] ) || 'ver=' . $wp_version === $parsed_url['query'] ) && false !== strpos( $url, 'wp-content/' ) ) {
 
 
 
 
 
 
2447
  $modified = $this->function_exists( 'filemtime' ) ? filemtime( get_template_directory() ) : '';
2448
  if ( empty( $modified ) ) {
2449
  $modified = $this->version;
@@ -2500,7 +2518,6 @@ if ( ! class_exists( 'ExactDN' ) ) {
2500
  return $image_url;
2501
  }
2502
 
2503
- // TODO: Not differentiated yet, but it will be, so stay tuned!
2504
  $jpg_quality = apply_filters( 'jpeg_quality', null, 'image_resize' );
2505
  $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
2506
 
@@ -2508,7 +2525,9 @@ if ( ! class_exists( 'ExactDN' ) ) {
2508
  if ( false === strpos( $image_url, 'strip=all' ) && $this->get_option( $this->prefix . 'metadata_remove' ) ) {
2509
  $more_args['strip'] = 'all';
2510
  }
2511
- if ( false === strpos( $image_url, 'lossy=' ) && $this->get_option( 'exactdn_lossy' ) ) {
 
 
2512
  $more_args['lossy'] = is_numeric( $this->get_option( 'exactdn_lossy' ) ) ? (int) $this->get_option( 'exactdn_lossy' ) : 80;
2513
  }
2514
  if ( false === strpos( $image_url, 'quality=' ) && ! is_null( $jpg_quality ) && 82 !== (int) $jpg_quality ) {
399
  $exactdn_activate_error = 'zone setup pending';
400
  }
401
  if ( ! empty( $test_result['response']['code'] ) && 200 !== (int) $test_result['response']['code'] ) {
402
+ $this->debug_message( 'received response code: ' . $test_result['response']['code'] );
403
  }
404
  add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
405
  return false;
603
  }
604
  }
605
  }
606
+ $this->user_exclusions[] = 'plugins/anti-captcha/';
607
  }
608
 
609
  /**
822
 
823
  // Find the width and height attributes.
824
  $width = $this->get_img_width( $images['img_tag'][ $index ] );
825
+ $height = $this->get_img_height( $images['img_tag'][ $index ] );
826
  // Falsify them if empty.
827
  $width = $width ? $width : false;
828
  $height = $height ? $height : false;
1146
  $content = $this->filter_prz_thumb( $content );
1147
  }
1148
  if ( $this->filtering_the_page && $this->get_option( 'exactdn_all_the_things' ) ) {
1149
+ $this->debug_message( 'rewriting all other wp-content/wp-includes urls' );
1150
+ $content = $this->filter_all_the_things( $content );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1151
  }
1152
  $this->debug_message( 'done parsing page' );
1153
  $this->filtering_the_content = false;
1242
  return $content;
1243
  }
1244
 
1245
+ /**
1246
+ * Parse page content looking for wp-content/wp-includes URLs to rewrite.
1247
+ *
1248
+ * @param string $content The HTML content to parse.
1249
+ * @return string The filtered HTML content.
1250
+ */
1251
+ function filter_all_the_things( $content ) {
1252
+ if ( $this->exactdn_domain && $this->upload_domain ) {
1253
+ $upload_domain = $this->upload_domain;
1254
+ if ( 0 === strpos( $this->upload_domain, 'www.' ) ) {
1255
+ $upload_domain = substr( $this->upload_domain, 4 );
1256
+ }
1257
+ $escaped_upload_domain = str_replace( '.', '\.', $upload_domain );
1258
+ $this->debug_message( $escaped_upload_domain );
1259
+ if ( ! empty( $this->user_exclusions ) ) {
1260
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)?(' . implode( '|', $this->user_exclusions ) . ')#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3$4', $content );
1261
+ }
1262
+ if ( strpos( $content, '<use ' ) ) {
1263
+ // Pre-empt rewriting of files within <use> tags, particularly to prevent security errors for SVGs.
1264
+ $content = preg_replace( '#(<use.+?href=["\'])(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)/wp-content/#is', '$1$2//' . $this->upload_domain . '$3/?wpcontent-bypass?/', $content );
1265
+ }
1266
+ // Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
1267
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(htm|html|php|ashx|m4v|mov|wvm|qt|webm|ogv|mp4|m4p|mpg|mpeg|mpv)#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
1268
+ $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
1269
+ if (
1270
+ false !== strpos( $this->upload_domain, 'amazonaws.com' ) ||
1271
+ false !== strpos( $this->upload_domain, 'digitaloceanspaces.com' ) ||
1272
+ false !== strpos( $this->upload_domain, 'storage.googleapis.com' )
1273
+ ) {
1274
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . $this->remove_path . '/#i', '$1//' . $this->exactdn_domain . '/', $content );
1275
+ } else {
1276
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1//' . $this->exactdn_domain . '/$2$3/', $content );
1277
+ }
1278
+ $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
1279
+ }
1280
+ return $content;
1281
+ }
1282
+
1283
  /**
1284
  * Allow resizing of images for some admin-ajax requests.
1285
  *
2411
  if ( false !== strpos( $url, 'xmlrpc.php' ) ) {
2412
  return $url;
2413
  }
 
 
 
2414
  /**
2415
  * Allow specific URLs to avoid going through ExactDN.
2416
  *
2455
 
2456
  global $wp_version;
2457
  // If a resource doesn't have a version string, we add one to help with cache-busting.
2458
+ if (
2459
+ (
2460
+ empty( $parsed_url['query'] ) ||
2461
+ ( 'ver=' . $wp_version === $parsed_url['query'] && false !== strpos( $url, 'wp-content/themes/' ) )
2462
+ ) &&
2463
+ false !== strpos( $url, 'wp-content/' )
2464
+ ) {
2465
  $modified = $this->function_exists( 'filemtime' ) ? filemtime( get_template_directory() ) : '';
2466
  if ( empty( $modified ) ) {
2467
  $modified = $this->version;
2518
  return $image_url;
2519
  }
2520
 
 
2521
  $jpg_quality = apply_filters( 'jpeg_quality', null, 'image_resize' );
2522
  $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
2523
 
2525
  if ( false === strpos( $image_url, 'strip=all' ) && $this->get_option( $this->prefix . 'metadata_remove' ) ) {
2526
  $more_args['strip'] = 'all';
2527
  }
2528
+ if ( false === strpos( $image_url, 'lossy=' ) && ! $this->get_option( 'exactdn_lossy' ) ) {
2529
+ $more_args['lossy'] = 0;
2530
+ } elseif ( false === strpos( $image_url, 'lossy=' ) && $this->get_option( 'exactdn_lossy' ) ) {
2531
  $more_args['lossy'] = is_numeric( $this->get_option( 'exactdn_lossy' ) ) ? (int) $this->get_option( 'exactdn_lossy' ) : 80;
2532
  }
2533
  if ( false === strpos( $image_url, 'quality=' ) && ! is_null( $jpg_quality ) && 82 !== (int) $jpg_quality ) {
common.php CHANGED
@@ -14,7 +14,6 @@
14
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
15
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
16
  // TODO: write some tests for AGR.
17
- // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
18
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
19
  // TODO: can some of the bulk "fallbacks" be implemented for async processing?
20
  // TODO: check to see if we can use PHP and WP core is_countable functions.
@@ -22,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
22
  exit;
23
  }
24
 
25
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '500.0' );
26
 
27
  // Initialize a couple globals.
28
  $eio_debug = '';
@@ -196,6 +195,10 @@ add_action( 'admin_action_ewww_image_optimizer_retest_background_optimization',
196
  add_action( 'admin_action_ewww_image_optimizer_view_debug_log', 'ewww_image_optimizer_view_debug_log' );
197
  // Non-AJAX handler to delete the debug log, and reroute back to the settings page.
198
  add_action( 'admin_action_ewww_image_optimizer_delete_debug_log', 'ewww_image_optimizer_delete_debug_log' );
 
 
 
 
199
  // Makes sure to flush out any scheduled jobs on deactivation.
200
  register_deactivation_hook( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, 'ewww_image_optimizer_network_deactivate' );
201
  // add_action( 'shutdown', 'ewwwio_memory_output' );.
@@ -851,6 +854,9 @@ function ewww_image_optimizer_admin_init() {
851
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_invalid_key' );
852
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_invalid_key' );
853
  }
 
 
 
854
  // Prevent ShortPixel AIO messiness.
855
  remove_action( 'admin_notices', 'autoptimizeMain::notice_plug_imgopt' );
856
  if ( class_exists( 'autoptimizeExtra' ) ) {
@@ -1005,6 +1011,18 @@ function ewww_image_optimizer_ajax_compat_check() {
1005
  ewww_image_optimizer_image_sizes( false );
1006
  return;
1007
  }
 
 
 
 
 
 
 
 
 
 
 
 
1008
  }
1009
 
1010
  /**
@@ -1113,7 +1131,7 @@ function ewww_image_optimizer_single_size_optimize( $id, $size ) {
1113
  } else {
1114
  $retina_path = false;
1115
  }
1116
- if ( $retina_path && is_file( $retina_path ) ) {
1117
  $ewww_image = new EWWW_Image( $id, 'media', $retina_path );
1118
  $ewww_image->resize = $size . '-retina';
1119
  ewww_image_optimizer( $retina_path );
@@ -1502,17 +1520,65 @@ function ewww_image_optimizer_remove_obsolete_settings() {
1502
  delete_option( 'ewww_image_optimizer_exactdn_suspended' );
1503
  }
1504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1505
  /**
1506
  * Display a success or failure message after PNGOUT installation.
1507
  */
1508
  function ewww_image_optimizer_pngout_installed() {
1509
  if ( 'success' === $_REQUEST['ewww_pngout'] ) {
1510
- echo "<div id='ewww-image-optimizer-pngout-success' class='updated fade'>\n" .
1511
  '<p>' . esc_html__( 'Pngout was successfully installed.', 'ewww-image-optimizer' ) . "</p>\n" .
1512
  "</div>\n";
1513
  }
1514
  if ( 'failed' === $_REQUEST['ewww_pngout'] ) {
1515
- echo "<div id='ewww-image-optimizer-pngout-failure' class='error'>\n" .
1516
  '<p>' . sprintf(
1517
  /* translators: 1: An error message 2: The folder where pngout should be installed */
1518
  esc_html__( 'Pngout was not installed: %1$s. Make sure this folder is writable: %2$s', 'ewww-image-optimizer' ),
@@ -1880,7 +1946,7 @@ function ewww_image_optimizer_path_renamed( $post, $old_filepath, $new_filepath
1880
  // Look for WebP variants and rename them.
1881
  $old_webp = $old_filepath . '.webp';
1882
  $new_webp = $new_filepath . '.webp';
1883
- if ( is_file( $old_webp ) && ! is_file( $new_webp ) ) {
1884
  ewwwio_debug_message( "renaming $old_webp to $new_webp" );
1885
  rename( $old_webp, $new_webp );
1886
  }
@@ -2010,7 +2076,7 @@ function ewww_image_optimizer_handle_upload( $params ) {
2010
  } else {
2011
  $file_path = $params['file'];
2012
  }
2013
- if ( ! is_file( $file_path ) || ! filesize( $file_path ) ) {
2014
  clearstatcache();
2015
  return $params;
2016
  }
@@ -2027,7 +2093,7 @@ function ewww_image_optimizer_handle_upload( $params ) {
2027
  $params['url'] = trailingslashit( dirname( $params['url'] ) ) . basename( $new_image );
2028
  }
2029
  $params['type'] = ewww_image_optimizer_mimetype( $new_image, 'i' );
2030
- if ( is_file( $file_path ) ) {
2031
  unlink( $file_path );
2032
  }
2033
  $file_path = $new_image;
@@ -2039,7 +2105,7 @@ function ewww_image_optimizer_handle_upload( $params ) {
2039
  } else {
2040
  $mime_type = $params['type'];
2041
  }
2042
- if ( ( ! is_wp_error( $params ) ) && is_file( $file_path ) && in_array( $mime_type, array( 'image/png', 'image/gif', 'image/jpeg' ), true ) ) {
2043
  ewww_image_optimizer_resize_upload( $file_path );
2044
  }
2045
  }
@@ -2240,7 +2306,7 @@ function ewww_image_optimizer_resize_dup_check() {
2240
  $resized_image = $editor->resize( 150, 150, true );
2241
  $new_file = $editor->generate_filename();
2242
  echo $new_file;
2243
- if ( is_file( $new_file ) ) {
2244
  echo '<br>file already exists<br>';
2245
  }
2246
  $saved = $editor->save( $new_file );
@@ -2319,7 +2385,7 @@ function ewww_image_optimizer_retina( $id, $retina_path ) {
2319
  ewwwio_debug_message( "retina path: $retina_path" );
2320
  $webp_path = $temp_path . '.webp';
2321
  ewwwio_debug_message( "retina webp path: $webp_path" );
2322
- if ( is_file( $webp_path ) ) {
2323
  rename( $webp_path, $retina_path . '.webp' );
2324
  }
2325
  $opt_size = ewww_image_optimizer_filesize( $retina_path );
@@ -2724,7 +2790,7 @@ function ewww_image_optimizer_webp_paths_sanitize( $paths ) {
2724
  );
2725
  continue;
2726
  }
2727
- $paths_saved[] = str_replace( 'http://', '', $path );
2728
  }
2729
  }
2730
  }
@@ -2810,7 +2876,7 @@ function ewww_image_optimizer_set_jpg_quality( $quality ) {
2810
  * @return int The size of the file or zero.
2811
  */
2812
  function ewww_image_optimizer_filesize( $file ) {
2813
- if ( is_file( $file ) ) {
2814
  // Flush the cache for filesize.
2815
  clearstatcache();
2816
  // Find out the size of the new PNG file.
@@ -2820,6 +2886,21 @@ function ewww_image_optimizer_filesize( $file ) {
2820
  }
2821
  }
2822
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2823
  /**
2824
  * Make sure an array/object can be parsed by a foreach().
2825
  *
@@ -3080,7 +3161,7 @@ function ewww_image_optimizer_cloud_restore_single_image( $image ) {
3080
  file_put_contents( $image['path'] . '.tmp', $result['body'] );
3081
  $new_type = ewww_image_optimizer_mimetype( $image['path'] . '.tmp', 'i' );
3082
  $old_type = '';
3083
- if ( is_file( $image['path'] ) ) {
3084
  $old_type = ewww_image_optimizer_mimetype( $image['path'], 'i' );
3085
  }
3086
  if ( ! in_array( $new_type, $enabled_types, true ) ) {
@@ -3088,7 +3169,7 @@ function ewww_image_optimizer_cloud_restore_single_image( $image ) {
3088
  }
3089
  if ( empty( $old_type ) || $old_type === $new_type ) {
3090
  if ( rename( $image['path'] . '.tmp', $image['path'] ) ) {
3091
- if ( is_file( $image['path'] . '.webp' ) && is_writable( $image['path'] . '.webp' ) ) {
3092
  unlink( $image['path'] . '.webp' );
3093
  }
3094
  // Set the results to nothing.
@@ -3131,18 +3212,18 @@ function ewww_image_optimizer_delete( $id ) {
3131
  if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
3132
  continue;
3133
  }
3134
- if ( ! empty( $image['path'] ) && is_file( $image['path'] ) ) {
3135
  unlink( $image['path'] );
3136
- if ( is_file( $image['path'] . '.webp' ) ) {
3137
  unlink( $image['path'] . '.webp' );
3138
  }
3139
  }
3140
  if ( ! empty( $image['converted'] ) ) {
3141
  $image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
3142
  }
3143
- if ( ! empty( $image['converted'] ) && is_file( $image['converted'] ) ) {
3144
  unlink( $image['converted'] );
3145
- if ( is_file( $image['converted'] . '.webp' ) ) {
3146
  unlink( $image['converted'] . '.webp' );
3147
  }
3148
  }
@@ -3162,17 +3243,17 @@ function ewww_image_optimizer_delete( $id ) {
3162
  // Delete any residual webp versions.
3163
  $webpfile = $filename . '.webp';
3164
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $filename );
3165
- if ( is_file( $webpfile ) ) {
3166
  unlink( $webpfile );
3167
  }
3168
- if ( is_file( $webpfileold ) ) {
3169
  unlink( $webpfileold );
3170
  }
3171
  // Retrieve any posts that link the original image.
3172
  $esql = "SELECT ID, post_content FROM $ewwwdb->posts WHERE post_content LIKE '%$filename%' LIMIT 1";
3173
  $rows = $ewwwdb->get_row( $esql );
3174
  // If the original file still exists and no posts contain links to the image.
3175
- if ( is_file( $file_path ) && empty( $rows ) ) {
3176
  unlink( $file_path );
3177
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3178
  }
@@ -3188,15 +3269,15 @@ function ewww_image_optimizer_delete( $id ) {
3188
  // Delete any residual webp versions.
3189
  $webpfile = $base_dir . $data['file'] . '.webp';
3190
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . $data['file'] );
3191
- if ( is_file( $webpfile ) ) {
3192
  unlink( $webpfile );
3193
  }
3194
- if ( is_file( $webpfileold ) ) {
3195
  unlink( $webpfileold );
3196
  }
3197
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['file'] ) ) );
3198
  // If the original resize is set, and still exists.
3199
- if ( ! empty( $data['orig_file'] ) && is_file( $base_dir . $data['orig_file'] ) ) {
3200
  unset( $srows );
3201
  // Retrieve the filename from the metadata.
3202
  $filename = $data['orig_file'];
@@ -3526,6 +3607,9 @@ function ewww_image_optimizer_cloud_quota( $raw = false ) {
3526
  */
3527
  function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $newfile = null, $newtype = null, $fullsize = false, $jpg_fill = '', $jpg_quality = 82 ) {
3528
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 
 
 
3529
  if ( ! ewwwio_check_memory_available( filesize( $file ) * 2.2 ) ) { // 2.2 = upload buffer + download buffer (2) multiplied by a factor of 1.1 for extra wiggle room.
3530
  $memory_required = filesize( $file ) * 2.2;
3531
  ewwwio_debug_message( "possibly insufficient memory for cloud (optimize) operation: $memory_required" );
@@ -3589,6 +3673,9 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3589
  if ( 'image/webp' === $newtype ) {
3590
  $webp = 1;
3591
  $jpg_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
 
 
 
3592
  } else {
3593
  $webp = 0;
3594
  }
@@ -3872,7 +3959,7 @@ function ewww_image_optimizer_cloud_backup( $file ) {
3872
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
3873
  return false;
3874
  }
3875
- if ( ! is_file( $file ) ) {
3876
  return false;
3877
  }
3878
  if ( ! ewwwio_check_memory_available( filesize( $file ) * 1.1 ) ) { // 1.1 = upload buffer (filesize) multiplied by a factor of 1.1 for extra wiggle room.
@@ -4575,7 +4662,7 @@ function ewww_image_optimizer_hidpi_optimize( $orig_path, $return_path = false,
4575
  return;
4576
  }
4577
  $hidpi_path = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $hidpi_suffix . '.' . $pathinfo['extension'];
4578
- if ( $validate_file && ! is_file( $hidpi_path ) ) {
4579
  return;
4580
  }
4581
  if ( $return_path ) {
@@ -4606,7 +4693,7 @@ function ewww_image_optimizer_hidpi_optimize( $orig_path, $return_path = false,
4606
  function ewww_image_optimizer_s3_uploads_image_cleanup( $file ) {
4607
  global $s3_uploads_image;
4608
  if ( ! ewww_image_optimizer_stream_wrapped( $file ) && strpos( $file, 's3-uploads' ) === false && ! empty( $s3_uploads_image ) ) {
4609
- if ( is_file( $file ) ) {
4610
  unlink( $file );
4611
  }
4612
  $file = $s3_uploads_image;
@@ -4849,7 +4936,7 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4849
  } // End if().
4850
  } // End if().
4851
  clearstatcache();
4852
- if ( ! empty( $filename ) && is_file( $filename ) ) {
4853
  return $filename;
4854
  } else {
4855
  return false;
@@ -5120,6 +5207,7 @@ function ewww_image_optimizer_autoconvert( $file ) {
5120
  */
5121
  function ewww_image_optimizer_noresize( $dimensions, $filename ) {
5122
  if ( strpos( $filename, 'noresize' ) !== false ) {
 
5123
  return array( 0, 0 );
5124
  }
5125
  $ignore_folders = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' );
@@ -5185,6 +5273,9 @@ function ewww_image_optimizer_resize_upload( $file ) {
5185
  if ( ! $file ) {
5186
  return false;
5187
  }
 
 
 
5188
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
5189
  wp_raise_memory_limit( 'image' );
5190
  }
@@ -5405,7 +5496,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
5405
  }
5406
  return array( $newwidth, $newheight );
5407
  } // End if().
5408
- if ( is_file( $new_file ) ) {
5409
  ewwwio_debug_message( "resizing did not create a smaller image: $new_size" );
5410
  unlink( $new_file );
5411
  }
@@ -5658,7 +5749,7 @@ function ewww_image_optimizer_test_parallel_opt( $type = '', $id = 0 ) {
5658
  */
5659
  function ewww_image_optimizer_rebuild_meta( $attachment_id ) {
5660
  $file = get_attached_file( $attachment_id );
5661
- if ( is_file( $file ) ) {
5662
  global $ewww_preempt_editor;
5663
  $ewww_preempt_editor = true;
5664
  remove_all_filters( 'wp_generate_attachment_metadata' );
@@ -5753,11 +5844,11 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5753
  if ( ! $new_image && class_exists( 'Amazon_S3_And_CloudFront' ) && ewww_image_optimizer_stream_wrapped( $file_path ) ) {
5754
  ewww_image_optimizer_check_table_as3cf( $meta, $id, $file_path );
5755
  }
5756
- if ( ! is_file( $file_path ) && class_exists( 'wpCloud\StatelessMedia\EWWW' ) && ! empty( $meta['gs_link'] ) ) {
5757
  $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
5758
  }
5759
  // If the local file is missing and we have valid metadata, see if we can fetch via CDN.
5760
- if ( ! is_file( $file_path ) || ( ewww_image_optimizer_stream_wrapped( $file_path ) && ! class_exists( 'S3_Uploads' ) ) ) {
5761
  $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
5762
  if ( ! $file_path ) {
5763
  ewwwio_debug_message( 'could not retrieve path' );
@@ -5943,7 +6034,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5943
  $base_dir = trailingslashit( dirname( $file_path ) );
5944
  $image_path = $base_dir . $data['file'];
5945
  $ims_path = $base_ims_dir . $data['file'];
5946
- if ( is_file( $ims_path ) ) {
5947
  ewwwio_debug_message( 'ims resize already exists, wahoo' );
5948
  ewwwio_debug_message( "ims path: $ims_path" );
5949
  $image_size = ewww_image_optimizer_filesize( $ims_path );
@@ -5980,13 +6071,13 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5980
  $size = 'pdf-full';
5981
  ewwwio_debug_message( 'processing full size pdf preview' );
5982
  }
5983
- if ( $parallel_opt && is_file( $resize_path ) ) {
5984
  $parallel_sizes[ $size ] = $resize_path;
5985
  } else {
5986
  $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
5987
  $ewww_image->resize = $size;
5988
  // Run the optimization and store the results.
5989
- list( $optimized_file, $results, $resize_conv, $original ) = ewww_image_optimizer( $resize_path );
5990
  }
5991
  // Optimize retina images, if they exist.
5992
  if ( function_exists( 'wr2x_get_retina' ) ) {
@@ -5994,7 +6085,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5994
  } else {
5995
  $retina_path = false;
5996
  }
5997
- if ( $retina_path && is_file( $retina_path ) ) {
5998
  if ( $parallel_opt ) {
5999
  $async_path = str_replace( $upload_path, '', $retina_path );
6000
  $ewwwio_async_optimize_media->data(
@@ -6024,13 +6115,13 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
6024
  ewwwio_debug_message( 'processing original_image' );
6025
  // Meta sizes don't contain a path, so we calculate one.
6026
  $resize_path = trailingslashit( dirname( $file_path ) ) . $meta['original_image'];
6027
- if ( $parallel_opt && is_file( $resize_path ) ) {
6028
  $parallel_sizes['original_image'] = $resize_path;
6029
  } else {
6030
  $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
6031
  $ewww_image->resize = 'original_image';
6032
- // Run the optimization and store the results.
6033
- list( $optimized_file, $results, $resize_conv, $original ) = ewww_image_optimizer( $resize_path );
6034
  }
6035
  } // End if().
6036
 
@@ -6040,7 +6131,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
6040
  $imagemeta_resize_path = '';
6041
  foreach ( $meta['image_meta']['resized_images'] as $imagemeta_resize ) {
6042
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
6043
- if ( $parallel_opt && is_file( $imagemeta_resize_path ) ) {
6044
  $async_path = str_replace( $upload_path, '', $imagemeta_resize_path );
6045
  $ewwwio_async_optimize_media->data(
6046
  array(
@@ -6128,7 +6219,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
6128
  while ( $parallel_opt && $processing ) {
6129
  $processing = false;
6130
  foreach ( $processing_sizes as $size => $filename ) {
6131
- if ( is_file( $filename . '.processing' ) ) {
6132
  ewwwio_debug_message( "still processing $size" );
6133
  $processing = true;
6134
  continue;
@@ -6152,7 +6243,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
6152
  }
6153
  if ( $timer > $timer_max ) {
6154
  foreach ( $processing_sizes as $filename ) {
6155
- if ( is_file( $filename . '.processing' ) ) {
6156
  unlink( $filename . '.processing' );
6157
  }
6158
  }
@@ -6245,7 +6336,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
6245
  function ewww_image_optimizer_lr_sync_update( $meta, $id = null ) {
6246
  update_option( 'ewww_image_optimizer_lr_sync', true, false );
6247
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
6248
- if ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! is_file( $file_path ) ) {
6249
  return $meta;
6250
  }
6251
  ewwwio_debug_message( "retrieved file path: $file_path" );
@@ -6315,7 +6406,7 @@ function ewww_image_optimizer_detect_wpsf_location_lock() {
6315
  function ewww_image_optimizer_as3cf_attachment_file_paths( $paths, $id ) {
6316
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6317
  foreach ( $paths as $size => $path ) {
6318
- if ( is_string( $path ) && is_file( $path . '.webp' ) ) {
6319
  $paths[ $size . '-webp' ] = $path . '.webp';
6320
  ewwwio_debug_message( "added $path.webp to as3cf queue" );
6321
  }
@@ -6330,7 +6421,7 @@ function ewww_image_optimizer_as3cf_attachment_file_paths( $paths, $id ) {
6330
  */
6331
  function ewww_image_optimizer_as3cf_object_meta( $args ) {
6332
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6333
- if ( ! empty( $args['SourceFile'] ) && is_file( $args['SourceFile'] ) && empty( $args['ContentType'] ) && false !== strpos( $args['SourceFile'], '.webp' ) ) {
6334
  $args['ContentType'] = ewww_image_optimizer_quick_mimetype( $args['SourceFile'] );
6335
  }
6336
  return $args;
@@ -6482,7 +6573,7 @@ function ewww_image_optimizer_attachment_path( $meta, $id, $file = '', $refresh_
6482
  ! ewww_image_optimizer_stream_wrapped( $filtered_file_path ) ||
6483
  ewww_image_optimizer_stream_wrapper_exists()
6484
  )
6485
- && is_file( $filtered_file_path )
6486
  ) {
6487
  return array( str_replace( '//_imsgalleries/', '/_imsgalleries/', $filtered_file_path ), $upload_path );
6488
  }
@@ -6492,18 +6583,18 @@ function ewww_image_optimizer_attachment_path( $meta, $id, $file = '', $refresh_
6492
  ! ewww_image_optimizer_stream_wrapped( $file_path ) ||
6493
  ewww_image_optimizer_stream_wrapper_exists()
6494
  )
6495
- && is_file( $file_path )
6496
  ) {
6497
  return array( str_replace( '//_imsgalleries/', '/_imsgalleries/', $file_path ), $upload_path );
6498
  }
6499
  if ( 'ims_image' === get_post_type( $id ) && is_array( $meta ) && ! empty( $meta['file'] ) ) {
6500
  ewwwio_debug_message( "finding path for IMS image: $id " );
6501
- if ( is_dir( $file_path ) && is_file( $file_path . $meta['file'] ) ) {
6502
  // Generate the absolute path.
6503
  $file_path = $file_path . $meta['file'];
6504
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
6505
  ewwwio_debug_message( "found path for IMS image: $file_path" );
6506
- } elseif ( is_file( $meta['file'] ) ) {
6507
  $file_path = $meta['file'];
6508
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
6509
  ewwwio_debug_message( "found path for IMS image: $file_path" );
@@ -6523,18 +6614,18 @@ function ewww_image_optimizer_attachment_path( $meta, $id, $file = '', $refresh_
6523
  return array( '', $upload_path );
6524
  }
6525
  ewwwio_debug_message( "looking for file at $file_path" );
6526
- if ( is_file( $file_path ) ) {
6527
  return array( $file_path, $upload_path );
6528
  }
6529
  $file_path = trailingslashit( $upload_path ) . $file_path;
6530
  ewwwio_debug_message( "that did not work, try it with the upload_dir: $file_path" );
6531
- if ( is_file( $file_path ) ) {
6532
  return array( $file_path, $upload_path );
6533
  }
6534
  $upload_path = trailingslashit( WP_CONTENT_DIR ) . 'uploads/';
6535
  $file_path = $upload_path . $meta['file'];
6536
  ewwwio_debug_message( "one last shot, using the wp-content/ constant: $file_path" );
6537
- if ( is_file( $file_path ) ) {
6538
  return array( $file_path, $upload_path );
6539
  }
6540
  }
@@ -6657,7 +6748,7 @@ function ewww_image_optimizer_size_unformat( $formatted ) {
6657
  function ewww_image_optimizer_unique_filename( $file, $fileext ) {
6658
  // Strip the file extension.
6659
  $filename = preg_replace( '/\.\w+$/', '', $file );
6660
- if ( ! is_file( $filename . $fileext ) ) {
6661
  return array( $filename . $fileext, '' );
6662
  }
6663
  // Set the increment to 1 (but allow the user to override it).
@@ -6698,7 +6789,7 @@ function ewww_image_optimizer_quick_mimetype( $path ) {
6698
  case 'pdf':
6699
  return 'application/pdf';
6700
  default:
6701
- if ( empty( $pathextension ) && ! ewww_image_optimizer_stream_wrapped( $path ) && is_file( $path ) ) {
6702
  return ewww_image_optimizer_mimetype( $path, 'i' );
6703
  }
6704
  return false;
@@ -6713,7 +6804,10 @@ function ewww_image_optimizer_quick_mimetype( $path ) {
6713
  */
6714
  function ewww_image_optimizer_png_alpha( $filename ) {
6715
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6716
- if ( ! is_file( $filename ) ) {
 
 
 
6717
  return false;
6718
  }
6719
  // Determine what color type is stored in the file.
@@ -6756,7 +6850,7 @@ function ewww_image_optimizer_png_alpha( $filename ) {
6756
  */
6757
  function ewww_image_optimizer_is_animated( $filename ) {
6758
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6759
- if ( ! is_file( $filename ) ) {
6760
  return false;
6761
  }
6762
  // If we can't open the file in read-only buffered mode.
@@ -7113,7 +7207,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
7113
  $output .= $msg;
7114
  }
7115
  $restorable = false;
7116
- if ( $converted && is_file( $converted ) ) {
7117
  $restorable = true;
7118
  }
7119
  if ( $restorable && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
@@ -7144,7 +7238,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
7144
  $sizes_to_opt
7145
  ) . '</div>';
7146
  } else {
7147
- $output .= '<div>' . esc_html__( 'Not processed', 'ewww-image-optimizer' ) . '</div>';
7148
  }
7149
  // Tell them the filesize.
7150
  $output .= '<div>' . sprintf(
@@ -7152,6 +7246,15 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
7152
  esc_html__( 'Image Size: %s', 'ewww-image-optimizer' ),
7153
  $file_size
7154
  ) . '</div>';
 
 
 
 
 
 
 
 
 
7155
  if ( empty( $msg ) && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
7156
  // Give the user the option to optimize the image right now.
7157
  $output .= sprintf( "<div><a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>", $id, esc_html__( 'Optimize now!', 'ewww-image-optimizer' ) );
@@ -7395,7 +7498,7 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
7395
  return $meta;
7396
  }
7397
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
7398
- if ( ! is_file( $file_path ) && ( class_exists( 'WindowsAzureStorageUtil' ) || class_exists( 'Amazon_S3_And_CloudFront' ) ) ) {
7399
  // Construct a $file_path and proceed IF a supported CDN plugin is installed.
7400
  $file_path = get_attached_file( $id );
7401
  if ( ! $file_path ) {
@@ -7784,6 +7887,38 @@ function ewww_image_optimizer_savings() {
7784
  return array( $total_opt, $total_orig );
7785
  }
7786
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7787
  /**
7788
  * Figure out where the .htaccess file should live.
7789
  *
@@ -7796,7 +7931,7 @@ function ewww_image_optimizer_htaccess_path() {
7796
  ewwwio_debug_message( 'WordPress Address and Site Address are different, possible subdir install' );
7797
  $path_diff = str_replace( get_option( 'home' ), '', get_option( 'siteurl' ) );
7798
  $newhtpath = trailingslashit( rtrim( $htpath, '/' ) . '/' . ltrim( $path_diff, '/' ) ) . '.htaccess';
7799
- if ( is_file( $newhtpath ) ) {
7800
  ewwwio_debug_message( 'subdir install confirmed' );
7801
  ewwwio_debug_message( "using $newhtpath" );
7802
  return $newhtpath;
@@ -7902,6 +8037,8 @@ function ewww_image_optimizer_webp_rewrite_verify() {
7902
  /**
7903
  * Extracts strings from between the BEGIN and END markers in the .htaccess file.
7904
  *
 
 
7905
  * @param string $filename The file within which to search.
7906
  * @param string $marker The bounary marker of the desired content.
7907
  * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers.
@@ -8036,10 +8173,12 @@ function ewww_image_optimizer_network_singlesite_options() {
8036
  * Displays the EWWW IO options along with status information, and debugging information.
8037
  *
8038
  * @global string $eio_debug In memory debug log.
 
8039
  *
8040
  * @param string $network Indicates which options should be shown in multisite installations.
8041
  */
8042
  function ewww_image_optimizer_options( $network = 'singlesite' ) {
 
8043
  global $ewwwio_temp_debug;
8044
  global $content_width;
8045
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
@@ -8683,7 +8822,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8683
  esc_html__( 'Optimize the original version of images that have been scaled down by WordPress.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8684
  ewwwio_debug_message( 'include originals: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_originals' ) ? 'on' : 'off' ) );
8685
  $aux_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ) ) : '';
8686
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_aux_paths'>" . esc_html__( 'Folders to Optimize', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . '</th><td>' .
 
8687
  /* translators: %s: the folder where WordPress is installed */
8688
  sprintf( esc_html__( 'One path per line, must be within %s. Use full paths, not relative paths.', 'ewww-image-optimizer' ), ABSPATH ) . "<br>\n" .
8689
  "<textarea id='ewww_image_optimizer_aux_paths' name='ewww_image_optimizer_aux_paths' rows='3' cols='60'>$aux_paths</textarea>\n" .
@@ -8832,39 +8972,50 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8832
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . '</label>' .
8833
  ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
8834
  "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp' name='ewww_image_optimizer_webp' value='true' " .
8835
- ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ? "checked='true'" : '' ) . ' /> <b>' .
8836
- esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'JPG to WebP conversion is lossy, but quality loss is minimal. PNG to WebP conversion is lossless.', 'ewww-image-optimizer' ) .
8837
  "</span>\n<p class='description'>" . esc_html__( 'Originals are never deleted, and WebP images should only be served to supported browsers.', 'ewww-image-optimizer' ) .
8838
- " <a href='#webp-rewrite'>" . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? esc_html__( 'You can use the rewrite rules below to serve WebP images with Apache.', 'ewww-image-optimizer' ) : '' ) . "</a></td></tr>\n";
8839
  ewwwio_debug_message( 'webp conversion: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ? 'on' : 'off' ) );
8840
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_force'>" . esc_html__( 'Force WebP', 'ewww-image-optimizer' ) . '</label>' .
8841
- ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
8842
- "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_force' name='ewww_image_optimizer_webp_force' value='true' " .
8843
- ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ? "checked='true'" : '' ) . ' /> ' .
8844
- esc_html__( 'WebP images will be generated and saved for all JPG/PNG images regardless of their size. The JS WebP Rewriting will not check if a file exists, only that the domain matches the home url.', 'ewww-image-optimizer' ) . "</span></td></tr>\n";
8845
- ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ? 'on' : 'off' ) );
8846
  }
8847
  if ( ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
8848
- $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
8849
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label>' .
8850
- ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) . '</th><td>' .
8851
- esc_html__( 'If Force WebP is enabled, enter URL patterns that should be permitted for JS WebP Rewriting. One pattern per line, may be partial URLs, but must include the domain name.', 'ewww-image-optimizer' ) . '<br>' .
8852
- "<textarea id='ewww_image_optimizer_webp_paths' name='ewww_image_optimizer_webp_paths' rows='3' cols='60'>$webp_paths</textarea></td></tr>\n";
8853
- ewwwio_debug_message( 'webp paths:' );
8854
- ewwwio_debug_message( $webp_paths );
8855
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_for_cdn'>" .
8856
  esc_html__( 'JS WebP Rewriting', 'ewww-image-optimizer' ) .
8857
- '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89,59443d162c7d3a0747cdf9f0' ) . "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_for_cdn' name='ewww_image_optimizer_webp_for_cdn' value='true' " .
 
8858
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? "checked='true'" : '' ) . ' /> ' .
8859
  esc_html__( 'Use this if the Apache rewrite rules do not work, or if your images are served from a CDN.', 'ewww-image-optimizer' ) . ' ' .
8860
- /* translators: %s: Cache Enabler (link) */
8861
- sprintf( esc_html__( 'Sites using a CDN may also use the WebP option in the %s plugin.', 'ewww-image-optimizer' ), '<a href="https://wordpress.org/plugins/cache-enabler/">Cache Enabler</a>' ) . '</span></td></tr>';
8862
  ewwwio_debug_message( 'alt webp rewriting: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? 'on' : 'off' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8863
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8864
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by ExactDN.', 'ewww-image-optimizer' ) . '</p></td></tr>';
8865
  } elseif ( get_option( 'easyio_exactdn' ) ) {
8866
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by Easy Image Optimizer.', 'ewww-image-optimizer' ) . '</p></td></tr>';
8867
  }
 
 
 
 
 
 
 
 
8868
  $output[] = "</table>\n</div>\n";
8869
 
8870
  $output[] = "<div id='ewww-support-settings'>\n";
@@ -8915,20 +9066,32 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8915
  ewww_image_optimizer_webp_rewrite_verify();
8916
  }
8917
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
 
 
 
 
 
8918
  if ( ! apache_mod_loaded( 'mod_rewrite' ) ) {
8919
  ewwwio_debug_message( 'webp missing mod_rewrite' );
8920
  /* translators: %s: mod_rewrite or mod_headers */
8921
- $output[] = '<p><strong>' . sprintf( esc_html( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.' ), 'mod_rewrite' ) . "</strong></p>\n";
8922
  }
8923
  if ( ! apache_mod_loaded( 'mod_headers' ) ) {
8924
  /* translators: %s: mod_rewrite or mod_headers */
8925
- $output[] = '<p><strong>' . sprintf( esc_html( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.' ), 'mod_headers' ) . "</strong></p>\n";
8926
  ewwwio_debug_message( 'webp missing mod_headers' );
8927
  }
 
 
 
 
 
 
8928
  $output[] = "<form id='ewww-webp-rewrite'>\n";
8929
  $output[] = '<p>' . esc_html__( 'There are many ways to serve WebP images to visitors with supported browsers. You may choose any you wish, but it is recommended to serve them with an .htaccess file using mod_rewrite and mod_headers. The plugin can insert the rules for you if the file is writable, or you can edit .htaccess yourself.', 'ewww-image-optimizer' ) . "</p>\n";
8930
- if ( ! ewww_image_optimizer_webp_rewrite_verify() ) {
8931
- $output[] = "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . "' style='float: right; padding: 0 0 10px 10px;'>\n" .
 
8932
  "<p id='ewww-webp-rewrite-status'><b>" . esc_html__( 'Rules verified successfully', 'ewww-image-optimizer' ) . "</b></p>\n" .
8933
  "<button type='button' id='ewww-webp-remove' class='button-secondary action'>" . esc_html__( 'Remove Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
8934
  ewwwio_debug_message( 'webp .htaccess rewriting enabled' );
@@ -8946,7 +9109,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8946
  "Header append Vary Accept env=REDIRECT_accept\n" .
8947
  "&lt;/IfModule&gt;\n" .
8948
  "AddType image/webp .webp</pre>\n" .
8949
- "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . "' style='float: right; padding-left: 10px;'>\n" .
8950
  "<p id='ewww-webp-rewrite-status'>" . esc_html__( 'The image to the right will display a WebP image with WEBP in white text, if your site is serving WebP images and your browser supports WebP.', 'ewww-image-optimizer' ) . "</p>\n" .
8951
  "<button type='button' id='ewww-webp-insert' class='button-secondary action'>" . esc_html__( 'Insert Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
8952
  ewwwio_debug_message( 'webp .htaccess rules not detected' );
@@ -8988,7 +9151,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8988
  global $eio_debug;
8989
  if ( ! empty( $eio_debug ) ) {
8990
  $debug_output = '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
8991
- if ( is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
8992
  $debug_output .= "&emsp;<a href='admin.php?action=ewww_image_optimizer_view_debug_log'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
8993
  }
8994
  $debug_output .= '</p>';
@@ -9315,7 +9478,7 @@ function ewww_image_optimizer_view_debug_log() {
9315
  if ( false === current_user_can( $permissions ) ) {
9316
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
9317
  }
9318
- if ( is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
9319
  ewwwio_ob_clean();
9320
  header( 'Content-Type: text/plain;charset=UTF-8' );
9321
  readfile( WP_CONTENT_DIR . '/ewww/debug.log' );
@@ -9332,7 +9495,7 @@ function ewww_image_optimizer_delete_debug_log() {
9332
  if ( false === current_user_can( $permissions ) ) {
9333
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
9334
  }
9335
- if ( is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
9336
  unlink( WP_CONTENT_DIR . '/ewww/debug.log' );
9337
  }
9338
  $sendback = wp_get_referer();
@@ -9356,7 +9519,6 @@ function ewwwio_debug_version_info() {
9356
 
9357
  // Check the WP version.
9358
  global $wp_version;
9359
- $my_version = substr( $wp_version, 0, 3 );
9360
  $eio_debug .= "WP version: $wp_version<br>";
9361
 
9362
  if ( defined( 'PHP_VERSION_ID' ) ) {
14
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
15
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
16
  // TODO: write some tests for AGR.
 
17
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
18
  // TODO: can some of the bulk "fallbacks" be implemented for async processing?
19
  // TODO: check to see if we can use PHP and WP core is_countable functions.
21
  exit;
22
  }
23
 
24
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '510.0' );
25
 
26
  // Initialize a couple globals.
27
  $eio_debug = '';
195
  add_action( 'admin_action_ewww_image_optimizer_view_debug_log', 'ewww_image_optimizer_view_debug_log' );
196
  // Non-AJAX handler to delete the debug log, and reroute back to the settings page.
197
  add_action( 'admin_action_ewww_image_optimizer_delete_debug_log', 'ewww_image_optimizer_delete_debug_log' );
198
+ // Check if WebP option was turned off and is now enabled.
199
+ add_filter( 'pre_update_option_ewww_image_optimizer_webp', 'ewww_image_optimizer_webp_maybe_enabled', 10, 2 );
200
+ // Check if JS WebP option has just been enabled and see if Force WebP is needed for WP Offload Media.
201
+ add_filter( 'pre_update_option_ewww_image_optimizer_webp_for_cdn', 'ewww_image_optimizer_webp_cdn_check_force', 10, 2 );
202
  // Makes sure to flush out any scheduled jobs on deactivation.
203
  register_deactivation_hook( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, 'ewww_image_optimizer_network_deactivate' );
204
  // add_action( 'shutdown', 'ewwwio_memory_output' );.
854
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_invalid_key' );
855
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_invalid_key' );
856
  }
857
+ if ( get_option( 'ewww_image_optimizer_webp_enabled' ) ) {
858
+ add_action( 'admin_notices', 'ewww_image_optimizer_notice_webp_bulk' );
859
+ }
860
  // Prevent ShortPixel AIO messiness.
861
  remove_action( 'admin_notices', 'autoptimizeMain::notice_plug_imgopt' );
862
  if ( class_exists( 'autoptimizeExtra' ) ) {
1011
  ewww_image_optimizer_image_sizes( false );
1012
  return;
1013
  }
1014
+ // Check for Image Regenerate and Select Crop (old way).
1015
+ if ( ! empty( $_REQUEST['action'] ) && 0 === strpos( $_REQUEST['action'], 'sirsc' ) ) {
1016
+ ewwwio_debug_message( 'IRSC action/regen' );
1017
+ ewww_image_optimizer_image_sizes( false );
1018
+ return;
1019
+ }
1020
+ // Check for Image Regenerate and Select Crop (better way).
1021
+ if ( defined( 'DOING_SIRSC' ) && DOING_SIRSC ) {
1022
+ ewwwio_debug_message( 'IRSC action/regen' );
1023
+ ewww_image_optimizer_image_sizes( false );
1024
+ return;
1025
+ }
1026
  }
1027
 
1028
  /**
1131
  } else {
1132
  $retina_path = false;
1133
  }
1134
+ if ( $retina_path && ewwwio_is_file( $retina_path ) ) {
1135
  $ewww_image = new EWWW_Image( $id, 'media', $retina_path );
1136
  $ewww_image->resize = $size . '-retina';
1137
  ewww_image_optimizer( $retina_path );
1520
  delete_option( 'ewww_image_optimizer_exactdn_suspended' );
1521
  }
1522
 
1523
+ /**
1524
+ * Checks to see if the WebP conversion was just enabled.
1525
+ *
1526
+ * @param mixed $new_value The new value, in this case it will be boolean usually.
1527
+ * @param mixed $old_value The old value, also a boolean generally.
1528
+ * @return mixed The new value, unaltered.
1529
+ */
1530
+ function ewww_image_optimizer_webp_maybe_enabled( $new_value, $old_value ) {
1531
+ if ( ! empty( $new_value ) && (bool) $new_value !== (bool) $old_value ) {
1532
+ update_option( 'ewww_image_optimizer_webp_enabled', true );
1533
+ }
1534
+ return $new_value;
1535
+ }
1536
+
1537
+ /**
1538
+ * Checks to see if the JS WebP Rewriting was just enabled and perhaps we should enable Force mode for S3.
1539
+ *
1540
+ * @param mixed $new_value The new value, in this case it will be boolean usually.
1541
+ * @param mixed $old_value The old value, also a boolean generally.
1542
+ * @return mixed The new value, unaltered.
1543
+ */
1544
+ function ewww_image_optimizer_webp_cdn_check_force( $new_value, $old_value ) {
1545
+ if ( ! empty( $new_value ) && (bool) $new_value !== (bool) $old_value ) {
1546
+ if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
1547
+ global $as3cf;
1548
+ if ( $as3cf->get_setting( 'serve-from-s3' ) && $as3cf->get_setting( 'remove-local-file' ) ) {
1549
+ update_option( 'ewww_image_optimizer_webp_force', true );
1550
+ }
1551
+ }
1552
+ }
1553
+ return $new_value;
1554
+ }
1555
+
1556
+ /**
1557
+ * Display a notice that the user should run the bulk optimizer after WebP activation.
1558
+ */
1559
+ function ewww_image_optimizer_notice_webp_bulk() {
1560
+ $already_done = ewww_image_optimizer_aux_images_table_count();
1561
+ if ( $already_done > 50 ) {
1562
+ $message = esc_html__( 'It looks like you already started optimizing your images, you will need to generate WebP images via the Bulk Optimizer.', 'ewww-image-optimizer' );
1563
+ echo "<div id='ewww-image-optimizer-pngout-success' class='notice notice-info'><p><a href='upload.php?page=ewww-image-optimizer-bulk&ewww_webp_only=1&ewww_force=1'>" . $message . '</a></p></div>';
1564
+ } else {
1565
+ $message = esc_html__( 'You may generate WebP images via the Bulk Optimizer.', 'ewww-image-optimizer' );
1566
+ echo "<div id='ewww-image-optimizer-pngout-success' class='notice notice-info'><p><a href='upload.php?page=ewww-image-optimizer-bulk'>" . $message . '</a></p></div>';
1567
+ }
1568
+ delete_option( 'ewww_image_optimizer_webp_enabled' );
1569
+ }
1570
+
1571
  /**
1572
  * Display a success or failure message after PNGOUT installation.
1573
  */
1574
  function ewww_image_optimizer_pngout_installed() {
1575
  if ( 'success' === $_REQUEST['ewww_pngout'] ) {
1576
+ echo "<div id='ewww-image-optimizer-pngout-success' class='notice notice-success fade'>\n" .
1577
  '<p>' . esc_html__( 'Pngout was successfully installed.', 'ewww-image-optimizer' ) . "</p>\n" .
1578
  "</div>\n";
1579
  }
1580
  if ( 'failed' === $_REQUEST['ewww_pngout'] ) {
1581
+ echo "<div id='ewww-image-optimizer-pngout-failure' class='notice notice-error'>\n" .
1582
  '<p>' . sprintf(
1583
  /* translators: 1: An error message 2: The folder where pngout should be installed */
1584
  esc_html__( 'Pngout was not installed: %1$s. Make sure this folder is writable: %2$s', 'ewww-image-optimizer' ),
1946
  // Look for WebP variants and rename them.
1947
  $old_webp = $old_filepath . '.webp';
1948
  $new_webp = $new_filepath . '.webp';
1949
+ if ( ewwwio_is_file( $old_webp ) && ! ewwwio_is_file( $new_webp ) ) {
1950
  ewwwio_debug_message( "renaming $old_webp to $new_webp" );
1951
  rename( $old_webp, $new_webp );
1952
  }
2076
  } else {
2077
  $file_path = $params['file'];
2078
  }
2079
+ if ( ! ewwwio_is_file( $file_path ) || ! filesize( $file_path ) ) {
2080
  clearstatcache();
2081
  return $params;
2082
  }
2093
  $params['url'] = trailingslashit( dirname( $params['url'] ) ) . basename( $new_image );
2094
  }
2095
  $params['type'] = ewww_image_optimizer_mimetype( $new_image, 'i' );
2096
+ if ( ewwwio_is_file( $file_path ) ) {
2097
  unlink( $file_path );
2098
  }
2099
  $file_path = $new_image;
2105
  } else {
2106
  $mime_type = $params['type'];
2107
  }
2108
+ if ( ( ! is_wp_error( $params ) ) && ewwwio_is_file( $file_path ) && in_array( $mime_type, array( 'image/png', 'image/gif', 'image/jpeg' ), true ) ) {
2109
  ewww_image_optimizer_resize_upload( $file_path );
2110
  }
2111
  }
2306
  $resized_image = $editor->resize( 150, 150, true );
2307
  $new_file = $editor->generate_filename();
2308
  echo $new_file;
2309
+ if ( ewwwio_is_file( $new_file ) ) {
2310
  echo '<br>file already exists<br>';
2311
  }
2312
  $saved = $editor->save( $new_file );
2385
  ewwwio_debug_message( "retina path: $retina_path" );
2386
  $webp_path = $temp_path . '.webp';
2387
  ewwwio_debug_message( "retina webp path: $webp_path" );
2388
+ if ( ewwwio_is_file( $webp_path ) ) {
2389
  rename( $webp_path, $retina_path . '.webp' );
2390
  }
2391
  $opt_size = ewww_image_optimizer_filesize( $retina_path );
2790
  );
2791
  continue;
2792
  }
2793
+ $paths_saved[] = trailingslashit( str_replace( 'http://', '', $path ) );
2794
  }
2795
  }
2796
  }
2876
  * @return int The size of the file or zero.
2877
  */
2878
  function ewww_image_optimizer_filesize( $file ) {
2879
+ if ( ewwwio_is_file( $file ) ) {
2880
  // Flush the cache for filesize.
2881
  clearstatcache();
2882
  // Find out the size of the new PNG file.
2886
  }
2887
  }
2888
 
2889
+ /**
2890
+ * Check if file exists, and that is is local rather than using a protocol like http:// or phar://
2891
+ *
2892
+ * @param string $file The path of the file to check.
2893
+ * @return bool True if the file exists and is local, false otherwise.
2894
+ */
2895
+ function ewwwio_is_file( $file ) {
2896
+ if ( false !== strpos( $file, '://' ) ) {
2897
+ return false;
2898
+ }
2899
+ if ( false !== strpos( $file, '../' ) ) {
2900
+ return false;
2901
+ }
2902
+ return is_file( $file );
2903
+ }
2904
  /**
2905
  * Make sure an array/object can be parsed by a foreach().
2906
  *
3161
  file_put_contents( $image['path'] . '.tmp', $result['body'] );
3162
  $new_type = ewww_image_optimizer_mimetype( $image['path'] . '.tmp', 'i' );
3163
  $old_type = '';
3164
+ if ( ewwwio_is_file( $image['path'] ) ) {
3165
  $old_type = ewww_image_optimizer_mimetype( $image['path'], 'i' );
3166
  }
3167
  if ( ! in_array( $new_type, $enabled_types, true ) ) {
3169
  }
3170
  if ( empty( $old_type ) || $old_type === $new_type ) {
3171
  if ( rename( $image['path'] . '.tmp', $image['path'] ) ) {
3172
+ if ( ewwwio_is_file( $image['path'] . '.webp' ) && is_writable( $image['path'] . '.webp' ) ) {
3173
  unlink( $image['path'] . '.webp' );
3174
  }
3175
  // Set the results to nothing.
3212
  if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
3213
  continue;
3214
  }
3215
+ if ( ! empty( $image['path'] ) && ewwwio_is_file( $image['path'] ) ) {
3216
  unlink( $image['path'] );
3217
+ if ( ewwwio_is_file( $image['path'] . '.webp' ) ) {
3218
  unlink( $image['path'] . '.webp' );
3219
  }
3220
  }
3221
  if ( ! empty( $image['converted'] ) ) {
3222
  $image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
3223
  }
3224
+ if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
3225
  unlink( $image['converted'] );
3226
+ if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
3227
  unlink( $image['converted'] . '.webp' );
3228
  }
3229
  }
3243
  // Delete any residual webp versions.
3244
  $webpfile = $filename . '.webp';
3245
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $filename );
3246
+ if ( ewwwio_is_file( $webpfile ) ) {
3247
  unlink( $webpfile );
3248
  }
3249
+ if ( ewwwio_is_file( $webpfileold ) ) {
3250
  unlink( $webpfileold );
3251
  }
3252
  // Retrieve any posts that link the original image.
3253
  $esql = "SELECT ID, post_content FROM $ewwwdb->posts WHERE post_content LIKE '%$filename%' LIMIT 1";
3254
  $rows = $ewwwdb->get_row( $esql );
3255
  // If the original file still exists and no posts contain links to the image.
3256
+ if ( ewwwio_is_file( $file_path ) && empty( $rows ) ) {
3257
  unlink( $file_path );
3258
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3259
  }
3269
  // Delete any residual webp versions.
3270
  $webpfile = $base_dir . $data['file'] . '.webp';
3271
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . $data['file'] );
3272
+ if ( ewwwio_is_file( $webpfile ) ) {
3273
  unlink( $webpfile );
3274
  }
3275
+ if ( ewwwio_is_file( $webpfileold ) ) {
3276
  unlink( $webpfileold );
3277
  }
3278
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['file'] ) ) );
3279
  // If the original resize is set, and still exists.
3280
+ if ( ! empty( $data['orig_file'] ) && ewwwio_is_file( $base_dir . $data['orig_file'] ) ) {
3281
  unset( $srows );
3282
  // Retrieve the filename from the metadata.
3283
  $filename = $data['orig_file'];
3607
  */
3608
  function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $newfile = null, $newtype = null, $fullsize = false, $jpg_fill = '', $jpg_quality = 82 ) {
3609
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3610
+ if ( ! ewwwio_is_file( $file ) || ! is_writable( $file ) || false !== strpos( $file, '..' ) ) {
3611
+ return array( $file, false, 'invalid file', 0, '' );
3612
+ }
3613
  if ( ! ewwwio_check_memory_available( filesize( $file ) * 2.2 ) ) { // 2.2 = upload buffer + download buffer (2) multiplied by a factor of 1.1 for extra wiggle room.
3614
  $memory_required = filesize( $file ) * 2.2;
3615
  ewwwio_debug_message( "possibly insufficient memory for cloud (optimize) operation: $memory_required" );
3673
  if ( 'image/webp' === $newtype ) {
3674
  $webp = 1;
3675
  $jpg_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
3676
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP' ) || ! EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP ) {
3677
+ $lossy = 0;
3678
+ }
3679
  } else {
3680
  $webp = 0;
3681
  }
3959
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
3960
  return false;
3961
  }
3962
+ if ( ! ewwwio_is_file( $file ) || ! is_readable( $file ) || false !== strpos( $file, '..' ) ) {
3963
  return false;
3964
  }
3965
  if ( ! ewwwio_check_memory_available( filesize( $file ) * 1.1 ) ) { // 1.1 = upload buffer (filesize) multiplied by a factor of 1.1 for extra wiggle room.
4662
  return;
4663
  }
4664
  $hidpi_path = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $hidpi_suffix . '.' . $pathinfo['extension'];
4665
+ if ( $validate_file && ! ewwwio_is_file( $hidpi_path ) ) {
4666
  return;
4667
  }
4668
  if ( $return_path ) {
4693
  function ewww_image_optimizer_s3_uploads_image_cleanup( $file ) {
4694
  global $s3_uploads_image;
4695
  if ( ! ewww_image_optimizer_stream_wrapped( $file ) && strpos( $file, 's3-uploads' ) === false && ! empty( $s3_uploads_image ) ) {
4696
+ if ( ewwwio_is_file( $file ) ) {
4697
  unlink( $file );
4698
  }
4699
  $file = $s3_uploads_image;
4936
  } // End if().
4937
  } // End if().
4938
  clearstatcache();
4939
+ if ( ! empty( $filename ) && ewwwio_is_file( $filename ) ) {
4940
  return $filename;
4941
  } else {
4942
  return false;
5207
  */
5208
  function ewww_image_optimizer_noresize( $dimensions, $filename ) {
5209
  if ( strpos( $filename, 'noresize' ) !== false ) {
5210
+ add_filter( 'big_image_size_threshold', '__return_false' );
5211
  return array( 0, 0 );
5212
  }
5213
  $ignore_folders = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' );
5273
  if ( ! $file ) {
5274
  return false;
5275
  }
5276
+ if ( ! empty( $_REQUEST['ewww_webp_only'] ) ) {
5277
+ return false;
5278
+ }
5279
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
5280
  wp_raise_memory_limit( 'image' );
5281
  }
5496
  }
5497
  return array( $newwidth, $newheight );
5498
  } // End if().
5499
+ if ( ewwwio_is_file( $new_file ) ) {
5500
  ewwwio_debug_message( "resizing did not create a smaller image: $new_size" );
5501
  unlink( $new_file );
5502
  }
5749
  */
5750
  function ewww_image_optimizer_rebuild_meta( $attachment_id ) {
5751
  $file = get_attached_file( $attachment_id );
5752
+ if ( ewwwio_is_file( $file ) ) {
5753
  global $ewww_preempt_editor;
5754
  $ewww_preempt_editor = true;
5755
  remove_all_filters( 'wp_generate_attachment_metadata' );
5844
  if ( ! $new_image && class_exists( 'Amazon_S3_And_CloudFront' ) && ewww_image_optimizer_stream_wrapped( $file_path ) ) {
5845
  ewww_image_optimizer_check_table_as3cf( $meta, $id, $file_path );
5846
  }
5847
+ if ( ! ewwwio_is_file( $file_path ) && class_exists( 'wpCloud\StatelessMedia\EWWW' ) && ! empty( $meta['gs_link'] ) ) {
5848
  $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
5849
  }
5850
  // If the local file is missing and we have valid metadata, see if we can fetch via CDN.
5851
+ if ( ! ewwwio_is_file( $file_path ) || ( ewww_image_optimizer_stream_wrapped( $file_path ) && ! class_exists( 'S3_Uploads' ) ) ) {
5852
  $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
5853
  if ( ! $file_path ) {
5854
  ewwwio_debug_message( 'could not retrieve path' );
6034
  $base_dir = trailingslashit( dirname( $file_path ) );
6035
  $image_path = $base_dir . $data['file'];
6036
  $ims_path = $base_ims_dir . $data['file'];
6037
+ if ( ewwwio_is_file( $ims_path ) ) {
6038
  ewwwio_debug_message( 'ims resize already exists, wahoo' );
6039
  ewwwio_debug_message( "ims path: $ims_path" );
6040
  $image_size = ewww_image_optimizer_filesize( $ims_path );
6071
  $size = 'pdf-full';
6072
  ewwwio_debug_message( 'processing full size pdf preview' );
6073
  }
6074
+ if ( $parallel_opt && ewwwio_is_file( $resize_path ) ) {
6075
  $parallel_sizes[ $size ] = $resize_path;
6076
  } else {
6077
  $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
6078
  $ewww_image->resize = $size;
6079
  // Run the optimization and store the results.
6080
+ ewww_image_optimizer( $resize_path );
6081
  }
6082
  // Optimize retina images, if they exist.
6083
  if ( function_exists( 'wr2x_get_retina' ) ) {
6085
  } else {
6086
  $retina_path = false;
6087
  }
6088
+ if ( $retina_path && ewwwio_is_file( $retina_path ) ) {
6089
  if ( $parallel_opt ) {
6090
  $async_path = str_replace( $upload_path, '', $retina_path );
6091
  $ewwwio_async_optimize_media->data(
6115
  ewwwio_debug_message( 'processing original_image' );
6116
  // Meta sizes don't contain a path, so we calculate one.
6117
  $resize_path = trailingslashit( dirname( $file_path ) ) . $meta['original_image'];
6118
+ if ( $parallel_opt && ewwwio_is_file( $resize_path ) ) {
6119
  $parallel_sizes['original_image'] = $resize_path;
6120
  } else {
6121
  $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
6122
  $ewww_image->resize = 'original_image';
6123
+ // Run the optimization and store the results (gallery type 5 and fullsize=true to obey lossy/metadata exclusions).
6124
+ ewww_image_optimizer( $resize_path, 5, false, false, true );
6125
  }
6126
  } // End if().
6127
 
6131
  $imagemeta_resize_path = '';
6132
  foreach ( $meta['image_meta']['resized_images'] as $imagemeta_resize ) {
6133
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
6134
+ if ( $parallel_opt && ewwwio_is_file( $imagemeta_resize_path ) ) {
6135
  $async_path = str_replace( $upload_path, '', $imagemeta_resize_path );
6136
  $ewwwio_async_optimize_media->data(
6137
  array(
6219
  while ( $parallel_opt && $processing ) {
6220
  $processing = false;
6221
  foreach ( $processing_sizes as $size => $filename ) {
6222
+ if ( ewwwio_is_file( $filename . '.processing' ) ) {
6223
  ewwwio_debug_message( "still processing $size" );
6224
  $processing = true;
6225
  continue;
6243
  }
6244
  if ( $timer > $timer_max ) {
6245
  foreach ( $processing_sizes as $filename ) {
6246
+ if ( ewwwio_is_file( $filename . '.processing' ) ) {
6247
  unlink( $filename . '.processing' );
6248
  }
6249
  }
6336
  function ewww_image_optimizer_lr_sync_update( $meta, $id = null ) {
6337
  update_option( 'ewww_image_optimizer_lr_sync', true, false );
6338
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
6339
+ if ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! ewwwio_is_file( $file_path ) ) {
6340
  return $meta;
6341
  }
6342
  ewwwio_debug_message( "retrieved file path: $file_path" );
6406
  function ewww_image_optimizer_as3cf_attachment_file_paths( $paths, $id ) {
6407
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6408
  foreach ( $paths as $size => $path ) {
6409
+ if ( is_string( $path ) && ewwwio_is_file( $path . '.webp' ) ) {
6410
  $paths[ $size . '-webp' ] = $path . '.webp';
6411
  ewwwio_debug_message( "added $path.webp to as3cf queue" );
6412
  }
6421
  */
6422
  function ewww_image_optimizer_as3cf_object_meta( $args ) {
6423
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6424
+ if ( ! empty( $args['SourceFile'] ) && ewwwio_is_file( $args['SourceFile'] ) && empty( $args['ContentType'] ) && false !== strpos( $args['SourceFile'], '.webp' ) ) {
6425
  $args['ContentType'] = ewww_image_optimizer_quick_mimetype( $args['SourceFile'] );
6426
  }
6427
  return $args;
6573
  ! ewww_image_optimizer_stream_wrapped( $filtered_file_path ) ||
6574
  ewww_image_optimizer_stream_wrapper_exists()
6575
  )
6576
+ && ewwwio_is_file( $filtered_file_path )
6577
  ) {
6578
  return array( str_replace( '//_imsgalleries/', '/_imsgalleries/', $filtered_file_path ), $upload_path );
6579
  }
6583
  ! ewww_image_optimizer_stream_wrapped( $file_path ) ||
6584
  ewww_image_optimizer_stream_wrapper_exists()
6585
  )
6586
+ && ewwwio_is_file( $file_path )
6587
  ) {
6588
  return array( str_replace( '//_imsgalleries/', '/_imsgalleries/', $file_path ), $upload_path );
6589
  }
6590
  if ( 'ims_image' === get_post_type( $id ) && is_array( $meta ) && ! empty( $meta['file'] ) ) {
6591
  ewwwio_debug_message( "finding path for IMS image: $id " );
6592
+ if ( is_dir( $file_path ) && ewwwio_is_file( $file_path . $meta['file'] ) ) {
6593
  // Generate the absolute path.
6594
  $file_path = $file_path . $meta['file'];
6595
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
6596
  ewwwio_debug_message( "found path for IMS image: $file_path" );
6597
+ } elseif ( ewwwio_is_file( $meta['file'] ) ) {
6598
  $file_path = $meta['file'];
6599
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
6600
  ewwwio_debug_message( "found path for IMS image: $file_path" );
6614
  return array( '', $upload_path );
6615
  }
6616
  ewwwio_debug_message( "looking for file at $file_path" );
6617
+ if ( ewwwio_is_file( $file_path ) ) {
6618
  return array( $file_path, $upload_path );
6619
  }
6620
  $file_path = trailingslashit( $upload_path ) . $file_path;
6621
  ewwwio_debug_message( "that did not work, try it with the upload_dir: $file_path" );
6622
+ if ( ewwwio_is_file( $file_path ) ) {
6623
  return array( $file_path, $upload_path );
6624
  }
6625
  $upload_path = trailingslashit( WP_CONTENT_DIR ) . 'uploads/';
6626
  $file_path = $upload_path . $meta['file'];
6627
  ewwwio_debug_message( "one last shot, using the wp-content/ constant: $file_path" );
6628
+ if ( ewwwio_is_file( $file_path ) ) {
6629
  return array( $file_path, $upload_path );
6630
  }
6631
  }
6748
  function ewww_image_optimizer_unique_filename( $file, $fileext ) {
6749
  // Strip the file extension.
6750
  $filename = preg_replace( '/\.\w+$/', '', $file );
6751
+ if ( ! ewwwio_is_file( $filename . $fileext ) ) {
6752
  return array( $filename . $fileext, '' );
6753
  }
6754
  // Set the increment to 1 (but allow the user to override it).
6789
  case 'pdf':
6790
  return 'application/pdf';
6791
  default:
6792
+ if ( empty( $pathextension ) && ! ewww_image_optimizer_stream_wrapped( $path ) && ewwwio_is_file( $path ) ) {
6793
  return ewww_image_optimizer_mimetype( $path, 'i' );
6794
  }
6795
  return false;
6804
  */
6805
  function ewww_image_optimizer_png_alpha( $filename ) {
6806
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6807
+ if ( ! ewwwio_is_file( $filename ) ) {
6808
+ return false;
6809
+ }
6810
+ if ( false !== strpos( $filename, '..' ) ) {
6811
  return false;
6812
  }
6813
  // Determine what color type is stored in the file.
6850
  */
6851
  function ewww_image_optimizer_is_animated( $filename ) {
6852
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6853
+ if ( ! ewwwio_is_file( $filename ) ) {
6854
  return false;
6855
  }
6856
  // If we can't open the file in read-only buffered mode.
7207
  $output .= $msg;
7208
  }
7209
  $restorable = false;
7210
+ if ( $converted && ewwwio_is_file( $converted ) ) {
7211
  $restorable = true;
7212
  }
7213
  if ( $restorable && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
7238
  $sizes_to_opt
7239
  ) . '</div>';
7240
  } else {
7241
+ $output .= '<div>' . esc_html__( 'Not optimized', 'ewww-image-optimizer' ) . '</div>';
7242
  }
7243
  // Tell them the filesize.
7244
  $output .= '<div>' . sprintf(
7246
  esc_html__( 'Image Size: %s', 'ewww-image-optimizer' ),
7247
  $file_size
7248
  ) . '</div>';
7249
+ // Determine filepath for webp.
7250
+ $webpfile = $file_path . '.webp';
7251
+ $webp_size = ewww_image_optimizer_filesize( $webpfile );
7252
+ if ( $webp_size ) {
7253
+ // Get a human readable filesize.
7254
+ $webp_size = ewww_image_optimizer_size_format( $webp_size );
7255
+ $webpurl = esc_url( wp_get_attachment_url( $id ) . '.webp' );
7256
+ $output .= "<div>WebP: <a href='$webpurl'>$webp_size</a></div>";
7257
+ }
7258
  if ( empty( $msg ) && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
7259
  // Give the user the option to optimize the image right now.
7260
  $output .= sprintf( "<div><a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>", $id, esc_html__( 'Optimize now!', 'ewww-image-optimizer' ) );
7498
  return $meta;
7499
  }
7500
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
7501
+ if ( ! ewwwio_is_file( $file_path ) && ( class_exists( 'WindowsAzureStorageUtil' ) || class_exists( 'Amazon_S3_And_CloudFront' ) ) ) {
7502
  // Construct a $file_path and proceed IF a supported CDN plugin is installed.
7503
  $file_path = get_attached_file( $id );
7504
  if ( ! $file_path ) {
7887
  return array( $total_opt, $total_orig );
7888
  }
7889
 
7890
+ /**
7891
+ * Manually verify if WebP rewriting is working.
7892
+ *
7893
+ * Requests the test.png and checks to see if it is actually of type image/webp.
7894
+ *
7895
+ * @return bool True if the test image is WebP, false otherwise.
7896
+ */
7897
+ function ewww_image_optimizer_test_webp_mime_verify() {
7898
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
7899
+ $test_url = plugins_url( '/images/test.png', __FILE__ ) . '?m=' . time();
7900
+ add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
7901
+ $test_result = wp_remote_get( $test_url, array( 'headers' => 'Accept: image/webp' ) );
7902
+ if ( is_wp_error( $test_result ) ) {
7903
+ $error_message = $test_result->get_error_message();
7904
+ ewwwio_debug_message( "webp verification request failed: $error_message" );
7905
+ return false;
7906
+ } elseif ( ! empty( $test_result['body'] ) && strlen( $test_result['body'] ) > 300 ) {
7907
+ if (
7908
+ 200 === (int) $test_result['response']['code'] &&
7909
+ '52494646' === bin2hex( substr( $test_result['body'], 0, 4 ) )
7910
+ ) {
7911
+ ewwwio_debug_message( 'webp (real-world) verification succeeded' );
7912
+ return true;
7913
+ }
7914
+ ewwwio_debug_message( 'webp mime check failed: ' . bin2hex( substr( $test_result['body'], 0, 3 ) ) );
7915
+ }
7916
+ if ( ! empty( $test_result['response']['code'] ) && 200 !== (int) $test_result['response']['code'] ) {
7917
+ ewwwio_debug_message( 'received response code: ' . $test_result['response']['code'] );
7918
+ }
7919
+ return false;
7920
+ }
7921
+
7922
  /**
7923
  * Figure out where the .htaccess file should live.
7924
  *
7931
  ewwwio_debug_message( 'WordPress Address and Site Address are different, possible subdir install' );
7932
  $path_diff = str_replace( get_option( 'home' ), '', get_option( 'siteurl' ) );
7933
  $newhtpath = trailingslashit( rtrim( $htpath, '/' ) . '/' . ltrim( $path_diff, '/' ) ) . '.htaccess';
7934
+ if ( ewwwio_is_file( $newhtpath ) ) {
7935
  ewwwio_debug_message( 'subdir install confirmed' );
7936
  ewwwio_debug_message( "using $newhtpath" );
7937
  return $newhtpath;
8037
  /**
8038
  * Extracts strings from between the BEGIN and END markers in the .htaccess file.
8039
  *
8040
+ * @global int $wp_version
8041
+ *
8042
  * @param string $filename The file within which to search.
8043
  * @param string $marker The bounary marker of the desired content.
8044
  * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers.
8173
  * Displays the EWWW IO options along with status information, and debugging information.
8174
  *
8175
  * @global string $eio_debug In memory debug log.
8176
+ * @global int $wp_version
8177
  *
8178
  * @param string $network Indicates which options should be shown in multisite installations.
8179
  */
8180
  function ewww_image_optimizer_options( $network = 'singlesite' ) {
8181
+ global $wp_version;
8182
  global $ewwwio_temp_debug;
8183
  global $content_width;
8184
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
8822
  esc_html__( 'Optimize the original version of images that have been scaled down by WordPress.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8823
  ewwwio_debug_message( 'include originals: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_originals' ) ? 'on' : 'off' ) );
8824
  $aux_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ) ) : '';
8825
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_aux_paths'>" . esc_html__( 'Folders to Optimize', 'ewww-image-optimizer' ) . '</label>'
8826
+ . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . '</th><td>' .
8827
  /* translators: %s: the folder where WordPress is installed */
8828
  sprintf( esc_html__( 'One path per line, must be within %s. Use full paths, not relative paths.', 'ewww-image-optimizer' ), ABSPATH ) . "<br>\n" .
8829
  "<textarea id='ewww_image_optimizer_aux_paths' name='ewww_image_optimizer_aux_paths' rows='3' cols='60'>$aux_paths</textarea>\n" .
8972
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . '</label>' .
8973
  ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
8974
  "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp' name='ewww_image_optimizer_webp' value='true' " .
8975
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ? "checked='true'" : '' ) . ' /> ' .
8976
+ esc_html__( 'JPG to WebP conversion is lossy, but quality loss is minimal. PNG to WebP conversion is lossless unless premium compression is active.', 'ewww-image-optimizer' ) .
8977
  "</span>\n<p class='description'>" . esc_html__( 'Originals are never deleted, and WebP images should only be served to supported browsers.', 'ewww-image-optimizer' ) .
8978
+ " <a href='#ewww-webp-rewrite'>" . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? esc_html__( 'You can use the rewrite rules below to serve WebP images with Apache.', 'ewww-image-optimizer' ) : '' ) . "</a></td></tr>\n";
8979
  ewwwio_debug_message( 'webp conversion: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ? 'on' : 'off' ) );
 
 
 
 
 
 
8980
  }
8981
  if ( ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
 
 
 
 
 
 
 
8982
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_for_cdn'>" .
8983
  esc_html__( 'JS WebP Rewriting', 'ewww-image-optimizer' ) .
8984
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89,59443d162c7d3a0747cdf9f0' ) .
8985
+ "</th><td><input type='checkbox' id='ewww_image_optimizer_webp_for_cdn' name='ewww_image_optimizer_webp_for_cdn' value='true' " .
8986
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? "checked='true'" : '' ) . ' /> ' .
8987
  esc_html__( 'Use this if the Apache rewrite rules do not work, or if your images are served from a CDN.', 'ewww-image-optimizer' ) . ' ' .
8988
+ '</td></tr>';
 
8989
  ewwwio_debug_message( 'alt webp rewriting: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? 'on' : 'off' ) );
8990
+ $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
8991
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label>' .
8992
+ ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) . '</th><td><span>' .
8993
+ esc_html__( 'Enter additional URL patterns, like a CDN URL, that should be permitted for JS WebP Rewriting. One URL per line, must include the domain name (cdn.example.com).', 'ewww-image-optimizer' ) . '</span>' .
8994
+ '<p>' . esc_html__( 'Optionally include a folder with the URL if your CDN path is different from your local path.', 'ewww-image-optimizer' ) . '</p>' .
8995
+ "<textarea id='ewww_image_optimizer_webp_paths' name='ewww_image_optimizer_webp_paths' rows='3' cols='60'>$webp_paths</textarea>" .
8996
+ "<p class='description'>" . sprintf(
8997
+ /* translators: 1: An image URL on a CDN 2: An image URL 3: An example folder URL */
8998
+ esc_html__( 'For example, with a CDN URL of %1$s and a local URL of %2$s you would enter %3$s.', 'ewww-image-optimizer' ),
8999
+ 'https://cdn.example.com/<strong>files/</strong>2038/01/image.jpg',
9000
+ 'https://example.com/<strong>wp-content/uploads/</strong>2038/01/image.jpg',
9001
+ 'https://cdn.example.com/<strong>files/</strong>'
9002
+ ) . '</p>' .
9003
+ "</td></tr>\n";
9004
+ ewwwio_debug_message( 'webp paths:' );
9005
+ ewwwio_debug_message( $webp_paths );
9006
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
9007
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by ExactDN.', 'ewww-image-optimizer' ) . '</p></td></tr>';
9008
  } elseif ( get_option( 'easyio_exactdn' ) ) {
9009
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by Easy Image Optimizer.', 'ewww-image-optimizer' ) . '</p></td></tr>';
9010
  }
9011
+ if ( ! ewww_image_optimizer_easy_active() || ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
9012
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_force'>" . esc_html__( 'Force WebP', 'ewww-image-optimizer' ) . '</label>' .
9013
+ ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
9014
+ "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_force' name='ewww_image_optimizer_webp_force' value='true' " .
9015
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ? "checked='true'" : '' ) . ' /> ' .
9016
+ esc_html__( 'WebP images will be generated and saved for all JPG/PNG images regardless of their size. The JS WebP Rewriting will not check if a file exists, only that the domain matches the home url, or one of the provided WebP URLs.', 'ewww-image-optimizer' ) . "</span></td></tr>\n";
9017
+ ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ? 'on' : 'off' ) );
9018
+ }
9019
  $output[] = "</table>\n</div>\n";
9020
 
9021
  $output[] = "<div id='ewww-support-settings'>\n";
9066
  ewww_image_optimizer_webp_rewrite_verify();
9067
  }
9068
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
9069
+ if ( defined( 'PHP_SAPI' ) && false === strpos( PHP_SAPI, 'apache' ) && false === strpos( PHP_SAPI, 'litespeed' ) ) {
9070
+ ewwwio_debug_message( 'PHP module: ' . PHP_SAPI );
9071
+ $false_positive_headers = esc_html( 'This may be a false positive. If so, the warning should go away once you implement the rewrite rules.' );
9072
+ }
9073
+ $header_error = '';
9074
  if ( ! apache_mod_loaded( 'mod_rewrite' ) ) {
9075
  ewwwio_debug_message( 'webp missing mod_rewrite' );
9076
  /* translators: %s: mod_rewrite or mod_headers */
9077
+ $header_error = '<p><strong>' . sprintf( esc_html( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.' ), 'mod_rewrite' ) . "</strong><br>$false_positive_headers</p>\n";
9078
  }
9079
  if ( ! apache_mod_loaded( 'mod_headers' ) ) {
9080
  /* translators: %s: mod_rewrite or mod_headers */
9081
+ $header_error = '<p><strong>' . sprintf( esc_html( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.' ), 'mod_headers' ) . "</strong><br>$false_positive_headers</p>\n";
9082
  ewwwio_debug_message( 'webp missing mod_headers' );
9083
  }
9084
+
9085
+ $webp_verified = ewww_image_optimizer_test_webp_mime_verify();
9086
+ if ( ! $webp_verified ) {
9087
+ $output[] = $header_error;
9088
+ }
9089
+
9090
  $output[] = "<form id='ewww-webp-rewrite'>\n";
9091
  $output[] = '<p>' . esc_html__( 'There are many ways to serve WebP images to visitors with supported browsers. You may choose any you wish, but it is recommended to serve them with an .htaccess file using mod_rewrite and mod_headers. The plugin can insert the rules for you if the file is writable, or you can edit .htaccess yourself.', 'ewww-image-optimizer' ) . "</p>\n";
9092
+
9093
+ if ( $webp_verified || ! ewww_image_optimizer_webp_rewrite_verify() ) {
9094
+ $output[] = "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . '?m=' . time() . "' style='float: right; padding: 0 0 10px 10px;'>\n" .
9095
  "<p id='ewww-webp-rewrite-status'><b>" . esc_html__( 'Rules verified successfully', 'ewww-image-optimizer' ) . "</b></p>\n" .
9096
  "<button type='button' id='ewww-webp-remove' class='button-secondary action'>" . esc_html__( 'Remove Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
9097
  ewwwio_debug_message( 'webp .htaccess rewriting enabled' );
9109
  "Header append Vary Accept env=REDIRECT_accept\n" .
9110
  "&lt;/IfModule&gt;\n" .
9111
  "AddType image/webp .webp</pre>\n" .
9112
+ "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . '?m=' . time() . "' style='float: right; padding-left: 10px;'>\n" .
9113
  "<p id='ewww-webp-rewrite-status'>" . esc_html__( 'The image to the right will display a WebP image with WEBP in white text, if your site is serving WebP images and your browser supports WebP.', 'ewww-image-optimizer' ) . "</p>\n" .
9114
  "<button type='button' id='ewww-webp-insert' class='button-secondary action'>" . esc_html__( 'Insert Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
9115
  ewwwio_debug_message( 'webp .htaccess rules not detected' );
9151
  global $eio_debug;
9152
  if ( ! empty( $eio_debug ) ) {
9153
  $debug_output = '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
9154
+ if ( ewwwio_is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
9155
  $debug_output .= "&emsp;<a href='admin.php?action=ewww_image_optimizer_view_debug_log'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
9156
  }
9157
  $debug_output .= '</p>';
9478
  if ( false === current_user_can( $permissions ) ) {
9479
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
9480
  }
9481
+ if ( ewwwio_is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
9482
  ewwwio_ob_clean();
9483
  header( 'Content-Type: text/plain;charset=UTF-8' );
9484
  readfile( WP_CONTENT_DIR . '/ewww/debug.log' );
9495
  if ( false === current_user_can( $permissions ) ) {
9496
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
9497
  }
9498
+ if ( ewwwio_is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
9499
  unlink( WP_CONTENT_DIR . '/ewww/debug.log' );
9500
  }
9501
  $sendback = wp_get_referer();
9519
 
9520
  // Check the WP version.
9521
  global $wp_version;
 
9522
  $eio_debug .= "WP version: $wp_version<br>";
9523
 
9524
  if ( defined( 'PHP_VERSION_ID' ) ) {
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: 5.0.0
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: 5.1.0
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
includes/eio.js CHANGED
@@ -71,6 +71,9 @@ jQuery(document).ready(function($) {
71
  }
72
  HSregister();
73
  if (!ewww_vars.scan_fail) {
 
 
 
74
  $('#ewww-webp-rewrite #ewww-webp-insert').click(function() {
75
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
76
  var ewww_webp_rewrite_data = {
@@ -80,7 +83,7 @@ jQuery(document).ready(function($) {
80
  $.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
81
  $('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
82
  ewww_webp_image = document.getElementById("webp-image").src;
83
- document.getElementById("webp-image").src = ewww_webp_image + '?m=' + new Date().getTime();
84
  });
85
  return false;
86
  });
@@ -93,7 +96,7 @@ jQuery(document).ready(function($) {
93
  $.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
94
  $('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
95
  ewww_webp_image = document.getElementById("webp-image").src;
96
- document.getElementById("webp-image").src = ewww_webp_image + '?m' + new Date().getTime();
97
  });
98
  return false;
99
  });
@@ -257,6 +260,7 @@ jQuery(document).ready(function($) {
257
  var ewww_k = 0;
258
  var ewww_import_total = 0;
259
  var ewww_force = 0;
 
260
  var ewww_delay = 0;
261
  var ewww_batch_limit = 0;
262
  var ewww_aux = false;
@@ -308,18 +312,17 @@ jQuery(document).ready(function($) {
308
  });
309
  $('#ewww-aux-start').submit(function() {
310
  ewww_aux = true;
311
- //ewww_init_action = 'bulk_init';
312
- //ewww_loop_action = 'bulk_aux_images_loop';
313
- //ewww_cleanup_action = 'bulk_aux_images_cleanup';
314
  if ($('#ewww-force:checkbox:checked').val()) {
315
  ewww_force = 1;
316
  }
 
 
 
317
  $('#ewww-aux-start').hide();
318
  $('.ewww-bulk-info').hide();
319
  $('.ewww-aux-table').hide();
320
  $('#ewww-show-table').hide();
321
  $('#ewww-scanning').show();
322
- //ewww_vars.scanning = $('#ewww-scanning').html();
323
  ewwwStartScan();
324
  return false;
325
  });
@@ -327,6 +330,7 @@ jQuery(document).ready(function($) {
327
  var ewww_scan_data = {
328
  action: ewww_scan_action,
329
  ewww_force: ewww_force,
 
330
  ewww_scan: true,
331
  ewww_wpnonce: ewww_vars._wpnonce,
332
  };
@@ -472,13 +476,17 @@ jQuery(document).ready(function($) {
472
  if ($('#ewww-force:checkbox:checked').val()) {
473
  ewww_force = 1;
474
  }
 
 
 
475
  var ewww_loop_data = {
476
- action: ewww_loop_action,
477
  ewww_wpnonce: ewww_vars._wpnonce,
478
  ewww_force: ewww_force,
 
479
  ewww_batch_limit: ewww_batch_limit,
480
  ewww_error_counter: ewww_error_counter,
481
- };
482
  var ewww_jqxhr = $.post(ajaxurl, ewww_loop_data, function(response) {
483
  var is_json = true;
484
  try {
@@ -500,6 +508,14 @@ jQuery(document).ready(function($) {
500
  ewww_i += ewww_response.completed;
501
  $('#ewww-bulk-progressbar').progressbar( "option", "value", ewww_i );
502
  $('#ewww-bulk-counter').html(ewww_vars.optimized + ' ' + ewww_i + '/' + ewww_attachments);
 
 
 
 
 
 
 
 
503
  if ( ewww_response.error ) {
504
  $('#ewww-bulk-loading').append('<p style="color: red"><b>' + ewww_response.error + '</b></p>');
505
  clearInterval(ewww_quota_update);
@@ -608,6 +624,7 @@ jQuery(document).ready(function($) {
608
  ewww_aux = false;
609
  ewww_i = 0;
610
  ewww_force = 0;
 
611
  }
612
  }
613
  function ewwwCountDown() {
71
  }
72
  HSregister();
73
  if (!ewww_vars.scan_fail) {
74
+ function removeQueryArg(url) {
75
+ return url.split('?')[0];
76
+ }
77
  $('#ewww-webp-rewrite #ewww-webp-insert').click(function() {
78
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
79
  var ewww_webp_rewrite_data = {
83
  $.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
84
  $('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
85
  ewww_webp_image = document.getElementById("webp-image").src;
86
+ document.getElementById("webp-image").src = removeQueryArg(ewww_webp_image) + '?m=' + new Date().getTime();
87
  });
88
  return false;
89
  });
96
  $.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
97
  $('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
98
  ewww_webp_image = document.getElementById("webp-image").src;
99
+ document.getElementById("webp-image").src = removeQueryArg(ewww_webp_image) + '?m' + new Date().getTime();
100
  });
101
  return false;
102
  });
260
  var ewww_k = 0;
261
  var ewww_import_total = 0;
262
  var ewww_force = 0;
263
+ var ewww_webp_only = 0;
264
  var ewww_delay = 0;
265
  var ewww_batch_limit = 0;
266
  var ewww_aux = false;
312
  });
313
  $('#ewww-aux-start').submit(function() {
314
  ewww_aux = true;
 
 
 
315
  if ($('#ewww-force:checkbox:checked').val()) {
316
  ewww_force = 1;
317
  }
318
+ if ($('#ewww-webp-only:checkbox:checked').val()) {
319
+ ewww_webp_only = 1;
320
+ }
321
  $('#ewww-aux-start').hide();
322
  $('.ewww-bulk-info').hide();
323
  $('.ewww-aux-table').hide();
324
  $('#ewww-show-table').hide();
325
  $('#ewww-scanning').show();
 
326
  ewwwStartScan();
327
  return false;
328
  });
330
  var ewww_scan_data = {
331
  action: ewww_scan_action,
332
  ewww_force: ewww_force,
333
+ ewww_webp_only: ewww_webp_only,
334
  ewww_scan: true,
335
  ewww_wpnonce: ewww_vars._wpnonce,
336
  };
476
  if ($('#ewww-force:checkbox:checked').val()) {
477
  ewww_force = 1;
478
  }
479
+ if ($('#ewww-webp-only:checkbox:checked').val()) {
480
+ ewww_webp_only = 1;
481
+ }
482
  var ewww_loop_data = {
483
+ action: ewww_loop_action,
484
  ewww_wpnonce: ewww_vars._wpnonce,
485
  ewww_force: ewww_force,
486
+ ewww_webp_only: ewww_webp_only,
487
  ewww_batch_limit: ewww_batch_limit,
488
  ewww_error_counter: ewww_error_counter,
489
+ };
490
  var ewww_jqxhr = $.post(ajaxurl, ewww_loop_data, function(response) {
491
  var is_json = true;
492
  try {
508
  ewww_i += ewww_response.completed;
509
  $('#ewww-bulk-progressbar').progressbar( "option", "value", ewww_i );
510
  $('#ewww-bulk-counter').html(ewww_vars.optimized + ' ' + ewww_i + '/' + ewww_attachments);
511
+ if ( ewww_response.update_meta ) {
512
+ var ewww_updatemeta_data = {
513
+ action: 'ewww_bulk_update_meta',
514
+ attachment_id: ewww_response.update_meta,
515
+ ewww_wpnonce: ewww_vars._wpnonce,
516
+ };
517
+ $.post(ajaxurl, ewww_updatemeta_data);
518
+ }
519
  if ( ewww_response.error ) {
520
  $('#ewww-bulk-loading').append('<p style="color: red"><b>' + ewww_response.error + '</b></p>');
521
  clearInterval(ewww_quota_update);
624
  ewww_aux = false;
625
  ewww_i = 0;
626
  ewww_force = 0;
627
+ ewww_webp_only = 0;
628
  }
629
  }
630
  function ewwwCountDown() {
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: optimize, image, convert, webp, resize, compress, lazy load, optimization,
5
  Requires at least: 5.0
6
  Tested up to: 5.3
7
  Requires PHP: 5.6
8
- Stable tag: 5.0.0
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.
@@ -173,6 +173,20 @@ https://developers.google.com/web/tools/lighthouse/audits/optimize-images
173
  * Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
174
  * 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/
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  = 5.0.0 =
177
  * added: use native lazy load attributes to supplement lazy loader and make placeholders more efficient
178
  * added: GCS sub-folder rewriting with ExactDN for cleaner URLs
5
  Requires at least: 5.0
6
  Tested up to: 5.3
7
  Requires PHP: 5.6
8
+ Stable tag: 5.1.0
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.
173
  * Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
174
  * 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/
175
 
176
+ = 5.1.0 =
177
+ * added: WebP-only mode for Bulk Optimizer
178
+ * added: JS WebP Rewriting for pull-mode CDNs via WebP URLS without Force WebP
179
+ * added: JS WebP Rewriting zero-conf for WP Offload Media
180
+ * added: force lossy PNG to WebP conversion with EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP override (set to true)
181
+ * changed: bulk optimizer runs wp_update_attachment_metadata() in separate request to avoid timeouts
182
+ * fixed: WebP warning regarding missing modules displayed even if green WebP test image is working
183
+ * fixed: Nextgen bulk actions not working
184
+ * fixed: unable to regenerate existing thumbnails with Image Regenerate & Select Crop plugin
185
+ * updated: WebP (cwebp) binary to version 1.0.3
186
+ * updated: Pngquant binary to version 2.12.5
187
+ * updated: cwebp requires Mac OS X 10.14
188
+ * updated: FreeBSD 10 is EOL, version 11 is the supported/tested version
189
+
190
  = 5.0.0 =
191
  * added: use native lazy load attributes to supplement lazy loader and make placeholders more efficient
192
  * added: GCS sub-folder rewriting with ExactDN for cleaner URLs
tests/test-convert.php CHANGED
@@ -328,13 +328,13 @@ class EWWWIO_Convert_Tests extends WP_UnitTestCase {
328
  * Cleans up the temp images.
329
  */
330
  public static function tearDownAfterClass() {
331
- if ( is_file( self::$test_jpg ) ) {
332
  unlink( self::$test_jpg );
333
  }
334
- if ( is_file( self::$test_png ) ) {
335
  unlink( self::$test_png );
336
  }
337
- if ( is_file( self::$test_gif ) ) {
338
  unlink( self::$test_gif );
339
  }
340
  ewww_image_optimizer_remove_binaries();
328
  * Cleans up the temp images.
329
  */
330
  public static function tearDownAfterClass() {
331
+ if ( ewwwio_is_file( self::$test_jpg ) ) {
332
  unlink( self::$test_jpg );
333
  }
334
+ if ( ewwwio_is_file( self::$test_png ) ) {
335
  unlink( self::$test_png );
336
  }
337
+ if ( ewwwio_is_file( self::$test_gif ) ) {
338
  unlink( self::$test_gif );
339
  }
340
  ewww_image_optimizer_remove_binaries();
tests/test-optimize.php CHANGED
@@ -139,8 +139,8 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
139
  update_site_option( 'ewww_image_optimizer_webp', '' );
140
  $this->assertEquals( 1348837, filesize( $results[0] ) );
141
  unlink( $results[0] );
142
- $this->assertEquals( 319938, filesize( $results[0] . '.webp' ) );
143
- if ( is_file( $results[0] . '.webp' ) ) {
144
  unlink( $results[0] . '.webp' );
145
  }
146
  }
@@ -166,8 +166,8 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
166
  $this->assertEquals( ewww_image_optimizer_get_orientation( $results[0], 'image/jpeg' ), 1 );
167
  unlink( $results[0] );
168
  // size of webp with meta.
169
- $this->assertEquals( 339520, filesize( $results[0] . '.webp' ) );
170
- if ( is_file( $results[0] . '.webp' ) ) {
171
  unlink( $results[0] . '.webp' );
172
  }
173
  }
@@ -191,8 +191,8 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
191
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
192
  $this->assertEquals( 1335586, filesize( $results[0] ) );
193
  unlink( $results[0] );
194
- $this->assertEquals( 284142, filesize( $results[0] . '.webp' ) );
195
- if ( is_file( $results[0] . '.webp' ) ) {
196
  unlink( $results[0] . '.webp' );
197
  }
198
  }
@@ -220,8 +220,8 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
220
  $this->assertEquals( ewww_image_optimizer_get_orientation( $results[0], 'image/jpeg' ), 1 );
221
  unlink( $results[0] );
222
  // size of webp with meta.
223
- $this->assertEquals( 303728, filesize( $results[0] . '.webp' ) );
224
- if ( is_file( $results[0] . '.webp' ) ) {
225
  unlink( $results[0] . '.webp' );
226
  }
227
  }
@@ -279,8 +279,8 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
279
  update_site_option( 'ewww_image_optimizer_webp', '' );
280
  $this->assertEquals( 188043, filesize( $results[0] ) );
281
  unlink( $results[0] );
282
- $this->assertEquals( 137366, filesize( $results[0] . '.webp' ) );
283
- if ( is_file( $results[0] . '.webp' ) ) {
284
  unlink( $results[0] . '.webp' );
285
  }
286
  }
@@ -334,7 +334,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
334
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
335
  update_site_option( 'ewww_image_optimizer_metadata_remove', true );
336
  $results = $this->optimize_png();
337
- $this->assertEquals( 37428, filesize( $results[0] ) );
338
  unlink( $results[0] );
339
  }
340
 
@@ -464,16 +464,16 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
464
  * Cleans up the temp images.
465
  */
466
  public static function tearDownAfterClass() {
467
- if ( is_file( self::$test_jpg ) ) {
468
  unlink( self::$test_jpg );
469
  }
470
- if ( is_file( self::$test_png ) ) {
471
  unlink( self::$test_png );
472
  }
473
- if ( is_file( self::$test_gif ) ) {
474
  unlink( self::$test_gif );
475
  }
476
- if ( is_file( self::$test_pdf ) ) {
477
  unlink( self::$test_pdf );
478
  }
479
  ewww_image_optimizer_remove_binaries();
139
  update_site_option( 'ewww_image_optimizer_webp', '' );
140
  $this->assertEquals( 1348837, filesize( $results[0] ) );
141
  unlink( $results[0] );
142
+ $this->assertEquals( 327964, filesize( $results[0] . '.webp' ) );
143
+ if ( ewwwio_is_file( $results[0] . '.webp' ) ) {
144
  unlink( $results[0] . '.webp' );
145
  }
146
  }
166
  $this->assertEquals( ewww_image_optimizer_get_orientation( $results[0], 'image/jpeg' ), 1 );
167
  unlink( $results[0] );
168
  // size of webp with meta.
169
+ $this->assertEquals( 347546, filesize( $results[0] . '.webp' ) );
170
+ if ( ewwwio_is_file( $results[0] . '.webp' ) ) {
171
  unlink( $results[0] . '.webp' );
172
  }
173
  }
191
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
192
  $this->assertEquals( 1335586, filesize( $results[0] ) );
193
  unlink( $results[0] );
194
+ $this->assertEquals( 284196, filesize( $results[0] . '.webp' ) );
195
+ if ( ewwwio_is_file( $results[0] . '.webp' ) ) {
196
  unlink( $results[0] . '.webp' );
197
  }
198
  }
220
  $this->assertEquals( ewww_image_optimizer_get_orientation( $results[0], 'image/jpeg' ), 1 );
221
  unlink( $results[0] );
222
  // size of webp with meta.
223
+ $this->assertEquals( 303782, filesize( $results[0] . '.webp' ) );
224
+ if ( ewwwio_is_file( $results[0] . '.webp' ) ) {
225
  unlink( $results[0] . '.webp' );
226
  }
227
  }
279
  update_site_option( 'ewww_image_optimizer_webp', '' );
280
  $this->assertEquals( 188043, filesize( $results[0] ) );
281
  unlink( $results[0] );
282
+ $this->assertEquals( 137108, filesize( $results[0] . '.webp' ) );
283
+ if ( ewwwio_is_file( $results[0] . '.webp' ) ) {
284
  unlink( $results[0] . '.webp' );
285
  }
286
  }
334
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
335
  update_site_option( 'ewww_image_optimizer_metadata_remove', true );
336
  $results = $this->optimize_png();
337
+ $this->assertEquals( 38639, filesize( $results[0] ) );
338
  unlink( $results[0] );
339
  }
340
 
464
  * Cleans up the temp images.
465
  */
466
  public static function tearDownAfterClass() {
467
+ if ( ewwwio_is_file( self::$test_jpg ) ) {
468
  unlink( self::$test_jpg );
469
  }
470
+ if ( ewwwio_is_file( self::$test_png ) ) {
471
  unlink( self::$test_png );
472
  }
473
+ if ( ewwwio_is_file( self::$test_gif ) ) {
474
  unlink( self::$test_gif );
475
  }
476
+ if ( ewwwio_is_file( self::$test_pdf ) ) {
477
  unlink( self::$test_pdf );
478
  }
479
  ewww_image_optimizer_remove_binaries();
tests/test-resize.php CHANGED
@@ -136,13 +136,13 @@ class EWWWIO_Resize_Tests extends WP_UnitTestCase {
136
  * Cleans up the temp images.
137
  */
138
  public static function tearDownAfterClass() {
139
- if ( is_file( self::$test_jpg ) ) {
140
  unlink( self::$test_jpg );
141
  }
142
- if ( is_file( self::$test_png ) ) {
143
  unlink( self::$test_png );
144
  }
145
- if ( is_file( self::$test_gif ) ) {
146
  unlink( self::$test_gif );
147
  }
148
  }
136
  * Cleans up the temp images.
137
  */
138
  public static function tearDownAfterClass() {
139
+ if ( ewwwio_is_file( self::$test_jpg ) ) {
140
  unlink( self::$test_jpg );
141
  }
142
+ if ( ewwwio_is_file( self::$test_png ) ) {
143
  unlink( self::$test_png );
144
  }
145
+ if ( ewwwio_is_file( self::$test_gif ) ) {
146
  unlink( self::$test_gif );
147
  }
148
  }
tests/test-tables.php CHANGED
@@ -115,7 +115,7 @@ class EWWWIO_Table_Tests extends WP_UnitTestCase {
115
  * Cleans up the temp images.
116
  */
117
  public static function tearDownAfterClass() {
118
- if ( is_file( self::$test_gif ) ) {
119
  unlink( self::$test_gif );
120
  }
121
  ewww_image_optimizer_remove_binaries();
115
  * Cleans up the temp images.
116
  */
117
  public static function tearDownAfterClass() {
118
+ if ( ewwwio_is_file( self::$test_gif ) ) {
119
  unlink( self::$test_gif );
120
  }
121
  ewww_image_optimizer_remove_binaries();
tests/test-utility.php CHANGED
@@ -27,7 +27,7 @@ class EWWWIO_Utility_Tests extends WP_UnitTestCase {
27
  $binaries = scandir( EWWW_IMAGE_OPTIMIZER_BINARY_PATH );
28
  foreach ( $binaries as $binary ) {
29
  $binary = trailingslashit( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . $binary;
30
- if ( ! is_file( $binary ) ) {
31
  continue;
32
  }
33
  $this->assertTrue( ewww_image_optimizer_md5check( $binary ) );
@@ -44,7 +44,7 @@ class EWWWIO_Utility_Tests extends WP_UnitTestCase {
44
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_debug', true );
45
  foreach ( $binaries as $binary ) {
46
  $binary = trailingslashit( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . $binary;
47
- if ( ! is_file( $binary ) ) {
48
  continue;
49
  }
50
  $this->assertTrue( (bool) ewww_image_optimizer_mimetype( $binary, 'b' ), $binary . ":\n" . str_replace( '<br>', "\n", $eio_debug ) );
27
  $binaries = scandir( EWWW_IMAGE_OPTIMIZER_BINARY_PATH );
28
  foreach ( $binaries as $binary ) {
29
  $binary = trailingslashit( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . $binary;
30
+ if ( ! ewwwio_is_file( $binary ) ) {
31
  continue;
32
  }
33
  $this->assertTrue( ewww_image_optimizer_md5check( $binary ) );
44
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_debug', true );
45
  foreach ( $binaries as $binary ) {
46
  $binary = trailingslashit( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . $binary;
47
+ if ( ! ewwwio_is_file( $binary ) ) {
48
  continue;
49
  }
50
  $this->assertTrue( (bool) ewww_image_optimizer_mimetype( $binary, 'b' ), $binary . ":\n" . str_replace( '<br>', "\n", $eio_debug ) );
unique.php CHANGED
@@ -183,9 +183,7 @@ function ewww_image_optimizer_notice_hosting_requires_api() {
183
  */
184
  function ewww_image_optimizer_notice_os() {
185
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
186
- echo "<div id='ewww-image-optimizer-warning-os' class='notice notice-error'><p><strong>" . esc_html__( 'EWWW Image Optimizer is supported on Linux, FreeBSD, Mac OSX, and Windows', 'ewww-image-optimizer' ) . '.</strong> ' .
187
- /* translators: %s: An operating system. */
188
- sprintf( esc_html__( 'Unfortunately, the EWWW Image Optimizer plugin does not work with %s', 'ewww-image-optimizer' ), htmlentities( PHP_OS ) ) . '.</p></div>';
189
  }
190
 
191
  /**
@@ -213,7 +211,7 @@ function ewww_image_optimizer_install_paths() {
213
  $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-mac';
214
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-mac';
215
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-mac';
216
- $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-mac12';
217
  $gifsicle_dst = $tool_path . 'gifsicle';
218
  $optipng_dst = $tool_path . 'optipng';
219
  $jpegtran_dst = $tool_path . 'jpegtran';
@@ -284,7 +282,7 @@ function ewww_image_optimizer_check_permissions( $file, $minimum ) {
284
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
285
  $perms = fileperms( $file );
286
  ewwwio_debug_message( "permissions for $file: " . substr( sprintf( '%o', $perms ), -4 ) );
287
- if ( ! is_file( $file ) ) {
288
  ewwwio_debug_message( 'permissions check failed, file not found' );
289
  return false;
290
  }
@@ -406,23 +404,6 @@ function ewww_image_optimizer_install_tools() {
406
  ewwwio_debug_message( 'could not copy webp' );
407
  }
408
  }
409
- // Install special version of cwebp for Mac OSX 10.8 systems.
410
- if ( PHP_OS === 'Darwin' && ! $skip['webp'] ) {
411
- $webp8_dst = $webp_dst . '-alt';
412
- $webp8_src = str_replace( 'mac9', 'mac8', $webp_src );
413
- if ( ! file_exists( $webp8_dst ) || ( ewww_image_optimizer_md5check( $webp8_dst ) && filesize( $webp8_dst ) !== filesize( $webp8_src ) ) ) {
414
- ewwwio_debug_message( "copying $webp8_src to $webp8_dst" );
415
- if ( ! copy( $webp8_src, $webp8_dst ) ) {
416
- // This isn't a fatal error, besides we'll see it in the debug if needed.
417
- ewwwio_debug_message( 'could not copy OSX 10.8 cwebp to cwebp-alt' );
418
- }
419
- if ( ! ewww_image_optimizer_check_permissions( $webp8_dst, 'rwxr-xr-x' ) ) {
420
- if ( ! is_writable( $webp8_dst ) || ! chmod( $webp8_dst, 0755 ) ) {
421
- ewwwio_debug_message( 'could not set cwebp8-alt permissions' );
422
- }
423
- }
424
- }
425
- }
426
 
427
  if ( PHP_OS !== 'WINNT' && ! $toolfail ) {
428
  ewwwio_debug_message( 'Linux/UNIX style OS, checking permissions' );
@@ -937,79 +918,79 @@ function ewww_image_optimizer_md5check( $path ) {
937
  $binary_sum = hash_file( 'sha256', $path );
938
  ewwwio_debug_message( "$path: $binary_sum" );
939
  $valid_sums = array(
940
- '463de9ba684d54d27185cb6487a0b22b7571a87419abde4dee72c9b107f23315', // jpegtran-mac 9, EWWW 1.3.0.
941
- '0b94f82e3d740d1853281e9aaee5cc7122c27fd63da9d6d62ed3398997cbed1e', // jpegtran-linux 9, EWWW 1.4.0.
942
  'f5f079bfe6f3f48c17738679292f35cdee44afe8f8413cdbc4f555cee7de4173', // jpegtran-linux64 9, EWWW 1.4.0.
943
- 'ec71f638d2101f08fab66f4d139746d4042352bc75d55bd093aa446081892e0c', // jpegtran-fbsd 9, EWWW 1.4.0.
944
- '356532227fce51fcb9df29f143ab9d202fbd40f18e2b8234aee95937c93bd67e', // jpegtran-fbsd64 9, EWWW 1.4.0.
945
- '7be857837764dff4f0d7d2c5d546bf4d2573af7f326ced908ac229d60fd054c6', // jpegtran.exe 9, EWWW 1.4.0.
946
- 'bce5205bb240532c01273b5442a44244a8a27a74fb47e2ce467c18b91fabea6b', // jpegtran-sol 9, EWWW 1.7.4.
947
- 'cadc7be4688632bf2860562a1596f1b2b54b9a9c8b27df7ecabca49b1dcd8a5f', // jpegtran-fbsd 9a, EWWW 2.0.0.
948
- 'bab4aa853c143534503464eeb35893d16799cf859ff22f9a4e62aa383f4fc99c', // jpegtran-fbsd64 9a, EWWW 2.0.0.
949
- 'deb7e0f579fac767196611aa110052864e3093017970ff74de709b41e265e8b1', // jpegtran-linux 9a, EWWW 2.0.0.
950
  'b991fde396ebcc0e4f805df44b1797fe369f7f19e9392684dd4052e3f23c441e', // jpegtran-linux64 9a, EWWW 2.0.0.
951
- '436835bd42b27d2f05440bc5dc5174f2a896d38f8a550d96704d39969951d9ac', // jpegtran-mac 9a, EWWW 2.0.0.
952
- 'bdf3c6b6cb16287a3f62e7cde8f69f8bda5d310abca28e00068c526f9f37cc89', // jpegtran-sol 9a, EWWW 2.0.0.
953
- '3c2746d0b1ae150b13b767715af45ff601e394c01ada929cbe16e6dcd18fb199', // jpegtran.exe 9a, EWWW 2.0.0.
954
- '8e11f7df5735b36d3ecc95c84b0e355355a766d3ccafbf751bcf343a8952432c', // jpegtran-fbsd 9b, EWWW 2.6.0.
955
  '21d8046e07cb298dfd2f3b1e321c67c378a4d35fa8adc3521acc42b5b8088d64', // jpegtran-linux 9b, EWWW 2.6.0.
956
- '4d1a1c601d291f96dc03ea7e42ab9137a17f93ebc391353db65b4e32c1e9fbdb', // jpegtran-mac 9b, EWWW 2.6.0.
957
- '7e8719703d31e1ab9bf2b2ad7ab633649012ab6aae46ea40462365b9c00876d5', // jpegtran-sol 9b, EWWW 2.6.0.
958
- '9767f05ae1b59d4fea25a73b276dcd1245f5281b53386dc03784539265bffbea', // jpegtran.exe 9b, EWWW 2.6.0.
959
  // end jpegtran.
960
  '6deddb5562ac13ffc3e46a0af79b592e92fb4553c5df294b6e0052bc890fd0e3', // optipng-linux 0.7.4, EWWW 1.2.0.
961
  '51df81fa8c765efbe0aa4c1cf5293e25e7e2e7f6962f5161615239c54aec4c01', // optipng-linux 0.7.4, EWWW 1.3.0.
962
- '7a56cca66471ce2b6cdff4460db0d75258ef05de8da1eda0448e4d4ad9ae252f', // optipng-mac 0.7.4, EWWW 1.3.0.
963
  '2f9140cdc3ef1f7687baa710f0bba84c5f7f11e3f62c3ce43124e23b849ac5ff', // optipng-linux 0.7.4, EWWW 1.3.7.
964
- '5d59467363c457bf743f4df121c365dd43365357f1cdea5f3752a7ca1b3e315a', // optipng-fbsd 0.7.4, EWWW 1.4.0.
965
- '1af8077958a88a3064a71903841f901179e27fe137774085565619fb199c653a', // optipng.exe 0.7.4, EWWW 1.4.0.
966
- 'f692fef395b8689de033b9f2ce80c867c8a229c52e948df733377e20b62773a9', // optipng-sol 0.7.4, EWWW 1.7.4.
967
- 'e17d327cd89ab34eff7f994806fe9f2c124d6cc6cd309fa4c3911d5ce90312c9', // optipng-fbsd 0.7.5, EWWW 2.0.0.
968
  'd263ecfb5b29ed08920e26cf604a86d3484daee5b80605e445cf97aa14d8aebc', // optipng-linux 0.7.5, EWWW 2.0.0.
969
- '6f15cb2e8d25e51037efa7bcec7499c96eb11e576536a478edfee500207655ae', // optipng-mac 0.7.5, EWWW 2.0.0.
970
- '1d2de40b009f16e9c709f9b0c15a47abb8da57668a918ac9a0723ddc6de6c30a', // optipng-sol 0.7.5, EWWW 2.0.0.
971
- 'fad3a0fd95706d53576f72593bf13d3e31d1c896c852bfd5b9ba602eca0bd2b6', // optipng.exe 0.7.5, EWWW 2.0.0.
972
- '9d60eaeb9dc5167a57a5f3af236d56b4149d1043b543f2faa38a0936fa6b54b2', // optipng-fbsd 0.7.6, EWWW 2.8.0.
973
  '853ca5936a2dd92a17b3518fd55db6be35e1b2bebfabca3949c34700072e08b8', // optipng-linux 0.7.6, EWWW 2.8.0.
974
- 'd4f11e96733aed64a72e744843dcd0929e144a7fc97f40d405a034a72eb9bbc6', // optipng-mac 0.7.6, EWWW 2.8.0.
975
- '1ed9343194cfca0a1c32677c974192746adfd48cb4cea6a2df668452df0e68f7', // optipng-sol 0.7.6, EWWW 2.8.0.
976
- '03b86ce2c08e2cc78d76d3d3dd173986b498b055c3c19e13a97a7c3c674772c6', // optipng.exe 0.7.6, EWWW 2.8.0.
977
- 'f01cba0ab658e08738315843ee635be273726bf102ae448416b3d8956843d864', // optipng-fbsd 0.7.7 EWWW 4.1.0.
978
  '4404076a4f9119d4dfbb7acb00eb65345e804186a019c7136d8f8e87fb0cb997', // optipng-linux 0.7.7 EWWW 4.1.0.
979
- '36535c1b262e0c457bbb0ed2bc71e812a49e26a6cada63b6acbd8d809c68a5a1', // optipng-mac 0.7.7 EWWW 4.1.0.
980
- '41a4c78e6c97ea26836f4b021157b34f1812a9e5c2341502aad8cde942b18576', // optipng-sol 0.7.7 EWWW 4.1.0.
981
- '6a321e07eca8e28fa8a969b5db3c1d3cc008a2064d636cf74762bbe4364b7b14', // optipng.exe 0.7.7 EWWW 4.1.0.
982
  // end optipng.
983
  'a2292c0085863a65c99cb41ff8418ce63033e162906df72e8fdde52f0633579b', // gifsicle linux 1.67, EWWW 1.2.0.
984
  'd7f9609b6fd0000b2eaad2bd0c3cb85476988b18705762e915bda3f2e6007801', // gifsicle-linux 1.68, EWWW 1.3.0.
985
  '204a839a50367adb8cd23fae5d1913a5ca8b41307f054156ed152748d3e7934d', // gifsicle-linux 1.68, EWWW 1.3.7.
986
- '23e208099fa7ce75a3f98144190d6362d69b90c6f0a534ffa45dbbf789f7d99c', // gifsicle-mac 1.68, EWWW 1.3.0.
987
- '8b08243a7cc655512a03403f6c3814176e28bbd140df7c059bd321a9a0151c18', // gifsicle-fbsd 1.70, EWWW 1.4.0.
988
  'fd074673967ee9d387208f047c081a6331663b4076f4a6a608d6f646622af718', // gifsicle-linux 1.70, EWWW 1.4.0 - 1.7.4.
989
- 'bc32a390e86d2d8f40e970b2dc059015b51afe26794d92a936c1fe7216db805d', // gifsicle-mac 1.70, EWWW 1.4.0.
990
- '41e67a35cd178f781b5224d196185e4243e6c2b3bece43277130fe07cdda402f', // gifsicle-sol 1.70, EWWW 1.7.4.
991
- '3c6d9fabd1ea1014b8f58063dd00a653980c06bc1b45e96a47d866247263a1e1', // gifsicle.exe 1.70, EWWW 1.4.0.
992
- 'decba7a95b637bee53847af680fd37bde8bd568528412c514b7bd794056fd4ff', // gifsicle-fbsd 1.78, EWWW 1.7.5.
993
  'c28e5e4b5344f77f415973d013e4cb393fc550e8de44117b090d534e98b30d1c', // gifsicle-linux 1.78, EWWW 1.7.5 - 1.9.3.
994
- 'fc2de863e8579b0d540003300e918cee450bc8e026018c631dffc0ed851a8c1c', // gifsicle-mac 1.78, EWWW 1.7.5.
995
- '74d011ee1b6d9fe6d5d8bdb4cd17db0c5987fa6e3d495b42439cd70b0763c07a', // gifsicle-sol 1.78, EWWW 1.7.5.
996
- '7c10da38f4afb28373779d40a30710aa9fb369e82f7f29363554bea965d132df', // gifsicle.exe 1.78, EWWW 1.7.5.
997
- 'e75acedd0725fba64ee72855b796cdfa8dac9959d63e89a9e0e5ba059ae013c2', // gifsicle-fbsd 1.84, EWWW 2.0.0.
998
  'a4f0f21bc4bea51f5d304fe944262c12f671d70a3e5f688061da7bb036e84ff8', // gifsicle-linux 1.84, EWWW 2.0.0 - 2.4.3.
999
- '5f4176b3fe69f975563d2ce7e76615ab558f5f1839b9bfa6f6de1b3c3fa11c02', // gifsicle-mac 1.84, EWWW 2.0.0.
1000
- '9f0027bed22d4be60012488ab726c3a131d9f3e1e276e9400c578173347a9a48', // gifsicle-sol 1.84, EWWW 2.0.0.
1001
- '72f0077e8591292d09efee09a181458b34fb3c0e9a6ac7e8e11cec574bf619ac', // gifsicle.exe 1.84, EWWW 2.0.0.
1002
- 'c64936b429e46b6a75339df00eb8daa39d335844c906fa16d4d0af481851e91e', // gifsicle-fbsd 1.87, EWWW 2.4.4.
1003
  'deea065a91c8429edecf42ccef78636065f7ae0dad867df7696128c6711e4735', // gifsicle-linux 1.87, EWWW 2.4.4.
1004
- '2e0d8b7413173555bbec6e019c3cd7c55f7d582a017a0af7b14cfd24a6921f51', // gifsicle-mac 1.87, EWWW 2.4.4.
1005
- '3966e01474601059c6a13aefbe4f313c6cb6d49c799f7850966950892a9ab45a', // gifsicle-sol 1.87, EWWW 2.4.4.
1006
- '40b86b2ea6642f4c921152923af1e631922b624f7d23189f53c659506c7179b5', // gifsicle.exe 1.87, EWWW 2.4.4.
1007
- '3da9e1a764a459d78dc1468ba60d882ff042050a86f82d895777b172b50f2f19', // gifsicle.exe 1.87, EWWW 2.4.5.
1008
- '327c21635ea8c789e3e9533210e6baf372db27c7bbed3791881d74a7dd41cef9', // gifsicle-fbsd 1.91, EWWW 4.1.0.
1009
  '566f058b2043c4f3c8c049b0507bfa78dcb33dac52b132cade5f67bbb62d91e4', // gifsicle-linux 1.91, EWWW 4.1.0.
1010
- '03602b141432af2211882fc079ba15a773a7ec782c92755cb31279eb6d8b99d4', // gifsicle-mac 1.91, EWWW 4.1.0.
1011
- '5fcdd102146984e41b01a160d072dd36852d7be14ab569a323c47e7e56916d0d', // gifsicle-sol 1.91, EWWW 4.x.
1012
- '7156bfe16dc5e33af7facdc6847d268154ffeb75c0217517e4e188b58b293c6a', // gifsicle.exe 1.91, EWWW 4.1.0.
1013
  // end gifsicle.
1014
  'bdea95497d6e60aae8938cae8e999ef74a255ad603531bf523dcdb531f61fc8f', // 20110722-bsd/i686/pngout.
1015
  '57c09b3ebd7d4623d16f6056efd7951e8f98e2362a27993a7d865af677875c00', // 20110722-bsd-static/i686/pngout-static.
@@ -1039,31 +1020,36 @@ function ewww_image_optimizer_md5check( $path ) {
1039
  '843f0be42e86680c1663c4ef58eb0677ace15fc29ab23897c83f4b7e5af3ef36', // 20150319-windows/pngout.exe 20150319.
1040
  'aa3993937455094c0f66ac77d60bf53be441fdf8f14618520c2af68f2253085d', // 20150920-mac/pngout.
1041
  // end pngout.
1042
- '8417d5d60bc66442ecc666e31ec7b9e1b7c55f48291e74b4b81f35703e2aef2e', // pngquant-fbsd 2.0.2, EWWW 1.8.3.
1043
  '78668c38d0be70764b18f3f4e0ea2b647df2ae87cedb2216d0ef69c8c55b688a', // pngquant-linux 2.0.2, EWWW 1.8.3.
1044
- '7df1b7f6ed73a189083dd931fb3380d236d34790318f00233b59c8f26f90665f', // pngquant-mac 2.0.2, EWWW 1.8.3.
1045
- '56d2c6212eb595f5eab8a7469e56fa8d3d0e6ffc231aef27742134fba4a39298', // pngquant-sol 2.0.2, EWWW 1.8.3.
1046
- 'd3851c962cd59d74a35174bf3ce71d876dfcd8bdf76f81cd428b2ab7e53c0515', // pngquant.exe 2.0.2, EWWW 1.8.3.
1047
- '0ee6f1dbf4fa168b11ce60860e5700ca0e5125323a43540a78c76644835abc84', // pngquant-fbsd 2.3.0, EWWW 2.0.0.
1048
  '85d8a70930a554f50181a1d061577cf67ef2e76e2cbd5bcb1b7f006064ff1444', // pngquant-linux 2.3.0, EWWW 2.0.0.
1049
- 'a807f769922fdad0ba07307c548df8cf8eeced649d04237d13dfc95757161459', // pngquant-mac 2.3.0, EWWW 2.0.0.
1050
- 'cf2cc40274c438b35e93bd0346c2a6d871bd7a7bdd90c52f4e79f369cb8ded74', // pngquant-sol 2.3.0, EWWW 2.0.0.
1051
- '7454aba77b1a2b63a42d8a5870d3c2d733c7efb2d828643d5e64784af1f65f2a', // pngquant.exe 2.3.0, EWWW 2.0.0.
1052
- '6287f1bb7179c7b6d71a41112222347ed97b6eae4e79b180d7e1e332a4bde3e2', // pngquant-fbsd 2.5.2, EWWW 2.5.4.
1053
  'fcfe4d3a602e7b491f4126a2707144f5f9cc9359d13f443575d7ea6a74e85ddb', // pngquant-linux 2.5.2, EWWW 2.5.4.
1054
- '35794819a35e949dc0c0d6f90d0bb675791fa9bc3f405eb19f48ea31bb6456a8', // pngquant-mac 2.5.2, EWWW 2.5.4.
1055
- 'c242586c70d83af544334f1846b838ef68c6ab4fc247b2cff9ad4b714f825866', // pngquant-sol 2.5.2, EWWW 2.5.4.
1056
- 'ad79d9b3395d41404b28362972bd68db3c58d5be5f063884df3a595fc38c6a98', // pngquant.exe 2.5.2, EWWW 2.5.4.
1057
- '54d632fc4446d88ad4d1beeaf73420d68d87786f02adc9d3363766cb93ec95a4', // pngquant-fbsd 2.9.1, EWWW 3.4.0.
1058
  '91f704f02468f86766007e46973a1ef9e282d6ccadc54caf339dc537c9b2b61d', // pngquant-linux 2.9.1, EWWW 3.4.0.
1059
- '65dc20f05af588d948fc6f4df37c294f4a3a1c1ad207a8b56d13e6829773165a', // pngquant-mac 2.9.1, EWWW 3.4.0.
1060
- 'dbc9e12d5bb3e806aaf5e2c3d30d122d569069027a633485761cbf072cf2236d', // pngquant-sol 2.9.1, EWWW 3.4.0.
1061
- '84e63e6f9f9630a1a0c3e782609349c12b8df9ea9d02c5a29230819379e56b3c', // pngquant.exe 2.8.1, EWWW 3.4.0.
1062
- 'd6433dc6ecf6a0fdedf754782e6d5c9e494ddec762426a6d0b1896a220bd6d3f', // pngquant-fbsd 2.11.7 EWWW 4.1.0.
1063
  '40b0860abba39342fb64612a612e0f24571d259b6b83d7483af9a1d586950d79', // pngquant-linux 2.11.7 EWWW 4.1.0.
1064
- 'c924e11d9a3166afd5ed19165193c1351ff4a2cc993498f1f28c7daee829ca76', // pngquant-mac 2.11.7 EWWW 4.1.0.
1065
- '34534e69929e7fe267f77c55f487e419f76cc1d24e41fdb642f9671383012c56', // pngquant-sol 2.11.7 EWWW 4.1.0.
1066
- 'af7598aa09ba519ad15305a56011949db19c5b2176187662640bc0ebc4ddd19a', // pngquant.exe 2.11.7 EWWW 4.1.0.
 
 
 
 
 
1067
  // end pngquant.
1068
  'bf0e12f996802dc114a864e5150647ce41089a5a2b5e36c3a270ac848b655c26', // cwebp-fbsd 0.4.1, EWWW 2.0.0.
1069
  '5349646072c3ef5f8b4588bbee8635e882c245439e2d86b863f04b7e27f4fafe', // cwebp-fbsd64 0.4.1, EWWW 2.0.0.
@@ -1089,24 +1075,29 @@ function ewww_image_optimizer_md5check( $path ) {
1089
  'b2bef90b62d80b35d4c5a41f793454e95e5159bf0aec2e4bd8c19fc3de3556bd', // cwebp-linux664 0.4.4, EWWW 2.5.4.
1090
  'd3c358524efd50f6e078362733870229ca1e1db8885580b6814c2535b4d20612', // cwebp-linux8 0.4.4, EWWW 2.5.4.
1091
  '271deeec579c252e364495addad03d9c1f3248c2177a01638002b25eee787ded', // cwebp-linux864 0.4.4, EWWW 2.5.4.
1092
- '379e2b95e20dd33f4667c134099df358e178f6a6bf32f3a5b6b78bbb6950b4b5', // cwebp-mac9 0.4.4, EWWW 2.5.4.
1093
- '118ea3f0bcdcce6128d64e34159c93c3324cb038c9e5a51efaf530ea52af7070', // cwebp-sol 0.4.4, EWWW 2.5.4.
1094
- '43941c1d7169e66fb1fd62a1950286b230d3e5bec3bbb14fdb4ac091ca7a0f9f', // cwebp.exe 0.4.4, EWWW 2.5.4.
1095
- '26d5d88dee2993d1d0e16f5e60318cd8adec485614facd6c7f9c22c71eb7b2e5', // cwebp-fbsd 0.5.0 EWWW 2.6.0.
1096
  '60b1738d6502691227a46658cd7656b4a52702680f169e8e04d72077e967aeed', // cwebp-linux 0.5.0, EWWW 2.6.0.
1097
- '276a0221a4c978825903572c2b68b3010399375d6b9dc7429286caf625cae95a', // cwebp-mac9 0.5.0, EWWW 2.6.0.
1098
- 'be3e81ec7267e7878ddd4ee01df1553966952f74bbfd30a5523d12d53f019ecb', // cwebp-sol 0.5.0, EWWW 2.6.0.
1099
- 'b41123ec06f21765f50ec1b017839f99ab4f28497d87da722817a6023e4a3b32', // cwebp.exe 0.5.0, EWWW 2.6.0.
1100
- 'f0547a6219c5c05d0af29c5e411e054b9d795567f4ae2e27893815af9383c60f', // cwebp-fbsd 0.5.1, EWWW 2.9.9.
1101
  '9eaf670bb2d567421c7e2918112dc00406c60f008b120f648cf0bdba73ee9b6b', // cwebp-linux 0.5.1, EWWW 2.9.9.
1102
- '1202ea932b315913d3736460dd3d50bc5b251b7a0a8f0468c63144ba427679c2', // cwebp-mac9 0.5.1, EWWW 2.9.9.
1103
- '27ba0abce52e74744f6235fcde9b153b5052b9c15cd78e74feffaea9dafcc178', // cwebp-sol 0.5.1, EWWW 2.9.9.
1104
- 'b02864989f0a1a263caa796c5b8caf18c1f774ed0ba08a9350e8820459875f51', // cwebp.exe 0.5.1, EWWW 2.9.9.
1105
- 'e5cbea11c97fadffe221fdf57c093c19af2737e4bbd2cb3cd5e908de64286573', // cwebp-fbsd 0.6.0, EWWW 3.4.0.
1106
  '43ca351e8f5d457b898c587151ebe3d8f6cce8dcfb7de44f6cb70148a31a68bc', // cwebp-linux 0.6.0, EWWW 3.4.0.
1107
  'a06a3ee436e375c89dbc1b0b2e8bd7729a55139ae072ed3f7bd2e07de0ebb379', // cwebp-mac12 0.6.0, EWWW 3.4.0.
1108
- '1febaffbb18e52dc2c524cda9eefd00c6db95bc388732868999c0f48deb73b4f', // cwebp-sol 0.6.0, EWWW 3.4.0.
1109
- '49e9cb98db30bfa27936933e6fd94d407e0386802cb192800d9fd824f6476873', // cwebp.exe 0.6.0, EWWW 3.4.0.
 
 
 
 
 
1110
  // end cwebp.
1111
  );
1112
  foreach ( $valid_sums as $checksum ) {
@@ -1134,6 +1125,9 @@ function ewww_image_optimizer_md5check( $path ) {
1134
  function ewww_image_optimizer_mimetype( $path, $case ) {
1135
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1136
  ewwwio_debug_message( "testing mimetype: $path" );
 
 
 
1137
  $type = false;
1138
  // For S3 images/files, don't attempt to read the file, just use the quick (filename) mime check.
1139
  if ( 'i' === $case && ewww_image_optimizer_stream_wrapped( $path ) ) {
@@ -1424,7 +1418,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1424
  ewwwio_debug_message( "$path: invalid output" );
1425
  break;
1426
  }
1427
- if ( ! empty( $webp_version ) && preg_match( '/0.\d.\d/', $webp_version[0] ) ) {
1428
  ewwwio_debug_message( 'optimizer found' );
1429
  return $webp_version[0];
1430
  }
@@ -1749,8 +1743,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1749
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
1750
  ewww_image_optimizer_cloud_init();
1751
  }
1752
- $bypass_optimization = apply_filters( 'ewww_image_optimizer_bypass', false, $file );
1753
- if ( true === $bypass_optimization ) {
1754
  ewwwio_debug_message( "optimization bypassed: $file" );
1755
  // Tell the user optimization was skipped.
1756
  return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
@@ -1772,14 +1765,20 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1772
  // Initialize the original filename.
1773
  $original = $file;
1774
  $result = '';
1775
- if ( false === is_file( $file ) ) {
 
 
 
 
 
 
1776
  /* translators: %s: Image filename */
1777
  $msg = sprintf( __( 'Could not find %s', 'ewww-image-optimizer' ), $file );
1778
  ewwwio_debug_message( "file doesn't appear to exist: $file" );
1779
  ewww_image_optimizer_s3_uploads_image_cleanup( $file );
1780
  return array( false, $msg, $converted, $original );
1781
  }
1782
- if ( false === is_writable( $file ) ) {
1783
  /* translators: %s: Image filename */
1784
  $msg = sprintf( __( '%s is not writable', 'ewww-image-optimizer' ), $file );
1785
  ewwwio_debug_message( "couldn't write to the file $file" );
@@ -1899,7 +1898,8 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1899
  if (
1900
  1 === (int) $gallery_type &&
1901
  $fullsize &&
1902
- ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) || ! empty( $_REQUEST['ewww_convert'] ) )
 
1903
  ) {
1904
  // Generate the filename for a PNG:
1905
  // If this is a resize version.
@@ -1925,7 +1925,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1925
  }
1926
  }
1927
  $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
1928
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
1929
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
1930
  if ( $converted ) {
1931
  // Check to see if the user wants the originals deleted.
@@ -1933,10 +1933,10 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1933
  // Delete the original JPG.
1934
  unlink( $original );
1935
  }
1936
- $converted = $filenum;
1937
- ewww_image_optimizer_webp_create( $file, $new_size, 'image/png', null, $orig_size !== $new_size );
1938
  } else {
1939
- ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
1940
  }
1941
  break;
1942
  }
@@ -1963,8 +1963,9 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1963
  ! $skip['webp']
1964
  );
1965
  }
1966
- // If jpegtran optimization is disabled.
1967
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) ) {
 
1968
  // Store an appropriate message in $result.
1969
  $result = __( 'JPG optimization is disabled', 'ewww-image-optimizer' );
1970
  // Otherwise, if we aren't skipping the utility verification and jpegtran doesn't exist.
@@ -2007,7 +2008,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2007
  $result = "$orig_size vs. $new_size";
2008
  // If the optimization didn't produce a smaller JPG.
2009
  } else {
2010
- if ( is_file( $progfile ) ) {
2011
  // Delete the optimized file.
2012
  unlink( $progfile );
2013
  }
@@ -2016,8 +2017,9 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2016
  $new_size = $orig_size;
2017
  }
2018
  } elseif ( ! $convert ) {
 
2019
  // If conversion and optimization are both turned OFF, finish the JPG processing.
2020
- ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['CWEBP'] );
2021
  break;
2022
  } // End if().
2023
  // If the conversion process is turned ON, or if this is a resize and the full-size was converted.
@@ -2059,10 +2061,10 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2059
  ewwwio_debug_message( 'attempting lossy reduction' );
2060
  exec( "$nice " . $tools['PNGQUANT'] . ' ' . ewww_image_optimizer_escapeshellarg( $pngfile ) );
2061
  $quantfile = preg_replace( '/\.\w+$/', '-fs8.png', $pngfile );
2062
- if ( is_file( $quantfile ) && filesize( $pngfile ) > filesize( $quantfile ) ) {
2063
  ewwwio_debug_message( 'lossy reduction is better: original - ' . filesize( $pngfile ) . ' vs. lossy - ' . filesize( $quantfile ) );
2064
  rename( $quantfile, $pngfile );
2065
- } elseif ( is_file( $quantfile ) ) {
2066
  ewwwio_debug_message( 'lossy reduction is worse: original - ' . filesize( $pngfile ) . ' vs. lossy - ' . filesize( $quantfile ) );
2067
  unlink( $quantfile );
2068
  } else {
@@ -2118,12 +2120,12 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2118
  ewwwio_debug_message( 'converted PNG is no good' );
2119
  // Otherwise delete the PNG.
2120
  $converted = false;
2121
- if ( is_file( $pngfile ) ) {
2122
  unlink( $pngfile );
2123
  }
2124
  }
2125
  } // End if().
2126
- ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size !== $new_size );
2127
  break;
2128
  case 'image/png':
2129
  $jpg_size = 0;
@@ -2133,7 +2135,8 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2133
  1 === (int) $gallery_type &&
2134
  $fullsize &&
2135
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) || ! empty( $_REQUEST['ewww_convert'] ) ) &&
2136
- ! $skip_lossy
 
2137
  ) {
2138
  ewwwio_debug_message( 'PNG to JPG conversion turned on' );
2139
  $cloud_background = '';
@@ -2182,7 +2185,11 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2182
  }
2183
  }
2184
  $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
2185
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) >= 20 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
 
 
 
 
2186
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer(
2187
  $file,
2188
  $type,
@@ -2199,10 +2206,10 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2199
  // Delete the original JPG.
2200
  unlink( $original );
2201
  }
2202
- $converted = $filenum;
2203
- ewww_image_optimizer_webp_create( $file, $new_size, 'image/jpeg', null, $orig_size !== $new_size );
2204
  } else {
2205
- ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
2206
  }
2207
  break;
2208
  }
@@ -2226,7 +2233,9 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2226
  );
2227
  }
2228
  // If png optimization is disabled.
2229
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) ) {
 
 
2230
  // Tell the user all PNG tools are disabled.
2231
  $result = __( 'PNG optimization is disabled', 'ewww-image-optimizer' );
2232
  // If the utility checking is on, optipng is enabled, but optipng cannot be found.
@@ -2248,10 +2257,10 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2248
  ewwwio_debug_message( 'attempting lossy reduction' );
2249
  exec( "$nice " . $tools['PNGQUANT'] . ' ' . ewww_image_optimizer_escapeshellarg( $file ) );
2250
  $quantfile = preg_replace( '/\.\w+$/', '-fs8.png', $file );
2251
- if ( is_file( $quantfile ) && filesize( $file ) > filesize( $quantfile ) && ewww_image_optimizer_mimetype( $quantfile, 'i' ) === $type ) {
2252
  ewwwio_debug_message( 'lossy reduction is better: original - ' . filesize( $file ) . ' vs. lossy - ' . filesize( $quantfile ) );
2253
  rename( $quantfile, $file );
2254
- } elseif ( is_file( $quantfile ) ) {
2255
  ewwwio_debug_message( 'lossy reduction is worse: original - ' . filesize( $file ) . ' vs. lossy - ' . filesize( $quantfile ) );
2256
  unlink( $quantfile );
2257
  } else {
@@ -2289,7 +2298,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2289
  $result = "$orig_size vs. $new_size";
2290
  // If the optimization didn't produce a smaller PNG.
2291
  } else {
2292
- if ( is_file( $tempfile ) ) {
2293
  // Delete the optimized file.
2294
  unlink( $tempfile );
2295
  }
@@ -2300,7 +2309,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2300
  } elseif ( ! $convert ) {
2301
  // If conversion and optimization are both disabled we are done here.
2302
  ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
2303
- ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['CWEBP'] );
2304
  break;
2305
  } // End if().
2306
  // Retrieve the new filesize of the PNG.
@@ -2411,7 +2420,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2411
  $jpg_size = $opt_jpg_size;
2412
  ewwwio_debug_message( 'optimized JPG was smaller than un-optimized version' );
2413
  // If the optimization didn't produce a smaller JPG.
2414
- } elseif ( is_file( $progfile ) ) {
2415
  unlink( $progfile );
2416
  }
2417
  }
@@ -2433,15 +2442,18 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2433
  $converted = $filenum;
2434
  } else {
2435
  $converted = false;
2436
- if ( is_file( $jpgfile ) ) {
2437
  // Otherwise delete the new JPG.
2438
  unlink( $jpgfile );
2439
  }
2440
  }
2441
  } // End if().
2442
- ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size !== $new_size );
2443
  break;
2444
  case 'image/gif':
 
 
 
2445
  // If gif2png is turned on, and the image is in the WordPress media library.
2446
  if (
2447
  1 === (int) $gallery_type &&
@@ -2481,8 +2493,8 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2481
  // Delete the original GIF.
2482
  unlink( $original );
2483
  }
2484
- $converted = $filenum;
2485
- ewww_image_optimizer_webp_create( $file, $new_size, 'image/png', null, $orig_size !== $new_size );
2486
  }
2487
  break;
2488
  }
@@ -2531,7 +2543,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2531
  $result = "$orig_size vs. $new_size";
2532
  // If the optimization didn't produce a smaller GIF.
2533
  } else {
2534
- if ( is_file( $tempfile ) ) {
2535
  // Delete the optimized file.
2536
  unlink( $tempfile );
2537
  }
@@ -2591,18 +2603,21 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2591
  // Let webp know what we're dealing with now.
2592
  $type = 'image/png';
2593
  // Normally this would be at the end of the section, but we only want to do webp if the image was successfully converted to a png.
2594
- ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size !== $new_size );
2595
  // Successful conversion, so we store the increment.
2596
  $converted = $filenum;
2597
  } else {
2598
  $converted = false;
2599
- if ( is_file( $pngfile ) ) {
2600
  unlink( $pngfile );
2601
  }
2602
  }
2603
  } // End if().
2604
  break;
2605
  case 'application/pdf':
 
 
 
2606
  if ( empty( $_REQUEST['ewww_force'] ) ) {
2607
  $results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
2608
  if ( $results_msg ) {
@@ -2641,6 +2656,9 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2641
  copy( $file, $s3_uploads_image );
2642
  }
2643
  $file = ewww_image_optimizer_s3_uploads_image_cleanup( $file );
 
 
 
2644
  ewwwio_memory( __FUNCTION__ );
2645
  return array( $file, $results_msg, $converted, $original );
2646
  } else {
@@ -2648,31 +2666,38 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2648
  }
2649
  ewwwio_memory( __FUNCTION__ );
2650
  // Otherwise, send back the filename, the results (some sort of error message), the $converted flag, and the name of the original image.
 
 
 
 
2651
  return array( false, $result, $converted, $original );
2652
  }
2653
 
2654
  /**
2655
- * Creates webp images alongside JPG and PNG files.
2656
  *
2657
  * @param string $file The name of the JPG/PNG file.
2658
  * @param int $orig_size The filesize of the JPG/PNG file.
2659
  * @param string $type The mime-type of the incoming file.
2660
  * @param string $tool The path to the cwebp binary, if installed.
2661
  * @param bool $recreate True to keep the .webp image even if it is larger than the JPG/PNG.
 
2662
  */
2663
  function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $recreate = false ) {
2664
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2665
- // Change the file extension.
2666
- $webpfile = $file . '.webp';
2667
- $bypass_webp = apply_filters( 'ewww_image_optimizer_bypass_webp', false, $file );
2668
- if ( true === $bypass_webp ) {
2669
  ewwwio_debug_message( "webp generation bypassed: $file" );
2670
- return;
2671
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
2672
- return;
2673
- } elseif ( is_file( $webpfile ) && empty( $_REQUEST['ewww_force'] ) && ! $recreate ) {
 
 
 
 
2674
  ewwwio_debug_message( 'webp file exists, not forcing or recreating' );
2675
- return;
2676
  }
2677
  if ( empty( $tool ) ) {
2678
  ewww_image_optimizer_cloud_optimizer( $file, $type, false, $webpfile, 'image/webp' );
@@ -2693,28 +2718,38 @@ function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $rec
2693
  // Copy all the metadata.
2694
  $copy_opt = 'all';
2695
  }
 
 
 
 
 
 
2696
  switch ( $type ) {
2697
  case 'image/jpeg':
2698
- $quality = (int) apply_filters( 'jpeg_quality', 82, 'image/webp' );
2699
  exec( "$nice " . $tool . " -q $quality -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1', $cli_output );
2700
  break;
2701
  case 'image/png':
2702
- exec( "$nice " . $tool . " -lossless -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1', $cli_output );
2703
  break;
2704
  }
2705
  }
2706
  $webp_size = ewww_image_optimizer_filesize( $webpfile );
2707
  ewwwio_debug_message( "webp is $webp_size vs. $type is $orig_size" );
2708
- if ( is_file( $webpfile ) && $orig_size < $webp_size && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
2709
  ewwwio_debug_message( 'webp file was too big, deleting' );
2710
  unlink( $webpfile );
2711
- } elseif ( is_file( $webpfile ) ) {
 
2712
  // Set correct file permissions.
2713
  $stat = stat( dirname( $webpfile ) );
2714
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2715
  chmod( $webpfile, $perms );
 
 
 
 
2716
  }
2717
- ewwwio_memory( __FUNCTION__ );
2718
  }
2719
 
2720
  /**
@@ -2777,7 +2812,7 @@ function ewww_image_optimizer_install_pngout() {
2777
  true
2778
  );
2779
 
2780
- if ( is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2781
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
2782
  if ( empty( $pngout_error ) ) {
2783
  $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
@@ -2817,7 +2852,7 @@ function ewww_image_optimizer_install_pngout() {
2817
  'pngout-' . $latest . '-darwin/pngout',
2818
  true
2819
  );
2820
- if ( is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout' ) ) {
2821
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout', $tool_path . 'pngout-static' ) ) {
2822
  if ( empty( $pngout_error ) ) {
2823
  $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
183
  */
184
  function ewww_image_optimizer_notice_os() {
185
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
186
+ echo "<div id='ewww-image-optimizer-warning-os' class='notice notice-error'><p><strong>" . esc_html__( 'The free mode of EWWW Image Optimizer is only supported on Linux, FreeBSD, Mac OSX, Solaris, and Windows.', 'ewww-image-optimizer' ) . '</strong></p></div>';
 
 
187
  }
188
 
189
  /**
211
  $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-mac';
212
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-mac';
213
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-mac';
214
+ $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-mac14';
215
  $gifsicle_dst = $tool_path . 'gifsicle';
216
  $optipng_dst = $tool_path . 'optipng';
217
  $jpegtran_dst = $tool_path . 'jpegtran';
282
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
283
  $perms = fileperms( $file );
284
  ewwwio_debug_message( "permissions for $file: " . substr( sprintf( '%o', $perms ), -4 ) );
285
+ if ( ! ewwwio_is_file( $file ) ) {
286
  ewwwio_debug_message( 'permissions check failed, file not found' );
287
  return false;
288
  }
404
  ewwwio_debug_message( 'could not copy webp' );
405
  }
406
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
 
408
  if ( PHP_OS !== 'WINNT' && ! $toolfail ) {
409
  ewwwio_debug_message( 'Linux/UNIX style OS, checking permissions' );
918
  $binary_sum = hash_file( 'sha256', $path );
919
  ewwwio_debug_message( "$path: $binary_sum" );
920
  $valid_sums = array(
921
+ '463de9ba684d54d27185cb6487a0b22b7571a87419abde4dee72c9b107f23315', // jpegtran-mac 9, EWWW 1.3.0.
922
+ '0b94f82e3d740d1853281e9aaee5cc7122c27fd63da9d6d62ed3398997cbed1e', // jpegtran-linux 9, EWWW 1.4.0.
923
  'f5f079bfe6f3f48c17738679292f35cdee44afe8f8413cdbc4f555cee7de4173', // jpegtran-linux64 9, EWWW 1.4.0.
924
+ 'ec71f638d2101f08fab66f4d139746d4042352bc75d55bd093aa446081892e0c', // jpegtran-fbsd 9, EWWW 1.4.0.
925
+ '356532227fce51fcb9df29f143ab9d202fbd40f18e2b8234aee95937c93bd67e', // jpegtran-fbsd64 9, EWWW 1.4.0.
926
+ '7be857837764dff4f0d7d2c5d546bf4d2573af7f326ced908ac229d60fd054c6', // jpegtran.exe 9, EWWW 1.4.0.
927
+ 'bce5205bb240532c01273b5442a44244a8a27a74fb47e2ce467c18b91fabea6b', // jpegtran-sol 9, EWWW 1.7.4.
928
+ 'cadc7be4688632bf2860562a1596f1b2b54b9a9c8b27df7ecabca49b1dcd8a5f', // jpegtran-fbsd 9a, EWWW 2.0.0.
929
+ 'bab4aa853c143534503464eeb35893d16799cf859ff22f9a4e62aa383f4fc99c', // jpegtran-fbsd64 9a, EWWW 2.0.0.
930
+ 'deb7e0f579fac767196611aa110052864e3093017970ff74de709b41e265e8b1', // jpegtran-linux 9a, EWWW 2.0.0.
931
  'b991fde396ebcc0e4f805df44b1797fe369f7f19e9392684dd4052e3f23c441e', // jpegtran-linux64 9a, EWWW 2.0.0.
932
+ '436835bd42b27d2f05440bc5dc5174f2a896d38f8a550d96704d39969951d9ac', // jpegtran-mac 9a, EWWW 2.0.0.
933
+ 'bdf3c6b6cb16287a3f62e7cde8f69f8bda5d310abca28e00068c526f9f37cc89', // jpegtran-sol 9a, EWWW 2.0.0.
934
+ '3c2746d0b1ae150b13b767715af45ff601e394c01ada929cbe16e6dcd18fb199', // jpegtran.exe 9a, EWWW 2.0.0.
935
+ '8e11f7df5735b36d3ecc95c84b0e355355a766d3ccafbf751bcf343a8952432c', // jpegtran-fbsd 9b, EWWW 2.6.0.
936
  '21d8046e07cb298dfd2f3b1e321c67c378a4d35fa8adc3521acc42b5b8088d64', // jpegtran-linux 9b, EWWW 2.6.0.
937
+ '4d1a1c601d291f96dc03ea7e42ab9137a17f93ebc391353db65b4e32c1e9fbdb', // jpegtran-mac 9b, EWWW 2.6.0.
938
+ '7e8719703d31e1ab9bf2b2ad7ab633649012ab6aae46ea40462365b9c00876d5', // jpegtran-sol 9b, EWWW 2.6.0.
939
+ '9767f05ae1b59d4fea25a73b276dcd1245f5281b53386dc03784539265bffbea', // jpegtran.exe 9b, EWWW 2.6.0.
940
  // end jpegtran.
941
  '6deddb5562ac13ffc3e46a0af79b592e92fb4553c5df294b6e0052bc890fd0e3', // optipng-linux 0.7.4, EWWW 1.2.0.
942
  '51df81fa8c765efbe0aa4c1cf5293e25e7e2e7f6962f5161615239c54aec4c01', // optipng-linux 0.7.4, EWWW 1.3.0.
943
+ '7a56cca66471ce2b6cdff4460db0d75258ef05de8da1eda0448e4d4ad9ae252f', // optipng-mac 0.7.4, EWWW 1.3.0.
944
  '2f9140cdc3ef1f7687baa710f0bba84c5f7f11e3f62c3ce43124e23b849ac5ff', // optipng-linux 0.7.4, EWWW 1.3.7.
945
+ '5d59467363c457bf743f4df121c365dd43365357f1cdea5f3752a7ca1b3e315a', // optipng-fbsd 0.7.4, EWWW 1.4.0.
946
+ '1af8077958a88a3064a71903841f901179e27fe137774085565619fb199c653a', // optipng.exe 0.7.4, EWWW 1.4.0.
947
+ 'f692fef395b8689de033b9f2ce80c867c8a229c52e948df733377e20b62773a9', // optipng-sol 0.7.4, EWWW 1.7.4.
948
+ 'e17d327cd89ab34eff7f994806fe9f2c124d6cc6cd309fa4c3911d5ce90312c9', // optipng-fbsd 0.7.5, EWWW 2.0.0.
949
  'd263ecfb5b29ed08920e26cf604a86d3484daee5b80605e445cf97aa14d8aebc', // optipng-linux 0.7.5, EWWW 2.0.0.
950
+ '6f15cb2e8d25e51037efa7bcec7499c96eb11e576536a478edfee500207655ae', // optipng-mac 0.7.5, EWWW 2.0.0.
951
+ '1d2de40b009f16e9c709f9b0c15a47abb8da57668a918ac9a0723ddc6de6c30a', // optipng-sol 0.7.5, EWWW 2.0.0.
952
+ 'fad3a0fd95706d53576f72593bf13d3e31d1c896c852bfd5b9ba602eca0bd2b6', // optipng.exe 0.7.5, EWWW 2.0.0.
953
+ '9d60eaeb9dc5167a57a5f3af236d56b4149d1043b543f2faa38a0936fa6b54b2', // optipng-fbsd 0.7.6, EWWW 2.8.0.
954
  '853ca5936a2dd92a17b3518fd55db6be35e1b2bebfabca3949c34700072e08b8', // optipng-linux 0.7.6, EWWW 2.8.0.
955
+ 'd4f11e96733aed64a72e744843dcd0929e144a7fc97f40d405a034a72eb9bbc6', // optipng-mac 0.7.6, EWWW 2.8.0.
956
+ '1ed9343194cfca0a1c32677c974192746adfd48cb4cea6a2df668452df0e68f7', // optipng-sol 0.7.6, EWWW 2.8.0.
957
+ '03b86ce2c08e2cc78d76d3d3dd173986b498b055c3c19e13a97a7c3c674772c6', // optipng.exe 0.7.6, EWWW 2.8.0.
958
+ 'f01cba0ab658e08738315843ee635be273726bf102ae448416b3d8956843d864', // optipng-fbsd 0.7.7 EWWW 4.1.0.
959
  '4404076a4f9119d4dfbb7acb00eb65345e804186a019c7136d8f8e87fb0cb997', // optipng-linux 0.7.7 EWWW 4.1.0.
960
+ '36535c1b262e0c457bbb0ed2bc71e812a49e26a6cada63b6acbd8d809c68a5a1', // optipng-mac 0.7.7 EWWW 4.1.0.
961
+ '41a4c78e6c97ea26836f4b021157b34f1812a9e5c2341502aad8cde942b18576', // optipng-sol 0.7.7 EWWW 4.1.0.
962
+ '6a321e07eca8e28fa8a969b5db3c1d3cc008a2064d636cf74762bbe4364b7b14', // optipng.exe 0.7.7 EWWW 4.1.0.
963
  // end optipng.
964
  'a2292c0085863a65c99cb41ff8418ce63033e162906df72e8fdde52f0633579b', // gifsicle linux 1.67, EWWW 1.2.0.
965
  'd7f9609b6fd0000b2eaad2bd0c3cb85476988b18705762e915bda3f2e6007801', // gifsicle-linux 1.68, EWWW 1.3.0.
966
  '204a839a50367adb8cd23fae5d1913a5ca8b41307f054156ed152748d3e7934d', // gifsicle-linux 1.68, EWWW 1.3.7.
967
+ '23e208099fa7ce75a3f98144190d6362d69b90c6f0a534ffa45dbbf789f7d99c', // gifsicle-mac 1.68, EWWW 1.3.0.
968
+ '8b08243a7cc655512a03403f6c3814176e28bbd140df7c059bd321a9a0151c18', // gifsicle-fbsd 1.70, EWWW 1.4.0.
969
  'fd074673967ee9d387208f047c081a6331663b4076f4a6a608d6f646622af718', // gifsicle-linux 1.70, EWWW 1.4.0 - 1.7.4.
970
+ 'bc32a390e86d2d8f40e970b2dc059015b51afe26794d92a936c1fe7216db805d', // gifsicle-mac 1.70, EWWW 1.4.0.
971
+ '41e67a35cd178f781b5224d196185e4243e6c2b3bece43277130fe07cdda402f', // gifsicle-sol 1.70, EWWW 1.7.4.
972
+ '3c6d9fabd1ea1014b8f58063dd00a653980c06bc1b45e96a47d866247263a1e1', // gifsicle.exe 1.70, EWWW 1.4.0.
973
+ 'decba7a95b637bee53847af680fd37bde8bd568528412c514b7bd794056fd4ff', // gifsicle-fbsd 1.78, EWWW 1.7.5.
974
  'c28e5e4b5344f77f415973d013e4cb393fc550e8de44117b090d534e98b30d1c', // gifsicle-linux 1.78, EWWW 1.7.5 - 1.9.3.
975
+ 'fc2de863e8579b0d540003300e918cee450bc8e026018c631dffc0ed851a8c1c', // gifsicle-mac 1.78, EWWW 1.7.5.
976
+ '74d011ee1b6d9fe6d5d8bdb4cd17db0c5987fa6e3d495b42439cd70b0763c07a', // gifsicle-sol 1.78, EWWW 1.7.5.
977
+ '7c10da38f4afb28373779d40a30710aa9fb369e82f7f29363554bea965d132df', // gifsicle.exe 1.78, EWWW 1.7.5.
978
+ 'e75acedd0725fba64ee72855b796cdfa8dac9959d63e89a9e0e5ba059ae013c2', // gifsicle-fbsd 1.84, EWWW 2.0.0.
979
  'a4f0f21bc4bea51f5d304fe944262c12f671d70a3e5f688061da7bb036e84ff8', // gifsicle-linux 1.84, EWWW 2.0.0 - 2.4.3.
980
+ '5f4176b3fe69f975563d2ce7e76615ab558f5f1839b9bfa6f6de1b3c3fa11c02', // gifsicle-mac 1.84, EWWW 2.0.0.
981
+ '9f0027bed22d4be60012488ab726c3a131d9f3e1e276e9400c578173347a9a48', // gifsicle-sol 1.84, EWWW 2.0.0.
982
+ '72f0077e8591292d09efee09a181458b34fb3c0e9a6ac7e8e11cec574bf619ac', // gifsicle.exe 1.84, EWWW 2.0.0.
983
+ 'c64936b429e46b6a75339df00eb8daa39d335844c906fa16d4d0af481851e91e', // gifsicle-fbsd 1.87, EWWW 2.4.4.
984
  'deea065a91c8429edecf42ccef78636065f7ae0dad867df7696128c6711e4735', // gifsicle-linux 1.87, EWWW 2.4.4.
985
+ '2e0d8b7413173555bbec6e019c3cd7c55f7d582a017a0af7b14cfd24a6921f51', // gifsicle-mac 1.87, EWWW 2.4.4.
986
+ '3966e01474601059c6a13aefbe4f313c6cb6d49c799f7850966950892a9ab45a', // gifsicle-sol 1.87, EWWW 2.4.4.
987
+ '40b86b2ea6642f4c921152923af1e631922b624f7d23189f53c659506c7179b5', // gifsicle.exe 1.87, EWWW 2.4.4.
988
+ '3da9e1a764a459d78dc1468ba60d882ff042050a86f82d895777b172b50f2f19', // gifsicle.exe 1.87, EWWW 2.4.5.
989
+ '327c21635ea8c789e3e9533210e6baf372db27c7bbed3791881d74a7dd41cef9', // gifsicle-fbsd 1.91, EWWW 4.1.0.
990
  '566f058b2043c4f3c8c049b0507bfa78dcb33dac52b132cade5f67bbb62d91e4', // gifsicle-linux 1.91, EWWW 4.1.0.
991
+ '03602b141432af2211882fc079ba15a773a7ec782c92755cb31279eb6d8b99d4', // gifsicle-mac 1.91, EWWW 4.1.0.
992
+ '5fcdd102146984e41b01a160d072dd36852d7be14ab569a323c47e7e56916d0d', // gifsicle-sol 1.91, EWWW 4.x.
993
+ '7156bfe16dc5e33af7facdc6847d268154ffeb75c0217517e4e188b58b293c6a', // gifsicle.exe 1.91, EWWW 4.1.0.
994
  // end gifsicle.
995
  'bdea95497d6e60aae8938cae8e999ef74a255ad603531bf523dcdb531f61fc8f', // 20110722-bsd/i686/pngout.
996
  '57c09b3ebd7d4623d16f6056efd7951e8f98e2362a27993a7d865af677875c00', // 20110722-bsd-static/i686/pngout-static.
1020
  '843f0be42e86680c1663c4ef58eb0677ace15fc29ab23897c83f4b7e5af3ef36', // 20150319-windows/pngout.exe 20150319.
1021
  'aa3993937455094c0f66ac77d60bf53be441fdf8f14618520c2af68f2253085d', // 20150920-mac/pngout.
1022
  // end pngout.
1023
+ '8417d5d60bc66442ecc666e31ec7b9e1b7c55f48291e74b4b81f35703e2aef2e', // pngquant-fbsd 2.0.2, EWWW 1.8.3.
1024
  '78668c38d0be70764b18f3f4e0ea2b647df2ae87cedb2216d0ef69c8c55b688a', // pngquant-linux 2.0.2, EWWW 1.8.3.
1025
+ '7df1b7f6ed73a189083dd931fb3380d236d34790318f00233b59c8f26f90665f', // pngquant-mac 2.0.2, EWWW 1.8.3.
1026
+ '56d2c6212eb595f5eab8a7469e56fa8d3d0e6ffc231aef27742134fba4a39298', // pngquant-sol 2.0.2, EWWW 1.8.3.
1027
+ 'd3851c962cd59d74a35174bf3ce71d876dfcd8bdf76f81cd428b2ab7e53c0515', // pngquant.exe 2.0.2, EWWW 1.8.3.
1028
+ '0ee6f1dbf4fa168b11ce60860e5700ca0e5125323a43540a78c76644835abc84', // pngquant-fbsd 2.3.0, EWWW 2.0.0.
1029
  '85d8a70930a554f50181a1d061577cf67ef2e76e2cbd5bcb1b7f006064ff1444', // pngquant-linux 2.3.0, EWWW 2.0.0.
1030
+ 'a807f769922fdad0ba07307c548df8cf8eeced649d04237d13dfc95757161459', // pngquant-mac 2.3.0, EWWW 2.0.0.
1031
+ 'cf2cc40274c438b35e93bd0346c2a6d871bd7a7bdd90c52f4e79f369cb8ded74', // pngquant-sol 2.3.0, EWWW 2.0.0.
1032
+ '7454aba77b1a2b63a42d8a5870d3c2d733c7efb2d828643d5e64784af1f65f2a', // pngquant.exe 2.3.0, EWWW 2.0.0.
1033
+ '6287f1bb7179c7b6d71a41112222347ed97b6eae4e79b180d7e1e332a4bde3e2', // pngquant-fbsd 2.5.2, EWWW 2.5.4.
1034
  'fcfe4d3a602e7b491f4126a2707144f5f9cc9359d13f443575d7ea6a74e85ddb', // pngquant-linux 2.5.2, EWWW 2.5.4.
1035
+ '35794819a35e949dc0c0d6f90d0bb675791fa9bc3f405eb19f48ea31bb6456a8', // pngquant-mac 2.5.2, EWWW 2.5.4.
1036
+ 'c242586c70d83af544334f1846b838ef68c6ab4fc247b2cff9ad4b714f825866', // pngquant-sol 2.5.2, EWWW 2.5.4.
1037
+ 'ad79d9b3395d41404b28362972bd68db3c58d5be5f063884df3a595fc38c6a98', // pngquant.exe 2.5.2, EWWW 2.5.4.
1038
+ '54d632fc4446d88ad4d1beeaf73420d68d87786f02adc9d3363766cb93ec95a4', // pngquant-fbsd 2.9.1, EWWW 3.4.0.
1039
  '91f704f02468f86766007e46973a1ef9e282d6ccadc54caf339dc537c9b2b61d', // pngquant-linux 2.9.1, EWWW 3.4.0.
1040
+ '65dc20f05af588d948fc6f4df37c294f4a3a1c1ad207a8b56d13e6829773165a', // pngquant-mac 2.9.1, EWWW 3.4.0.
1041
+ 'dbc9e12d5bb3e806aaf5e2c3d30d122d569069027a633485761cbf072cf2236d', // pngquant-sol 2.9.1, EWWW 3.4.0.
1042
+ '84e63e6f9f9630a1a0c3e782609349c12b8df9ea9d02c5a29230819379e56b3c', // pngquant.exe 2.8.1, EWWW 3.4.0.
1043
+ 'd6433dc6ecf6a0fdedf754782e6d5c9e494ddec762426a6d0b1896a220bd6d3f', // pngquant-fbsd 2.11.7 EWWW 4.1.0.
1044
  '40b0860abba39342fb64612a612e0f24571d259b6b83d7483af9a1d586950d79', // pngquant-linux 2.11.7 EWWW 4.1.0.
1045
+ 'c924e11d9a3166afd5ed19165193c1351ff4a2cc993498f1f28c7daee829ca76', // pngquant-mac 2.11.7 EWWW 4.1.0.
1046
+ '34534e69929e7fe267f77c55f487e419f76cc1d24e41fdb642f9671383012c56', // pngquant-sol 2.11.7 EWWW 4.1.0.
1047
+ 'af7598aa09ba519ad15305a56011949db19c5b2176187662640bc0ebc4ddd19a', // pngquant.exe 2.11.7 EWWW 4.1.0.
1048
+ '6b1d4e685a4f5b3cbed9b9c7b71c7f75ae860684783e4a8274cdc66247d11fae', // pngquant.exe 2.12.5 EWWW 5.1.0.
1049
+ '1ab09e21dd0c8aafe482227c2b53f13faf00fa9ba2b9046c1e9f8c4d4d851b9d', // pngquant-fbsd 2.12.5 EWWW 5.1.0.
1050
+ 'b580c7d68c3ec7cd7685fb388cdbb2635aae92c7d520e54e8f67c57fc6215db0', // pngquant-linux 2.12.5 EWWW 5.1.0.
1051
+ 'ddec62d4074d54d76dde9313302b6a95025286ad82006a0f83eb0452cc86da6c', // pngquant-mac 2.12.5 EWWW 5.1.0.
1052
+ '7c10d643f936114aaa307c5fa2024c5bd5f9a25fa90a07e7f2b100c161f15898', // pngquant-sol 2.12.5 EWWW 5.1.0.
1053
  // end pngquant.
1054
  'bf0e12f996802dc114a864e5150647ce41089a5a2b5e36c3a270ac848b655c26', // cwebp-fbsd 0.4.1, EWWW 2.0.0.
1055
  '5349646072c3ef5f8b4588bbee8635e882c245439e2d86b863f04b7e27f4fafe', // cwebp-fbsd64 0.4.1, EWWW 2.0.0.
1075
  'b2bef90b62d80b35d4c5a41f793454e95e5159bf0aec2e4bd8c19fc3de3556bd', // cwebp-linux664 0.4.4, EWWW 2.5.4.
1076
  'd3c358524efd50f6e078362733870229ca1e1db8885580b6814c2535b4d20612', // cwebp-linux8 0.4.4, EWWW 2.5.4.
1077
  '271deeec579c252e364495addad03d9c1f3248c2177a01638002b25eee787ded', // cwebp-linux864 0.4.4, EWWW 2.5.4.
1078
+ '379e2b95e20dd33f4667c134099df358e178f6a6bf32f3a5b6b78bbb6950b4b5', // cwebp-mac9 0.4.4, EWWW 2.5.4.
1079
+ '118ea3f0bcdcce6128d64e34159c93c3324cb038c9e5a51efaf530ea52af7070', // cwebp-sol 0.4.4, EWWW 2.5.4.
1080
+ '43941c1d7169e66fb1fd62a1950286b230d3e5bec3bbb14fdb4ac091ca7a0f9f', // cwebp.exe 0.4.4, EWWW 2.5.4.
1081
+ '26d5d88dee2993d1d0e16f5e60318cd8adec485614facd6c7f9c22c71eb7b2e5', // cwebp-fbsd 0.5.0, EWWW 2.6.0.
1082
  '60b1738d6502691227a46658cd7656b4a52702680f169e8e04d72077e967aeed', // cwebp-linux 0.5.0, EWWW 2.6.0.
1083
+ '276a0221a4c978825903572c2b68b3010399375d6b9dc7429286caf625cae95a', // cwebp-mac9 0.5.0, EWWW 2.6.0.
1084
+ 'be3e81ec7267e7878ddd4ee01df1553966952f74bbfd30a5523d12d53f019ecb', // cwebp-sol 0.5.0, EWWW 2.6.0.
1085
+ 'b41123ec06f21765f50ec1b017839f99ab4f28497d87da722817a6023e4a3b32', // cwebp.exe 0.5.0, EWWW 2.6.0.
1086
+ 'f0547a6219c5c05d0af29c5e411e054b9d795567f4ae2e27893815af9383c60f', // cwebp-fbsd 0.5.1, EWWW 2.9.9.
1087
  '9eaf670bb2d567421c7e2918112dc00406c60f008b120f648cf0bdba73ee9b6b', // cwebp-linux 0.5.1, EWWW 2.9.9.
1088
+ '1202ea932b315913d3736460dd3d50bc5b251b7a0a8f0468c63144ba427679c2', // cwebp-mac9 0.5.1, EWWW 2.9.9.
1089
+ '27ba0abce52e74744f6235fcde9b153b5052b9c15cd78e74feffaea9dafcc178', // cwebp-sol 0.5.1, EWWW 2.9.9.
1090
+ 'b02864989f0a1a263caa796c5b8caf18c1f774ed0ba08a9350e8820459875f51', // cwebp.exe 0.5.1, EWWW 2.9.9.
1091
+ 'e5cbea11c97fadffe221fdf57c093c19af2737e4bbd2cb3cd5e908de64286573', // cwebp-fbsd 0.6.0, EWWW 3.4.0.
1092
  '43ca351e8f5d457b898c587151ebe3d8f6cce8dcfb7de44f6cb70148a31a68bc', // cwebp-linux 0.6.0, EWWW 3.4.0.
1093
  'a06a3ee436e375c89dbc1b0b2e8bd7729a55139ae072ed3f7bd2e07de0ebb379', // cwebp-mac12 0.6.0, EWWW 3.4.0.
1094
+ '1febaffbb18e52dc2c524cda9eefd00c6db95bc388732868999c0f48deb73b4f', // cwebp-sol 0.6.0, EWWW 3.4.0.
1095
+ '49e9cb98db30bfa27936933e6fd94d407e0386802cb192800d9fd824f6476873', // cwebp.exe 0.6.0, EWWW 3.4.0.
1096
+ 'dde516a971fed2960442e3354df9e8043328acecfd1d68dae8712183a0a06f48', // cwebp-fbsd 1.0.3, EWWW 5.1.0.
1097
+ '90a506eea038e89ef53b41bfcae2cf2d67db6a3eae57fa43ca02da407420e0b6', // cwebp-linux 1.0.3, EWWW 5.1.0.
1098
+ '7332ed5f0d4091e2379b1eaa32a764f8c0d51b7926996a1dc8b4ef4e3c441a12', // cwebp-mac14 1.0.3, EWWW 5.1.0.
1099
+ '66568f3b31f8f22deef38aa6ba3d2be19516514e94b7d623cd2ce2a290ccdd69', // cwebp-sol 1.0.3, EWWW 5.1.0.
1100
+ 'e1041c5486fb4e57e31155c45d66117f8fc270e5a56a1049408a05f54bd52969', // cwebp.exe 1.0.3, EWWW 5.1.0.
1101
  // end cwebp.
1102
  );
1103
  foreach ( $valid_sums as $checksum ) {
1125
  function ewww_image_optimizer_mimetype( $path, $case ) {
1126
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1127
  ewwwio_debug_message( "testing mimetype: $path" );
1128
+ if ( false !== strpos( $path, '..' ) ) {
1129
+ return false;
1130
+ }
1131
  $type = false;
1132
  // For S3 images/files, don't attempt to read the file, just use the quick (filename) mime check.
1133
  if ( 'i' === $case && ewww_image_optimizer_stream_wrapped( $path ) ) {
1418
  ewwwio_debug_message( "$path: invalid output" );
1419
  break;
1420
  }
1421
+ if ( ! empty( $webp_version ) && preg_match( '/\d.\d.\d/', $webp_version[0] ) ) {
1422
  ewwwio_debug_message( 'optimizer found' );
1423
  return $webp_version[0];
1424
  }
1743
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
1744
  ewww_image_optimizer_cloud_init();
1745
  }
1746
+ if ( apply_filters( 'ewww_image_optimizer_bypass', false, $file ) ) {
 
1747
  ewwwio_debug_message( "optimization bypassed: $file" );
1748
  // Tell the user optimization was skipped.
1749
  return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
1765
  // Initialize the original filename.
1766
  $original = $file;
1767
  $result = '';
1768
+ if ( false !== strpos( $file, '..' ) ) {
1769
+ $msg = __( 'Path traversal in filename not allowed.', 'ewww-image-optimizer' );
1770
+ ewwwio_debug_message( "file is using .. potential path traversal blocked: $file" );
1771
+ ewww_image_optimizer_s3_uploads_image_cleanup( $file );
1772
+ return array( false, $msg, $converted, $original );
1773
+ }
1774
+ if ( ! ewwwio_is_file( $file ) ) {
1775
  /* translators: %s: Image filename */
1776
  $msg = sprintf( __( 'Could not find %s', 'ewww-image-optimizer' ), $file );
1777
  ewwwio_debug_message( "file doesn't appear to exist: $file" );
1778
  ewww_image_optimizer_s3_uploads_image_cleanup( $file );
1779
  return array( false, $msg, $converted, $original );
1780
  }
1781
+ if ( ! is_writable( $file ) ) {
1782
  /* translators: %s: Image filename */
1783
  $msg = sprintf( __( '%s is not writable', 'ewww-image-optimizer' ), $file );
1784
  ewwwio_debug_message( "couldn't write to the file $file" );
1898
  if (
1899
  1 === (int) $gallery_type &&
1900
  $fullsize &&
1901
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) || ! empty( $_REQUEST['ewww_convert'] ) ) &&
1902
+ empty( $_REQUEST['ewww_webp_only'] )
1903
  ) {
1904
  // Generate the filename for a PNG:
1905
  // If this is a resize version.
1925
  }
1926
  }
1927
  $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
1928
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 && empty( $_REQUEST['ewww_webp_only'] ) ) {
1929
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
1930
  if ( $converted ) {
1931
  // Check to see if the user wants the originals deleted.
1933
  // Delete the original JPG.
1934
  unlink( $original );
1935
  }
1936
+ $converted = $filenum;
1937
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, 'image/png', null, $orig_size !== $new_size );
1938
  } else {
1939
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
1940
  }
1941
  break;
1942
  }
1963
  ! $skip['webp']
1964
  );
1965
  }
1966
+ if ( ! empty( $_REQUEST['ewww_webp_only'] ) ) {
1967
+ $optimize = false;
1968
+ } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) ) {
1969
  // Store an appropriate message in $result.
1970
  $result = __( 'JPG optimization is disabled', 'ewww-image-optimizer' );
1971
  // Otherwise, if we aren't skipping the utility verification and jpegtran doesn't exist.
2008
  $result = "$orig_size vs. $new_size";
2009
  // If the optimization didn't produce a smaller JPG.
2010
  } else {
2011
+ if ( ewwwio_is_file( $progfile ) ) {
2012
  // Delete the optimized file.
2013
  unlink( $progfile );
2014
  }
2017
  $new_size = $orig_size;
2018
  }
2019
  } elseif ( ! $convert ) {
2020
+ ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
2021
  // If conversion and optimization are both turned OFF, finish the JPG processing.
2022
+ $webp_result = ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['CWEBP'] );
2023
  break;
2024
  } // End if().
2025
  // If the conversion process is turned ON, or if this is a resize and the full-size was converted.
2061
  ewwwio_debug_message( 'attempting lossy reduction' );
2062
  exec( "$nice " . $tools['PNGQUANT'] . ' ' . ewww_image_optimizer_escapeshellarg( $pngfile ) );
2063
  $quantfile = preg_replace( '/\.\w+$/', '-fs8.png', $pngfile );
2064
+ if ( ewwwio_is_file( $quantfile ) && filesize( $pngfile ) > filesize( $quantfile ) ) {
2065
  ewwwio_debug_message( 'lossy reduction is better: original - ' . filesize( $pngfile ) . ' vs. lossy - ' . filesize( $quantfile ) );
2066
  rename( $quantfile, $pngfile );
2067
+ } elseif ( ewwwio_is_file( $quantfile ) ) {
2068
  ewwwio_debug_message( 'lossy reduction is worse: original - ' . filesize( $pngfile ) . ' vs. lossy - ' . filesize( $quantfile ) );
2069
  unlink( $quantfile );
2070
  } else {
2120
  ewwwio_debug_message( 'converted PNG is no good' );
2121
  // Otherwise delete the PNG.
2122
  $converted = false;
2123
+ if ( ewwwio_is_file( $pngfile ) ) {
2124
  unlink( $pngfile );
2125
  }
2126
  }
2127
  } // End if().
2128
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size !== $new_size );
2129
  break;
2130
  case 'image/png':
2131
  $jpg_size = 0;
2135
  1 === (int) $gallery_type &&
2136
  $fullsize &&
2137
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) || ! empty( $_REQUEST['ewww_convert'] ) ) &&
2138
+ ! $skip_lossy &&
2139
+ empty( $_REQUEST['ewww_webp_only'] )
2140
  ) {
2141
  ewwwio_debug_message( 'PNG to JPG conversion turned on' );
2142
  $cloud_background = '';
2185
  }
2186
  }
2187
  $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
2188
+ if (
2189
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) >= 20 &&
2190
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
2191
+ empty( $_REQUEST['ewww_webp_only'] )
2192
+ ) {
2193
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer(
2194
  $file,
2195
  $type,
2206
  // Delete the original JPG.
2207
  unlink( $original );
2208
  }
2209
+ $converted = $filenum;
2210
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, 'image/jpeg', null, $orig_size !== $new_size );
2211
  } else {
2212
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
2213
  }
2214
  break;
2215
  }
2233
  );
2234
  }
2235
  // If png optimization is disabled.
2236
+ if ( ! empty( $_REQUEST['ewww_webp_only'] ) ) {
2237
+ $optimize = false;
2238
+ } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) ) {
2239
  // Tell the user all PNG tools are disabled.
2240
  $result = __( 'PNG optimization is disabled', 'ewww-image-optimizer' );
2241
  // If the utility checking is on, optipng is enabled, but optipng cannot be found.
2257
  ewwwio_debug_message( 'attempting lossy reduction' );
2258
  exec( "$nice " . $tools['PNGQUANT'] . ' ' . ewww_image_optimizer_escapeshellarg( $file ) );
2259
  $quantfile = preg_replace( '/\.\w+$/', '-fs8.png', $file );
2260
+ if ( ewwwio_is_file( $quantfile ) && filesize( $file ) > filesize( $quantfile ) && ewww_image_optimizer_mimetype( $quantfile, 'i' ) === $type ) {
2261
  ewwwio_debug_message( 'lossy reduction is better: original - ' . filesize( $file ) . ' vs. lossy - ' . filesize( $quantfile ) );
2262
  rename( $quantfile, $file );
2263
+ } elseif ( ewwwio_is_file( $quantfile ) ) {
2264
  ewwwio_debug_message( 'lossy reduction is worse: original - ' . filesize( $file ) . ' vs. lossy - ' . filesize( $quantfile ) );
2265
  unlink( $quantfile );
2266
  } else {
2298
  $result = "$orig_size vs. $new_size";
2299
  // If the optimization didn't produce a smaller PNG.
2300
  } else {
2301
+ if ( ewwwio_is_file( $tempfile ) ) {
2302
  // Delete the optimized file.
2303
  unlink( $tempfile );
2304
  }
2309
  } elseif ( ! $convert ) {
2310
  // If conversion and optimization are both disabled we are done here.
2311
  ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
2312
+ $webp_result = ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['CWEBP'] );
2313
  break;
2314
  } // End if().
2315
  // Retrieve the new filesize of the PNG.
2420
  $jpg_size = $opt_jpg_size;
2421
  ewwwio_debug_message( 'optimized JPG was smaller than un-optimized version' );
2422
  // If the optimization didn't produce a smaller JPG.
2423
+ } elseif ( ewwwio_is_file( $progfile ) ) {
2424
  unlink( $progfile );
2425
  }
2426
  }
2442
  $converted = $filenum;
2443
  } else {
2444
  $converted = false;
2445
+ if ( ewwwio_is_file( $jpgfile ) ) {
2446
  // Otherwise delete the new JPG.
2447
  unlink( $jpgfile );
2448
  }
2449
  }
2450
  } // End if().
2451
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size !== $new_size );
2452
  break;
2453
  case 'image/gif':
2454
+ if ( ! empty( $_REQUEST['ewww_webp_only'] ) ) {
2455
+ break;
2456
+ }
2457
  // If gif2png is turned on, and the image is in the WordPress media library.
2458
  if (
2459
  1 === (int) $gallery_type &&
2493
  // Delete the original GIF.
2494
  unlink( $original );
2495
  }
2496
+ $converted = $filenum;
2497
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, 'image/png', null, $orig_size !== $new_size );
2498
  }
2499
  break;
2500
  }
2543
  $result = "$orig_size vs. $new_size";
2544
  // If the optimization didn't produce a smaller GIF.
2545
  } else {
2546
+ if ( ewwwio_is_file( $tempfile ) ) {
2547
  // Delete the optimized file.
2548
  unlink( $tempfile );
2549
  }
2603
  // Let webp know what we're dealing with now.
2604
  $type = 'image/png';
2605
  // Normally this would be at the end of the section, but we only want to do webp if the image was successfully converted to a png.
2606
+ $webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size !== $new_size );
2607
  // Successful conversion, so we store the increment.
2608
  $converted = $filenum;
2609
  } else {
2610
  $converted = false;
2611
+ if ( ewwwio_is_file( $pngfile ) ) {
2612
  unlink( $pngfile );
2613
  }
2614
  }
2615
  } // End if().
2616
  break;
2617
  case 'application/pdf':
2618
+ if ( ! empty( $_REQUEST['ewww_webp_only'] ) ) {
2619
+ break;
2620
+ }
2621
  if ( empty( $_REQUEST['ewww_force'] ) ) {
2622
  $results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
2623
  if ( $results_msg ) {
2656
  copy( $file, $s3_uploads_image );
2657
  }
2658
  $file = ewww_image_optimizer_s3_uploads_image_cleanup( $file );
2659
+ if ( ! empty( $webp_result ) ) {
2660
+ $results_msg .= '<br>' . $webp_result;
2661
+ }
2662
  ewwwio_memory( __FUNCTION__ );
2663
  return array( $file, $results_msg, $converted, $original );
2664
  } else {
2666
  }
2667
  ewwwio_memory( __FUNCTION__ );
2668
  // Otherwise, send back the filename, the results (some sort of error message), the $converted flag, and the name of the original image.
2669
+ if ( ! empty( $webp_result ) && ! empty( $_REQUEST['ewww_webp_only'] ) ) {
2670
+ $result = $webp_result;
2671
+ return array( true, $result, $converted, $original );
2672
+ }
2673
  return array( false, $result, $converted, $original );
2674
  }
2675
 
2676
  /**
2677
+ * Creates WebP images alongside JPG and PNG files.
2678
  *
2679
  * @param string $file The name of the JPG/PNG file.
2680
  * @param int $orig_size The filesize of the JPG/PNG file.
2681
  * @param string $type The mime-type of the incoming file.
2682
  * @param string $tool The path to the cwebp binary, if installed.
2683
  * @param bool $recreate True to keep the .webp image even if it is larger than the JPG/PNG.
2684
+ * @return string Results of the WebP operation for display.
2685
  */
2686
  function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $recreate = false ) {
2687
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2688
+ $webpfile = $file . '.webp';
2689
+ if ( apply_filters( 'ewww_image_optimizer_bypass_webp', false, $file ) ) {
 
 
2690
  ewwwio_debug_message( "webp generation bypassed: $file" );
2691
+ return '';
2692
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
2693
+ return '';
2694
+ } elseif ( ! ewwwio_is_file( $file ) ) {
2695
+ return esc_html__( 'Could not find file.', 'ewww-image-optimizer' );
2696
+ } elseif ( ! is_writable( $file ) ) {
2697
+ return esc_html__( 'File is not writable.', 'ewww-image-optimizer' );
2698
+ } elseif ( ewwwio_is_file( $webpfile ) && empty( $_REQUEST['ewww_force'] ) && ! $recreate ) {
2699
  ewwwio_debug_message( 'webp file exists, not forcing or recreating' );
2700
+ return esc_html__( 'WebP image already exists.', 'ewww-image-optimizer' );
2701
  }
2702
  if ( empty( $tool ) ) {
2703
  ewww_image_optimizer_cloud_optimizer( $file, $type, false, $webpfile, 'image/webp' );
2718
  // Copy all the metadata.
2719
  $copy_opt = 'all';
2720
  }
2721
+ $quality = (int) apply_filters( 'jpeg_quality', 82, 'image/webp' );
2722
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP' ) && EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP ) {
2723
+ $lossless = "-q $quality";
2724
+ } else {
2725
+ $lossless = '-lossless';
2726
+ }
2727
  switch ( $type ) {
2728
  case 'image/jpeg':
 
2729
  exec( "$nice " . $tool . " -q $quality -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1', $cli_output );
2730
  break;
2731
  case 'image/png':
2732
+ exec( "$nice " . $tool . " $lossless -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1', $cli_output );
2733
  break;
2734
  }
2735
  }
2736
  $webp_size = ewww_image_optimizer_filesize( $webpfile );
2737
  ewwwio_debug_message( "webp is $webp_size vs. $type is $orig_size" );
2738
+ if ( ewwwio_is_file( $webpfile ) && $orig_size < $webp_size && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
2739
  ewwwio_debug_message( 'webp file was too big, deleting' );
2740
  unlink( $webpfile );
2741
+ return esc_html__( 'WebP image was larger than original.', 'ewww-image-optimizer' );
2742
+ } elseif ( ewwwio_is_file( $webpfile ) ) {
2743
  // Set correct file permissions.
2744
  $stat = stat( dirname( $webpfile ) );
2745
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2746
  chmod( $webpfile, $perms );
2747
+ if ( $orig_size < $webp_size && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
2748
+ return esc_html__( 'WebP image larger than original, saved anyway with Force WebP option.', 'ewww-image-optimizer' );
2749
+ }
2750
+ return 'WebP: ' . ewww_image_optimizer_image_results( $orig_size, $webp_size );
2751
  }
2752
+ return esc_html__( 'Image could not be converted to WebP.', 'ewww-image-optimizer' );
2753
  }
2754
 
2755
  /**
2812
  true
2813
  );
2814
 
2815
+ if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2816
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
2817
  if ( empty( $pngout_error ) ) {
2818
  $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
2852
  'pngout-' . $latest . '-darwin/pngout',
2853
  true
2854
  );
2855
+ if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout' ) ) {
2856
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout', $tool_path . 'pngout-static' ) ) {
2857
  if ( empty( $pngout_error ) ) {
2858
  $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );