EWWW Image Optimizer - Version 5.1.4

Version Description

  • fixed: warnings on FlaGallery's manage gallery page
  • fixed: cwebp version test results in false-positives
  • fixed: EWWW IO resize limits are ignored when higher than WP default
  • fixed: PNGOUT warning during one-click conversion
  • fixed: WebP images not removed from remote storage when an attachment is deleted (WP Offload Media)
  • fixed: after running regen for single thumbs with Image Regenerate & Select Crop plugin, regenerated images were not automatically optimized
Download this release

Release Info

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

Code changes from version 5.1.1 to 5.1.4

.travis.yml CHANGED
@@ -22,7 +22,7 @@ services:
22
 
23
  env:
24
  - WP_VERSION=latest WP_MULTISITE=0
25
- - WP_VERSION=4.9 WP_MULTISITE=0
26
 
27
  matrix:
28
  include:
@@ -44,7 +44,7 @@ before_script:
44
  composer global require phpunit/phpunit ^5
45
  fi
46
  - |
47
- - composer global require wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer
48
 
49
  script:
50
  - if [[ "$WPSNIFF" == "1" ]]; then phpcs --standard=phpcs.ruleset.xml --extensions=php .; fi
22
 
23
  env:
24
  - WP_VERSION=latest WP_MULTISITE=0
25
+ - WP_VERSION=5.0 WP_MULTISITE=0
26
 
27
  matrix:
28
  include:
44
  composer global require phpunit/phpunit ^5
45
  fi
46
  - |
47
+ - composer global require squizlabs/php_codesniffer:3.5.0 wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer
48
 
49
  script:
50
  - if [[ "$WPSNIFF" == "1" ]]; then phpcs --standard=phpcs.ruleset.xml --extensions=php .; fi
aux-optimize.php CHANGED
@@ -42,39 +42,20 @@ function ewww_image_optimizer_aux_images() {
42
  }
43
  echo $output;
44
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
45
- /* $help_instructions = esc_html__( 'Please turn on the Debugging option. Then copy and paste the Debug Information from the bottom of the settings page. This will allow us to assist you more quickly.', 'ewww-image-optimizer' ); */
46
  $current_user = wp_get_current_user();
47
  $help_email = $current_user->user_email;
48
- $hs_config = array(
49
- 'color' => '#3eadc9',
50
- 'icon' => 'buoy',
51
- 'instructions' => $help_instructions,
52
- 'poweredBy' => false,
53
- 'showContactFields' => true,
54
- 'showSubject' => true,
55
- 'topArticles' => true,
56
- 'zIndex' => 100000,
57
- );
58
- $hs_identify = array(
59
- 'email' => utf8_encode( $help_email ),
60
- );
61
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
62
- $eio_debug_array = explode( '<br>', $eio_debug );
63
- $eio_debug_i = 0;
64
- foreach ( $eio_debug_array as $eio_debug_line ) {
65
- $hs_identify[ 'debug_info_' . $eio_debug_i ] = $eio_debug_line;
66
- $eio_debug_i++;
67
  }
68
  }
69
  ?>
70
- <script type='text/javascript'>
71
- !function(e,o,n){window.HSCW=o,window.HS=n,n.beacon=n.beacon||{};var t=n.beacon;t.userConfig={},t.readyQueue=[],t.config=function(e){this.userConfig=e},t.ready=function(e){this.readyQueue.push(e)},o.config={docs:{enabled:!0,baseUrl:"//ewwwio.helpscoutdocs.com/"},contact:{enabled:!0,formId:"af75cf17-310a-11e7-9841-0ab63ef01522"}};var r=e.getElementsByTagName("script")[0],c=e.createElement("script");c.type="text/javascript",c.async=!0,c.src="https://djtflbt20bdde.cloudfront.net/",r.parentNode.insertBefore(c,r)}(document,window.HSCW||{},window.HS||{});
72
- HS.beacon.config(<?php echo json_encode( $hs_config ); ?>);
73
- HS.beacon.ready(function() {
74
- HS.beacon.identify(
75
- <?php echo json_encode( $hs_identify ); ?>
76
- );
77
- });
78
  </script>
79
  <?php
80
  }
@@ -863,8 +844,8 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
863
  $upload_dir = wp_upload_dir();
864
  // Retrieve the path of the upload folder.
865
  $upload_path = $upload_dir['basedir'];
866
- $this_month = date( 'm' );
867
- $this_year = date( 'Y' );
868
  ewww_image_optimizer_image_scan( "$upload_path/$this_year/$this_month/", $started );
869
  if ( class_exists( 'DateTime' ) ) {
870
  $date = new DateTime();
@@ -888,8 +869,8 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
888
  $usage = ewww_image_optimizer_cloud_quota( true );
889
  }
890
  ewwwio_memory( __FUNCTION__ );
891
- /* translators: %d: number of images */
892
- $ready_msg = sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $image_count, 'ewww-image-optimizer' ) ), $image_count );
893
  if ( is_array( $usage ) && ! $usage['metered'] ) {
894
  $credits_available = $usage['licensed'] - $usage['consumed'];
895
  if ( $credits_available < $image_count ) {
@@ -903,8 +884,10 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
903
  die(
904
  ewwwio_json_encode(
905
  array(
906
- 'ready' => $image_count,
907
- 'message' => $ready_msg,
 
 
908
  )
909
  )
910
  );
42
  }
43
  echo $output;
44
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
45
+ $hs_prefill = '';
46
  $current_user = wp_get_current_user();
47
  $help_email = $current_user->user_email;
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
49
+ if ( ! empty( $eio_debug ) ) {
50
+ $hs_debug = str_replace( array( "'", '<br>' ), array( '', '\n' ), $eio_debug );
51
+ $hs_prefill = "Beacon('prefill', { fields: [ { id: 18778, value: '$hs_debug' } ] });";
 
 
52
  }
53
  }
54
  ?>
55
+ <script type="text/javascript">!function(e,t,n){function a(){var e=t.getElementsByTagName("script")[0],n=t.createElement("script");n.type="text/javascript",n.async=!0,n.src="https://beacon-v2.helpscout.net",e.parentNode.insertBefore(n,e)}if(e.Beacon=n=function(t,n,a){e.Beacon.readyQueue.push({method:t,options:n,data:a})},n.readyQueue=[],"complete"===t.readyState)return a();e.attachEvent?e.attachEvent("onload",a):e.addEventListener("load",a,!1)}(window,document,window.Beacon||function(){});</script>
56
+ <script type="text/javascript">
57
+ window.Beacon('init', 'aa9c3d3b-d4bc-4e9b-b6cb-f11c9f69da87');
58
+ <?php echo $hs_prefill; ?>
 
 
 
 
59
  </script>
60
  <?php
61
  }
844
  $upload_dir = wp_upload_dir();
845
  // Retrieve the path of the upload folder.
846
  $upload_path = $upload_dir['basedir'];
847
+ $this_month = gmdate( 'm' );
848
+ $this_year = gmdate( 'Y' );
849
  ewww_image_optimizer_image_scan( "$upload_path/$this_year/$this_month/", $started );
850
  if ( class_exists( 'DateTime' ) ) {
851
  $date = new DateTime();
869
  $usage = ewww_image_optimizer_cloud_quota( true );
870
  }
871
  ewwwio_memory( __FUNCTION__ );
872
+ /* translators: %s: number of images */
873
+ $ready_msg = sprintf( esc_html( _n( 'There is %s image ready to optimize.', 'There are %s images ready to optimize.', $image_count, 'ewww-image-optimizer' ) ), '<strong>' . number_format_i18n( $image_count ) . '</strong>' );
874
  if ( is_array( $usage ) && ! $usage['metered'] ) {
875
  $credits_available = $usage['licensed'] - $usage['consumed'];
876
  if ( $credits_available < $image_count ) {
884
  die(
885
  ewwwio_json_encode(
886
  array(
887
+ 'ready' => $image_count,
888
+ 'message' => $ready_msg,
889
+ /* translators: %s: number of images */
890
+ 'start_button' => sprintf( esc_attr__( 'Optimize %s images', 'ewww-image-optimizer' ), number_format_i18n( $image_count ) ),
891
  )
892
  )
893
  );
bulk.php CHANGED
@@ -29,8 +29,8 @@ function ewww_image_optimizer_display_tools() {
29
 
30
  $output = '';
31
  $output .= "<div id='ewww-aux-forms'>\n";
32
- /* translators: %d: number of images */
33
- $output .= "<p id='ewww-table-info' class='ewww-tool-info'>" . sprintf( esc_html__( 'The plugin keeps track of already optimized images to prevent re-optimization. There are %d images that have been optimized so far.', 'ewww-image-optimizer' ), $already_optimized ) . "</p>\n";
34
  $output .= "<form id='ewww-show-table' class='ewww-bulk-form' method='post' action=''>\n";
35
  $output .= '<button type="submit" class="button-primary action">' . esc_html__( 'Show Optimized Images', 'ewww-image-optimizer' ) . "</button>\n";
36
  $output .= "</form>\n";
@@ -138,16 +138,27 @@ function ewww_image_optimizer_bulk_preview() {
138
  echo '<p>' . esc_html__( 'You do not appear to have uploaded any images yet.', 'ewww-image-optimizer' ) . '</p>';
139
  } else {
140
  if ( 'true' === $resume ) {
141
- /* translators: %d: number of images */
142
- echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '</p>';
143
  } else {
 
 
 
 
 
144
  if ( ! empty( $_REQUEST['ids'] ) && ( preg_match( '/^[\d,]+$/', $_REQUEST['ids'] ) || is_numeric( $_REQUEST['ids'] ) ) ) {
145
- /* translators: %d: number of images */
146
- echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( '%1$d image in the Media Library has been selected.', '%1$d images in the Media Library have been selected.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '</p>';
 
 
 
147
  } else {
148
- /* translators: %d: number of images */
149
- echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( '%1$d image in the Media Library has been selected.', '%1$d images in the Media Library have been selected.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '<br />' .
150
- esc_html__( 'The active theme, BuddyPress, WP Symposium, and folders that you have configured will also be scanned for unoptimized images.', 'ewww-image-optimizer' ) . '</p>';
 
 
 
 
151
  }
152
  }
153
  ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume );
@@ -237,11 +248,13 @@ function ewww_image_optimizer_bulk_webp_only() {
237
  */
238
  function ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume = '' ) {
239
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
240
- /* translators: %d: number of images */
241
- $scanning_starter_message = sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), $fullsize_count );
242
  if ( 'true' === $resume ) {
243
- $scan_hide = 'style="display:none"';
244
- $start_hide = '';
 
 
245
  } else {
246
  $start_hide = 'style="display:none"';
247
  $scan_hide = '';
@@ -252,10 +265,9 @@ function ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count,
252
  <p id="ewww-scanning" class="ewww-bulk-info" style="display:none"><?php echo $scanning_starter_message; ?>&nbsp;<img src='<?php echo $loading_image; ?>' alt='loading'/></p>
253
  <form id="ewww-aux-start" class="ewww-bulk-form" <?php echo $scan_hide; ?> method="post" action="">
254
  <input id="ewww-aux-first" type="submit" class="button-primary action" value="<?php esc_attr_e( 'Scan for unoptimized images', 'ewww-image-optimizer' ); ?>" />
255
- <input id="ewww-aux-again" type="submit" class="button-secondary action" style="display:none" value="<?php esc_attr_e( 'Scan Again', 'ewww-image-optimizer' ); ?>" />
256
  </form>
257
  <form id="ewww-bulk-start" class="ewww-bulk-form" <?php echo $start_hide; ?> method="post" action="">
258
- <input id="ewww-aux-first" type="submit" class="button-primary action" value="<?php echo $button_text; ?>" />
259
  </form>
260
  <?php
261
  }
@@ -265,11 +277,11 @@ function ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count,
265
  */
266
  function ewww_image_optimizer_bulk_reset_form_output() {
267
  ?>
268
- <p class="ewww-media-info ewww-bulk-info"><?php esc_html_e( 'If you would like to start over again, press the Reset Status button to reset the bulk operation status.', 'ewww-image-optimizer' ); ?></p>
269
  <form class="ewww-bulk-form" method="post" action="">
270
  <?php wp_nonce_field( 'ewww-image-optimizer-bulk-reset', 'ewww_wpnonce' ); ?>
271
  <input type="hidden" name="ewww_reset" value="1">
272
- <button id="ewww-bulk-reset" type="submit" class="button-secondary action"><?php esc_html_e( 'Reset Status', 'ewww-image-optimizer' ); ?></button>
273
  </form>
274
  <?php
275
  }
@@ -1300,8 +1312,8 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1300
  die(
1301
  ewwwio_json_encode(
1302
  array(
1303
- /* translators: %d: number of images */
1304
- 'remaining' => sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), $remaining ) . "&nbsp;<img src='$loading_image' />",
1305
  'notice' => $notice,
1306
  'bad_attachment' => $bad_attachment,
1307
  'tiny_skip' => $tiny_notice,
@@ -1823,7 +1835,11 @@ function ewww_image_optimizer_bulk_cleanup() {
1823
  // Let the user know we are done.
1824
  ewwwio_memory( __FUNCTION__ );
1825
  ewwwio_ob_clean();
1826
- die( '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b> - <a href="upload.php">' . esc_html__( 'Return to Media Library', 'ewww-image-optimizer' ) . '</a></p>' );
 
 
 
 
1827
  }
1828
 
1829
  add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_bulk_script' );
29
 
30
  $output = '';
31
  $output .= "<div id='ewww-aux-forms'>\n";
32
+ /* translators: %s: number of images */
33
+ $output .= "<p id='ewww-table-info' class='ewww-tool-info'>" . sprintf( esc_html__( 'The plugin keeps track of already optimized images to prevent re-optimization. There are %s images that have been optimized so far.', 'ewww-image-optimizer' ), number_format_i18n( $already_optimized ) ) . "</p>\n";
34
  $output .= "<form id='ewww-show-table' class='ewww-bulk-form' method='post' action=''>\n";
35
  $output .= '<button type="submit" class="button-primary action">' . esc_html__( 'Show Optimized Images', 'ewww-image-optimizer' ) . "</button>\n";
36
  $output .= "</form>\n";
138
  echo '<p>' . esc_html__( 'You do not appear to have uploaded any images yet.', 'ewww-image-optimizer' ) . '</p>';
139
  } else {
140
  if ( 'true' === $resume ) {
141
+ echo '<p class="ewww-media-info ewww-bulk-info">' . esc_html__( 'Resume where you left off:', 'ewww-image-optimizer' ) . '</p>';
 
142
  } else {
143
+ $resizes = ewww_image_optimizer_get_image_sizes();
144
+ if ( is_array( $resizes ) ) {
145
+ $resize_count = count( $resizes );
146
+ }
147
+ $resize_count = ( ! empty( $resize_count ) && $resize_count > 1 ? $resize_count : 6 );
148
  if ( ! empty( $_REQUEST['ids'] ) && ( preg_match( '/^[\d,]+$/', $_REQUEST['ids'] ) || is_numeric( $_REQUEST['ids'] ) ) ) {
149
+ echo '<p class="ewww-media-info ewww-bulk-info">' .
150
+ /* translators: %1$s: number of images %2$d: number of registered image sizes */
151
+ sprintf( esc_html( _n( '%1$s uploaded item in the Media Library has been selected with up to %2$d image files per upload.', '%1$s uploaded items in the Media Library have been selected with up to %2$d image files per upload.', $fullsize_count, 'ewww-image-optimizer' ) ), number_format_i18n( $fullsize_count ), $resize_count ) .
152
+ ' ' . esc_html__( 'The total number of images found will be displayed before optimization begins.', 'ewww-image-optimizer' ) .
153
+ '</p>';
154
  } else {
155
+ echo '<p class="ewww-media-info ewww-bulk-info">' .
156
+ /* translators: %1$s: number of images %2$d: number of registered image sizes */
157
+ sprintf( esc_html( _n( '%1$s uploaded item in the Media Library has been selected with up to %2$d image files per upload.', '%1$s uploaded items in the Media Library have been selected with up to %2$d image files per upload.', $fullsize_count, 'ewww-image-optimizer' ) ), number_format_i18n( $fullsize_count ), $resize_count ) .
158
+ ' ' . esc_html__( 'The total number of images found will be displayed before optimization begins.', 'ewww-image-optimizer' ) .
159
+ '<br />' .
160
+ esc_html__( 'The active theme, BuddyPress, WP Symposium, and folders that you have configured will also be scanned for unoptimized images.', 'ewww-image-optimizer' ) .
161
+ '</p>';
162
  }
163
  }
164
  ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume );
248
  */
249
  function ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume = '' ) {
250
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
251
+ /* translators: %s: number of images */
252
+ $scanning_starter_message = sprintf( esc_html__( 'Stage 1, %s items left to scan.', 'ewww-image-optimizer' ), number_format_i18n( $fullsize_count ) );
253
  if ( 'true' === $resume ) {
254
+ /* translators: %s: number of images, formatted for locale */
255
+ $button_text = sprintf( esc_attr__( 'Optimize %s images', 'ewww-image-optimizer' ), number_format_i18n( $fullsize_count ) );
256
+ $scan_hide = 'style="display:none"';
257
+ $start_hide = '';
258
  } else {
259
  $start_hide = 'style="display:none"';
260
  $scan_hide = '';
265
  <p id="ewww-scanning" class="ewww-bulk-info" style="display:none"><?php echo $scanning_starter_message; ?>&nbsp;<img src='<?php echo $loading_image; ?>' alt='loading'/></p>
266
  <form id="ewww-aux-start" class="ewww-bulk-form" <?php echo $scan_hide; ?> method="post" action="">
267
  <input id="ewww-aux-first" type="submit" class="button-primary action" value="<?php esc_attr_e( 'Scan for unoptimized images', 'ewww-image-optimizer' ); ?>" />
 
268
  </form>
269
  <form id="ewww-bulk-start" class="ewww-bulk-form" <?php echo $start_hide; ?> method="post" action="">
270
+ <input id="ewww-bulk-first" type="submit" class="button-primary action" value="<?php echo $button_text; ?>" />
271
  </form>
272
  <?php
273
  }
277
  */
278
  function ewww_image_optimizer_bulk_reset_form_output() {
279
  ?>
280
+ <p class="ewww-media-info ewww-bulk-info" style="margin-top:3em;"><?php esc_html_e( 'Would like to clear the queue and rescan for images?', 'ewww-image-optimizer' ); ?></p>
281
  <form class="ewww-bulk-form" method="post" action="">
282
  <?php wp_nonce_field( 'ewww-image-optimizer-bulk-reset', 'ewww_wpnonce' ); ?>
283
  <input type="hidden" name="ewww_reset" value="1">
284
+ <button id="ewww-bulk-reset" type="submit" class="button-secondary action"><?php esc_html_e( 'Clear Queue', 'ewww-image-optimizer' ); ?></button>
285
  </form>
286
  <?php
287
  }
1312
  die(
1313
  ewwwio_json_encode(
1314
  array(
1315
+ /* translators: %s: number of images */
1316
+ 'remaining' => sprintf( esc_html__( 'Stage 1, %s items left to scan.', 'ewww-image-optimizer' ), number_format_i18n( $remaining ) ) . "&nbsp;<img src='$loading_image' />",
1317
  'notice' => $notice,
1318
  'bad_attachment' => $bad_attachment,
1319
  'tiny_skip' => $tiny_notice,
1835
  // Let the user know we are done.
1836
  ewwwio_memory( __FUNCTION__ );
1837
  ewwwio_ob_clean();
1838
+ die(
1839
+ '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b> - ' .
1840
+ '<a target="_blank" href="https://wordpress.org/support/plugin/ewww-image-optimizer/reviews/#new-post">' .
1841
+ esc_html__( 'Write a Review', 'ewww-image-optimizer' ) . '</a></p>'
1842
+ );
1843
  }
1844
 
1845
  add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_bulk_script' );
changelog.txt CHANGED
@@ -1,3 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 5.1.1 =
2
  * fixed: no optimization when escapeshellarg() is disabled
3
  * fixed: warning thrown by implode() when JS WebP is enabled with no WebP URLs
1
+ = 5.1.4 =
2
+ * fixed: warnings on FlaGallery's manage gallery page
3
+ * fixed: cwebp version test results in false-positives
4
+ * fixed: EWWW IO resize limits are ignored when higher than WP default
5
+ * fixed: PNGOUT warning during one-click conversion
6
+ * fixed: WebP images not removed from remote storage when an attachment is deleted (WP Offload Media)
7
+ * fixed: after running regen for single thumbs with Image Regenerate & Select Crop plugin, regenerated images were not automatically optimized
8
+
9
+ = 5.1.3 =
10
+ * added: better compatibility with Divi filterable grid images and parallax backgrounds
11
+ * added: cleanup .webp and database records when using Enable Media Replace
12
+ * fixed: Divi builder will not load with Easy IO and Include All Resources active
13
+ * fixed: image cover block with fixed width scaled too much
14
+ * fixed: PNG placeholders could use more memory than available
15
+ * removed: Lazy Load CSS gradient for blank placeholders
16
+
17
+ = 5.1.2 =
18
+ * added: disable native lazy-load attributes with EWWWIO_DISABLE_NATIVE_LAZY
19
+ * added: ability to choose LQIP or blank placeholders for lazy load
20
+ * changed: renaming ExactDN as Easy IO
21
+ * changed: default to blank placeholders with Easy IO
22
+ * changed: regenerated images are automatically re-optimized after running Image Regenerate & Select Crop plugin
23
+ * fixed: low-quality placeholders sometimes had larger dimensions than necessary
24
+ * fixed: database records and .webp images are not removed when Image Regenerate & Select Crop plugin deletes a thumbnail
25
+ * fixed: path traversal protection preventing normal files from optimizing
26
+ * fixed: Slider Revolution dummy.png not properly handled by Easy IO
27
+
28
  = 5.1.1 =
29
  * fixed: no optimization when escapeshellarg() is disabled
30
  * fixed: warning thrown by implode() when JS WebP is enabled with no WebP URLs
classes/class-eio-alt-webp.php CHANGED
@@ -385,8 +385,6 @@ class EIO_Alt_Webp extends EIO_Page_Parser {
385
  return $buffer;
386
  }
387
 
388
- /* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
389
-
390
  $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false );
391
  if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
392
  foreach ( $images[0] as $index => $image ) {
385
  return $buffer;
386
  }
387
 
 
 
388
  $images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false );
389
  if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
390
  foreach ( $images[0] as $index => $image ) {
classes/class-eio-base.php CHANGED
@@ -54,11 +54,11 @@ if ( ! class_exists( 'EIO_Base' ) ) {
54
  * @param string $child_class_path The location of the child class extending the base class.
55
  */
56
  function __construct( $child_class_path = '' ) {
57
- if ( strpos( $child_class_path, 'ewww' ) ) {
58
  $this->content_url = content_url( 'ewww/' );
59
  $this->content_dir = WP_CONTENT_DIR . '/ewww/';
60
  $this->version = EWWW_IMAGE_OPTIMIZER_VERSION;
61
- } elseif ( strpos( $child_class_path, 'easy' ) ) {
62
  $this->content_url = content_url( 'easyio/' );
63
  $this->content_dir = WP_CONTENT_DIR . '/easyio/';
64
  $this->version = EASYIO_VERSION;
@@ -86,7 +86,7 @@ if ( ! class_exists( 'EIO_Base' ) ) {
86
  if ( ! empty( $eio_debug ) && empty( $ewwwio_temp_debug ) && empty( $easyio_temp_debug ) && $debug_enabled && is_writable( $this->content_dir ) ) {
87
  $memory_limit = $this->memory_limit();
88
  clearstatcache();
89
- $timestamp = date( 'Y-m-d H:i:s' ) . "\n";
90
  if ( ! file_exists( $debug_log ) ) {
91
  touch( $debug_log );
92
  } else {
54
  * @param string $child_class_path The location of the child class extending the base class.
55
  */
56
  function __construct( $child_class_path = '' ) {
57
+ if ( strpos( $child_class_path, 'plugins/ewww' ) ) {
58
  $this->content_url = content_url( 'ewww/' );
59
  $this->content_dir = WP_CONTENT_DIR . '/ewww/';
60
  $this->version = EWWW_IMAGE_OPTIMIZER_VERSION;
61
+ } elseif ( strpos( $child_class_path, 'plugins/easy' ) ) {
62
  $this->content_url = content_url( 'easyio/' );
63
  $this->content_dir = WP_CONTENT_DIR . '/easyio/';
64
  $this->version = EASYIO_VERSION;
86
  if ( ! empty( $eio_debug ) && empty( $ewwwio_temp_debug ) && empty( $easyio_temp_debug ) && $debug_enabled && is_writable( $this->content_dir ) ) {
87
  $memory_limit = $this->memory_limit();
88
  clearstatcache();
89
+ $timestamp = gmdate( 'Y-m-d H:i:s' ) . "\n";
90
  if ( ! file_exists( $debug_log ) ) {
91
  touch( $debug_log );
92
  } else {
classes/class-eio-hs-beacon.php CHANGED
@@ -103,9 +103,9 @@ if ( ! class_exists( 'EIO_HS_Beacon' ) ) {
103
  ) {
104
  return;
105
  }
106
- if ( strpos( __FILE__, 'ewww' ) ) {
107
  ewww_image_optimizer_notice_beacon();
108
- } elseif ( strpos( __FILE__, 'easy' ) ) {
109
  easyio_notice_beacon();
110
  }
111
  }
103
  ) {
104
  return;
105
  }
106
+ if ( strpos( __FILE__, 'plugins/ewww' ) ) {
107
  ewww_image_optimizer_notice_beacon();
108
+ } elseif ( strpos( __FILE__, 'plugins/easy' ) ) {
109
  easyio_notice_beacon();
110
  }
111
  }
classes/class-eio-lazy-load.php CHANGED
@@ -83,7 +83,6 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
83
  }
84
 
85
  // Filter early, so that others at the default priority take precendence.
86
- add_filter( 'eio_use_lqip', array( $this, 'maybe_lqip' ), 9 );
87
  add_filter( 'eio_use_piip', array( $this, 'maybe_piip' ), 9 );
88
  add_filter( 'eio_use_siip', array( $this, 'maybe_siip' ), 9 );
89
 
@@ -223,22 +222,25 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
223
  $this->set_attribute( $image, 'data-src', $file, true );
224
  $srcset = $this->get_attribute( $image, 'srcset' );
225
 
 
 
226
  $placeholder_src = $this->placeholder_src;
227
  if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && apply_filters( 'eio_use_lqip', true, $file ) && $this->parsing_exactdn && strpos( $file, $this->exactdn_domain ) ) {
228
  $this->debug_message( 'using lqip' );
229
- list( $width, $height ) = $this->get_dimensions_from_filename( $file );
230
  if ( $width && $height && $width < 201 && $height < 201 ) {
231
  $placeholder_src = $exactdn->generate_url( $this->content_url . 'lazy/placeholder-' . $width . 'x' . $height . '.png' );
232
- } else {
233
  $placeholder_src = add_query_arg( array( 'lazy' => 1 ), $file );
 
 
 
 
234
  }
235
  } elseif ( $this->allow_piip && $srcset && apply_filters( 'eio_use_piip', true, $file ) ) {
236
  $this->debug_message( 'trying piip' );
237
  // Get image dimensions for PNG placeholder.
238
- list( $width, $height ) = $this->get_dimensions_from_filename( $file );
239
-
240
- $width_attr = $this->get_attribute( $image, 'width' );
241
- $height_attr = $this->get_attribute( $image, 'height' );
242
 
243
  // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
244
  if ( false !== strpos( $width_attr, '%' ) || false !== strpos( $height_attr, '%' ) ) {
@@ -260,8 +262,8 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
260
  }
261
  } elseif ( apply_filters( 'eio_use_siip', true, $file ) ) {
262
  $this->debug_message( 'trying siip' );
263
- $width = $this->get_attribute( $image, 'width' );
264
- $height = $this->get_attribute( $image, 'height' );
265
 
266
  // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
267
  if ( false !== strpos( $width, '%' ) || false !== strpos( $height, '%' ) ) {
@@ -298,7 +300,12 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
298
  } else {
299
  $this->set_attribute( $image, 'src', $placeholder_src, true );
300
  }
301
- $this->set_attribute( $image, 'loading', 'lazy' );
 
 
 
 
 
302
  $this->set_attribute( $image, 'class', $this->get_attribute( $image, 'class' ) . ' lazyload', true );
303
  $buffer = str_replace( $orig_img, $image . $noscript, $buffer );
304
  }
@@ -527,6 +534,11 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
527
  }
528
  $height = min( $height, 1920 );
529
 
 
 
 
 
 
530
  $piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
531
  if ( $this->parsing_exactdn ) {
532
  global $exactdn;
@@ -565,22 +577,6 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
565
  return $allow;
566
  }
567
 
568
- /**
569
- * Check if LQIP should be used, but allow filters to alter the option.
570
- *
571
- * @param bool $use_lqip Whether LL should use low-quality image placeholders.
572
- * @return bool True to use LQIP, false to skip them.
573
- */
574
- function maybe_lqip( $use_lqip ) {
575
- if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_LQIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_LQIP ) {
576
- return false;
577
- }
578
- if ( defined( 'EASYIO_USE_LQIP' ) && ! EASYIO_USE_LQIP ) {
579
- return false;
580
- }
581
- return $use_lqip;
582
- }
583
-
584
  /**
585
  * Check if PIIP should be used, but allow filters to alter the option.
586
  *
@@ -594,6 +590,9 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
594
  if ( defined( 'EASYIO_USE_PIIP' ) && ! EASYIO_USE_PIIP ) {
595
  return false;
596
  }
 
 
 
597
  return $use_piip;
598
  }
599
 
83
  }
84
 
85
  // Filter early, so that others at the default priority take precendence.
 
86
  add_filter( 'eio_use_piip', array( $this, 'maybe_piip' ), 9 );
87
  add_filter( 'eio_use_siip', array( $this, 'maybe_siip' ), 9 );
88
 
222
  $this->set_attribute( $image, 'data-src', $file, true );
223
  $srcset = $this->get_attribute( $image, 'srcset' );
224
 
225
+ $width_attr = $this->get_attribute( $image, 'width' );
226
+ $height_attr = $this->get_attribute( $image, 'height' );
227
  $placeholder_src = $this->placeholder_src;
228
  if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && apply_filters( 'eio_use_lqip', true, $file ) && $this->parsing_exactdn && strpos( $file, $this->exactdn_domain ) ) {
229
  $this->debug_message( 'using lqip' );
230
+ list( $width, $height ) = $this->get_dimensions_from_filename( $file, true );
231
  if ( $width && $height && $width < 201 && $height < 201 ) {
232
  $placeholder_src = $exactdn->generate_url( $this->content_url . 'lazy/placeholder-' . $width . 'x' . $height . '.png' );
233
+ } elseif ( $this->get_option( $this->prefix . 'use_lqip' ) ) {
234
  $placeholder_src = add_query_arg( array( 'lazy' => 1 ), $file );
235
+ } elseif ( $width && $height ) {
236
+ $placeholder_src = $exactdn->generate_url( $this->content_url . 'lazy/placeholder-' . $width . 'x' . $height . '.png' );
237
+ } else {
238
+ $placeholder_src = add_query_arg( array( 'lazy' => 2 ), $file );
239
  }
240
  } elseif ( $this->allow_piip && $srcset && apply_filters( 'eio_use_piip', true, $file ) ) {
241
  $this->debug_message( 'trying piip' );
242
  // Get image dimensions for PNG placeholder.
243
+ list( $width, $height ) = $this->get_dimensions_from_filename( $file, $this->parsing_exactdn );
 
 
 
244
 
245
  // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
246
  if ( false !== strpos( $width_attr, '%' ) || false !== strpos( $height_attr, '%' ) ) {
262
  }
263
  } elseif ( apply_filters( 'eio_use_siip', true, $file ) ) {
264
  $this->debug_message( 'trying siip' );
265
+ $width = $width_attr;
266
+ $height = $height_attr;
267
 
268
  // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
269
  if ( false !== strpos( $width, '%' ) || false !== strpos( $height, '%' ) ) {
300
  } else {
301
  $this->set_attribute( $image, 'src', $placeholder_src, true );
302
  }
303
+ if (
304
+ ( ! defined( 'EWWWIO_DISABLE_NATIVE_LAZY' ) || ! EWWWIO_DISABLE_NATIVE_LAZY ) &&
305
+ ( ! defined( 'EASYIO_DISABLE_NATIVE_LAZY' ) || ! EASYIO_DISABLE_NATIVE_LAZY )
306
+ ) {
307
+ $this->set_attribute( $image, 'loading', 'lazy' );
308
+ }
309
  $this->set_attribute( $image, 'class', $this->get_attribute( $image, 'class' ) . ' lazyload', true );
310
  $buffer = str_replace( $orig_img, $image . $noscript, $buffer );
311
  }
534
  }
535
  $height = min( $height, 1920 );
536
 
537
+ $memory_required = 5 * $height * $width;
538
+ if ( function_exists( 'ewwwio_check_memory_available' ) && ! ewwwio_check_memory_available( $memory_required + 500000 ) ) {
539
+ return $this->placeholder_src;
540
+ }
541
+
542
  $piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
543
  if ( $this->parsing_exactdn ) {
544
  global $exactdn;
577
  return $allow;
578
  }
579
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  /**
581
  * Check if PIIP should be used, but allow filters to alter the option.
582
  *
590
  if ( defined( 'EASYIO_USE_PIIP' ) && ! EASYIO_USE_PIIP ) {
591
  return false;
592
  }
593
+ if ( function_exists( 'ewwwio_check_memory_available' ) && ! ewwwio_check_memory_available( 15000000 ) ) {
594
+ return false;
595
+ }
596
  return $use_piip;
597
  }
598
 
classes/class-eio-page-parser.php CHANGED
@@ -158,12 +158,31 @@ if ( ! class_exists( 'EIO_Page_Parser' ) ) {
158
  * Try to determine height and width from strings WP appends to resized image filenames.
159
  *
160
  * @param string $src The image URL.
 
161
  * @return array An array consisting of width and height.
162
  */
163
- function get_dimensions_from_filename( $src ) {
164
  $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
165
  $width_height_string = array();
166
  $this->debug_message( "looking for dimensions in $src" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $width_height_string ) ) {
168
  $width = (int) $width_height_string[1];
169
  $height = (int) $width_height_string[2];
@@ -173,11 +192,17 @@ if ( ! class_exists( 'EIO_Page_Parser' ) ) {
173
  $height = 2 * $height;
174
  }
175
  if ( $width && $height ) {
 
 
 
 
 
 
176
  $this->debug_message( "found w$width h$height" );
177
  return array( $width, $height );
178
  }
179
  }
180
- return array( false, false );
181
  }
182
 
183
  /**
158
  * Try to determine height and width from strings WP appends to resized image filenames.
159
  *
160
  * @param string $src The image URL.
161
+ * @param bool $use_params Check ExactDN image parameters for additional size information. Default to false.
162
  * @return array An array consisting of width and height.
163
  */
164
+ function get_dimensions_from_filename( $src, $use_params = false ) {
165
  $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
166
  $width_height_string = array();
167
  $this->debug_message( "looking for dimensions in $src" );
168
+ $width_param = false;
169
+ $height_param = false;
170
+ if ( $use_params && strpos( $src, '?' ) ) {
171
+ $url_params = urldecode( $this->parse_url( $src, PHP_URL_QUERY ) );
172
+ if ( $url_params && false !== strpos( $url_params, 'resize=' ) ) {
173
+ preg_match( '/resize=(\d+),(\d+)/', $url_params, $resize_matches );
174
+ if ( is_array( $resize_matches ) && ! empty( $resize_matches[1] ) && ! empty( $resize_matches[2] ) ) {
175
+ $width_param = (int) $resize_matches[1];
176
+ $height_param = (int) $resize_matches[2];
177
+ }
178
+ } elseif ( false !== strpos( $url_params, 'fit=' ) ) {
179
+ preg_match( '/fit=(\d+),(\d+)/', $url_params, $fit_matches );
180
+ if ( is_array( $fit_matches ) && ! empty( $fit_matches[1] ) && ! empty( $fit_matches[2] ) ) {
181
+ $width_param = (int) $fit_matches[1];
182
+ $height_param = (int) $fit_matches[2];
183
+ }
184
+ }
185
+ }
186
  if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $width_height_string ) ) {
187
  $width = (int) $width_height_string[1];
188
  $height = (int) $width_height_string[2];
192
  $height = 2 * $height;
193
  }
194
  if ( $width && $height ) {
195
+ if ( $width_param && $width_param < $width ) {
196
+ $width = $width_param;
197
+ }
198
+ if ( $height_param && $height_param < $height ) {
199
+ $height = $height_param;
200
+ }
201
  $this->debug_message( "found w$width h$height" );
202
  return array( $width, $height );
203
  }
204
  }
205
+ return array( $width_param, $height_param ); // These may be false, unless URL parameters were found.
206
  }
207
 
208
  /**
classes/class-ewww-flag.php CHANGED
@@ -737,6 +737,10 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
737
  // Get the mimetype.
738
  $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
739
  $valid = true;
 
 
 
 
740
  // If we don't have a valid tool for the image type, output the appropriate message.
741
  $skip = ewww_image_optimizer_skip_tools();
742
  switch ( $type ) {
737
  // Get the mimetype.
738
  $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
739
  $valid = true;
740
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_JPEGTRAN' ) ) {
741
+ ewww_image_optimizer_tool_init();
742
+ ewww_image_optimizer_notice_utils( 'quiet' );
743
+ }
744
  // If we don't have a valid tool for the image type, output the appropriate message.
745
  $skip = ewww_image_optimizer_skip_tools();
746
  switch ( $type ) {
classes/class-ewww-image.php CHANGED
@@ -259,10 +259,8 @@ class EWWW_Image {
259
  $new_name = $this->convert( $size_queried['path'] );
260
  if ( $new_name ) {
261
  $this->convert_retina( $size_queried['path'] );
262
- $this->convert_db_path( $size_queried['path'], $new_name, $size_queried['id'] );
263
- /* ewwwio_debug_message( print_r( $meta['sizes'], true ) ); */
264
 
265
- /* ewwwio_debug_message( print_r( $size_queried, true ) ); */
266
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
267
  ewwwio_debug_message( 'updating regular size' );
268
  $meta['sizes'][ $size_queried['resize'] ]['file'] = basename( $new_name );
@@ -276,9 +274,7 @@ class EWWW_Image {
276
  }
277
  }
278
  ewwwio_debug_message( "converted {$size_queried['resize']} from db query" );
279
- /* ewwwio_debug_message( print_r( $meta, true ) ); */
280
  }
281
- /* ewwwio_debug_message( print_r( $meta, true ) ); */
282
 
283
  /* ewwwio_debug_message( 'next up for conversion search: meta' ); */
284
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
@@ -840,9 +836,9 @@ class EWWW_Image {
840
  *
841
  * @param string $path The old path to search for.
842
  * @param string $new_path The new path to update.
843
- * @param int $id Optional. Database record id for the original image.
844
  */
845
- private function convert_db_path( $path, $new_path, $id = false ) {
846
  if ( empty( $path ) || empty( $new_path ) ) {
847
  return;
848
  }
@@ -853,10 +849,10 @@ class EWWW_Image {
853
  } else {
854
  $ewwwdb = $wpdb;
855
  }
856
- if ( ! $id ) {
857
  $image_record = ewww_image_optimizer_find_already_optimized( $path );
858
  if ( ! empty( $image_record ) && is_array( $image_record ) && ! empty( $image_record['id'] ) ) {
859
- $id = $image_record['id'];
860
  } else { // Insert a new record.
861
  $ewwwdb->insert(
862
  $ewwwdb->ewwwio_images,
@@ -866,7 +862,7 @@ class EWWW_Image {
866
  'orig_size' => filesize( $new_path ),
867
  'attachment_id' => $this->attachment_id,
868
  'results' => __( 'No savings', 'ewww-image-optimizer' ),
869
- 'updated' => date( 'Y-m-d H:i:s' ),
870
  'updates' => 0,
871
  )
872
  );
@@ -878,12 +874,12 @@ class EWWW_Image {
878
  array(
879
  'path' => ewww_image_optimizer_relativize_path( $new_path ),
880
  'converted' => ewww_image_optimizer_relativize_path( $path ),
881
- 'results' => ewww_image_optimizer_image_results( $image_record['orig_size'], filesize( $new_path ) ),
882
  'updates' => 0,
883
  'trace' => '',
884
  ),
885
  array(
886
- 'id' => $id,
887
  )
888
  );
889
  }
259
  $new_name = $this->convert( $size_queried['path'] );
260
  if ( $new_name ) {
261
  $this->convert_retina( $size_queried['path'] );
262
+ $this->convert_db_path( $size_queried['path'], $new_name, $size_queried );
 
263
 
 
264
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
265
  ewwwio_debug_message( 'updating regular size' );
266
  $meta['sizes'][ $size_queried['resize'] ]['file'] = basename( $new_name );
274
  }
275
  }
276
  ewwwio_debug_message( "converted {$size_queried['resize']} from db query" );
 
277
  }
 
278
 
279
  /* ewwwio_debug_message( 'next up for conversion search: meta' ); */
280
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
836
  *
837
  * @param string $path The old path to search for.
838
  * @param string $new_path The new path to update.
839
+ * @param array $record Optional. Database record for the original image.
840
  */
841
+ private function convert_db_path( $path, $new_path, $record = false ) {
842
  if ( empty( $path ) || empty( $new_path ) ) {
843
  return;
844
  }
849
  } else {
850
  $ewwwdb = $wpdb;
851
  }
852
+ if ( ! $record ) {
853
  $image_record = ewww_image_optimizer_find_already_optimized( $path );
854
  if ( ! empty( $image_record ) && is_array( $image_record ) && ! empty( $image_record['id'] ) ) {
855
+ $record = $image_record;
856
  } else { // Insert a new record.
857
  $ewwwdb->insert(
858
  $ewwwdb->ewwwio_images,
862
  'orig_size' => filesize( $new_path ),
863
  'attachment_id' => $this->attachment_id,
864
  'results' => __( 'No savings', 'ewww-image-optimizer' ),
865
+ 'updated' => gmdate( 'Y-m-d H:i:s' ),
866
  'updates' => 0,
867
  )
868
  );
874
  array(
875
  'path' => ewww_image_optimizer_relativize_path( $new_path ),
876
  'converted' => ewww_image_optimizer_relativize_path( $path ),
877
+ 'results' => ewww_image_optimizer_image_results( $record['orig_size'], filesize( $new_path ) ),
878
  'updates' => 0,
879
  'trace' => '',
880
  ),
881
  array(
882
+ 'id' => $record['id'],
883
  )
884
  );
885
  }
classes/class-ewwwio-media-background-process.php CHANGED
@@ -491,7 +491,7 @@ 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 ( false !== strpos( $file_path, '..' ) ) {
495
  return false;
496
  }
497
  if ( ewwwio_is_file( $file_path ) ) {
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 ) ) {
classes/class-ewwwio-relative-migration.php CHANGED
@@ -75,7 +75,7 @@ class EWWWIO_Relative_Migration {
75
  $this->started = time();
76
  $this->offset = (int) get_option( 'ewww_image_optimizer_relative_migration_offset' );
77
  $records = $this->get_records();
78
- ewwwio_debug_message( 'starting at ' . date( 'Y-m-d H:i:s', $this->started ) . " with offset $this->offset" );
79
  while ( ! empty( $records ) ) {
80
  foreach ( $records as $record ) {
81
  if ( $this->already_migrated( $record['path'] ) ) {
75
  $this->started = time();
76
  $this->offset = (int) get_option( 'ewww_image_optimizer_relative_migration_offset' );
77
  $records = $this->get_records();
78
+ ewwwio_debug_message( 'starting at ' . gmdate( 'Y-m-d H:i:s', $this->started ) . " with offset $this->offset" );
79
  while ( ! empty( $records ) ) {
80
  foreach ( $records as $record ) {
81
  if ( $this->already_migrated( $record['path'] ) ) {
classes/class-ewwwio-tracking.php CHANGED
@@ -199,7 +199,7 @@ class EWWWIO_Tracking {
199
  $this->setup_data();
200
  ewwwio_debug_message( 'sending site data' );
201
  $request = wp_remote_post(
202
- 'https://stats.exactlywww.com/stats/report.php',
203
  array(
204
  'timeout' => 5,
205
  'body' => $this->data,
199
  $this->setup_data();
200
  ewwwio_debug_message( 'sending site data' );
201
  $request = wp_remote_post(
202
+ 'https://optimize.exactlywww.com/stats/report.php',
203
  array(
204
  'timeout' => 5,
205
  'body' => $this->data,
classes/class-exactdn.php CHANGED
@@ -328,6 +328,8 @@ if ( ! class_exists( 'ExactDN' ) ) {
328
  }
329
  if ( get_option( 'exactdn_never_been_active' ) ) {
330
  $this->set_option( $this->prefix . 'lazy_load', true );
 
 
331
  delete_option( 'exactdn_never_been_active' );
332
  }
333
  if ( 'external' === get_option( 'elementor_css_print_method' ) ) {
@@ -1199,8 +1201,12 @@ if ( ! class_exists( 'ExactDN' ) ) {
1199
  $element_class = $this->get_attribute( $element, 'class' );
1200
  if ( false !== strpos( $element_class, 'alignfull' ) && current_theme_supports( 'align-wide' ) ) {
1201
  $args['w'] = apply_filters( 'exactdn_full_align_bgimage_width', 1920, $bg_image_url );
 
 
1202
  } elseif ( false !== strpos( $element_class, 'alignwide' ) && current_theme_supports( 'align-wide' ) ) {
1203
  $args['w'] = apply_filters( 'exactdn_wide_align_bgimage_width', 1500, $bg_image_url );
 
 
1204
  } elseif ( 'div' === $tag_type && $content_width ) {
1205
  $args['w'] = apply_filters( 'exactdn_content_bgimage_width', $content_width, $bg_image_url );
1206
  }
@@ -1265,7 +1271,10 @@ if ( ! class_exists( 'ExactDN' ) ) {
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' ) ||
@@ -2347,7 +2356,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
2347
  if ( strpos( $image_url, 'easyio/lazy/placeholder' ) ) {
2348
  return array();
2349
  }
2350
- if ( strpos( $image_url, 'revslider/admin/assets/images/dummy.png' ) ) {
2351
  return array();
2352
  }
2353
  if ( strpos( $image_url, '/lazy.png' ) ) {
328
  }
329
  if ( get_option( 'exactdn_never_been_active' ) ) {
330
  $this->set_option( $this->prefix . 'lazy_load', true );
331
+ $this->set_option( 'exactdn_lossy', true );
332
+ $this->set_option( 'exactdn_all_the_things', true );
333
  delete_option( 'exactdn_never_been_active' );
334
  }
335
  if ( 'external' === get_option( 'elementor_css_print_method' ) ) {
1201
  $element_class = $this->get_attribute( $element, 'class' );
1202
  if ( false !== strpos( $element_class, 'alignfull' ) && current_theme_supports( 'align-wide' ) ) {
1203
  $args['w'] = apply_filters( 'exactdn_full_align_bgimage_width', 1920, $bg_image_url );
1204
+ } elseif ( false !== strpos( $element_class, 'wp-block-cover' ) && false !== strpos( $element_class, 'has-parallax' ) ) {
1205
+ $args['w'] = apply_filters( 'exactdn_wp_cover_parallax_bgimage_width', 1920, $bg_image_url );
1206
  } elseif ( false !== strpos( $element_class, 'alignwide' ) && current_theme_supports( 'align-wide' ) ) {
1207
  $args['w'] = apply_filters( 'exactdn_wide_align_bgimage_width', 1500, $bg_image_url );
1208
+ } elseif ( false !== strpos( $element_class, 'et_parallax_bg' ) ) {
1209
+ $args['w'] = apply_filters( 'exactdn_et_parallax_bgimage_width', 1920, $bg_image_url );
1210
  } elseif ( 'div' === $tag_type && $content_width ) {
1211
  $args['w'] = apply_filters( 'exactdn_content_bgimage_width', $content_width, $bg_image_url );
1212
  }
1271
  }
1272
  // Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
1273
  $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 );
1274
+ // Pre-empt partial paths that are used by JS to build other URLs.
1275
  $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
1276
+ $content = str_replace( 'wp-content/plugins/onesignal-free-web-push-notifications/sdk_files/"', '?wpcontent-bypass?/plugins/onesignal-free-web-push-notifications/sdk_files/"', $content );
1277
+ $content = str_replace( 'wp-content/plugins/u-shortcodes/shortcodes/monthview/"', '?wpcontent-bypass?/plugins/u-shortcodes/shortcodes/monthview/"', $content );
1278
  if (
1279
  false !== strpos( $this->upload_domain, 'amazonaws.com' ) ||
1280
  false !== strpos( $this->upload_domain, 'digitaloceanspaces.com' ) ||
2356
  if ( strpos( $image_url, 'easyio/lazy/placeholder' ) ) {
2357
  return array();
2358
  }
2359
+ if ( strpos( $image_url, '/dummy.png' ) ) {
2360
  return array();
2361
  }
2362
  if ( strpos( $image_url, '/lazy.png' ) ) {
common.php CHANGED
@@ -17,11 +17,12 @@
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.
 
20
  if ( ! defined( 'ABSPATH' ) ) {
21
  exit;
22
  }
23
 
24
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '511.0' );
25
 
26
  // Initialize a couple globals.
27
  $eio_debug = '';
@@ -84,6 +85,8 @@ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) ) {
84
  add_filter( 'mpp_handle_upload', 'ewww_image_optimizer_handle_mpp_upload' );
85
  // Processes a MediaPress image via the metadata after upload.
86
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
 
 
87
  }
88
  // Skips resizing for images with 'noresize' in the filename.
89
  add_filter( 'ewww_image_optimizer_resize_dimensions', 'ewww_image_optimizer_noresize', 10, 2 );
@@ -99,8 +102,7 @@ add_filter( 'ewww_image_optimizer_bulk_permissions', 'ewww_image_optimizer_admin
99
  add_filter( 'ewww_image_optimizer_admin_permissions', 'ewww_image_optimizer_admin_permissions', 8 );
100
  add_filter( 'ewww_image_optimizer_superadmin_permissions', 'ewww_image_optimizer_superadmin_permissions', 8 );
101
  // Add a link to the plugins page so the user can go straight to the settings page.
102
- $ewww_plugin_slug = plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
103
- add_filter( "plugin_action_links_$ewww_plugin_slug", 'ewww_image_optimizer_settings_link' );
104
  // Filter the registered sizes so we can remove any that the user disabled.
105
  add_filter( 'intermediate_image_sizes_advanced', 'ewww_image_optimizer_image_sizes_advanced' );
106
  // Ditto for PDF files (or anything non-image).
@@ -115,10 +117,14 @@ add_filter( 'myarcade_filter_thumbnail', 'ewww_image_optimizer_myarcade_thumbnai
115
  add_filter( 'load_image_to_edit_path', 'ewww_image_optimizer_editor_save_pre' );
116
  // Allows the user to override the default JPG quality used by WordPress.
117
  add_filter( 'jpeg_quality', 'ewww_image_optimizer_set_jpg_quality' );
 
 
118
  // Makes sure the plugin bypasses any files affected by the Folders to Ignore setting.
119
  add_filter( 'ewww_image_optimizer_bypass', 'ewww_image_optimizer_ignore_file', 10, 2 );
120
  // Ensure we populate the queue with webp images for WP Offload S3.
121
  add_filter( 'as3cf_attachment_file_paths', 'ewww_image_optimizer_as3cf_attachment_file_paths', 10, 2 );
 
 
122
  // Fix the ContentType for WP Offload S3 on WebP images.
123
  add_filter( 'as3cf_object_meta', 'ewww_image_optimizer_as3cf_object_meta' );
124
  // Loads the plugin translations.
@@ -143,6 +149,10 @@ add_action( 'admin_action_ewww_image_optimizer_manual_cloud_restore', 'ewww_imag
143
  add_action( 'admin_action_ewww_image_optimizer_manual_convert', 'ewww_image_optimizer_manual' );
144
  // Cleanup routine when an attachment is deleted.
145
  add_action( 'delete_attachment', 'ewww_image_optimizer_delete' );
 
 
 
 
146
  // Adds the EWWW IO pages to the admin menu.
147
  add_action( 'admin_menu', 'ewww_image_optimizer_admin_menu', 60 );
148
  // Adds the EWWW IO settings to the network admin menu.
@@ -588,17 +598,9 @@ function ewww_image_optimizer_upgrade() {
588
  if ( get_option( 'ewww_image_optimizer_version' ) < 280 ) {
589
  ewww_image_optimizer_migrate_settings_to_levels();
590
  }
591
- if ( get_option( 'ewww_image_optimizer_version' ) < 407 ) {
592
- add_option( 'exactdn_all_the_things', true );
593
- add_site_option( 'exactdn_all_the_things', true );
594
- }
595
  if ( get_option( 'ewww_image_optimizer_version' ) > 0 && get_option( 'ewww_image_optimizer_version' ) < 434 && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
596
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_metadata_remove', false );
597
  }
598
- if ( get_option( 'ewww_image_optimizer_version' ) > 0 && get_option( 'ewww_image_optimizer_version' ) < 440 && ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) ) {
599
- add_option( 'exactdn_lossy', true );
600
- add_site_option( 'exactdn_lossy', true );
601
- }
602
  if ( get_option( 'ewww_image_optimizer_version' ) < 454 ) {
603
  update_option( 'ewww_image_optimizer_bulk_resume', '' );
604
  update_option( 'ewww_image_optimizer_aux_resume', '' );
@@ -679,6 +681,10 @@ function ewww_image_optimizer_retest_background_optimization() {
679
  function ewww_image_optimizer_admin_init() {
680
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
681
  ewwwio_memory( __FUNCTION__ );
 
 
 
 
682
  /**
683
  * Require the file that does the bulk processing.
684
  */
@@ -750,6 +756,8 @@ function ewww_image_optimizer_admin_init() {
750
  update_site_option( 'exactdn_lossy', $_POST['exactdn_lossy'] );
751
  $_POST['ewww_image_optimizer_lazy_load'] = ( empty( $_POST['ewww_image_optimizer_lazy_load'] ) ? false : true );
752
  update_site_option( 'ewww_image_optimizer_lazy_load', $_POST['ewww_image_optimizer_lazy_load'] );
 
 
753
  $_POST['ewww_image_optimizer_maxmediawidth'] = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediawidth'];
754
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
755
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
@@ -829,6 +837,7 @@ function ewww_image_optimizer_admin_init() {
829
  register_setting( 'ewww_image_optimizer_options', 'exactdn_all_the_things', 'boolval' );
830
  register_setting( 'ewww_image_optimizer_options', 'exactdn_lossy', 'boolval' );
831
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_lazy_load', 'boolval' );
 
832
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
833
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
834
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
@@ -887,6 +896,7 @@ function ewww_image_optimizer_admin_init() {
887
  || 'force-regenerate-thumbnails' === $_GET['page']
888
  || 'ajax-thumbnail-rebuild' === $_GET['page']
889
  || 'regenerate_thumbnails_advanced' === $_GET['page']
 
890
  ) {
891
  // Add a notice for thumb regeneration.
892
  add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
@@ -964,7 +974,9 @@ function ewww_image_optimizer_ajax_compat_check() {
964
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
965
  // Check for (Force) Regenerate Thumbnails action (includes MLP regenerate).
966
  if ( ! empty( $_REQUEST['action'] ) ) {
967
- if ( 'regeneratethumbnail' === $_REQUEST['action'] ||
 
 
968
  'meauh_save_image' === $_REQUEST['action'] ||
969
  'hotspot_save' === $_REQUEST['action']
970
  ) {
@@ -1011,14 +1023,13 @@ function ewww_image_optimizer_ajax_compat_check() {
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;
@@ -1038,9 +1049,9 @@ function ewww_image_optimizer_privacy_policy_content() {
1038
  if ( ! defined( 'EWWW_IO_CLOUD_PLUGIN' ) || ! EWWW_IO_CLOUD_PLUGIN ) {
1039
  $content .= wp_kses_post( __( 'By default, the EWWW Image Optimizer does not store any personal data nor share it with anyone.', 'ewww-image-optimizer' ) ) . '</p><p>';
1040
  }
1041
- $content .= wp_kses_post( __( 'If you accept user-submitted images and use the API or ExactDN, those images may be transmitted to third-party servers in foreign countries. If Backup Originals is enabled, images are stored for 30 days. Otherwise, no images are stored on the API for longer than 30 minutes.', 'ewww-image-optimizer' ) ) . '</p>';
1042
  $content .= '<p><strong>' . wp_kses_post( __( 'Suggested API Text:' ) ) . '</strong> <i>' . wp_kses_post( __( 'User-submitted images may be transmitted to image compression servers in the United States and stored there for up to 30 days.' ) ) . '</i></p>';
1043
- $content .= '<p><strong>' . wp_kses_post( __( 'Suggested ExactDN Text:' ) ) . '</strong> <i>' . wp_kses_post( __( 'User-submitted images that are displayed on this site will be transmitted and stored on a global network of third-party servers (a CDN).' ) ) . '</i></p>';
1044
  wp_add_privacy_policy_content( 'EWWW Image Optimizer', $content );
1045
  }
1046
 
@@ -1562,7 +1573,7 @@ function ewww_image_optimizer_notice_webp_bulk() {
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' );
@@ -1598,7 +1609,7 @@ function ewww_image_optimizer_notice_exactdn_activation_error() {
1598
  $exactdn_activate_error = 'error unknown';
1599
  }
1600
  echo '<div id="ewww-image-optimizer-notice-exactdn-error" class="notice notice-error"><p>' .
1601
- esc_html__( 'Could not activate ExactDN, please try again in a few minutes. If this error continues, please contact support and provide this complete error message.', 'ewww-image-optimizer' ) .
1602
  '<br><code>' . $exactdn_activate_error . '</code>' .
1603
  '</p></div>';
1604
  }
@@ -1608,7 +1619,7 @@ function ewww_image_optimizer_notice_exactdn_activation_error() {
1608
  */
1609
  function ewww_image_optimizer_notice_exactdn_activation_success() {
1610
  echo '<div id="ewww-image-optimizer-notice-exactdn-success" class="notice notice-success"><p>' .
1611
- esc_html__( 'ExactDN setup and verification is complete.', 'ewww-image-optimizer' ) .
1612
  '</p></div>';
1613
  }
1614
 
@@ -1623,7 +1634,7 @@ function ewww_image_optimizer_php55_warning() {
1623
  * Inform the user that we disabled SP AIO to prevent conflicts with ExactDN.
1624
  */
1625
  function ewww_image_optimizer_notice_exactdn_sp_conflict() {
1626
- echo "<div id='ewww-image-optimizer-exactdn-sp' class='notice notice-warning'><p>" . esc_html__( 'ShortPixel image optimization has been disabled to prevent conflicts with ExactDN (EWWW Image Optimizer).', 'ewww-image-optimizer' ) . '</p></div>';
1627
  }
1628
 
1629
  /**
@@ -2339,7 +2350,7 @@ function ewww_image_optimizer_admin_menu() {
2339
  'EWWW Image Optimizer', // Page title.
2340
  'EWWW Image Optimizer', // Menu title.
2341
  apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability.
2342
- EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug.
2343
  'ewww_image_optimizer_options' // Function to call.
2344
  );
2345
  } else {
@@ -2348,7 +2359,7 @@ function ewww_image_optimizer_admin_menu() {
2348
  'EWWW Image Optimizer', // Page title.
2349
  'EWWW Image Optimizer', // Menu title.
2350
  apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability.
2351
- EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug.
2352
  'ewww_image_optimizer_network_singlesite_options' // Function to call.
2353
  );
2354
  }
@@ -2535,6 +2546,9 @@ function ewww_image_optimizer_settings_link( $links ) {
2535
  // Need to include the plugin library for the is_plugin_active function.
2536
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
2537
  }
 
 
 
2538
  // Load the html for the settings link.
2539
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
2540
  $settings_link = '<a href="network/settings.php?page=' . plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) . '">' . esc_html__( 'Settings', 'ewww-image-optimizer' ) . '</a>';
@@ -2864,9 +2878,34 @@ function ewww_image_optimizer_jpg_quality( $quality = null ) {
2864
  function ewww_image_optimizer_set_jpg_quality( $quality ) {
2865
  $new_quality = ewww_image_optimizer_jpg_quality();
2866
  if ( ! empty( $new_quality ) ) {
2867
- return $new_quality;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2868
  }
2869
- return $quality;
 
 
 
 
 
2870
  }
2871
 
2872
  /**
@@ -3212,8 +3251,10 @@ function ewww_image_optimizer_delete( $id ) {
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
  }
@@ -3235,14 +3276,13 @@ function ewww_image_optimizer_delete( $id ) {
3235
  $meta = wp_get_attachment_metadata( $id );
3236
  // If the attachment has an original file set.
3237
  if ( ! empty( $meta['orig_file'] ) ) {
3238
- unset( $rows );
3239
  // Get the filepath from the metadata.
3240
  $file_path = $meta['orig_file'];
3241
  // Get the base filename.
3242
  $filename = basename( $file_path );
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
  }
@@ -3258,8 +3298,21 @@ function ewww_image_optimizer_delete( $id ) {
3258
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3259
  }
3260
  }
3261
- // Remove the regular image from the ewwwio_images tables.
3262
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3263
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3264
  // Resized versions, so we can continue.
3265
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
@@ -3293,7 +3346,158 @@ function ewww_image_optimizer_delete( $id ) {
3293
  }
3294
  }
3295
  ewwwio_memory( __FUNCTION__ );
3296
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3297
  }
3298
 
3299
  /**
@@ -3607,7 +3811,7 @@ function ewww_image_optimizer_cloud_quota( $raw = false ) {
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.
@@ -3959,7 +4163,7 @@ function ewww_image_optimizer_cloud_backup( $file ) {
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.
@@ -4420,7 +4624,7 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
4420
  $updates['level'] = $ewww_image->level;
4421
  }
4422
  $updates['orig_size'] = $orig_size;
4423
- $updates['updated'] = date( 'Y-m-d H:i:s' );
4424
  $ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
4425
  } else {
4426
  if ( is_array( $already_optimized ) && empty( $already_optimized['orig_size'] ) ) {
@@ -6413,6 +6617,27 @@ function ewww_image_optimizer_as3cf_attachment_file_paths( $paths, $id ) {
6413
  }
6414
  return $paths;
6415
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6416
  /**
6417
  * Fixes the ContentType for WebP images because WP mimetype detection stinks.
6418
  *
@@ -6807,7 +7032,7 @@ function ewww_image_optimizer_png_alpha( $filename ) {
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.
@@ -7021,7 +7246,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
7021
  switch ( $type ) {
7022
  case 'image/jpeg':
7023
  // If jpegtran is missing and should not be skipped.
7024
- if ( ! EWWW_IMAGE_OPTIMIZER_JPEGTRAN && ! $skip['jpegtran'] ) {
7025
  $msg = '<div>' . sprintf(
7026
  /* translators: %s: name of a tool like jpegtran */
7027
  esc_html__( '%s is missing', 'ewww-image-optimizer' ),
@@ -7040,7 +7265,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
7040
  break;
7041
  case 'image/png':
7042
  // If pngout and optipng are missing and should not be skipped.
7043
- if ( ! EWWW_IMAGE_OPTIMIZER_PNGOUT && ! EWWW_IMAGE_OPTIMIZER_OPTIPNG && ! $skip['optipng'] && ! $skip['pngout'] ) {
7044
  $msg = '<div>' . sprintf(
7045
  /* translators: %s: name of a tool like jpegtran */
7046
  esc_html__( '%s is missing', 'ewww-image-optimizer' ),
@@ -7053,7 +7278,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
7053
  break;
7054
  case 'image/gif':
7055
  // If gifsicle is missing and should not be skipped.
7056
- if ( ! EWWW_IMAGE_OPTIMIZER_GIFSICLE && ! $skip['gifsicle'] ) {
7057
  $msg = '<div>' . sprintf(
7058
  /* translators: %s: name of a tool like jpegtran */
7059
  esc_html__( '%s is missing', 'ewww-image-optimizer' ),
@@ -8292,12 +8517,13 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8292
  } else {
8293
  delete_option( 'ewww_image_optimizer_cloud_key_invalid' );
8294
  if ( ! class_exists( 'ExactDN' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8295
- $compress_recommendations[] = esc_html__( 'Enable premium compression with an API key or ExactDN.', 'ewww-image-optimizer' );
8296
  }
8297
  $disable_level = "disabled='disabled'";
8298
  }
 
8299
  if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8300
- $status_notices .= '<p><b>ExactDN:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
8301
  } elseif ( get_option( 'easyio_exactdn' ) ) {
8302
  ewww_image_optimizer_webp_rewrite_verify();
8303
  update_option( 'ewww_image_optimizer_exactdn', false );
@@ -8306,12 +8532,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8306
  $compress_score += 80;
8307
  $resize_score += 50;
8308
  } elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8309
- $status_notices .= '<p><b>ExactDN:</b> ';
8310
  global $exactdn;
8311
  if ( $exactdn->get_exactdn_domain() && $exactdn->verify_domain( $exactdn->get_exactdn_domain() ) ) {
8312
  $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
8313
  if ( defined( 'WP_ROCKET_VERSION' ) ) {
8314
- $status_notices .= '<br><i>' . esc_html__( 'If you use the File Optimization options within WP Rocket, you should also enter your ExactDN CNAME in the WP Rocket CDN settings (reserved for CSS and Javascript):', 'ewww-image-optimizer' ) . ' ' . $exactdn->get_exactdn_domain() . '</i>';
8315
  }
8316
  if ( $compress_score < 50 ) {
8317
  $compress_score = 50;
@@ -8322,6 +8548,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8322
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) {
8323
  $compress_recommendations[] = esc_html__( 'Enable premium compression.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' );
8324
  }
 
8325
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
8326
  $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
8327
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'suspended' ) ) {
@@ -8331,12 +8558,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8331
  $status_notices .= '<span style="color: red; font-weight: bolder"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
8332
  }
8333
  if ( function_exists( 'remove_query_strings_link' ) || function_exists( 'rmqrst_loader_src' ) || function_exists( 'qsr_remove_query_strings_1' ) ) {
8334
- $status_notices .= '<br><i>' . esc_html__( 'Plugins that remove query strings are unnecessary with ExactDN. You may remove them at your convenience.', 'ewww-image-optimizer' ) . '</i>' . ewwwio_help_link( 'https://docs.ewww.io/article/50-exactdn-and-query-strings', '5a3d278a2c7d3a1943677b52' );
8335
  }
8336
  $status_notices .= '</p>';
8337
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8338
- $status_notices .= '<p><b>ExactDN:</b> ' . esc_html__( 'Inactive, enable to activate automatic resizing and more', 'ewww-image-optimizer' ) . '</p>';
8339
- $resize_recommendations[] = esc_html__( 'Enable ExactDN for automatic resizing.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/44-introduction-to-exactdn', '59bc5ad6042863033a1ce370,59de6631042863379ddc953c,59c44349042863033a1d06d3,5ada43a12c7d3a0e93678b8c,5a3d278a2c7d3a1943677b52,5a9868eb04286374f7087795,59de68482c7d3a40f0ed6035,592dd69b2c7d3a074e8aed5b' );
8340
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
8341
  delete_option( 'ewww_image_optimizer_exactdn_failures' );
8342
  delete_option( 'ewww_image_optimizer_exactdn_checkin' );
@@ -8350,6 +8577,15 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8350
  delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
8351
  delete_site_option( 'ewww_image_optimizer_exactdn_suspended' );
8352
  }
 
 
 
 
 
 
 
 
 
8353
  if (
8354
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) ||
8355
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) ||
@@ -8575,15 +8811,15 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8575
  if ( ( 'network-multisite' !== $network || ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) && // Display tabs so long as this isn't the network admin OR single-site override is disabled.
8576
  ! ( 'network-singlesite' === $network && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) ) { // Also make sure that this isn't single site without override mode.
8577
  $output[] = "<ul class='ewww-tab-nav'>\n" .
8578
- "<li class='ewww-tab ewww-general-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Basic', 'ewww-image-optimizer' ) . "</span></li>\n" .
8579
- ( get_option( 'easyio_exactdn' ) ? '' : "<li class='ewww-tab ewww-exactdn-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) . "</span></li>\n" ) .
8580
- "<li class='ewww-tab ewww-optimization-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Advanced', 'ewww-image-optimizer' ) . "</span></li>\n" .
8581
- "<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</span></li>\n" .
8582
- "<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Convert', 'ewww-image-optimizer' ) . "</span></li>\n" .
8583
- "<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP', 'ewww-image-optimizer' ) . "</span></li>\n" .
8584
- "<li class='ewww-tab ewww-overrides-nav'><span class='ewww-tab-hidden'><a href='https://docs.ewww.io/article/40-override-options' target='_blank'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
8585
- "<li class='ewww-tab ewww-support-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Support', 'ewww-image-optimizer' ) . "</span></li>\n" .
8586
- "<li class='ewww-tab ewww-contribute-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Contribute', 'ewww-image-optimizer' ) . "</span></li>\n" .
8587
  "</ul>\n";
8588
  }
8589
  if ( 'network-multisite' === $network ) {
@@ -8604,6 +8840,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8604
  }
8605
  $output[] = "<div id='ewww-general-settings'>\n";
8606
  $output[] = '<noscript><h2>' . esc_html__( 'Basic', 'ewww-image-optimizer' ) . '</h2></noscript>';
 
 
 
8607
  $output[] = "<table class='form-table'>\n";
8608
  if ( is_multisite() ) {
8609
  if ( is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
@@ -8621,7 +8860,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8621
  }
8622
  echo '</table></div><!-- end container general settings -->';
8623
  echo "<p class='submit'><input type='submit' class='button-primary' value='" . esc_attr__( 'Save Changes', 'ewww-image-optimizer' ) . "' /></p>\n";
8624
- echo '</form></div><!-- end container left --></div><!-- end container wrap -->';
8625
  ewww_image_optimizer_temp_debug_clear();
8626
  return;
8627
  }
@@ -8634,7 +8873,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8634
  }
8635
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_metadata_remove'>" . esc_html__( 'Remove Metadata', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
8636
  "<td><input type='checkbox' id='ewww_image_optimizer_metadata_remove' name='ewww_image_optimizer_metadata_remove' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will remove ALL metadata: EXIF, comments, color profiles, and anything else that is not pixel data.', 'ewww-image-optimizer' ) .
8637
- "<p class ='description'>" . esc_html__( 'Color profiles are preserved when using the API or ExactDN.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8638
  ewwwio_debug_message( 'remove metadata: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ? 'on' : 'off' ) );
8639
 
8640
  $maybe_api_level = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? '*' : '';
@@ -8696,10 +8935,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8696
  }
8697
  $output[] = "</table>\n</div>\n";
8698
  $output[] = "<div id='ewww-exactdn-settings'>\n";
 
 
 
8699
  $output[] = "<table class='form-table'>\n";
8700
- $output[] = '<noscript><h2>' . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) . '</h2></noscript>';
8701
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_exactdn'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) .
8702
- '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/44-introduction-to-exactdn', '59bc5ad6042863033a1ce370,59de6631042863379ddc953c,59c44349042863033a1d06d3,5ada43a12c7d3a0e93678b8c,5a3d278a2c7d3a1943677b52,5a9868eb04286374f7087795,59de68482c7d3a40f0ed6035,592dd69b2c7d3a074e8aed5b' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_exactdn' name='ewww_image_optimizer_exactdn' value='true' " .
8703
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? "checked='true'" : '' ) . ' /> ' .
8704
  esc_html__( 'Enables CDN and automatic image resizing to fit your pages.', 'ewww-image-optimizer' ) .
8705
  ' <a href="https://ewww.io/resize/" target="_blank">' . esc_html__( 'Purchase a subscription for your site.', 'ewww-image-optimizer' ) . '</a>' .
@@ -8709,23 +8950,51 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8709
  esc_html__( 'Premium Compression', 'ewww-image-optimizer' ) . '<br>' .
8710
  esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
8711
  esc_html__( 'JS/CSS Minification and Compression', 'ewww-image-optimizer' ) . '<br>' .
8712
- '<a href="https://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about ExactDN', 'ewww-image-optimizer' ) . '</a>' .
8713
  "</p></td></tr>\n";
8714
  ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? 'on' : 'off' ) );
8715
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_backup_files'>" . esc_html__( 'Include All Resources', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' ) . '</th>' .
8716
  "<td><input type='checkbox' id='exactdn_all_the_things' name='exactdn_all_the_things' value='true' " .
8717
- ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ? "checked='true'" : '' ) . '> ' . esc_html__( 'Use ExactDN for all resources in wp-includes/ and wp-content/, including JavaScript, CSS, fonts, etc.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
 
 
8718
  ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ? 'on' : 'off' ) );
8719
- $output[] = "<tr class='$network_class'><th scope='row'><label for='exactdn_lossy'>" . esc_html__( 'Premium Compression', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' ) . '</th>' .
8720
  "<td><input type='checkbox' id='exactdn_lossy' name='exactdn_lossy' value='true' " .
8721
- ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ? "checked='true'" : '' ) . '> ' . esc_html__( 'Enable high quality premium compression for all images. Disable to use Pixel Perfect mode instead.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8722
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_lazy_load'>" . esc_html__( 'Lazy Load', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/74-lazy-load', '5c6c36ed042863543ccd2d9b' ) .
8723
- "</th><td><input type='checkbox' id='ewww_image_optimizer_lazy_load' name='ewww_image_optimizer_lazy_load' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lazy_load' ) ? "checked='true'" : '' ) . ' /> ' .
8724
- esc_html__( 'Improves actual and perceived loading time as images will be loaded only as they enter (or are about to enter) the viewport. When used with the ExactDN and WebP features, the plugin will load the best available image size and format for each device.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8725
  ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
8726
  ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) ? 'on' : 'off' ) );
8727
  ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) ? 'off' : 'on' ) );
8728
  ewwwio_debug_message( 'lazy load: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lazy_load' ) ? 'on' : 'off' ) );
 
8729
  if ( defined( 'EXACTDN_EXCLUDE' ) && EXACTDN_EXCLUDE ) {
8730
  $exactdn_user_exclusions = EXACTDN_EXCLUDE;
8731
  if ( is_array( $exactdn_user_exclusions ) ) {
@@ -8746,6 +9015,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8746
  ewwwio_debug_message( 'pngout level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' ) );
8747
  }
8748
  $output[] = "<tr class='$network_class'><th scope='row'><span><label for='ewww_image_optimizer_jpg_quality'>" . esc_html__( 'JPG Quality Level:', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,58543c69c697912ffd6c19a7' ) . "</th><td><input type='text' id='ewww_image_optimizer_jpg_quality' name='ewww_image_optimizer_jpg_quality' class='small-text' value='" . ewww_image_optimizer_jpg_quality() . "' /> " . esc_html__( 'Valid values are 1-100.', 'ewww-image-optimizer' ) . "\n<p class='description'>" . esc_html__( 'Use this to override the default WordPress quality level of 82. Applies to image editing, resizing, PNG to JPG conversion, and JPG to WebP conversion. Does not affect the original uploaded image unless maximum dimensions are set and resizing occurs.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
 
8749
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_parallel_optimization'>" . esc_html__( 'Parallel Optimization', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,598cb8be2c7d3a73488be237' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_parallel_optimization' name='ewww_image_optimizer_parallel_optimization' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'All resizes generated from a single upload are optimized in parallel for faster optimization. If this is causing performance issues, disable parallel optimization to reduce the load on your server.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8750
  ewwwio_debug_message( 'parallel optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ? 'on' : 'off' ) );
8751
  ewwwio_debug_message( 'background optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ? 'on' : 'off' ) );
@@ -8892,6 +9162,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8892
  $output[] = '<table><tr class="network-singlesite"><th scope="col">' . esc_html__( 'Disable Optimization', 'ewww-image-optimizer' ) . '</th><th scope="col">' . esc_html__( 'Disable Creation', 'ewww-image-optimizer' ) . "</th></tr>\n";
8893
  ewwwio_debug_message( 'disabled resizes:' );
8894
  foreach ( $image_sizes as $size => $dimensions ) {
 
 
 
8895
  if ( 'thumbnail' === $size ) {
8896
  $output[] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' disabled /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - {$dimensions['width']}x{$dimensions['height']}</label></td></tr>\n";
8897
  } elseif ( 'pdf-full' === $size ) {
@@ -8967,6 +9240,10 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8967
 
8968
  $output[] = "<div id='ewww-webp-settings'>\n";
8969
  $output[] = '<noscript><h2>' . esc_html__( 'WebP', 'ewww-image-optimizer' ) . '</h2></noscript>';
 
 
 
 
8970
  $output[] = "<table class='form-table'>\n";
8971
  if ( ! ewww_image_optimizer_easy_active() || ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
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>' .
@@ -9004,7 +9281,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
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
  }
@@ -9120,17 +9397,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
9120
  $test_png_image = plugins_url( '/images/test.png', __FILE__ );
9121
  $output[] = "<noscript data-img='$test_png_image' data-webp='$test_webp_image' data-style='float: right; padding: 0 0 10px 10px;' class='ewww_webp'><img src='$test_png_image' style='float: right; padding: 0 0 10px 10px;'></noscript>\n";
9122
  }
9123
- $output[] = "<!--</div>--><!-- end container left -->\n";
9124
- $output[] = "<!--<div id='ewww-container-right' style='border: 1px solid #e5e5e5; float: right; margin-left: -215px; padding: 0em 1.5em 1em; background-color: #fff; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); display: inline-block; width: 174px;'>\n" .
9125
- '<h2>' . esc_html__( 'Support EWWW I.O.', 'ewww-image-optimizer' ) . "</h2>\n" .
9126
- "<p><a href='https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/'>" . esc_html__( 'Help translate EWWW I.O.', 'ewww-image-optimizer' ) . "</a></p>\n" .
9127
- "<p><a href='https://wordpress.org/support/view/plugin-reviews/ewww-image-optimizer#postform'>" . esc_html__( 'Write a review.', 'ewww-image-optimizer' ) . "</a></p>\n" .
9128
- '<p>' . esc_html__( 'Signup for premium image optimization:', 'ewww-image-optimizer' ) . "<br>\n" .
9129
- "<a target='_blank' href='https://ewww.io/plans/'>" . esc_html__( 'Compress', 'ewww-image-optimizer' ) . "</a><br>\n" .
9130
- "<a target='_blank' href='https://ewww.io/resize/'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</a></p>\n" .
9131
- '<p><b>' . esc_html_x( 'CDN:', 'abbreviation for Content Delivery Network', 'ewww-image-optimizer' ) . "</b><br><a target='_blank' href='https://ewww.io/resize/'>" . esc_html__( 'Add ExactDN to increase website speeds dramatically!', 'ewww-image-optimizer' ) . "</a></p>\n" .
9132
- "</div>-->\n" .
9133
- "</div>\n";
9134
  ewwwio_debug_message( 'max_execution_time: ' . ini_get( 'max_execution_time' ) );
9135
  ewww_image_optimizer_stl_check();
9136
  ewww_image_optimizer_function_exists( 'sleep', true );
@@ -9145,9 +9412,6 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
9145
  $eio_alt_webp->inline_script();
9146
  }
9147
 
9148
- $help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
9149
- esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
9150
-
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>';
@@ -9157,15 +9421,33 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
9157
  $debug_output .= '</p>';
9158
  $debug_output .= '<div id="ewww-debug-info" style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;" contenteditable="true">' . $eio_debug . '</div>';
9159
 
9160
- $help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
9161
- esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
9162
-
9163
  $output = str_replace( 'DEBUG_PLACEHOLDER', $debug_output, $output );
9164
  } else {
9165
  $output = str_replace( 'DEBUG_PLACEHOLDER', '', $output );
9166
  }
9167
 
9168
  echo $output;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9169
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
9170
  $current_user = wp_get_current_user();
9171
  $help_email = $current_user->user_email;
@@ -9452,7 +9734,7 @@ function ewww_image_optimizer_debug_log() {
9452
  if ( ! empty( $eio_debug ) && empty( $ewwwio_temp_debug ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && is_writable( WP_CONTENT_DIR . '/ewww/' ) ) {
9453
  $memory_limit = ewwwio_memory_limit();
9454
  clearstatcache();
9455
- $timestamp = date( 'Y-m-d H:i:s' ) . "\n";
9456
  if ( ! file_exists( $debug_log ) ) {
9457
  touch( $debug_log );
9458
  } else {
@@ -9812,7 +10094,7 @@ function ewwwio_memory( $function ) {
9812
  function ewwwio_memory_output() {
9813
  if ( WP_DEBUG ) {
9814
  global $ewww_memory;
9815
- $timestamp = date( 'y-m-d h:i:s.u' ) . ' ';
9816
  if ( ! file_exists( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'memory.log' ) ) {
9817
  touch( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'memory.log' );
9818
  }
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.
20
+ // TODO: make sure all settings (like lazy load) are in usage reporting.
21
  if ( ! defined( 'ABSPATH' ) ) {
22
  exit;
23
  }
24
 
25
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '514.0' );
26
 
27
  // Initialize a couple globals.
28
  $eio_debug = '';
85
  add_filter( 'mpp_handle_upload', 'ewww_image_optimizer_handle_mpp_upload' );
86
  // Processes a MediaPress image via the metadata after upload.
87
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
88
+ // Processes an attachment after IRSC has done a thumb regen.
89
+ add_filter( 'sirsc_attachment_images_ready', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
90
  }
91
  // Skips resizing for images with 'noresize' in the filename.
92
  add_filter( 'ewww_image_optimizer_resize_dimensions', 'ewww_image_optimizer_noresize', 10, 2 );
102
  add_filter( 'ewww_image_optimizer_admin_permissions', 'ewww_image_optimizer_admin_permissions', 8 );
103
  add_filter( 'ewww_image_optimizer_superadmin_permissions', 'ewww_image_optimizer_superadmin_permissions', 8 );
104
  // Add a link to the plugins page so the user can go straight to the settings page.
105
+ add_filter( 'plugin_action_links_' . EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL, 'ewww_image_optimizer_settings_link' );
 
106
  // Filter the registered sizes so we can remove any that the user disabled.
107
  add_filter( 'intermediate_image_sizes_advanced', 'ewww_image_optimizer_image_sizes_advanced' );
108
  // Ditto for PDF files (or anything non-image).
117
  add_filter( 'load_image_to_edit_path', 'ewww_image_optimizer_editor_save_pre' );
118
  // Allows the user to override the default JPG quality used by WordPress.
119
  add_filter( 'jpeg_quality', 'ewww_image_optimizer_set_jpg_quality' );
120
+ // Prevent WP from over-riding EWWW IO's resize settings.
121
+ add_filter( 'big_image_size_threshold', 'ewww_image_optimizer_adjust_big_image_threshold', 10, 3 );
122
  // Makes sure the plugin bypasses any files affected by the Folders to Ignore setting.
123
  add_filter( 'ewww_image_optimizer_bypass', 'ewww_image_optimizer_ignore_file', 10, 2 );
124
  // Ensure we populate the queue with webp images for WP Offload S3.
125
  add_filter( 'as3cf_attachment_file_paths', 'ewww_image_optimizer_as3cf_attachment_file_paths', 10, 2 );
126
+ // Make sure to remove webp images from remote storage when an attachment is deleted.
127
+ add_filter( 'as3cf_remove_attachment_paths', 'ewww_image_optimizer_as3cf_remove_attachment_file_paths', 10, 2 );
128
  // Fix the ContentType for WP Offload S3 on WebP images.
129
  add_filter( 'as3cf_object_meta', 'ewww_image_optimizer_as3cf_object_meta' );
130
  // Loads the plugin translations.
149
  add_action( 'admin_action_ewww_image_optimizer_manual_convert', 'ewww_image_optimizer_manual' );
150
  // Cleanup routine when an attachment is deleted.
151
  add_action( 'delete_attachment', 'ewww_image_optimizer_delete' );
152
+ // Cleanup db records when Enable Media Replace replaces a file.
153
+ add_action( 'wp_handle_replace', 'ewww_image_optimizer_media_replace' );
154
+ // Cleanup db records when Image Regenerate & Select Crop deletes a file.
155
+ add_action( 'sirsc_image_file_deleted', 'ewww_image_optimizer_file_deleted', 10, 2 );
156
  // Adds the EWWW IO pages to the admin menu.
157
  add_action( 'admin_menu', 'ewww_image_optimizer_admin_menu', 60 );
158
  // Adds the EWWW IO settings to the network admin menu.
598
  if ( get_option( 'ewww_image_optimizer_version' ) < 280 ) {
599
  ewww_image_optimizer_migrate_settings_to_levels();
600
  }
 
 
 
 
601
  if ( get_option( 'ewww_image_optimizer_version' ) > 0 && get_option( 'ewww_image_optimizer_version' ) < 434 && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
602
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_metadata_remove', false );
603
  }
 
 
 
 
604
  if ( get_option( 'ewww_image_optimizer_version' ) < 454 ) {
605
  update_option( 'ewww_image_optimizer_bulk_resume', '' );
606
  update_option( 'ewww_image_optimizer_aux_resume', '' );
681
  function ewww_image_optimizer_admin_init() {
682
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
683
  ewwwio_memory( __FUNCTION__ );
684
+ /**
685
+ * EWWWIO_HS_Beacon class for embedding the HelpScout Beacon.
686
+ */
687
+ require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-hs-beacon.php' );
688
  /**
689
  * Require the file that does the bulk processing.
690
  */
756
  update_site_option( 'exactdn_lossy', $_POST['exactdn_lossy'] );
757
  $_POST['ewww_image_optimizer_lazy_load'] = ( empty( $_POST['ewww_image_optimizer_lazy_load'] ) ? false : true );
758
  update_site_option( 'ewww_image_optimizer_lazy_load', $_POST['ewww_image_optimizer_lazy_load'] );
759
+ $_POST['ewww_image_optimizer_use_lqip'] = ( empty( $_POST['ewww_image_optimizer_use_lqip'] ) ? false : true );
760
+ update_site_option( 'ewww_image_optimizer_use_lqip', $_POST['ewww_image_optimizer_use_lqip'] );
761
  $_POST['ewww_image_optimizer_maxmediawidth'] = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediawidth'];
762
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
763
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
837
  register_setting( 'ewww_image_optimizer_options', 'exactdn_all_the_things', 'boolval' );
838
  register_setting( 'ewww_image_optimizer_options', 'exactdn_lossy', 'boolval' );
839
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_lazy_load', 'boolval' );
840
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_use_lqip', 'boolval' );
841
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
842
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
843
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
896
  || 'force-regenerate-thumbnails' === $_GET['page']
897
  || 'ajax-thumbnail-rebuild' === $_GET['page']
898
  || 'regenerate_thumbnails_advanced' === $_GET['page']
899
+ || 'rta_generate_thumbnails' === $_GET['page']
900
  ) {
901
  // Add a notice for thumb regeneration.
902
  add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
974
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
975
  // Check for (Force) Regenerate Thumbnails action (includes MLP regenerate).
976
  if ( ! empty( $_REQUEST['action'] ) ) {
977
+ if (
978
+ 'regeneratethumbnail' === $_REQUEST['action'] ||
979
+ 'rta_regenerate_thumbnails' === $_REQUEST['action'] ||
980
  'meauh_save_image' === $_REQUEST['action'] ||
981
  'hotspot_save' === $_REQUEST['action']
982
  ) {
1023
  ewww_image_optimizer_image_sizes( false );
1024
  return;
1025
  }
1026
+ // Check for Image Regenerate and Select Crop (better way).
1027
+ if ( defined( 'DOING_SIRSC' ) && DOING_SIRSC ) {
1028
  ewwwio_debug_message( 'IRSC action/regen' );
1029
  ewww_image_optimizer_image_sizes( false );
1030
  return;
1031
+ } elseif ( ! empty( $_REQUEST['action'] ) && 0 === strpos( $_REQUEST['action'], 'sirsc' ) ) {
1032
+ // Image Regenerate and Select Crop (old check).
 
1033
  ewwwio_debug_message( 'IRSC action/regen' );
1034
  ewww_image_optimizer_image_sizes( false );
1035
  return;
1049
  if ( ! defined( 'EWWW_IO_CLOUD_PLUGIN' ) || ! EWWW_IO_CLOUD_PLUGIN ) {
1050
  $content .= wp_kses_post( __( 'By default, the EWWW Image Optimizer does not store any personal data nor share it with anyone.', 'ewww-image-optimizer' ) ) . '</p><p>';
1051
  }
1052
+ $content .= wp_kses_post( __( 'If you accept user-submitted images and use the API or Easy IO, those images may be transmitted to third-party servers in foreign countries. If Backup Originals is enabled, images are stored for 30 days. Otherwise, no images are stored on the API for longer than 30 minutes.', 'ewww-image-optimizer' ) ) . '</p>';
1053
  $content .= '<p><strong>' . wp_kses_post( __( 'Suggested API Text:' ) ) . '</strong> <i>' . wp_kses_post( __( 'User-submitted images may be transmitted to image compression servers in the United States and stored there for up to 30 days.' ) ) . '</i></p>';
1054
+ $content .= '<p><strong>' . wp_kses_post( __( 'Suggested Easy IO Text:' ) ) . '</strong> <i>' . wp_kses_post( __( 'User-submitted images that are displayed on this site will be transmitted and stored on a global network of third-party servers (a CDN).' ) ) . '</i></p>';
1055
  wp_add_privacy_policy_content( 'EWWW Image Optimizer', $content );
1056
  }
1057
 
1573
  $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' );
1574
  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>';
1575
  } else {
1576
+ $message = esc_html__( 'Use the Bulk Optimizer to generate WebP images for existing uploads.', 'ewww-image-optimizer' );
1577
  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>';
1578
  }
1579
  delete_option( 'ewww_image_optimizer_webp_enabled' );
1609
  $exactdn_activate_error = 'error unknown';
1610
  }
1611
  echo '<div id="ewww-image-optimizer-notice-exactdn-error" class="notice notice-error"><p>' .
1612
+ esc_html__( 'Could not activate Easy IO, please try again in a few minutes. If this error continues, please contact support and provide this complete error message.', 'ewww-image-optimizer' ) .
1613
  '<br><code>' . $exactdn_activate_error . '</code>' .
1614
  '</p></div>';
1615
  }
1619
  */
1620
  function ewww_image_optimizer_notice_exactdn_activation_success() {
1621
  echo '<div id="ewww-image-optimizer-notice-exactdn-success" class="notice notice-success"><p>' .
1622
+ esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) .
1623
  '</p></div>';
1624
  }
1625
 
1634
  * Inform the user that we disabled SP AIO to prevent conflicts with ExactDN.
1635
  */
1636
  function ewww_image_optimizer_notice_exactdn_sp_conflict() {
1637
+ echo "<div id='ewww-image-optimizer-exactdn-sp' class='notice notice-warning'><p>" . esc_html__( 'ShortPixel image optimization has been disabled to prevent conflicts with Easy IO (EWWW Image Optimizer).', 'ewww-image-optimizer' ) . '</p></div>';
1638
  }
1639
 
1640
  /**
2350
  'EWWW Image Optimizer', // Page title.
2351
  'EWWW Image Optimizer', // Menu title.
2352
  apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability.
2353
+ EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL, // Slug.
2354
  'ewww_image_optimizer_options' // Function to call.
2355
  );
2356
  } else {
2359
  'EWWW Image Optimizer', // Page title.
2360
  'EWWW Image Optimizer', // Menu title.
2361
  apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability.
2362
+ EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL, // Slug.
2363
  'ewww_image_optimizer_network_singlesite_options' // Function to call.
2364
  );
2365
  }
2546
  // Need to include the plugin library for the is_plugin_active function.
2547
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
2548
  }
2549
+ if ( ! is_array( $links ) ) {
2550
+ $links = array();
2551
+ }
2552
  // Load the html for the settings link.
2553
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
2554
  $settings_link = '<a href="network/settings.php?page=' . plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) . '">' . esc_html__( 'Settings', 'ewww-image-optimizer' ) . '</a>';
2878
  function ewww_image_optimizer_set_jpg_quality( $quality ) {
2879
  $new_quality = ewww_image_optimizer_jpg_quality();
2880
  if ( ! empty( $new_quality ) ) {
2881
+ return min( 92, $new_quality );
2882
+ }
2883
+ return min( 92, $quality );
2884
+ }
2885
+
2886
+ /**
2887
+ * Check default WP threshold and adjust to comply with normal EWWW IO behavior.
2888
+ *
2889
+ * @param int $size The default WP scaling size, or whatever has been filtered by other plugins.
2890
+ * @param array $imagesize {
2891
+ * Indexed array of the image width and height in pixels.
2892
+ *
2893
+ * @type int $0 The image width.
2894
+ * @type int $1 The image height.
2895
+ * }
2896
+ * @param string $file Full path to the uploaded image file.
2897
+ * @return int The proper size to use for scaling originals.
2898
+ */
2899
+ function ewww_image_optimizer_adjust_big_image_threshold( $size, $imagesize, $file ) {
2900
+ if ( false !== strpos( $file, 'noresize' ) ) {
2901
+ return false;
2902
  }
2903
+ $max_size = max(
2904
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ),
2905
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ),
2906
+ (int) $size
2907
+ );
2908
+ return $max_size;
2909
  }
2910
 
2911
  /**
3251
  if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
3252
  continue;
3253
  }
3254
+ if ( ! empty( $image['path'] ) ) {
3255
+ if ( ewwwio_is_file( $image['path'] ) ) {
3256
+ unlink( $image['path'] );
3257
+ }
3258
  if ( ewwwio_is_file( $image['path'] . '.webp' ) ) {
3259
  unlink( $image['path'] . '.webp' );
3260
  }
3276
  $meta = wp_get_attachment_metadata( $id );
3277
  // If the attachment has an original file set.
3278
  if ( ! empty( $meta['orig_file'] ) ) {
 
3279
  // Get the filepath from the metadata.
3280
  $file_path = $meta['orig_file'];
3281
  // Get the base filename.
3282
  $filename = basename( $file_path );
3283
  // Delete any residual webp versions.
3284
+ $webpfile = $file_path . '.webp';
3285
+ $webpfileold = preg_replace( '/\.\w+$/', '.webp', $file_path );
3286
  if ( ewwwio_is_file( $webpfile ) ) {
3287
  unlink( $webpfile );
3288
  }
3298
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3299
  }
3300
  }
 
3301
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
3302
+ // If the attachment has an original file set.
3303
+ if ( ! empty( $meta['original_image'] ) ) {
3304
+ // One way or another, $file_path is now set, and we can get the base folder name.
3305
+ $base_dir = dirname( $file_path ) . '/';
3306
+ // Get the original filename from the metadata.
3307
+ $orig_path = $base_dir . basename( $meta['original_image'] );
3308
+ // Delete any residual webp versions.
3309
+ $webpfile = $orig_path . '.webp';
3310
+ if ( ewwwio_is_file( $webpfile ) ) {
3311
+ unlink( $webpfile );
3312
+ }
3313
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $orig_path ) ) );
3314
+ }
3315
+ // Remove the regular image from the ewwwio_images tables.
3316
  $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3317
  // Resized versions, so we can continue.
3318
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
3346
  }
3347
  }
3348
  ewwwio_memory( __FUNCTION__ );
3349
+ }
3350
+
3351
+ /**
3352
+ * Cleans up when a file has been deleted.
3353
+ *
3354
+ * Removes any .webp images, backups from conversion, and removes related database records.
3355
+ *
3356
+ * @global object $wpdb
3357
+ * @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
3358
+ *
3359
+ * @param int $id The id number for the attachment being deleted.
3360
+ * @param string $file The file being deleted.
3361
+ */
3362
+ function ewww_image_optimizer_file_deleted( $id, $file ) {
3363
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3364
+ global $wpdb;
3365
+ if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
3366
+ ewww_image_optimizer_db_init();
3367
+ global $ewwwdb;
3368
+ } else {
3369
+ $ewwwdb = $wpdb;
3370
+ }
3371
+ $id = (int) $id;
3372
+ // Finds non-meta images to remove from disk, and from db, as well as converted originals.
3373
+ $maybe_relative_path = ewww_image_optimizer_relativize_path( $file );
3374
+ $query = $ewwwdb->prepare( "SELECT * FROM $ewwwdb->ewwwio_images WHERE path = %s", $maybe_relative_path );
3375
+ $optimized_images = $ewwwdb->get_results( $query, ARRAY_A );
3376
+ if ( ewww_image_optimizer_iterable( $optimized_images ) ) {
3377
+ foreach ( $optimized_images as $image ) {
3378
+ if ( ! empty( $image['path'] ) ) {
3379
+ $image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
3380
+ }
3381
+ if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
3382
+ continue;
3383
+ }
3384
+ if ( ! empty( $image['converted'] ) ) {
3385
+ $image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
3386
+ }
3387
+ if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
3388
+ unlink( $image['converted'] );
3389
+ if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
3390
+ unlink( $image['converted'] . '.webp' );
3391
+ }
3392
+ }
3393
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'id' => $image['id'] ) );
3394
+ }
3395
+ }
3396
+ if ( ewwwio_is_file( $file . '.webp' ) ) {
3397
+ unlink( $file . '.webp' );
3398
+ }
3399
+ }
3400
+
3401
+ /**
3402
+ * Cleans records from database when an image is being replaced.
3403
+ *
3404
+ * @param array $image An array with the attachment/image ID.
3405
+ */
3406
+ function ewww_image_optimizer_media_replace( $image ) {
3407
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3408
+ global $wpdb;
3409
+ if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
3410
+ ewww_image_optimizer_db_init();
3411
+ global $ewwwdb;
3412
+ } else {
3413
+ $ewwwdb = $wpdb;
3414
+ }
3415
+ $id = (int) $image['post_id'];
3416
+ // Finds non-meta images to remove from disk, and from db, as well as converted originals.
3417
+ $optimized_images = $ewwwdb->get_results( "SELECT path,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media'", ARRAY_A );
3418
+ if ( $optimized_images ) {
3419
+ if ( ewww_image_optimizer_iterable( $optimized_images ) ) {
3420
+ foreach ( $optimized_images as $image ) {
3421
+ if ( ! empty( $image['path'] ) ) {
3422
+ $image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
3423
+ }
3424
+ if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
3425
+ continue;
3426
+ }
3427
+ if ( ! empty( $image['path'] ) ) {
3428
+ if ( ewwwio_is_file( $image['path'] . '.webp' ) ) {
3429
+ unlink( $image['path'] . '.webp' );
3430
+ }
3431
+ }
3432
+ if ( ! empty( $image['converted'] ) ) {
3433
+ $image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
3434
+ }
3435
+ if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
3436
+ unlink( $image['converted'] );
3437
+ if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
3438
+ unlink( $image['converted'] . '.webp' );
3439
+ }
3440
+ }
3441
+ }
3442
+ }
3443
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'attachment_id' => $id ) );
3444
+ }
3445
+ // Retrieve the image metadata.
3446
+ $meta = wp_get_attachment_metadata( $id );
3447
+ // If the attachment has an original file set.
3448
+ if ( ! empty( $meta['orig_file'] ) ) {
3449
+ // Get the filepath from the metadata.
3450
+ $file_path = $meta['orig_file'];
3451
+
3452
+ $webpfile = $file_path . '.webp';
3453
+ $webpfileold = preg_replace( '/\.\w+$/', '.webp', $file_path );
3454
+ if ( ewwwio_is_file( $webpfile ) ) {
3455
+ unlink( $webpfile );
3456
+ }
3457
+ if ( ewwwio_is_file( $webpfileold ) ) {
3458
+ unlink( $webpfileold );
3459
+ }
3460
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3461
+ }
3462
+ list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
3463
+ // If the attachment has an original file set.
3464
+ if ( ! empty( $meta['original_image'] ) ) {
3465
+ // One way or another, $file_path is now set, and we can get the base folder name.
3466
+ $base_dir = dirname( $file_path ) . '/';
3467
+ // Get the original filename from the metadata.
3468
+ $orig_path = $base_dir . basename( $meta['original_image'] );
3469
+ // Delete any residual webp versions.
3470
+ $webpfile = $orig_path . '.webp';
3471
+ if ( ewwwio_is_file( $webpfile ) ) {
3472
+ unlink( $webpfile );
3473
+ }
3474
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $orig_path ) ) );
3475
+ }
3476
+ // Remove the regular image from the ewwwio_images tables.
3477
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
3478
+ // Resized versions, so we can continue.
3479
+ if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
3480
+ // One way or another, $file_path is now set, and we can get the base folder name.
3481
+ $base_dir = dirname( $file_path ) . '/';
3482
+ foreach ( $meta['sizes'] as $size => $data ) {
3483
+ // Delete any residual webp versions.
3484
+ $webpfile = $base_dir . $data['file'] . '.webp';
3485
+ $webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . $data['file'] );
3486
+ if ( ewwwio_is_file( $webpfile ) ) {
3487
+ unlink( $webpfile );
3488
+ }
3489
+ if ( ewwwio_is_file( $webpfileold ) ) {
3490
+ unlink( $webpfileold );
3491
+ }
3492
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['file'] ) ) );
3493
+ // If the original resize is set, and still exists.
3494
+ if ( ! empty( $data['orig_file'] ) ) {
3495
+ // Retrieve the filename from the metadata.
3496
+ $filename = $data['orig_file'];
3497
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize( $base_dir . $data['orig_file'] ) ) );
3498
+ }
3499
+ }
3500
+ }
3501
  }
3502
 
3503
  /**
3811
  */
3812
  function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $newfile = null, $newtype = null, $fullsize = false, $jpg_fill = '', $jpg_quality = 82 ) {
3813
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3814
+ if ( ! ewwwio_is_file( $file ) || ! is_writable( $file ) || false !== strpos( $file, '../' ) ) {
3815
  return array( $file, false, 'invalid file', 0, '' );
3816
  }
3817
  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.
4163
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
4164
  return false;
4165
  }
4166
+ if ( ! ewwwio_is_file( $file ) || ! is_readable( $file ) || false !== strpos( $file, '../' ) ) {
4167
  return false;
4168
  }
4169
  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.
4624
  $updates['level'] = $ewww_image->level;
4625
  }
4626
  $updates['orig_size'] = $orig_size;
4627
+ $updates['updated'] = gmdate( 'Y-m-d H:i:s' );
4628
  $ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
4629
  } else {
4630
  if ( is_array( $already_optimized ) && empty( $already_optimized['orig_size'] ) ) {
6617
  }
6618
  return $paths;
6619
  }
6620
+
6621
+ /**
6622
+ * Cleanup remote storage for WP Offload S3.
6623
+ *
6624
+ * Checks for WebP derivatives so that they can be removed.
6625
+ *
6626
+ * @param array $paths The image paths currently queued for deletion.
6627
+ * @param int $id The ID number of the image in the database.
6628
+ * @return array A list of paths to remove.
6629
+ */
6630
+ function ewww_image_optimizer_as3cf_remove_attachment_file_paths( $paths, $id ) {
6631
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6632
+ foreach ( $paths as $path ) {
6633
+ if ( is_string( $path ) ) {
6634
+ $paths[] = $path . '.webp';
6635
+ ewwwio_debug_message( "added $path.webp to as3cf deletion queue" );
6636
+ }
6637
+ }
6638
+ return $paths;
6639
+ }
6640
+
6641
  /**
6642
  * Fixes the ContentType for WebP images because WP mimetype detection stinks.
6643
  *
7032
  if ( ! ewwwio_is_file( $filename ) ) {
7033
  return false;
7034
  }
7035
+ if ( false !== strpos( $filename, '../' ) ) {
7036
  return false;
7037
  }
7038
  // Determine what color type is stored in the file.
7246
  switch ( $type ) {
7247
  case 'image/jpeg':
7248
  // If jpegtran is missing and should not be skipped.
7249
+ if ( ! $skip['jpegtran'] && defined( 'EWWW_IMAGE_OPTIMIZER_JPEGTRAN' ) && ! EWWW_IMAGE_OPTIMIZER_JPEGTRAN ) {
7250
  $msg = '<div>' . sprintf(
7251
  /* translators: %s: name of a tool like jpegtran */
7252
  esc_html__( '%s is missing', 'ewww-image-optimizer' ),
7265
  break;
7266
  case 'image/png':
7267
  // If pngout and optipng are missing and should not be skipped.
7268
+ if ( ! $skip['optipng'] && ! $skip['pngout'] && ! EWWW_IMAGE_OPTIMIZER_PNGOUT && ! EWWW_IMAGE_OPTIMIZER_OPTIPNG ) {
7269
  $msg = '<div>' . sprintf(
7270
  /* translators: %s: name of a tool like jpegtran */
7271
  esc_html__( '%s is missing', 'ewww-image-optimizer' ),
7278
  break;
7279
  case 'image/gif':
7280
  // If gifsicle is missing and should not be skipped.
7281
+ if ( ! $skip['gifsicle'] && ! EWWW_IMAGE_OPTIMIZER_GIFSICLE ) {
7282
  $msg = '<div>' . sprintf(
7283
  /* translators: %s: name of a tool like jpegtran */
7284
  esc_html__( '%s is missing', 'ewww-image-optimizer' ),
8517
  } else {
8518
  delete_option( 'ewww_image_optimizer_cloud_key_invalid' );
8519
  if ( ! class_exists( 'ExactDN' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8520
+ $compress_recommendations[] = esc_html__( 'Enable premium compression with an API key or Easy IO.', 'ewww-image-optimizer' );
8521
  }
8522
  $disable_level = "disabled='disabled'";
8523
  }
8524
+ $exactdn_enabled = false;
8525
  if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8526
+ $status_notices .= '<p><b>Easy IO:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
8527
  } elseif ( get_option( 'easyio_exactdn' ) ) {
8528
  ewww_image_optimizer_webp_rewrite_verify();
8529
  update_option( 'ewww_image_optimizer_exactdn', false );
8532
  $compress_score += 80;
8533
  $resize_score += 50;
8534
  } elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8535
+ $status_notices .= '<p><b>Easy IO:</b> ';
8536
  global $exactdn;
8537
  if ( $exactdn->get_exactdn_domain() && $exactdn->verify_domain( $exactdn->get_exactdn_domain() ) ) {
8538
  $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
8539
  if ( defined( 'WP_ROCKET_VERSION' ) ) {
8540
+ $status_notices .= '<br><i>' . esc_html__( 'If you use the File Optimization options within WP Rocket, you should also enter your Easy IO CNAME in the WP Rocket CDN settings (reserved for CSS and Javascript):', 'ewww-image-optimizer' ) . ' ' . $exactdn->get_exactdn_domain() . '</i>';
8541
  }
8542
  if ( $compress_score < 50 ) {
8543
  $compress_score = 50;
8548
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) {
8549
  $compress_recommendations[] = esc_html__( 'Enable premium compression.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' );
8550
  }
8551
+ $exactdn_enabled = true;
8552
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
8553
  $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
8554
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'suspended' ) ) {
8558
  $status_notices .= '<span style="color: red; font-weight: bolder"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
8559
  }
8560
  if ( function_exists( 'remove_query_strings_link' ) || function_exists( 'rmqrst_loader_src' ) || function_exists( 'qsr_remove_query_strings_1' ) ) {
8561
+ $status_notices .= '<br><i>' . esc_html__( 'Plugins that remove query strings are unnecessary with Easy IO. You may remove them at your convenience.', 'ewww-image-optimizer' ) . '</i>' . ewwwio_help_link( 'https://docs.ewww.io/article/50-exactdn-and-query-strings', '5a3d278a2c7d3a1943677b52' );
8562
  }
8563
  $status_notices .= '</p>';
8564
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8565
+ $status_notices .= '<p><b>Easy IO:</b> ' . esc_html__( 'Inactive, enable to activate automatic resizing and more', 'ewww-image-optimizer' ) . '</p>';
8566
+ $resize_recommendations[] = esc_html__( 'Enable Easy IO for automatic resizing.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/44-introduction-to-exactdn', '59bc5ad6042863033a1ce370,5c0042892c7d3a31944e88a4' );
8567
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
8568
  delete_option( 'ewww_image_optimizer_exactdn_failures' );
8569
  delete_option( 'ewww_image_optimizer_exactdn_checkin' );
8577
  delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
8578
  delete_site_option( 'ewww_image_optimizer_exactdn_suspended' );
8579
  }
8580
+ if ( $exactdn_enabled && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
8581
+ $output[] = "<script type='text/javascript'>\n" .
8582
+ 'var exactdn_enabled = true;' . "\n" .
8583
+ "</script>\n";
8584
+ } else {
8585
+ $output[] = "<script type='text/javascript'>\n" .
8586
+ 'var exactdn_enabled = false;' . "\n" .
8587
+ "</script>\n";
8588
+ }
8589
  if (
8590
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) ||
8591
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) ||
8811
  if ( ( 'network-multisite' !== $network || ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) && // Display tabs so long as this isn't the network admin OR single-site override is disabled.
8812
  ! ( 'network-singlesite' === $network && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) ) { // Also make sure that this isn't single site without override mode.
8813
  $output[] = "<ul class='ewww-tab-nav'>\n" .
8814
+ "<li class='ewww-tab ewww-general-nav'><span>" . esc_html__( 'Basic', 'ewww-image-optimizer' ) . "</span></li>\n" .
8815
+ ( get_option( 'easyio_exactdn' ) ? '' : "<li class='ewww-tab ewww-exactdn-nav'><span>" . esc_html__( 'Easy Mode', 'ewww-image-optimizer' ) . "</span></li>\n" ) .
8816
+ "<li class='ewww-tab ewww-optimization-nav'><span>" . esc_html__( 'Advanced', 'ewww-image-optimizer' ) . "</span></li>\n" .
8817
+ "<li class='ewww-tab ewww-resize-nav'><span>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</span></li>\n" .
8818
+ "<li class='ewww-tab ewww-conversion-nav'><span>" . esc_html__( 'Convert', 'ewww-image-optimizer' ) . "</span></li>\n" .
8819
+ "<li class='ewww-tab ewww-webp-nav'><span>" . esc_html__( 'WebP', 'ewww-image-optimizer' ) . "</span></li>\n" .
8820
+ "<li class='ewww-tab ewww-overrides-nav'><span><a href='https://docs.ewww.io/article/40-override-options' target='_blank'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
8821
+ "<li class='ewww-tab ewww-support-nav'><span>" . esc_html__( 'Support', 'ewww-image-optimizer' ) . "</span></li>\n" .
8822
+ "<li class='ewww-tab ewww-contribute-nav'><span>" . esc_html__( 'Contribute', 'ewww-image-optimizer' ) . "</span></li>\n" .
8823
  "</ul>\n";
8824
  }
8825
  if ( 'network-multisite' === $network ) {
8840
  }
8841
  $output[] = "<div id='ewww-general-settings'>\n";
8842
  $output[] = '<noscript><h2>' . esc_html__( 'Basic', 'ewww-image-optimizer' ) . '</h2></noscript>';
8843
+ if ( $exactdn_enabled && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
8844
+ $output[] = '<p>' . esc_html__( 'Easy IO copies your images to our CDN for optimization and does not affect the local images stored on your server. The Basic settings are not necessary for performance while Easy IO is active, but can help you to save server storage space.', 'ewww-image-optimizer' ) . "</p>\n";
8845
+ }
8846
  $output[] = "<table class='form-table'>\n";
8847
  if ( is_multisite() ) {
8848
  if ( is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
8860
  }
8861
  echo '</table></div><!-- end container general settings -->';
8862
  echo "<p class='submit'><input type='submit' class='button-primary' value='" . esc_attr__( 'Save Changes', 'ewww-image-optimizer' ) . "' /></p>\n";
8863
+ echo '</form></div><!-- end container wrap -->';
8864
  ewww_image_optimizer_temp_debug_clear();
8865
  return;
8866
  }
8873
  }
8874
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_metadata_remove'>" . esc_html__( 'Remove Metadata', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
8875
  "<td><input type='checkbox' id='ewww_image_optimizer_metadata_remove' name='ewww_image_optimizer_metadata_remove' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will remove ALL metadata: EXIF, comments, color profiles, and anything else that is not pixel data.', 'ewww-image-optimizer' ) .
8876
+ "<p class ='description'>" . esc_html__( 'Color profiles are preserved when using the API or Easy IO.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8877
  ewwwio_debug_message( 'remove metadata: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ? 'on' : 'off' ) );
8878
 
8879
  $maybe_api_level = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? '*' : '';
8935
  }
8936
  $output[] = "</table>\n</div>\n";
8937
  $output[] = "<div id='ewww-exactdn-settings'>\n";
8938
+ $output[] = '<noscript><h2>' . esc_html__( 'Easy Mode', 'ewww-image-optimizer' ) . '</h2></noscript>';
8939
+ $output[] = '<p>' . esc_html__( 'Having problems? Try disabling Lazy Load and Include All Resources. Finally, disable Easy IO if problems remain.', 'ewww-image-optimizer' ) . "<br>\n" .
8940
+ "<a class='ewww-docs-root' href='https://ewww.io/contact-us/'>" . esc_html__( 'Then, let us know so we can find a fix for the problem.', 'ewww-image-optimizer' ) . "</a></p>\n";
8941
  $output[] = "<table class='form-table'>\n";
8942
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_exactdn'>" . esc_html__( 'Easy IO', 'ewww-image-optimizer' ) .
8943
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/44-introduction-to-exactdn', '59bc5ad6042863033a1ce370,5c0042892c7d3a31944e88a4' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_exactdn' name='ewww_image_optimizer_exactdn' value='true' " .
 
8944
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? "checked='true'" : '' ) . ' /> ' .
8945
  esc_html__( 'Enables CDN and automatic image resizing to fit your pages.', 'ewww-image-optimizer' ) .
8946
  ' <a href="https://ewww.io/resize/" target="_blank">' . esc_html__( 'Purchase a subscription for your site.', 'ewww-image-optimizer' ) . '</a>' .
8950
  esc_html__( 'Premium Compression', 'ewww-image-optimizer' ) . '<br>' .
8951
  esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
8952
  esc_html__( 'JS/CSS Minification and Compression', 'ewww-image-optimizer' ) . '<br>' .
8953
+ '<a href="https://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about Easy IO', 'ewww-image-optimizer' ) . '</a>' .
8954
  "</p></td></tr>\n";
8955
  ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? 'on' : 'off' ) );
8956
+ $output[] = "<tr class='$network_class'><td>&nbsp;</td>" .
8957
  "<td><input type='checkbox' id='exactdn_all_the_things' name='exactdn_all_the_things' value='true' " .
8958
+ ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? ' disabled ' : '' ) .
8959
+ ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ? "checked='true'" : '' ) . '> ' .
8960
+ "<label for='exactdn_all_the_things'><strong>" . esc_html__( 'Include All Resources', 'ewww-image-optimizer' ) . '</strong></label>' . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' ) .
8961
+ "<p class='description'>" . esc_html__( 'Use Easy IO for all resources in wp-includes/ and wp-content/, including JavaScript, CSS, fonts, etc.', 'ewww-image-optimizer' ) . '</p>' .
8962
+ "</td></tr>\n";
8963
  ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ? 'on' : 'off' ) );
8964
+ $output[] = "<tr class='$network_class'><td>&nbsp;</td>" .
8965
  "<td><input type='checkbox' id='exactdn_lossy' name='exactdn_lossy' value='true' " .
8966
+ ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? ' disabled ' : '' ) .
8967
+ ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ? "checked='true'" : '' ) . '> ' .
8968
+ "<label for='exactdn_lossy'><strong>" . esc_html__( 'Premium Compression', 'ewww-image-optimizer' ) . '</strong></label>' . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' ) .
8969
+ "<p class='description'>" . esc_html__( 'Enable high quality premium compression for all images. Disable to use Pixel Perfect mode instead.', 'ewww-image-optimizer' ) . '</p>' .
8970
+ "</td></tr>\n";
8971
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8972
+ $output[] = "<input type='hidden' id='exactdn_all_the_things' name='exactdn_all_the_things' " .
8973
+ ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ? "value='1'" : "value='0'" ) . ">\n";
8974
+ $output[] = "<input type='hidden' id='exactdn_lossy' name='exactdn_lossy' " .
8975
+ ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ? "value='1'" : "value='0'" ) . ">\n";
8976
+ $output[] = "<input type='hidden' id='ewww_image_optimizer_use_lqip' name='ewww_image_optimizer_use_lqip' " .
8977
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_use_lqip' ) ? "value='1'" : "value='0'" ) . ">\n";
8978
+ }
8979
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_lazy_load'>" . esc_html__( 'Lazy Load', 'ewww-image-optimizer' ) . '</label>' .
8980
+ ewwwio_help_link( 'https://docs.ewww.io/article/74-lazy-load', '5c6c36ed042863543ccd2d9b' ) .
8981
+ "</th><td><input type='checkbox' id='ewww_image_optimizer_lazy_load' name='ewww_image_optimizer_lazy_load' value='true' " .
8982
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lazy_load' ) ? "checked='true'" : '' ) . ' /> ' .
8983
+ esc_html__( 'Improves actual and perceived loading time as images will be loaded only as they enter (or are about to enter) the viewport.', 'ewww-image-optimizer' ) .
8984
+ "<p class='description'>" . esc_html__( 'When used with Easy IO and/or JS WebP Rewriting, the plugin will load the best available image size and format for each device.', 'ewww-image-optimizer' ) . "</p>\n" .
8985
+ "</td></tr>\n";
8986
+ $output[] = "<tr class='$network_class'><td>&nbsp;</td><td><input type='checkbox' id='ewww_image_optimizer_use_lqip' name='ewww_image_optimizer_use_lqip' value='true' " .
8987
+ ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? ' disabled ' : '' ) .
8988
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_use_lqip' ) ? "checked='true'" : '' ) . ' /> ' .
8989
+ "<label for='ewww_image_optimizer_use_lqip'><strong>LQIP</strong></label>" .
8990
+ ewwwio_help_link( 'https://docs.ewww.io/article/75-lazy-load-placeholders', '5c9a7a302c7d3a1544615e47' ) . "\n" .
8991
+ "<p class='description'>" . esc_html__( 'Use low-quality versions of your images as placeholders via Easy IO. Can improve user experience, but may be slower than blank placeholders.', 'ewww-image-optimizer' ) . '</p>' .
8992
+ "</td></tr>\n";
8993
  ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
8994
  ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) ? 'on' : 'off' ) );
8995
  ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) ? 'off' : 'on' ) );
8996
  ewwwio_debug_message( 'lazy load: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lazy_load' ) ? 'on' : 'off' ) );
8997
+ ewwwio_debug_message( 'LQIP: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_use_lqip' ) ? 'on' : 'off' ) );
8998
  if ( defined( 'EXACTDN_EXCLUDE' ) && EXACTDN_EXCLUDE ) {
8999
  $exactdn_user_exclusions = EXACTDN_EXCLUDE;
9000
  if ( is_array( $exactdn_user_exclusions ) ) {
9015
  ewwwio_debug_message( 'pngout level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' ) );
9016
  }
9017
  $output[] = "<tr class='$network_class'><th scope='row'><span><label for='ewww_image_optimizer_jpg_quality'>" . esc_html__( 'JPG Quality Level:', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,58543c69c697912ffd6c19a7' ) . "</th><td><input type='text' id='ewww_image_optimizer_jpg_quality' name='ewww_image_optimizer_jpg_quality' class='small-text' value='" . ewww_image_optimizer_jpg_quality() . "' /> " . esc_html__( 'Valid values are 1-100.', 'ewww-image-optimizer' ) . "\n<p class='description'>" . esc_html__( 'Use this to override the default WordPress quality level of 82. Applies to image editing, resizing, PNG to JPG conversion, and JPG to WebP conversion. Does not affect the original uploaded image unless maximum dimensions are set and resizing occurs.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
9018
+ ewwwio_debug_message( 'effective quality: ' . ewww_image_optimizer_set_jpg_quality( 82 ) );
9019
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_parallel_optimization'>" . esc_html__( 'Parallel Optimization', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,598cb8be2c7d3a73488be237' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_parallel_optimization' name='ewww_image_optimizer_parallel_optimization' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'All resizes generated from a single upload are optimized in parallel for faster optimization. If this is causing performance issues, disable parallel optimization to reduce the load on your server.', 'ewww-image-optimizer' ) . "</td></tr>\n";
9020
  ewwwio_debug_message( 'parallel optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ? 'on' : 'off' ) );
9021
  ewwwio_debug_message( 'background optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ? 'on' : 'off' ) );
9162
  $output[] = '<table><tr class="network-singlesite"><th scope="col">' . esc_html__( 'Disable Optimization', 'ewww-image-optimizer' ) . '</th><th scope="col">' . esc_html__( 'Disable Creation', 'ewww-image-optimizer' ) . "</th></tr>\n";
9163
  ewwwio_debug_message( 'disabled resizes:' );
9164
  foreach ( $image_sizes as $size => $dimensions ) {
9165
+ if ( empty( $dimensions['width'] ) && empty( $dimensions['height'] ) ) {
9166
+ continue;
9167
+ }
9168
  if ( 'thumbnail' === $size ) {
9169
  $output[] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' disabled /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - {$dimensions['width']}x{$dimensions['height']}</label></td></tr>\n";
9170
  } elseif ( 'pdf-full' === $size ) {
9240
 
9241
  $output[] = "<div id='ewww-webp-settings'>\n";
9242
  $output[] = '<noscript><h2>' . esc_html__( 'WebP', 'ewww-image-optimizer' ) . '</h2></noscript>';
9243
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) && ! ewww_image_optimizer_easy_active() ) {
9244
+ $output[] = '<p>' . esc_html__( 'Once JPG/PNG to WebP is enabled, WebP images will be generated for new uploads, but you will need to use the Bulk Optimizer for existing uploads.', 'ewww-image-optimizer' ) . "<br>\n" .
9245
+ esc_html__( 'See Easy Mode for automatic on-demand WebP conversion instead.', 'ewww-image-optimizer' ) . "</p>\n";
9246
+ }
9247
  $output[] = "<table class='form-table'>\n";
9248
  if ( ! ewww_image_optimizer_easy_active() || ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
9249
  $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . '</label>' .
9281
  ewwwio_debug_message( 'webp paths:' );
9282
  ewwwio_debug_message( $webp_paths );
9283
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
9284
+ $output[] = "<tr class='$network_class'><th>&nbsp;</th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by Easy IO.', 'ewww-image-optimizer' ) . '</p></td></tr>';
9285
  } elseif ( get_option( 'easyio_exactdn' ) ) {
9286
  $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>';
9287
  }
9397
  $test_png_image = plugins_url( '/images/test.png', __FILE__ );
9398
  $output[] = "<noscript data-img='$test_png_image' data-webp='$test_webp_image' data-style='float: right; padding: 0 0 10px 10px;' class='ewww_webp'><img src='$test_png_image' style='float: right; padding: 0 0 10px 10px;'></noscript>\n";
9399
  }
9400
+ $output[] = "</div><!-- end container wrap -->\n";
 
 
 
 
 
 
 
 
 
 
9401
  ewwwio_debug_message( 'max_execution_time: ' . ini_get( 'max_execution_time' ) );
9402
  ewww_image_optimizer_stl_check();
9403
  ewww_image_optimizer_function_exists( 'sleep', true );
9412
  $eio_alt_webp->inline_script();
9413
  }
9414
 
 
 
 
9415
  global $eio_debug;
9416
  if ( ! empty( $eio_debug ) ) {
9417
  $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>';
9421
  $debug_output .= '</p>';
9422
  $debug_output .= '<div id="ewww-debug-info" style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;" contenteditable="true">' . $eio_debug . '</div>';
9423
 
 
 
 
9424
  $output = str_replace( 'DEBUG_PLACEHOLDER', $debug_output, $output );
9425
  } else {
9426
  $output = str_replace( 'DEBUG_PLACEHOLDER', '', $output );
9427
  }
9428
 
9429
  echo $output;
9430
+
9431
+ if ( false && ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
9432
+ $current_user = wp_get_current_user();
9433
+ $help_email = $current_user->user_email;
9434
+ if ( ! empty( $eio_debug ) ) {
9435
+ $hs_debug = str_replace( array( "'", '<br>' ), array( '', '\n' ), $eio_debug );
9436
+ }
9437
+ ?>
9438
+ <script type="text/javascript">!function(e,t,n){function a(){var e=t.getElementsByTagName("script")[0],n=t.createElement("script");n.type="text/javascript",n.async=!0,n.src="https://beacon-v2.helpscout.net",e.parentNode.insertBefore(n,e)}if(e.Beacon=n=function(t,n,a){e.Beacon.readyQueue.push({method:t,options:n,data:a})},n.readyQueue=[],"complete"===t.readyState)return a();e.attachEvent?e.attachEvent("onload",a):e.addEventListener("load",a,!1)}(window,document,window.Beacon||function(){});</script>
9439
+ <script type="text/javascript">
9440
+ window.Beacon('init', 'aa9c3d3b-d4bc-4e9b-b6cb-f11c9f69da87');
9441
+ Beacon( 'prefill', {
9442
+ email: '<?php echo utf8_encode( $help_email ); ?>',
9443
+ });
9444
+ Beacon( 'session-data', {
9445
+ 'Debug Info': '<?php echo $hs_debug; ?>',
9446
+ });
9447
+ </script>
9448
+ <?php
9449
+ }
9450
+ $help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' );
9451
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
9452
  $current_user = wp_get_current_user();
9453
  $help_email = $current_user->user_email;
9734
  if ( ! empty( $eio_debug ) && empty( $ewwwio_temp_debug ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && is_writable( WP_CONTENT_DIR . '/ewww/' ) ) {
9735
  $memory_limit = ewwwio_memory_limit();
9736
  clearstatcache();
9737
+ $timestamp = gmdate( 'Y-m-d H:i:s' ) . "\n";
9738
  if ( ! file_exists( $debug_log ) ) {
9739
  touch( $debug_log );
9740
  } else {
10094
  function ewwwio_memory_output() {
10095
  if ( WP_DEBUG ) {
10096
  global $ewww_memory;
10097
+ $timestamp = gmdate( 'y-m-d h:i:s.u' ) . ' ';
10098
  if ( ! file_exists( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'memory.log' ) ) {
10099
  touch( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'memory.log' );
10100
  }
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.1.1
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
@@ -83,7 +83,7 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50600 ) {
83
  *
84
  * @var string EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL
85
  */
86
- define( 'EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL', basename( plugin_dir_path( __FILE__ ) ) . '/' . basename( __FILE__ ) );
87
  /**
88
  * This is the full system path to the plugin folder.
89
  *
@@ -127,10 +127,6 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50600 ) {
127
  * EWWWIO_Tracking class for reporting anonymous site data.
128
  */
129
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-tracking.php' );
130
- /**
131
- * EWWWIO_HS_Beacon class for embedding the HelpScout Beacon.
132
- */
133
- require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-hs-beacon.php' );
134
  } // End if().
135
 
136
  if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
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.4
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
83
  *
84
  * @var string EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL
85
  */
86
+ define( 'EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL', plugin_basename( __FILE__ ) );
87
  /**
88
  * This is the full system path to the plugin folder.
89
  *
127
  * EWWWIO_Tracking class for reporting anonymous site data.
128
  */
129
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-tracking.php' );
 
 
 
 
130
  } // End if().
131
 
132
  if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
includes/eio.js CHANGED
@@ -101,9 +101,15 @@ jQuery(document).ready(function($) {
101
  return false;
102
  });
103
  $('#ewww-webp-settings').hide();
104
- $('#ewww-exactdn-settings').hide();
105
- $('#ewww-general-settings').show();
106
- $('li.ewww-general-nav').addClass('ewww-selected');
 
 
 
 
 
 
107
  if($('#ewww_image_optimizer_debug').length){
108
  $('#ewww-resize-settings').hide();
109
  console.log($('#ewww_image_optimizer_debug').length);
@@ -375,24 +381,20 @@ jQuery(document).ready(function($) {
375
  } else if ( ewww_response.ready ) {
376
  ewww_attachments = ewww_response.ready;
377
  if (ewww_attachments == 0) {
378
- // $('#ewww-bulk-loading').hide();
379
  $('#ewww-scanning').hide();
380
  $('#ewww-nothing').show();
381
  if ( ewww_tiny_skip ) {
382
  $('#ewww-nothing').append( '<br><i>' + ewww_tiny_skip + '</i>' );
383
  console.log( 'done, skipped some tiny images' );
384
  }
385
- //$('#ewww-aux-start').show();
386
- //$('#ewww-aux-again').show();
387
- //$('#ewww-aux-first').hide();
388
  } else {
389
  $('#ewww-scanning').html(ewww_response.message);
390
  if ( ewww_tiny_skip ) {
391
  $('#ewww-scanning').append( '<br><i>' + ewww_tiny_skip + '</i>' );
392
  console.log( 'done, skipped some tiny images' );
393
  }
 
394
  $('#ewww-bulk-start').show();
395
- // ewwwStartOpt();
396
  }
397
  }
398
  })
101
  return false;
102
  });
103
  $('#ewww-webp-settings').hide();
104
+ if (exactdn_enabled) {
105
+ $('#ewww-exactdn-settings').show();
106
+ $('#ewww-general-settings').hide();
107
+ $('li.ewww-exactdn-nav').addClass('ewww-selected');
108
+ } else {
109
+ $('#ewww-exactdn-settings').hide();
110
+ $('#ewww-general-settings').show();
111
+ $('li.ewww-general-nav').addClass('ewww-selected');
112
+ }
113
  if($('#ewww_image_optimizer_debug').length){
114
  $('#ewww-resize-settings').hide();
115
  console.log($('#ewww_image_optimizer_debug').length);
381
  } else if ( ewww_response.ready ) {
382
  ewww_attachments = ewww_response.ready;
383
  if (ewww_attachments == 0) {
 
384
  $('#ewww-scanning').hide();
385
  $('#ewww-nothing').show();
386
  if ( ewww_tiny_skip ) {
387
  $('#ewww-nothing').append( '<br><i>' + ewww_tiny_skip + '</i>' );
388
  console.log( 'done, skipped some tiny images' );
389
  }
 
 
 
390
  } else {
391
  $('#ewww-scanning').html(ewww_response.message);
392
  if ( ewww_tiny_skip ) {
393
  $('#ewww-scanning').append( '<br><i>' + ewww_tiny_skip + '</i>' );
394
  console.log( 'done, skipped some tiny images' );
395
  }
396
+ $('#ewww-bulk-first').val(ewww_response.start_button);
397
  $('#ewww-bulk-start').show();
 
398
  }
399
  }
400
  })
includes/lazysizes-post.js CHANGED
@@ -17,14 +17,14 @@ function constrainSrc(url,objectWidth,objectHeight,objectType){
17
  }
18
  var resultW = regW.exec(url);
19
  if(resultW && objectWidth <= resultW[1]){
20
- if('bg-cover'===objectType){
21
  return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight );
22
  }
23
  return url.replace(regW, 'w=' + objectWidth);
24
  }
25
  var resultFit = regFit.exec(decUrl);
26
  if(resultFit && objectWidth < resultFit[1]){
27
- if('bg-cover'===objectType){
28
  return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight );
29
  }
30
  return decUrl.replace(regFit, 'fit=' + objectWidth + ',' + objectHeight);
@@ -33,7 +33,7 @@ function constrainSrc(url,objectWidth,objectHeight,objectType){
33
  if('img'===objectType){
34
  return url + '&fit=' + objectWidth + ',' + objectHeight;
35
  }
36
- if('bg-cover'===objectType){
37
  return url + '?resize=' + objectWidth + ',' + objectHeight;
38
  }
39
  if(objectHeight>objectWidth){
@@ -46,7 +46,7 @@ function constrainSrc(url,objectWidth,objectHeight,objectType){
46
  if('img'===objectType){
47
  return url + '?fit=' + objectWidth + ',' + objectHeight;
48
  }
49
- if('bg-cover'===objectType){
50
  return url + '?resize=' + objectWidth + ',' + objectHeight;
51
  }
52
  if(objectHeight>objectWidth){
@@ -84,7 +84,11 @@ document.addEventListener('lazybeforeunveil', function(e){
84
  //console.log('using data-src-webp');
85
  src = webpsrc;
86
  }
87
- var newSrc = constrainSrc(src,targetWidth,targetHeight,'img');
 
 
 
 
88
  if (newSrc && src != newSrc){
89
  target.setAttribute('data-src', newSrc);
90
  }
17
  }
18
  var resultW = regW.exec(url);
19
  if(resultW && objectWidth <= resultW[1]){
20
+ if('bg-cover'===objectType || 'img-scale'===objectType){
21
  return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight );
22
  }
23
  return url.replace(regW, 'w=' + objectWidth);
24
  }
25
  var resultFit = regFit.exec(decUrl);
26
  if(resultFit && objectWidth < resultFit[1]){
27
+ if('bg-cover'===objectType || 'img-scale'===objectType){
28
  return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight );
29
  }
30
  return decUrl.replace(regFit, 'fit=' + objectWidth + ',' + objectHeight);
33
  if('img'===objectType){
34
  return url + '&fit=' + objectWidth + ',' + objectHeight;
35
  }
36
+ if('bg-cover'===objectType || 'img-scale'===objectType){
37
  return url + '?resize=' + objectWidth + ',' + objectHeight;
38
  }
39
  if(objectHeight>objectWidth){
46
  if('img'===objectType){
47
  return url + '?fit=' + objectWidth + ',' + objectHeight;
48
  }
49
+ if('bg-cover'===objectType || 'img-scale'===objectType){
50
  return url + '?resize=' + objectWidth + ',' + objectHeight;
51
  }
52
  if(objectHeight>objectWidth){
84
  //console.log('using data-src-webp');
85
  src = webpsrc;
86
  }
87
+ if (window.lazySizes.hC(target,'et_pb_jt_filterable_grid_item_image')) {
88
+ var newSrc = constrainSrc(src,targetWidth,targetHeight,'img-scale');
89
+ } else {
90
+ var newSrc = constrainSrc(src,targetWidth,targetHeight,'img');
91
+ }
92
  if (newSrc && src != newSrc){
93
  target.setAttribute('data-src', newSrc);
94
  }
includes/lazysizes.js CHANGED
@@ -313,7 +313,7 @@
313
  isBodyHidden = getCSS(document.body, 'visibility') == 'hidden';
314
  }
315
 
316
- return isBodyHidden || (getCSS(elem.parentNode, 'visibility') != 'hidden' && getCSS(elem, 'visibility') != 'hidden');
317
  };
318
 
319
  var isNestedVisible = function(elem, elemExpand){
313
  isBodyHidden = getCSS(document.body, 'visibility') == 'hidden';
314
  }
315
 
316
+ return isBodyHidden || !(getCSS(elem.parentNode, 'visibility') == 'hidden' && getCSS(elem, 'visibility') == 'hidden');
317
  };
318
 
319
  var isNestedVisible = function(elem, elemExpand){
includes/lazysizes.min.js CHANGED
@@ -1 +1 @@
1
- var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a,i){if(null===e)return e;var r=/w=(\d+)/,n=/fit=(\d+),(\d+)/,o=/resize=(\d+),(\d+)/,s=decodeURIComponent(e);if(void 0===eio_lazy_vars)var eio_lazy_vars={exactdn_domain:".exactdn.com"};if(0<e.search("\\?")&&0<e.search(eio_lazy_vars.exactdn_domain)){var l=o.exec(s);if(l&&t<l[1])return s.replace(o,"resize="+t+","+a);var d=r.exec(e);if(d&&t<=d[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):e.replace(r,"w="+t);var c=n.exec(s);if(c&&t<c[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):s.replace(n,"fit="+t+","+a);if(!d&&!c&&!l)return"img"===i?e+"&fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:t<a?e+"&h="+a:e+"&w="+t}return-1==e.search("\\?")&&0<e.search(eio_lazy_vars.exactdn_domain)?"img"===i?e+"?fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:t<a?e+"?h="+a:e+"?w="+t:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";var g,z;if(function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e])}(),!A||!A.getElementsByClassName)return{init:function(){},cfg:z,noSupport:!0};var v=A.documentElement,n=i.Date,r=i.HTMLPictureElement,o="addEventListener",h="getAttribute",e=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},m=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[h]("class")||"")&&d[t]},p=function(e,t){c(e,t)||e.setAttribute("class",(e[h]("class")||"").trim()+" "+t)},y=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[h]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,r){var n=A.createEvent("Event");return a||(a={}),a.instance=g,n.initEvent(t,!i,!r),n.detail=a,e.dispatchEvent(n),n},C=function(e,t){var a;!r&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[h]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},S=(we=[],Ce=[],_e=we,Ee=function(){var e=_e;for(_e=we.length?Ce:we,be=!(ye=!0);e.length;)e.shift()();ye=!1},Se=function(e,t){ye&&!t?e.apply(this,arguments):(_e.push(e),be||(be=!0,(A.hidden?u:a)(Ee)))},Se._lsFlush=Ee,Se),t=function(a,e){return e?function(){S(a)}:function(){var e=this,t=arguments;S(function(){a.apply(e,t)})}},x=function(e){var t,a,i=function(){t=null,e()},r=function(){var e=n.now()-a;e<99?u(r,99-e):(s||i)(i)};return function(){a=n.now(),t||(t=u(r,99))}},W=(ee=/^img$/i,te=/^iframe$/i,ae="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ie=0,re=0,ne=-1,oe=function(e){re--,(!e||re<0||!e.target)&&(re=0)},se=function(e){return null==$&&($="hidden"==_(A.body,"visibility")),$||"hidden"!=_(e.parentNode,"visibility")&&"hidden"!=_(e,"visibility")},le=function(e,t){var a,i=e,r=se(e);for(I-=t,G+=t,J-=t,O+=t;r&&(i=i.offsetParent)&&i!=A.body&&i!=v;)(r=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),r=O>a.left&&J<a.right&&G>a.top-1&&I<a.bottom+1);return r},de=function(){var e,t,a,i,r,n,o,s,l,d,c,u,f=g.elements;if((T=z.loadMode)&&re<8&&(e=f.length)){for(t=0,ne++;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(!ae||g.prematureUnveil&&g.prematureUnveil(f[t]))ve(f[t]);else if((s=f[t][h]("data-expand"))&&(n=1*s)||(n=ie),d||(d=!z.expand||z.expand<1?500<v.clientHeight&&500<v.clientWidth?500:370:z.expand,g._defEx=d,c=d*z.expFactor,u=z.hFac,$=null,ie<c&&re<1&&2<ne&&2<T&&!A.hidden?(ie=c,ne=0):ie=1<T&&1<ne&&re<6?d:0),l!==n&&(H=innerWidth+n*u,F=innerHeight+n,o=-1*n,l=n),a=f[t].getBoundingClientRect(),(G=a.bottom)>=o&&(I=a.top)<=F&&(O=a.right)>=o*u&&(J=a.left)<=H&&(G||O||J||I)&&(z.loadHidden||se(f[t]))&&(k&&re<3&&!s&&(T<3||ne<4)||le(f[t],n))){if(ve(f[t]),r=!0,9<re)break}else!r&&k&&!i&&re<4&&ne<4&&2<T&&(P[0]||z.preloadAfterLoad)&&(P[0]||!s&&(G||O||J||I||"auto"!=f[t][h](z.sizesAttr)))&&(i=P[0]||f[t]);i&&!r&&ve(i)}},q=de,V=0,X=z.throttleDelay,Y=z.ricTimeout,K=function(){j=!1,V=n.now(),q()},Z=s&&49<Y?function(){s(K,{timeout:Y}),Y!==z.ricTimeout&&(Y=z.ricTimeout)}:t(function(){u(K)},!0),ce=function(e){var t;(e=!0===e)&&(Y=33),j||(j=!0,(t=X-(n.now()-V))<0&&(t=0),e||t<9?Z():u(Z,t))},ue=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(oe(e),p(t,z.loadedClass),y(t,z.loadingClass),b(t,Ae),w(t,"lazyloaded"))},fe=t(ue),Ae=function(e){fe({target:e.target})},ge=function(e){var t,a=e[h](z.srcsetAttr);(t=z.customMedia[e[h]("data-media")||e[h]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},ze=t(function(t,e,a,i,r){var n,o,s,l,d,c;(d=w(t,"lazybeforeunveil",e)).defaultPrevented||(i&&(a?p(t,z.autosizesClass):t.setAttribute("sizes",i)),o=t[h](z.srcsetAttr),n=t[h](z.srcAttr),r&&(s=t.parentNode,l=s&&f.test(s.nodeName||"")),c=e.firesLoad||"src"in t&&(o||n||l),d={target:t},p(t,z.loadingClass),c&&(clearTimeout(D),D=u(oe,2500),b(t,Ae,!0)),l&&m.call(s.getElementsByTagName("source"),ge),o?t.setAttribute("srcset",o):n&&!l&&(te.test(t.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(t,n):t.src=n),r&&(o||l)&&C(t,{src:n})),t._lazyRace&&delete t._lazyRace,y(t,z.lazyClass),S(function(){var e=t.complete&&1<t.naturalWidth;c&&!e||(e&&p(t,"ls-is-cached"),ue(d),t._lazyCache=!0,u(function(){"_lazyCache"in t&&delete t._lazyCache},9)),"lazy"==t.loading&&re--},!0)}),ve=function(e){if(!e._lazyRace){var t,a=ee.test(e.nodeName),i=a&&(e[h](z.sizesAttr)||e[h]("sizes")),r="auto"==i;(!r&&k||!a||!e[h]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,r&&B.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,re++,ze(e,t,r,i,a))}},he=x(function(){z.loadMode=3,ce()}),me=function(){3==z.loadMode&&(z.loadMode=2),he()},pe=function(){k||(n.now()-U<999?u(pe,999):(k=!0,z.loadMode=3,ce(),e("scroll",me,!0)))},{_:function(){U=n.now(),g.elements=A.getElementsByClassName(z.lazyClass),P=A.getElementsByClassName(z.lazyClass+" "+z.preloadClass),e("scroll",ce,!0),e("resize",ce,!0),i.MutationObserver?new MutationObserver(ce).observe(v,{childList:!0,subtree:!0,attributes:!0}):(v[o]("DOMNodeInserted",ce,!0),v[o]("DOMAttrModified",ce,!0),setInterval(ce,999)),e("hashchange",ce,!0),["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){A[o](e,ce,!0)}),/d$|^c/.test(A.readyState)?pe():(e("load",pe),A[o]("DOMContentLoaded",ce),u(pe,2e4)),g.elements.length?(de(),S._lsFlush()):ce()},checkElems:ce,unveil:ve,_aLSL:me}),B=(L=t(function(e,t,a,i){var r,n,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(r=t.getElementsByTagName("source"),n=0,o=r.length;n<o;n++)r[n].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),N=function(e,t,a){var i,r=e.parentNode;r&&(a=E(e,r,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&L(e,r,i,a))},Q=x(function(){var e,t=R.length;if(t)for(e=0;e<t;e++)N(R[e])}),{_:function(){R=A.getElementsByClassName(z.autosizesClass),e("resize",Q)},checkElems:Q,updateElem:N}),M=function(){!M.i&&A.getElementsByClassName&&(M.i=!0,B._(),W._())};var R,L,N,Q;var P,k,D,T,U,H,F,I,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,re,ne,oe,se,le,de,ce,ue,fe,Ae,ge,ze,ve,he,me,pe;var ye,be,we,Ce,_e,Ee,Se;return u(function(){z.init&&M()}),g={cfg:z,autoSizer:B,loader:W,init:M,uP:C,aC:p,rC:y,hC:c,fire:w,gW:E,rAF:S}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}("undefined"!=typeof window?window:{}),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&1<t.naturalWidth&&1<t.naturalHeight){var i=window.devicePixelRatio||1,r=1.25*t.clientWidth<t.naturalWidth,n=1.25*t.clientHeight<t.naturalHeight;if(r||n){var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");ewww_webp_supported&&d&&-1==l.search("webp=1")&&(l=d);var c=constrainSrc(l,o,s,"img");c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var r=s.devicePixelRatio||1,n=Math.round(e.target.offsetWidth*r),o=Math.round(e.target.offsetHeight*r);t=s.lazySizes.hC(e.target,"wp-block-cover")?constrainSrc(t,n,o,"bg-cover"):s.lazySizes.hC(e.target,"elementor-bg")?constrainSrc(t,n,o,"bg-cover"):constrainSrc(t,n,o,"bg"),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
1
+ var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a,i){if(null===e)return e;var r=/w=(\d+)/,n=/fit=(\d+),(\d+)/,o=/resize=(\d+),(\d+)/,s=decodeURIComponent(e);if(void 0===eio_lazy_vars)var eio_lazy_vars={exactdn_domain:".exactdn.com"};if(0<e.search("\\?")&&0<e.search(eio_lazy_vars.exactdn_domain)){var l=o.exec(s);if(l&&t<l[1])return s.replace(o,"resize="+t+","+a);var d=r.exec(e);if(d&&t<=d[1])return"bg-cover"===i||"img-scale"===i?e.replace(r,"resize="+t+","+a):e.replace(r,"w="+t);var c=n.exec(s);if(c&&t<c[1])return"bg-cover"===i||"img-scale"===i?e.replace(r,"resize="+t+","+a):s.replace(n,"fit="+t+","+a);if(!d&&!c&&!l)return"img"===i?e+"&fit="+t+","+a:"bg-cover"===i||"img-scale"===i?e+"?resize="+t+","+a:t<a?e+"&h="+a:e+"&w="+t}return-1==e.search("\\?")&&0<e.search(eio_lazy_vars.exactdn_domain)?"img"===i?e+"?fit="+t+","+a:"bg-cover"===i||"img-scale"===i?e+"?resize="+t+","+a:t<a?e+"?h="+a:e+"?w="+t:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";var g,z;if(function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e])}(),!A||!A.getElementsByClassName)return{init:function(){},cfg:z,noSupport:!0};var h=A.documentElement,n=i.Date,r=i.HTMLPictureElement,o="addEventListener",m="getAttribute",e=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},v=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[m]("class")||"")&&d[t]},p=function(e,t){c(e,t)||e.setAttribute("class",(e[m]("class")||"").trim()+" "+t)},y=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[m]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,r){var n=A.createEvent("Event");return a||(a={}),a.instance=g,n.initEvent(t,!i,!r),n.detail=a,e.dispatchEvent(n),n},C=function(e,t){var a;!r&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[m]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},S=(we=[],Ce=[],_e=we,Ee=function(){var e=_e;for(_e=we.length?Ce:we,be=!(ye=!0);e.length;)e.shift()();ye=!1},Se=function(e,t){ye&&!t?e.apply(this,arguments):(_e.push(e),be||(be=!0,(A.hidden?u:a)(Ee)))},Se._lsFlush=Ee,Se),t=function(a,e){return e?function(){S(a)}:function(){var e=this,t=arguments;S(function(){a.apply(e,t)})}},x=function(e){var t,a,i=function(){t=null,e()},r=function(){var e=n.now()-a;e<99?u(r,99-e):(s||i)(i)};return function(){a=n.now(),t||(t=u(r,99))}},W=(ee=/^img$/i,te=/^iframe$/i,ae="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ie=0,re=0,ne=-1,oe=function(e){re--,(!e||re<0||!e.target)&&(re=0)},se=function(e){return null==$&&($="hidden"==_(A.body,"visibility")),$||!("hidden"==_(e.parentNode,"visibility")&&"hidden"==_(e,"visibility"))},le=function(e,t){var a,i=e,r=se(e);for(I-=t,G+=t,J-=t,O+=t;r&&(i=i.offsetParent)&&i!=A.body&&i!=h;)(r=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),r=O>a.left&&J<a.right&&G>a.top-1&&I<a.bottom+1);return r},de=function(){var e,t,a,i,r,n,o,s,l,d,c,u,f=g.elements;if((T=z.loadMode)&&re<8&&(e=f.length)){for(t=0,ne++;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(!ae||g.prematureUnveil&&g.prematureUnveil(f[t]))he(f[t]);else if((s=f[t][m]("data-expand"))&&(n=1*s)||(n=ie),d||(d=!z.expand||z.expand<1?500<h.clientHeight&&500<h.clientWidth?500:370:z.expand,g._defEx=d,c=d*z.expFactor,u=z.hFac,$=null,ie<c&&re<1&&2<ne&&2<T&&!A.hidden?(ie=c,ne=0):ie=1<T&&1<ne&&re<6?d:0),l!==n&&(H=innerWidth+n*u,F=innerHeight+n,o=-1*n,l=n),a=f[t].getBoundingClientRect(),(G=a.bottom)>=o&&(I=a.top)<=F&&(O=a.right)>=o*u&&(J=a.left)<=H&&(G||O||J||I)&&(z.loadHidden||se(f[t]))&&(k&&re<3&&!s&&(T<3||ne<4)||le(f[t],n))){if(he(f[t]),r=!0,9<re)break}else!r&&k&&!i&&re<4&&ne<4&&2<T&&(P[0]||z.preloadAfterLoad)&&(P[0]||!s&&(G||O||J||I||"auto"!=f[t][m](z.sizesAttr)))&&(i=P[0]||f[t]);i&&!r&&he(i)}},j=de,V=0,X=z.throttleDelay,Y=z.ricTimeout,K=function(){q=!1,V=n.now(),j()},Z=s&&49<Y?function(){s(K,{timeout:Y}),Y!==z.ricTimeout&&(Y=z.ricTimeout)}:t(function(){u(K)},!0),ce=function(e){var t;(e=!0===e)&&(Y=33),q||(q=!0,(t=X-(n.now()-V))<0&&(t=0),e||t<9?Z():u(Z,t))},ue=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(oe(e),p(t,z.loadedClass),y(t,z.loadingClass),b(t,Ae),w(t,"lazyloaded"))},fe=t(ue),Ae=function(e){fe({target:e.target})},ge=function(e){var t,a=e[m](z.srcsetAttr);(t=z.customMedia[e[m]("data-media")||e[m]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},ze=t(function(t,e,a,i,r){var n,o,s,l,d,c;(d=w(t,"lazybeforeunveil",e)).defaultPrevented||(i&&(a?p(t,z.autosizesClass):t.setAttribute("sizes",i)),o=t[m](z.srcsetAttr),n=t[m](z.srcAttr),r&&(s=t.parentNode,l=s&&f.test(s.nodeName||"")),c=e.firesLoad||"src"in t&&(o||n||l),d={target:t},p(t,z.loadingClass),c&&(clearTimeout(D),D=u(oe,2500),b(t,Ae,!0)),l&&v.call(s.getElementsByTagName("source"),ge),o?t.setAttribute("srcset",o):n&&!l&&(te.test(t.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(t,n):t.src=n),r&&(o||l)&&C(t,{src:n})),t._lazyRace&&delete t._lazyRace,y(t,z.lazyClass),S(function(){var e=t.complete&&1<t.naturalWidth;c&&!e||(e&&p(t,"ls-is-cached"),ue(d),t._lazyCache=!0,u(function(){"_lazyCache"in t&&delete t._lazyCache},9)),"lazy"==t.loading&&re--},!0)}),he=function(e){if(!e._lazyRace){var t,a=ee.test(e.nodeName),i=a&&(e[m](z.sizesAttr)||e[m]("sizes")),r="auto"==i;(!r&&k||!a||!e[m]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,r&&M.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,re++,ze(e,t,r,i,a))}},me=x(function(){z.loadMode=3,ce()}),ve=function(){3==z.loadMode&&(z.loadMode=2),me()},pe=function(){k||(n.now()-U<999?u(pe,999):(k=!0,z.loadMode=3,ce(),e("scroll",ve,!0)))},{_:function(){U=n.now(),g.elements=A.getElementsByClassName(z.lazyClass),P=A.getElementsByClassName(z.lazyClass+" "+z.preloadClass),e("scroll",ce,!0),e("resize",ce,!0),i.MutationObserver?new MutationObserver(ce).observe(h,{childList:!0,subtree:!0,attributes:!0}):(h[o]("DOMNodeInserted",ce,!0),h[o]("DOMAttrModified",ce,!0),setInterval(ce,999)),e("hashchange",ce,!0),["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){A[o](e,ce,!0)}),/d$|^c/.test(A.readyState)?pe():(e("load",pe),A[o]("DOMContentLoaded",ce),u(pe,2e4)),g.elements.length?(de(),S._lsFlush()):ce()},checkElems:ce,unveil:he,_aLSL:ve}),M=(L=t(function(e,t,a,i){var r,n,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(r=t.getElementsByTagName("source"),n=0,o=r.length;n<o;n++)r[n].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),N=function(e,t,a){var i,r=e.parentNode;r&&(a=E(e,r,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&L(e,r,i,a))},Q=x(function(){var e,t=R.length;if(t)for(e=0;e<t;e++)N(R[e])}),{_:function(){R=A.getElementsByClassName(z.autosizesClass),e("resize",Q)},checkElems:Q,updateElem:N}),B=function(){!B.i&&A.getElementsByClassName&&(B.i=!0,M._(),W._())};var R,L,N,Q;var P,k,D,T,U,H,F,I,J,O,G,$,j,q,V,X,Y,K,Z,ee,te,ae,ie,re,ne,oe,se,le,de,ce,ue,fe,Ae,ge,ze,he,me,ve,pe;var ye,be,we,Ce,_e,Ee,Se;return u(function(){z.init&&B()}),g={cfg:z,autoSizer:M,loader:W,init:B,uP:C,aC:p,rC:y,hC:c,fire:w,gW:E,rAF:S}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}("undefined"!=typeof window?window:{}),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&1<t.naturalWidth&&1<t.naturalHeight){var i=window.devicePixelRatio||1,r=1.25*t.clientWidth<t.naturalWidth,n=1.25*t.clientHeight<t.naturalHeight;if(r||n){var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");if(ewww_webp_supported&&d&&-1==l.search("webp=1")&&(l=d),window.lazySizes.hC(t,"et_pb_jt_filterable_grid_item_image"))var c=constrainSrc(l,o,s,"img-scale");else c=constrainSrc(l,o,s,"img");c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var r=s.devicePixelRatio||1,n=Math.round(e.target.offsetWidth*r),o=Math.round(e.target.offsetHeight*r);t=s.lazySizes.hC(e.target,"wp-block-cover")?(s.lazySizes.hC(e.target,"has-parallax")&&(n=Math.round(s.screen.width*r),o=Math.round(s.screen.height*r)),constrainSrc(t,n,o,"bg-cover")):s.lazySizes.hC(e.target,"elementor-bg")?constrainSrc(t,n,o,"bg-cover"):constrainSrc(t,n,o,"bg"),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
includes/ls.unveilhooks.js CHANGED
@@ -83,9 +83,13 @@ For background images, use data-bg attribute:
83
  }
84
  }
85
  var dPR = (window.devicePixelRatio || 1);
86
- var targetWidth = Math.round(e.target.offsetWidth * dPR);
87
  var targetHeight = Math.round(e.target.offsetHeight * dPR);
88
  if (window.lazySizes.hC(e.target,'wp-block-cover')) {
 
 
 
 
89
  bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
90
  } else if (window.lazySizes.hC(e.target,'elementor-bg')){
91
  bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
83
  }
84
  }
85
  var dPR = (window.devicePixelRatio || 1);
86
+ var targetWidth = Math.round(e.target.offsetWidth * dPR);
87
  var targetHeight = Math.round(e.target.offsetHeight * dPR);
88
  if (window.lazySizes.hC(e.target,'wp-block-cover')) {
89
+ if (window.lazySizes.hC(e.target,'has-parallax')) {
90
+ targetWidth = Math.round(window.screen.width * dPR);
91
+ targetHeight = Math.round(window.screen.height * dPR);
92
+ }
93
  bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
94
  } else if (window.lazySizes.hC(e.target,'elementor-bg')){
95
  bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
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.1.1
9
  License: GPLv3
10
 
11
  Speed up your website to better connect with your visitors. Properly compress and size/scale images. Includes lazy load and WebP convert.
@@ -32,9 +32,9 @@ Images can be optimized using tools on your own server for free (jpegtran, optip
32
 
33
  If you need a version of this plugin for API use only, see [EWWW Image Optimizer Cloud](https://wordpress.org/plugins/ewww-image-optimizer-cloud/). It is much more compact as it does not contain any binaries or any mention of the exec() function.
34
 
35
- = Automatic Resizing =
36
 
37
- With ExactDN support, images will be automatically resized to fit the page and device size. ExactDN also enables basic retina support and automatic compression.
38
 
39
  = Support =
40
 
@@ -59,7 +59,7 @@ All images created by the built-in WP_Image_Editor class will be automatically o
59
 
60
  = WebP Images =
61
 
62
- Automatic WebP conversion with ExactDN, no additional configuration. Otherwise, can generate WebP versions of your images, and enables you to serve even smaller images to supported browsers. Several methods are available for serving WebP images, including Apache-compatible rewrite rules and our JS WebP Rewriting option compatible with caches and CDNs. Also works with the WebP option in the Cache Enabler plugin from KeyCDN.
63
 
64
  = WP-CLI =
65
 
@@ -173,6 +173,33 @@ 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.1.1 =
177
  * fixed: no optimization when escapeshellarg() is disabled
178
  * fixed: warning thrown by implode() when JS WebP is enabled with no WebP URLs
@@ -206,6 +233,6 @@ https://developers.google.com/web/tools/lighthouse/audits/optimize-images
206
  = Earlier versions =
207
  Please refer to the separate changelog.txt file.
208
 
209
- == Contact and Credits ==
210
 
211
- Written by [Shane Bishop](https://ewww.io). Based upon CW Image Optimizer, which was written by [Jacob Allred](http://www.jacoballred.com/) at [Corban Works, LLC](http://www.corbanworks.com/). CW Image Optimizer was based on WP Smush.it. Jpegtran is the work of the Independent JPEG Group. PEL is the work of Martin Geisler, Lars Olesen, and Erik Oskam. ExactDN and HTML parsing classes based upon the Photon module from Jetpack.
5
  Requires at least: 5.0
6
  Tested up to: 5.3
7
  Requires PHP: 5.6
8
+ Stable tag: 5.1.4
9
  License: GPLv3
10
 
11
  Speed up your website to better connect with your visitors. Properly compress and size/scale images. Includes lazy load and WebP convert.
32
 
33
  If you need a version of this plugin for API use only, see [EWWW Image Optimizer Cloud](https://wordpress.org/plugins/ewww-image-optimizer-cloud/). It is much more compact as it does not contain any binaries or any mention of the exec() function.
34
 
35
+ = Automatic Everything =
36
 
37
+ With Easy IO, images are automatically compressed, scaled to fit the page and device size, lazy loaded, and converted to the next-gen WebP format.
38
 
39
  = Support =
40
 
59
 
60
  = WebP Images =
61
 
62
+ Automatic WebP conversion with Easy IO, no additional configuration. Otherwise, can generate WebP versions of your images, and enables you to serve even smaller images to supported browsers. Several methods are available for serving WebP images, including Apache-compatible rewrite rules and our JS WebP Rewriting option compatible with caches and CDNs. Also works with the WebP option in the Cache Enabler plugin from KeyCDN.
63
 
64
  = WP-CLI =
65
 
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.4 =
177
+ * fixed: warnings on FlaGallery's manage gallery page
178
+ * fixed: cwebp version test results in false-positives
179
+ * fixed: EWWW IO resize limits are ignored when higher than WP default
180
+ * fixed: PNGOUT warning during one-click conversion
181
+ * fixed: WebP images not removed from remote storage when an attachment is deleted (WP Offload Media)
182
+ * fixed: after running regen for single thumbs with Image Regenerate & Select Crop plugin, regenerated images were not automatically optimized
183
+
184
+ = 5.1.3 =
185
+ * added: better compatibility with Divi filterable grid images and parallax backgrounds
186
+ * added: cleanup .webp and database records when using Enable Media Replace
187
+ * fixed: Divi builder will not load with Easy IO and Include All Resources active
188
+ * fixed: image cover block with fixed width scaled too much
189
+ * fixed: PNG placeholders could use more memory than available
190
+ * removed: Lazy Load CSS gradient for blank placeholders
191
+
192
+ = 5.1.2 =
193
+ * added: disable native lazy-load attributes with EWWWIO_DISABLE_NATIVE_LAZY
194
+ * added: ability to choose LQIP or blank placeholders for lazy load
195
+ * changed: renaming ExactDN as Easy IO
196
+ * changed: default to blank placeholders with Easy IO
197
+ * changed: regenerated images are automatically re-optimized after running Image Regenerate & Select Crop plugin
198
+ * fixed: low-quality placeholders sometimes had larger dimensions than necessary
199
+ * fixed: database records and .webp images are not removed when Image Regenerate & Select Crop plugin deletes a thumbnail
200
+ * fixed: path traversal protection preventing normal files from optimizing
201
+ * fixed: Slider Revolution dummy.png not properly handled by Easy IO
202
+
203
  = 5.1.1 =
204
  * fixed: no optimization when escapeshellarg() is disabled
205
  * fixed: warning thrown by implode() when JS WebP is enabled with no WebP URLs
233
  = Earlier versions =
234
  Please refer to the separate changelog.txt file.
235
 
236
+ == Credits ==
237
 
238
+ Written by [Shane Bishop](https://ewww.io) with special thanks to my [Lord and Savior](https://www.iamsecond.com/). Based upon CW Image Optimizer, which was written by [Jacob Allred](http://www.jacoballred.com/) at [Corban Works, LLC](http://www.corbanworks.com/). CW Image Optimizer was based on WP Smush.it. Jpegtran is the work of the Independent JPEG Group. PEL is the work of Martin Geisler, Lars Olesen, and Erik Oskam. Easy IO and HTML parsing classes based upon the Photon module from Jetpack.
unique.php CHANGED
@@ -91,7 +91,6 @@ function ewww_image_optimizer_exec_init() {
91
  add_action( 'load-plugins.php', 'ewww_image_optimizer_tool_init' );
92
  add_action( 'load-ims_gallery_page_ewww-ims-optimize', 'ewww_image_optimizer_tool_init' );
93
  add_action( 'load-media_page_ewww-image-optimizer-unoptimized', 'ewww_image_optimizer_tool_init' );
94
- add_action( 'load-flagallery_page_flag-manage-gallery', 'ewww_image_optimizer_tool_init' );
95
  }
96
  ewwwio_memory( __FUNCTION__ );
97
  }
@@ -173,7 +172,7 @@ function ewww_image_optimizer_notice_hosting_requires_api() {
173
  $settings_url = admin_url( "$options_page?page=" . plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
174
  echo "<div id='ewww-image-optimizer-cloud-key-required' class='notice notice-error'><p><strong>" .
175
  /* translators: %s: Name of a web host, like WordPress.com or Pantheon. */
176
- sprintf( esc_html__( 'The EWWW Image Optimizer requires an API key or an ExactDN subscription to optimize images on %s sites.', 'ewww-image-optimizer-cloud' ), $webhost ) .
177
  "</strong> <a href='https://ewww.io/plans/'>" . esc_html__( 'Purchase a subscription.', 'ewww-image-optimizer-cloud' ) .
178
  "</a> <a href='$settings_url'>" . esc_html__( 'Then, activate it on the settings page.', 'ewww-image-optimizer-cloud' ) . '</a></p></div>';
179
  }
@@ -464,8 +463,8 @@ function ewww_image_optimizer_skip_tools() {
464
  $skip['jpegtran'] = false;
465
  $skip['optipng'] = false;
466
  $skip['gifsicle'] = false;
467
- $skip['pngout'] = false;
468
  // Except these which are off by default.
 
469
  $skip['pngquant'] = true;
470
  $skip['webp'] = true;
471
  // If the user has disabled a tool, we aren't going to bother checking to see if it is there.
@@ -478,8 +477,8 @@ function ewww_image_optimizer_skip_tools() {
478
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
479
  $skip['gifsicle'] = true;
480
  }
481
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) || ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) || ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10 ) ) {
482
- $skip['pngout'] = true;
483
  }
484
  if ( 40 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
485
  $skip['pngquant'] = false;
@@ -551,8 +550,8 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
551
  $exactdn_dismiss = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? true : false;
552
  // Display a warning if exec() is disabled, can't run local tools without it.
553
  echo "<div id='ewww-image-optimizer-warning-exec' " . ( $exactdn_dismiss ? "class='notice notice-warning is-dismissible'" : "class='notice notice-error'" ) . '><p>' . esc_html__( 'EWWW Image Optimizer requires exec() to perform local compression. Your system administrator has disabled the exec() function, ask them to enable it.', 'ewww-image-optimizer' ) .
554
- ( ! $exactdn_dismiss ? '<br>' . esc_html__( 'An API key or ExactDN subscription will allow you to offload the compression to our dedicated servers instead.', 'ewww-image-optimizer' )
555
- : '<br>' . esc_html__( 'Sites that use ExactDN already have built-in image optimization and may dismiss this notice to disable local compression.', 'ewww-image-optimizer' ) ) .
556
  '</p></div>';
557
  echo
558
  "<script>\n" .
@@ -1125,7 +1124,7 @@ function ewww_image_optimizer_md5check( $path ) {
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;
@@ -1408,7 +1407,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1408
  ewwwio_debug_message( "$path: invalid output" );
1409
  break;
1410
  }
1411
- if ( ! empty( $webp_version ) && preg_match( '/\d.\d.\d/', $webp_version[0] ) ) {
1412
  ewwwio_debug_message( 'optimizer found' );
1413
  return $webp_version[0];
1414
  }
@@ -1755,7 +1754,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1755
  // Initialize the original filename.
1756
  $original = $file;
1757
  $result = '';
1758
- if ( false !== strpos( $file, '..' ) ) {
1759
  $msg = __( 'Path traversal in filename not allowed.', 'ewww-image-optimizer' );
1760
  ewwwio_debug_message( "file is using .. potential path traversal blocked: $file" );
1761
  ewww_image_optimizer_s3_uploads_image_cleanup( $file );
91
  add_action( 'load-plugins.php', 'ewww_image_optimizer_tool_init' );
92
  add_action( 'load-ims_gallery_page_ewww-ims-optimize', 'ewww_image_optimizer_tool_init' );
93
  add_action( 'load-media_page_ewww-image-optimizer-unoptimized', 'ewww_image_optimizer_tool_init' );
 
94
  }
95
  ewwwio_memory( __FUNCTION__ );
96
  }
172
  $settings_url = admin_url( "$options_page?page=" . plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
173
  echo "<div id='ewww-image-optimizer-cloud-key-required' class='notice notice-error'><p><strong>" .
174
  /* translators: %s: Name of a web host, like WordPress.com or Pantheon. */
175
+ sprintf( esc_html__( 'The EWWW Image Optimizer requires an API key or an Easy IO subscription to optimize images on %s sites.', 'ewww-image-optimizer-cloud' ), $webhost ) .
176
  "</strong> <a href='https://ewww.io/plans/'>" . esc_html__( 'Purchase a subscription.', 'ewww-image-optimizer-cloud' ) .
177
  "</a> <a href='$settings_url'>" . esc_html__( 'Then, activate it on the settings page.', 'ewww-image-optimizer-cloud' ) . '</a></p></div>';
178
  }
463
  $skip['jpegtran'] = false;
464
  $skip['optipng'] = false;
465
  $skip['gifsicle'] = false;
 
466
  // Except these which are off by default.
467
+ $skip['pngout'] = true;
468
  $skip['pngquant'] = true;
469
  $skip['webp'] = true;
470
  // If the user has disabled a tool, we aren't going to bother checking to see if it is there.
477
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
478
  $skip['gifsicle'] = true;
479
  }
480
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
481
+ $skip['pngout'] = false;
482
  }
483
  if ( 40 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
484
  $skip['pngquant'] = false;
550
  $exactdn_dismiss = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? true : false;
551
  // Display a warning if exec() is disabled, can't run local tools without it.
552
  echo "<div id='ewww-image-optimizer-warning-exec' " . ( $exactdn_dismiss ? "class='notice notice-warning is-dismissible'" : "class='notice notice-error'" ) . '><p>' . esc_html__( 'EWWW Image Optimizer requires exec() to perform local compression. Your system administrator has disabled the exec() function, ask them to enable it.', 'ewww-image-optimizer' ) .
553
+ ( ! $exactdn_dismiss ? '<br>' . esc_html__( 'An API key or Easy IO subscription will allow you to offload the compression to our dedicated servers instead.', 'ewww-image-optimizer' )
554
+ : '<br>' . esc_html__( 'Sites that use Easy IO already have built-in image optimization and may dismiss this notice to disable local compression.', 'ewww-image-optimizer' ) ) .
555
  '</p></div>';
556
  echo
557
  "<script>\n" .
1124
  function ewww_image_optimizer_mimetype( $path, $case ) {
1125
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1126
  ewwwio_debug_message( "testing mimetype: $path" );
1127
+ if ( false !== strpos( $path, '../' ) ) {
1128
  return false;
1129
  }
1130
  $type = false;
1407
  ewwwio_debug_message( "$path: invalid output" );
1408
  break;
1409
  }
1410
+ if ( ! empty( $webp_version ) && preg_match( '/\d\.\d\.\d/', $webp_version[0] ) ) {
1411
  ewwwio_debug_message( 'optimizer found' );
1412
  return $webp_version[0];
1413
  }
1754
  // Initialize the original filename.
1755
  $original = $file;
1756
  $result = '';
1757
+ if ( false !== strpos( $file, '../' ) ) {
1758
  $msg = __( 'Path traversal in filename not allowed.', 'ewww-image-optimizer' );
1759
  ewwwio_debug_message( "file is using .. potential path traversal blocked: $file" );
1760
  ewww_image_optimizer_s3_uploads_image_cleanup( $file );