EWWW Image Optimizer - Version 4.2.0

Version Description

  • added: disable ExactDN attachment ID queries if they take too long
  • added: ExactDN compatibility with a3 Lazy Load
  • added: ability to re-test async/background mode if it gets disabled
  • changed: better compatibility between Autoptimize and ExactDN
  • changed: .webp files removed when restoring original from API
  • changed: Force re-optimize checkbox persists up to an hour if bulk optimizer is interrupted
  • fixed: CSS, JS, and other resources could be skipped by ExactDN in certain circumstances
  • fixed: Jupiter theme captcha incompatible with ExactDN
  • fixed: prevent calls to php_uname when it is disabled
  • fixed: MacOS X installer for PNGOUT
  • fixed: prevent notices due to empty output from exec()
  • fixed: ExactDN fails to crop when image_downsize() is called with explicit dimensions
  • fixed: ExactDN breaks image resizing with Themify themes
  • fixed: multi-site settings throws error during submission when ExactDN is active
  • fixed: single-site override option displayed when plugin activated per-site
  • removed: PHP 5.3 no longer supported
Download this release

Release Info

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

Code changes from version 4.1.3 to 4.2.0

Files changed (9) hide show
  1. .travis.yml +2 -6
  2. aux-optimize.php +6 -0
  3. bulk.php +16 -2
  4. changelog.txt +18 -0
  5. classes/class-exactdn.php +165 -34
  6. common.php +63 -34
  7. ewww-image-optimizer.php +3 -3
  8. readme.txt +24 -70
  9. unique.php +57 -111
.travis.yml CHANGED
@@ -25,13 +25,9 @@ env:
25
 
26
  matrix:
27
  include:
28
- - php: 5.3
29
- env: WP_VERSION=latest WP_MULTISITE=0
30
- dist: precise
31
- - php: 5.3
32
  env: WP_VERSION=latest WP_MULTISITE=1
33
- dist: precise
34
- - php: 7.0
35
  env: WP_VERSION=latest WP_MULTISITE=1
36
 
37
  before_script:
25
 
26
  matrix:
27
  include:
28
+ - php: 5.4
 
 
 
29
  env: WP_VERSION=latest WP_MULTISITE=1
30
+ - php: 7.1
 
31
  env: WP_VERSION=latest WP_MULTISITE=1
32
 
33
  before_script:
aux-optimize.php CHANGED
@@ -363,6 +363,12 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
363
  ewwwio_debug_message( "scanning folder for images: $dir" );
364
  $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
365
  $start = microtime( true );
 
 
 
 
 
 
366
  if ( empty( $optimized_list ) || ! is_array( $optimized_list ) ) {
367
  ewww_image_optimizer_optimized_list();
368
  }
363
  ewwwio_debug_message( "scanning folder for images: $dir" );
364
  $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
365
  $start = microtime( true );
366
+ // Make the Force Re-optimize option persistent.
367
+ if ( ! empty( $_REQUEST['ewww_force'] ) ) {
368
+ set_transient( 'ewww_image_optimizer_force_reopt', true, HOUR_IN_SECONDS );
369
+ } else {
370
+ delete_transient( 'ewww_image_optimizer_force_reopt' );
371
+ }
372
  if ( empty( $optimized_list ) || ! is_array( $optimized_list ) ) {
373
  ewww_image_optimizer_optimized_list();
374
  }
bulk.php CHANGED
@@ -108,8 +108,9 @@ function ewww_image_optimizer_bulk_head_output() {
108
  </div>
109
  </div>
110
  <form class="ewww-bulk-form">
111
- <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="checkbox" id="ewww-force" name="ewww-force">
112
- &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?></p>
 
113
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
114
  <div id="ewww-delay-slider" style="width:50%"></div>
115
  </form>
@@ -667,6 +668,12 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
667
  // Retrieve the time when the scan starts.
668
  $started = microtime( true );
669
  $attachment_ids = get_option( 'ewww_image_optimizer_scanning_attachments' );
 
 
 
 
 
 
670
 
671
  if ( ! empty( $attachment_ids ) && count( $attachment_ids ) > 300 ) {
672
  ewww_image_optimizer_debug_log();
@@ -1477,6 +1484,12 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1477
  $started = microtime( true );
1478
  // Prevent the scheduled optimizer from firing during a bulk optimization.
1479
  set_transient( 'ewww_image_optimizer_no_scheduled_optimization', true, 10 * MINUTE_IN_SECONDS );
 
 
 
 
 
 
1480
  // Find out if our nonce is on it's last leg/tick.
1481
  if ( ! empty( $_REQUEST['ewww_wpnonce'] ) ) {
1482
  $tick = wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' );
@@ -1677,6 +1690,7 @@ function ewww_image_optimizer_bulk_cleanup() {
1677
  update_option( 'ewww_image_optimizer_bulk_resume', '' );
1678
  update_option( 'ewww_image_optimizer_bulk_attachments', '', false );
1679
  delete_transient( 'ewww_image_optimizer_skip_aux' );
 
1680
  // Let the user know we are done.
1681
  ewwwio_memory( __FUNCTION__ );
1682
  ewwwio_ob_clean();
108
  </div>
109
  </div>
110
  <form class="ewww-bulk-form">
111
+ <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label>
112
+ &emsp;<input type="checkbox" id="ewww-force" name="ewww-force"<?php echo ( get_transient( 'ewww_image_optimizer_force_reopt' ) ) ? ' checked' : ''; ?>>
113
+ &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?></p>
114
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
115
  <div id="ewww-delay-slider" style="width:50%"></div>
116
  </form>
668
  // Retrieve the time when the scan starts.
669
  $started = microtime( true );
670
  $attachment_ids = get_option( 'ewww_image_optimizer_scanning_attachments' );
671
+ // Make the Force Re-optimize option persistent.
672
+ if ( ! empty( $_REQUEST['ewww_force'] ) ) {
673
+ set_transient( 'ewww_image_optimizer_force_reopt', true, HOUR_IN_SECONDS );
674
+ } else {
675
+ delete_transient( 'ewww_image_optimizer_force_reopt' );
676
+ }
677
 
678
  if ( ! empty( $attachment_ids ) && count( $attachment_ids ) > 300 ) {
679
  ewww_image_optimizer_debug_log();
1484
  $started = microtime( true );
1485
  // Prevent the scheduled optimizer from firing during a bulk optimization.
1486
  set_transient( 'ewww_image_optimizer_no_scheduled_optimization', true, 10 * MINUTE_IN_SECONDS );
1487
+ // Make the Force Re-optimize option persistent.
1488
+ if ( ! empty( $_REQUEST['ewww_force'] ) ) {
1489
+ set_transient( 'ewww_image_optimizer_force_reopt', true, HOUR_IN_SECONDS );
1490
+ } else {
1491
+ delete_transient( 'ewww_image_optimizer_force_reopt' );
1492
+ }
1493
  // Find out if our nonce is on it's last leg/tick.
1494
  if ( ! empty( $_REQUEST['ewww_wpnonce'] ) ) {
1495
  $tick = wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' );
1690
  update_option( 'ewww_image_optimizer_bulk_resume', '' );
1691
  update_option( 'ewww_image_optimizer_bulk_attachments', '', false );
1692
  delete_transient( 'ewww_image_optimizer_skip_aux' );
1693
+ delete_transient( 'ewww_image_optimizer_force_reopt' );
1694
  // Let the user know we are done.
1695
  ewwwio_memory( __FUNCTION__ );
1696
  ewwwio_ob_clean();
changelog.txt CHANGED
@@ -1,3 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.1.3 =
2
  * fixed: infinite loop when removing invalid API key
3
  * fixed: img elements with incorrect attachment ID being replaced with wrong image src
1
+ = 4.2.0 =
2
+ * added: disable ExactDN attachment ID queries if they take too long
3
+ * added: ExactDN compatibility with a3 Lazy Load
4
+ * added: ability to re-test async/background mode if it gets disabled
5
+ * changed: better compatibility between Autoptimize and ExactDN
6
+ * changed: .webp files removed when restoring original from API
7
+ * changed: Force re-optimize checkbox persists up to an hour if bulk optimizer is interrupted
8
+ * fixed: CSS, JS, and other resources could be skipped by ExactDN in certain circumstances
9
+ * fixed: Jupiter theme captcha incompatible with ExactDN
10
+ * fixed: prevent calls to php_uname when it is disabled
11
+ * fixed: MacOS X installer for PNGOUT
12
+ * fixed: prevent notices due to empty output from exec()
13
+ * fixed: ExactDN fails to crop when image_downsize() is called with explicit dimensions
14
+ * fixed: ExactDN breaks image resizing with Themify themes
15
+ * fixed: multi-site settings throws error during submission when ExactDN is active
16
+ * fixed: single-site override option displayed when plugin activated per-site
17
+ * removed: PHP 5.3 no longer supported
18
+
19
  = 4.1.3 =
20
  * fixed: infinite loop when removing invalid API key
21
  * fixed: img elements with incorrect attachment ID being replaced with wrong image src
classes/class-exactdn.php CHANGED
@@ -120,6 +120,8 @@ class ExactDN {
120
  } else {
121
  ewwwio_debug_message( 'aq_resize detected, image_downsize filter disabled' );
122
  }
 
 
123
 
124
  // Overrides for admin-ajax images.
125
  add_filter( 'exactdn_admin_allow_image_downsize', array( $this, 'allow_admin_image_downsize' ), 10, 2 );
@@ -145,8 +147,14 @@ class ExactDN {
145
  }
146
 
147
  // Configure Autoptimize with our CDN domain.
148
- if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && ! ewww_image_optimizer_get_option( 'autoptimize_cdn_url' ) ) {
149
- ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
 
 
 
 
 
 
150
  }
151
 
152
  // Find the "local" domain.
@@ -162,6 +170,7 @@ class ExactDN {
162
  $this->allowed_domains[] = $nonwww;
163
  }
164
  }
 
165
  }
166
 
167
  /**
@@ -196,16 +205,23 @@ class ExactDN {
196
  $this->exactdn_domain = $exactdn_domain;
197
  ewwwio_debug_message( 'exactdn_domain: ' . $exactdn_domain );
198
  return true;
199
- } elseif ( get_option( 'ewww_image_optimizer_exactdn_failures' ) < 5 ) {
200
  $failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
201
  $failures++;
202
  ewwwio_debug_message( "could not verify existing exactDN domain, failures: $failures" );
203
  update_option( 'ewww_image_optimizer_exactdn_failures', $failures );
204
- $this->set_exactdn_checkin( time() + 3600 );
 
 
 
 
 
205
  return false;
206
  }
207
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
 
208
  delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
 
209
  return false;
210
  }
211
 
@@ -251,13 +267,49 @@ class ExactDN {
251
  * @return bool Whether the domain is still valid.
252
  */
253
  function verify_domain( $domain ) {
 
 
 
254
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
255
  // Check the time, to see how long it has been since we verified the domain.
256
- $last_checkin = $this->get_exactdn_checkin();
257
  if ( ! empty( $last_checkin ) && $last_checkin > time() ) {
258
- ewwwio_debug_message( 'not time yet' );
 
 
 
259
  return true;
260
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  $url = 'http://optimize.exactlywww.com/exactdn/verify.php';
262
  $ssl = wp_http_supports( array( 'ssl' ) );
263
  if ( $ssl ) {
@@ -272,22 +324,52 @@ class ExactDN {
272
  if ( is_wp_error( $result ) ) {
273
  $error_message = $result->get_error_message();
274
  ewwwio_debug_message( "exactdn verification request failed: $error_message" );
 
275
  return false;
276
  } elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) === false ) {
277
  $response = json_decode( $result['body'], true );
278
  if ( ! empty( $response['success'] ) ) {
279
- $this->set_exactdn_checkin( time() + 86400 );
 
 
 
280
  return true;
281
  }
282
  } elseif ( ! empty( $result['body'] ) ) {
283
  $response = json_decode( $result['body'], true );
284
  $error_message = $response['error'];
285
  ewwwio_debug_message( "exactdn activation request failed: $error_message" );
 
286
  return false;
287
  }
 
288
  return false;
289
  }
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  /**
292
  * Validate the ExactDN domain.
293
  *
@@ -316,7 +398,6 @@ class ExactDN {
316
  * @return string The ExactDN domain name for this site or network.
317
  */
318
  function get_exactdn_domain() {
319
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
320
  if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
321
  return $this->sanitize_domain( EXACTDN_DOMAIN );
322
  }
@@ -329,21 +410,21 @@ class ExactDN {
329
  }
330
 
331
  /**
332
- * Get the ExactDN last check-in time.
333
  *
334
- * @return int The last time we verified the ExactDN domain.
 
335
  */
336
- function get_exactdn_checkin() {
337
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
338
  if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
339
- return (int) get_option( 'ewww_image_optimizer_exactdn_validation' );
340
  }
341
  if ( is_multisite() ) {
342
  if ( ! SUBDOMAIN_INSTALL ) {
343
- return (int) get_site_option( 'ewww_image_optimizer_exactdn_validation' );
344
  }
345
  }
346
- return (int) get_option( 'ewww_image_optimizer_exactdn_validation' );
347
  }
348
 
349
  /**
@@ -371,21 +452,23 @@ class ExactDN {
371
  }
372
 
373
  /**
374
- * Set the last check-in time for ExactDN.
375
  *
376
- * @param int $time The last time we verified the ExactDN domain.
 
 
377
  */
378
- function set_exactdn_checkin( $time ) {
379
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
380
  if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
381
- return update_option( 'ewww_image_optimizer_exactdn_validation', $time );
382
  }
383
  if ( is_multisite() ) {
384
  if ( ! SUBDOMAIN_INSTALL ) {
385
- return update_site_option( 'ewww_image_optimizer_exactdn_validation', $time );
386
  }
387
  }
388
- return update_option( 'ewww_image_optimizer_exactdn_validation', $time );
389
  }
390
 
391
  /**
@@ -538,6 +621,11 @@ class ExactDN {
538
  $placeholder_src_orig = $src;
539
  $src = $lazy_load_src[1];
540
  $src_orig = $lazy_load_src[1];
 
 
 
 
 
541
  }
542
 
543
  // Check if image URL should be used with ExactDN.
@@ -806,24 +894,29 @@ class ExactDN {
806
  }
807
  } // End if().
808
  } // End foreach().
809
- if ( $this->filtering_the_page && ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
810
- ewwwio_debug_message( 'rewriting all other wp_content urls' );
811
- if ( $this->exactdn_domain && $this->upload_domain ) {
812
- $escaped_upload_domain = str_replace( '.', '\.', $this->upload_domain );
813
- ewwwio_debug_message( $escaped_upload_domain );
814
- // Pre-empt rewriting of wp-includes and wp-content if the extension is php/ashx by using a temporary placeholder.
815
- $content = preg_replace( '#(https?)://' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(php|ashx)#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
816
- $content = preg_replace( '#(https?)://' . $escaped_upload_domain . '/([^"\'?>]+?)?wp-(includes|content)#i', '$1://' . $this->exactdn_domain . '/$2wp-$3', $content );
817
- $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
818
- }
819
- }
820
  } // End if();
 
 
 
 
 
 
 
 
 
 
 
 
821
  ewwwio_debug_message( 'done parsing page' );
822
  $this->filtering_the_content = false;
823
 
824
  $elapsed_time = microtime( true ) - $started;
825
  ewwwio_debug_message( "parsing the_content took $elapsed_time seconds" );
826
  $this->elapsed_time += microtime( true ) - $started;
 
 
 
 
827
  return $content;
828
  }
829
 
@@ -850,6 +943,25 @@ class ExactDN {
850
  return $allow;
851
  }
852
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  /**
854
  * Filter post thumbnail image retrieval, passing images through ExactDN.
855
  *
@@ -1052,22 +1164,26 @@ class ExactDN {
1052
  if ( ! $width || ! $height ) {
1053
  return $image;
1054
  }
 
1055
 
1056
  $image_meta = wp_get_attachment_metadata( $attachment_id );
1057
  if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
1058
- $image_resized = image_resize_dimensions( $image_meta['width'], $image_meta['height'], $width, $height );
1059
 
1060
  if ( $image_resized ) { // This could be false when the requested image size is larger than the full-size image.
1061
  $width = $image_resized[6];
1062
  $height = $image_resized[7];
 
1063
  } else {
1064
  $width = $image_meta['width'];
1065
  $height = $image_meta['height'];
 
1066
  }
1067
  $has_size_meta = true;
1068
  }
1069
 
1070
  list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
 
1071
 
1072
  // Expose arguments to a filter before passing to ExactDN.
1073
  $exactdn_args = array(
@@ -1633,7 +1749,7 @@ class ExactDN {
1633
 
1634
  // Make sure this is an allowed image domain/hostname for ExactDN on this site.
1635
  if ( ! $this->allow_image_domain( $parsed_url['host'] ) ) {
1636
- ewwwio_debug_message( 'invalid host for ExactDN' );
1637
  return $url;
1638
  }
1639
 
@@ -1875,6 +1991,21 @@ class ExactDN {
1875
  printf( "<link rel='dns-prefetch' href='%s'>\r\n", '//' . esc_attr( $this->exactdn_domain ) );
1876
  }
1877
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1878
  }
1879
 
1880
  global $exactdn;
120
  } else {
121
  ewwwio_debug_message( 'aq_resize detected, image_downsize filter disabled' );
122
  }
123
+ // Disable image_downsize filter during themify_get_image().
124
+ add_action( 'themify_before_post_image', array( $this, 'disable_image_downsize' ) );
125
 
126
  // Overrides for admin-ajax images.
127
  add_filter( 'exactdn_admin_allow_image_downsize', array( $this, 'allow_admin_image_downsize' ), 10, 2 );
147
  }
148
 
149
  // Configure Autoptimize with our CDN domain.
150
+ add_filter( 'autoptimize_filter_cssjs_multidomain', array( $this, 'autoptimize_cdn_url' ) );
151
+ if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) ) {
152
+ $ao_cdn_url = ewww_image_optimizer_get_option( 'autoptimize_cdn_url' );
153
+ if ( empty( $ao_cdn_url ) ) {
154
+ ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
155
+ } elseif ( strpos( $ao_cdn_url, 'exactdn' ) && '//' . $this->exactdn_domain !== $ao_cdn_url ) {
156
+ ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
157
+ }
158
  }
159
 
160
  // Find the "local" domain.
170
  $this->allowed_domains[] = $nonwww;
171
  }
172
  }
173
+ $this->allowed_domains = apply_filters( 'exactdn_allowed_domains', $this->allowed_domains );
174
  }
175
 
176
  /**
205
  $this->exactdn_domain = $exactdn_domain;
206
  ewwwio_debug_message( 'exactdn_domain: ' . $exactdn_domain );
207
  return true;
208
+ } elseif ( $this->get_exactdn_option( 'checkin' ) < time() - 5 && get_option( 'ewww_image_optimizer_exactdn_failures' ) < 10 ) {
209
  $failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
210
  $failures++;
211
  ewwwio_debug_message( "could not verify existing exactDN domain, failures: $failures" );
212
  update_option( 'ewww_image_optimizer_exactdn_failures', $failures );
213
+ $this->set_exactdn_option( 'checkin', time() + 300 );
214
+ return false;
215
+ } elseif ( get_option( 'ewww_image_optimizer_exactdn_failures' ) < 10 ) {
216
+ $failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
217
+ ewwwio_debug_message( 'could not verify existing exactDN domain, waiting for ' . human_time_diff( $this->get_exactdn_option( 'checkin' ) ) );
218
+ ewwwio_debug_message( 10 - $failures . ' attempts remaining' );
219
  return false;
220
  }
221
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
222
+ delete_option( 'ewww_image_optimizer_exactdn_verified' );
223
  delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
224
+ delete_site_option( 'ewww_image_optimizer_exactdn_verified' );
225
  return false;
226
  }
227
 
267
  * @return bool Whether the domain is still valid.
268
  */
269
  function verify_domain( $domain ) {
270
+ if ( empty( $domain ) ) {
271
+ return false;
272
+ }
273
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
274
  // Check the time, to see how long it has been since we verified the domain.
275
+ $last_checkin = $this->get_exactdn_option( 'checkin' );
276
  if ( ! empty( $last_checkin ) && $last_checkin > time() ) {
277
+ ewwwio_debug_message( 'not time yet: ' . human_time_diff( $this->get_exactdn_option( 'checkin' ) ) );
278
+ if ( $this->get_exactdn_option( 'suspended' ) ) {
279
+ return false;
280
+ }
281
  return true;
282
  }
283
+
284
+ $this->check_verify_method();
285
+
286
+ if ( $this->get_exactdn_option( 'verify_method' ) > 0 ) {
287
+ // Test with an image file that should be available on the ExactDN zone.
288
+ $test_url = plugins_url( '/images/testorig.jpg', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
289
+ $local_domain = $this->parse_url( $test_url, PHP_URL_HOST );
290
+ $test_url = str_replace( $local_domain, $domain, $test_url );
291
+ ewwwio_debug_message( "test url is $test_url" );
292
+ $test_result = wp_remote_get( $test_url );
293
+ if ( is_wp_error( $test_result ) ) {
294
+ $error_message = $test_result->get_error_message();
295
+ ewwwio_debug_message( "exactdn verification request failed: $error_message" );
296
+ $this->set_exactdn_option( 'suspended', 1 );
297
+ return false;
298
+ } elseif ( ! empty( $test_result['body'] ) && strlen( $test_result['body'] ) > 300 ) {
299
+ if ( 200 === $test_result['response']['code'] && 'ffd8ff' === bin2hex( substr( $test_result['body'], 0, 3 ) ) ) {
300
+ ewwwio_debug_message( 'exactdn (real-world) verification succeeded' );
301
+ $this->set_exactdn_option( 'checkin', time() + 3600 );
302
+ $this->set_exactdn_option( 'verified', 1, false );
303
+ $this->set_exactdn_option( 'suspended', 0 );
304
+ return true;
305
+ }
306
+ ewwwio_debug_message( 'mime check failed' . bin2hex( substr( $test_result['body'], 0, 3 ) ) );
307
+ }
308
+ $this->set_exactdn_option( 'suspended', 1 );
309
+ return false;
310
+ }
311
+
312
+ // Secondary test against the API db.
313
  $url = 'http://optimize.exactlywww.com/exactdn/verify.php';
314
  $ssl = wp_http_supports( array( 'ssl' ) );
315
  if ( $ssl ) {
324
  if ( is_wp_error( $result ) ) {
325
  $error_message = $result->get_error_message();
326
  ewwwio_debug_message( "exactdn verification request failed: $error_message" );
327
+ $this->set_exactdn_option( 'suspended', 1 );
328
  return false;
329
  } elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) === false ) {
330
  $response = json_decode( $result['body'], true );
331
  if ( ! empty( $response['success'] ) ) {
332
+ ewwwio_debug_message( 'exactdn (secondary) verification succeeded' );
333
+ $this->set_exactdn_option( 'checkin', time() + 3600 );
334
+ $this->set_exactdn_option( 'verified', 1, false );
335
+ $this->set_exactdn_option( 'suspended', 0 );
336
  return true;
337
  }
338
  } elseif ( ! empty( $result['body'] ) ) {
339
  $response = json_decode( $result['body'], true );
340
  $error_message = $response['error'];
341
  ewwwio_debug_message( "exactdn activation request failed: $error_message" );
342
+ $this->set_exactdn_option( 'suspended', 1 );
343
  return false;
344
  }
345
+ $this->set_exactdn_option( 'suspended', 1 );
346
  return false;
347
  }
348
 
349
+ /**
350
+ * Run a simulation to decide which verification method to use.
351
+ */
352
+ function check_verify_method() {
353
+ if ( ! $this->get_exactdn_option( 'verify_method' ) ) {
354
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
355
+ // Prelim test with a known valid image to ensure http(s) connectivity.
356
+ $sim_url = 'https://optimize.exactlywww.com/exactdn/testorig.jpg';
357
+ $sim_result = wp_remote_get( $sim_url );
358
+ if ( is_wp_error( $sim_result ) ) {
359
+ $error_message = $sim_result->get_error_message();
360
+ ewwwio_debug_message( "exactdn (simulated) verification request failed: $error_message" );
361
+ } elseif ( ! empty( $sim_result['body'] ) && strlen( $sim_result['body'] ) > 300 ) {
362
+ if ( 'ffd8ff' === bin2hex( substr( $sim_result['body'], 0, 3 ) ) ) {
363
+ ewwwio_debug_message( 'exactdn (simulated) verification succeeded' );
364
+ $this->set_exactdn_option( 'verify_method', 1, false );
365
+ return;
366
+ }
367
+ }
368
+ ewwwio_debug_message( 'exactdn (simulated) verification request failed, error unknown' );
369
+ $this->set_exactdn_option( 'verify_method', -1, false );
370
+ }
371
+ }
372
+
373
  /**
374
  * Validate the ExactDN domain.
375
  *
398
  * @return string The ExactDN domain name for this site or network.
399
  */
400
  function get_exactdn_domain() {
 
401
  if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
402
  return $this->sanitize_domain( EXACTDN_DOMAIN );
403
  }
410
  }
411
 
412
  /**
413
+ * Get the ExactDN option.
414
  *
415
+ * @param string $option_name The name of the ExactDN option.
416
+ * @return int The numerical value of the option.
417
  */
418
+ function get_exactdn_option( $option_name ) {
 
419
  if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
420
+ return (int) get_option( 'ewww_image_optimizer_exactdn_' . $option_name );
421
  }
422
  if ( is_multisite() ) {
423
  if ( ! SUBDOMAIN_INSTALL ) {
424
+ return (int) get_site_option( 'ewww_image_optimizer_exactdn_' . $option_name );
425
  }
426
  }
427
+ return (int) get_option( 'ewww_image_optimizer_exactdn_' . $option_name );
428
  }
429
 
430
  /**
452
  }
453
 
454
  /**
455
+ * Set an option for ExactDN.
456
  *
457
+ * @param string $option_name The name of the ExactDN option.
458
+ * @param int $option_value The value to set for the ExactDN option.
459
+ * @param bool $autoload Optional. Whether to load the option when WordPress starts up.
460
  */
461
+ function set_exactdn_option( $option_name, $option_value, $autoload = null ) {
462
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
463
  if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
464
+ return update_option( 'ewww_image_optimizer_exactdn_' . $option_name, $option_value, $autoload );
465
  }
466
  if ( is_multisite() ) {
467
  if ( ! SUBDOMAIN_INSTALL ) {
468
+ return update_site_option( 'ewww_image_optimizer_exactdn_' . $option_name, $option_value );
469
  }
470
  }
471
+ return update_option( 'ewww_image_optimizer_exactdn_' . $option_name, $option_value, $autoload );
472
  }
473
 
474
  /**
621
  $placeholder_src_orig = $src;
622
  $src = $lazy_load_src[1];
623
  $src_orig = $lazy_load_src[1];
624
+ } elseif ( strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) && preg_match( '#data-src=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
625
+ $placeholder_src = $src;
626
+ $placeholder_src_orig = $src;
627
+ $src = $lazy_load_src[1];
628
+ $src_orig = $lazy_load_src[1];
629
  }
630
 
631
  // Check if image URL should be used with ExactDN.
894
  }
895
  } // End if().
896
  } // End foreach().
 
 
 
 
 
 
 
 
 
 
 
897
  } // End if();
898
+ if ( $this->filtering_the_page && ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
899
+ ewwwio_debug_message( 'rewriting all other wp_content urls' );
900
+ if ( $this->exactdn_domain && $this->upload_domain ) {
901
+ $escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
902
+ ewwwio_debug_message( $escaped_upload_domain );
903
+ // Pre-empt rewriting of wp-includes and wp-content if the extension is php/ashx by using a temporary placeholder.
904
+ $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(php|ashx)#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
905
+ $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
906
+ $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?wp-(includes|content)#i', '$1://' . $this->exactdn_domain . '/$2wp-$3', $content );
907
+ $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
908
+ }
909
+ }
910
  ewwwio_debug_message( 'done parsing page' );
911
  $this->filtering_the_content = false;
912
 
913
  $elapsed_time = microtime( true ) - $started;
914
  ewwwio_debug_message( "parsing the_content took $elapsed_time seconds" );
915
  $this->elapsed_time += microtime( true ) - $started;
916
+ ewwwio_debug_message( "parsing the page took $this->elapsed_time seconds so far" );
917
+ if ( $this->elapsed_time > .5 ) {
918
+ ewww_image_optimizer_set_option( 'exactdn_prevent_db_queries', true );
919
+ }
920
  return $content;
921
  }
922
 
943
  return $allow;
944
  }
945
 
946
+ /**
947
+ * Disable resizing of images during image_downsize().
948
+ *
949
+ * @param mixed $param Could be anything (or nothing), we just pass it along untouched.
950
+ * @return mixed Just the same value, going back out the door.
951
+ */
952
+ function disable_image_downsize( $param = false ) {
953
+ remove_filter( 'image_downsize', array( $this, 'filter_image_downsize' ) );
954
+ add_action( 'themify_after_post_image', array( $this, 'enable_image_downsize' ) );
955
+ return $param;
956
+ }
957
+
958
+ /**
959
+ * Re-enable resizing of images during image_downsize().
960
+ */
961
+ function enable_image_downsize() {
962
+ add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
963
+ }
964
+
965
  /**
966
  * Filter post thumbnail image retrieval, passing images through ExactDN.
967
  *
1164
  if ( ! $width || ! $height ) {
1165
  return $image;
1166
  }
1167
+ ewwwio_debug_message( "requested w$width by h$height" );
1168
 
1169
  $image_meta = wp_get_attachment_metadata( $attachment_id );
1170
  if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
1171
+ $image_resized = image_resize_dimensions( $image_meta['width'], $image_meta['height'], $width, $height, true );
1172
 
1173
  if ( $image_resized ) { // This could be false when the requested image size is larger than the full-size image.
1174
  $width = $image_resized[6];
1175
  $height = $image_resized[7];
1176
+ ewwwio_debug_message( "using resize dims w$width by h$height" );
1177
  } else {
1178
  $width = $image_meta['width'];
1179
  $height = $image_meta['height'];
1180
+ ewwwio_debug_message( "using meta dims w$width by h$height" );
1181
  }
1182
  $has_size_meta = true;
1183
  }
1184
 
1185
  list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
1186
+ ewwwio_debug_message( "constrained to w$width by h$height" );
1187
 
1188
  // Expose arguments to a filter before passing to ExactDN.
1189
  $exactdn_args = array(
1749
 
1750
  // Make sure this is an allowed image domain/hostname for ExactDN on this site.
1751
  if ( ! $this->allow_image_domain( $parsed_url['host'] ) ) {
1752
+ ewwwio_debug_message( "invalid host for ExactDN: {$parsed_url['host']}" );
1753
  return $url;
1754
  }
1755
 
1991
  printf( "<link rel='dns-prefetch' href='%s'>\r\n", '//' . esc_attr( $this->exactdn_domain ) );
1992
  }
1993
  }
1994
+
1995
+ /**
1996
+ * Adds the ExactDN domain to the list of 'local' domains for Autoptimize.
1997
+ *
1998
+ * @param array $domains A list of domains considered 'local' by Autoptimize.
1999
+ * @return array The same list, with the ExactDN domain appended.
2000
+ */
2001
+ function autoptimize_cdn_url( $domains ) {
2002
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2003
+ if ( is_array( $domains ) && ! in_array( $this->exactdn_domain, $domains ) ) {
2004
+ ewwwio_debug_message( 'adding to AO list: ' . $this->exactdn_domain );
2005
+ $domains[] = $this->exactdn_domain;
2006
+ }
2007
+ return $domains;
2008
+ }
2009
  }
2010
 
2011
  global $exactdn;
common.php CHANGED
@@ -11,7 +11,7 @@
11
  */
12
 
13
  // TODO: use <picture> element to serve webp (#54).
14
- // TODO: attempt lazy load support with a3 plugin and one from automattic for starters.
15
  // TODO: prevent bad ajax errors from firing when we click the toggle on the Optimization Log, and the plugin status from doing 403s...
16
  // TODO: use a transient to do health checks on the schedule optimizer.
17
  // TODO: add a column to track compression level used for each image, and later implement a way to (re)compress at a specific compression level.
@@ -26,19 +26,14 @@
26
  // TODO: integrate AGR, since it's "abandoned", but possibly using gifsicle for better GIFs.
27
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
28
  // TODO: on images without srscet, add 2x and 3x versions anyway.
29
- // TODO: check what happens to WebP images when restoring original from backups.
30
- // TODO: fix ExactDN failure after multisite save settings.
31
- // TODO: add ExactDN compat with A3 lazy.
32
  // TODO: can svg/use tags be exluded from all the things?
33
- // TODO: make the force checkbox persistent.
34
- // TODO: find the link between attachment ID numbers in WPML.
35
  // TODO: match Adaptive Images functionality with ExactDN.
36
- // TODO: add a re-test button for async mode.
37
  if ( ! defined( 'ABSPATH' ) ) {
38
  exit;
39
  }
40
 
41
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '413.0' );
42
 
43
  // Initialize a couple globals.
44
  $ewww_debug = '';
@@ -180,6 +175,8 @@ add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_resize_detection_script'
180
  add_action( 'admin_bar_init', 'ewww_image_optimizer_admin_bar_init' );
181
  // Non-AJAX handler to delete the API key, and reroute back to the settings page.
182
  add_action( 'admin_action_ewww_image_optimizer_remove_cloud_key', 'ewww_image_optimizer_remove_cloud_key' );
 
 
183
  // Non-AJAX handler to delete the debug log, and reroute back to the settings page.
184
  add_action( 'admin_action_ewww_image_optimizer_delete_debug_log', 'ewww_image_optimizer_delete_debug_log' );
185
  // Makes sure to flush out any scheduled jobs on deactivation.
@@ -225,10 +222,10 @@ if ( defined( 'WP_CLI' ) && WP_CLI ) {
225
  }
226
 
227
  /**
228
- * Display a notice that PHP version 5.3 support is going away.
229
  */
230
- function ewww_image_optimizer_php53_warning() {
231
- echo '<div id="ewww-image-optimizer-notice-php53" class="notice notice-info is-dismissible"><p><a href="https://docs.ewww.io/article/55-upgrading-php" target="_blank" data-beacon-article="5ab2baa6042863478ea7c2ae">' . esc_html__( 'The next major release of EWWW Image Optimizer will require PHP 5.4 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</a></p></div>';
232
  }
233
 
234
  /**
@@ -659,7 +656,7 @@ function ewww_image_optimizer_filter_webp_page_output( $buffer ) {
659
  $html->encoding = 'utf-8';
660
  $home_url = get_site_url();
661
  ewwwio_debug_message( "home url: $home_url" );
662
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
663
  global $exactdn;
664
  $exactdn_domain = $exactdn->get_exactdn_domain();
665
  $home_url_parts = $exactdn->parse_url( $home_url );
@@ -1076,9 +1073,6 @@ if ( ! function_exists( 'boolval' ) ) {
1076
  */
1077
  function ewww_image_optimizer_stl_check() {
1078
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1079
- if ( ewww_image_optimizer_safemode_check() ) {
1080
- return false;
1081
- }
1082
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_STL' ) && EWWW_IMAGE_OPTIMIZER_DISABLE_STL ) {
1083
  ewwwio_debug_message( 'stl disabled by user' );
1084
  return false;
@@ -1182,6 +1176,10 @@ function ewww_image_optimizer_upgrade() {
1182
  ewww_image_optimizer_enable_background_optimization();
1183
  ewww_image_optimizer_install_table();
1184
  ewww_image_optimizer_set_defaults();
 
 
 
 
1185
  if ( get_option( 'ewww_image_optimizer_version' ) < 297.5 ) {
1186
  // Cleanup background test mess.
1187
  wp_clear_scheduled_hook( 'wp_ewwwio_test_optimize_cron' );
@@ -1233,6 +1231,21 @@ function ewww_image_optimizer_enable_background_optimization() {
1233
  ewww_image_optimizer_debug_log();
1234
  }
1235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1236
  /**
1237
  * Plugin initialization for admin area.
1238
  *
@@ -1419,9 +1432,10 @@ function ewww_image_optimizer_admin_init() {
1419
  }
1420
  }
1421
  ewww_image_optimizer_ajax_compat_check();
1422
- if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50400 ) {
1423
- add_action( 'network_admin_notices', 'ewww_image_optimizer_php53_warning' );
1424
- add_action( 'admin_notices', 'ewww_image_optimizer_php53_warning' );
 
1425
  }
1426
  ewwwio_memory( __FUNCTION__ );
1427
  }
@@ -2399,8 +2413,8 @@ function ewww_image_optimizer_network_deactivate( $network_wide ) {
2399
  wp_clear_scheduled_hook( 'ewww_image_optimizer_auto' );
2400
  wp_clear_scheduled_hook( 'ewww_image_optimizer_defer' );
2401
  // Un-configure Autoptimize CDN domain.
2402
- if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && strpos( get_option( 'autoptimize_cdn_url' ), 'exactdn' ) ) {
2403
- update_option( 'autoptimize_cdn_url', '' );
2404
  }
2405
  restore_current_blog();
2406
  }
@@ -3323,6 +3337,9 @@ function ewww_image_optimizer_cloud_restore_single_image( $image ) {
3323
  }
3324
  if ( empty( $old_type ) || $old_type == $new_type ) {
3325
  if ( rename( $image['path'] . '.tmp', $image['path'] ) ) {
 
 
 
3326
  // Set the results to nothing.
3327
  $ewwwdb->query( "UPDATE $ewwwdb->ewwwio_images SET results = '', image_size = 0, updates = 0, updated=updated, level = 0 WHERE id = {$image['id']}" );
3328
  return true;
@@ -7383,6 +7400,7 @@ function ewww_image_optimizer_get_image_sizes() {
7383
  * @global string $ewww_debug In memory debug log.
7384
  */
7385
  function ewww_image_optimizer_network_options() {
 
7386
  add_filter( 'ewww_image_optimizer_settings', 'ewww_image_optimizer_filter_network_settings_page', 9 );
7387
  ewww_image_optimizer_options( 'network-multisite' );
7388
  }
@@ -7396,6 +7414,7 @@ function ewww_image_optimizer_network_options() {
7396
  * @global string $ewww_debug In memory debug log.
7397
  */
7398
  function ewww_image_optimizer_network_singlesite_options() {
 
7399
  add_filter( 'ewww_image_optimizer_settings', 'ewww_image_optimizer_filter_network_singlesite_settings_page', 9 );
7400
  ewww_image_optimizer_options( 'network-singlesite' );
7401
  }
@@ -7499,24 +7518,37 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7499
  if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7500
  $status_output .= '<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>';
7501
  $collapsible = false;
7502
- } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7503
  $status_output .= '<p><b>ExactDN:</b> ';
7504
  global $exactdn;
7505
- if ( $exactdn->get_exactdn_domain() ) {
7506
  $status_output .= '<span style="color: green">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
 
 
 
 
 
 
7507
  } else {
 
7508
  $status_output .= '<span style="color: red"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
7509
  $collapsible = false;
7510
  }
7511
  $status_output .= '</p>';
7512
- } else {
7513
  $status_output .= '<p><b>ExactDN:</b> ' . esc_html__( 'Inactive, enable automatic resizing in the Resize Settings', 'ewww-image-optimizer' ) . '</p>';
7514
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
7515
  delete_option( 'ewww_image_optimizer_exactdn_failures' );
 
 
7516
  delete_option( 'ewww_image_optimizer_exactdn_validation' );
 
7517
  delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
7518
  delete_site_option( 'ewww_image_optimizer_exactdn_failures' );
 
 
7519
  delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
 
7520
  }
7521
  if ( ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7522
  list ( $jpegtran_src, $optipng_src, $gifsicle_src, $jpegtran_dst, $optipng_dst, $gifsicle_dst ) = ewww_image_optimizer_install_paths();
@@ -7614,12 +7646,6 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7614
  }
7615
  }
7616
  if ( ! ewww_image_optimizer_full_cloud() ) {
7617
- if ( ewww_image_optimizer_safemode_check() ) {
7618
- $status_output .= 'safe mode: <span style="color: red; font-weight: bolder">' . esc_html__( 'On', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7619
- $collapsible = false;
7620
- } else {
7621
- $status_output .= 'safe mode: <span style="color: green; font-weight: bolder">' . esc_html__( 'Off', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7622
- }
7623
  if ( ewww_image_optimizer_exec_check() ) {
7624
  $status_output .= 'exec(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Disabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7625
  $collapsible = false;
@@ -7731,9 +7757,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7731
  } elseif ( ! ewww_image_optimizer_function_exists( 'sleep' ) ) {
7732
  $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled, sleep function missing', 'ewww-image-optimizer' ) . '</span>';
7733
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
7734
- $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled automatically, async requests blocked', 'ewww-image-optimizer' ) . '</span>';
7735
  } elseif ( ewww_image_optimizer_detect_wpsf_location_lock() ) {
7736
- $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( "Disabled by Shield's Lock to Location feature", 'ewww-image-optimizer' ) . '</p>';
7737
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ) {
7738
  $status_output .= '<span>' . esc_html__( 'Background mode active, enable Parallel Optimization in Advanced Settings', 'ewww-image-optimizer' ) . '</span>';
7739
  } else {
@@ -7754,6 +7780,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7754
  "<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7755
  "<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Conversion Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7756
  "<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
 
7757
  "</ul>\n";
7758
  }
7759
  if ( 'network-multisite' == $network ) {
@@ -7770,7 +7797,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7770
  $output[] = "<div id='ewww-general-settings'>\n";
7771
  $output[] = "<table class='form-table'>\n";
7772
  if ( is_multisite() ) {
7773
- $output[] = "<tr class='network-only'><th><label for='ewww_image_optimizer_allow_multisite_override'>" . esc_html__( 'Allow Single-site Override', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_multisite_override' name='ewww_image_optimizer_allow_multisite_override' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow individual sites to configure their own settings and override all network options.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
7774
  if ( 'network-multisite' == $network && get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
7775
  $output[] = "<tr><th><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7776
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
@@ -7788,8 +7817,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7788
  }
7789
  }
7790
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7791
- $blog_id = get_current_blog_id();
7792
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_notkey'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_notkey' name='ewww_image_optimizer_cloud_notkey' readonly='readonly' value='****************************" . substr( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ), 28 ) . "' size='32' /> <a href='admin.php?action=ewww_image_optimizer_remove_cloud_key&site=$blog_id'>" . esc_html__( 'Remove API key', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7793
  $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7794
  } else {
7795
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_key'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='' size='32' /> " . esc_html__( 'API Key will be validated when you save your settings.', 'ewww-image-optimizer' ) . " <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Purchase an API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
@@ -7958,6 +7986,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7958
  ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) == true ? 'on' : 'off' ) );
7959
  ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
7960
  ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) == true ? 'on' : 'off' ) );
 
7961
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7962
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? 'on' : 'off' ) );
7963
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
11
  */
12
 
13
  // TODO: use <picture> element to serve webp (#54).
14
+ // TODO: attempt lazy load support with a3 plugin and one from automattic for alt webp. or are we back here: https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/
15
  // TODO: prevent bad ajax errors from firing when we click the toggle on the Optimization Log, and the plugin status from doing 403s...
16
  // TODO: use a transient to do health checks on the schedule optimizer.
17
  // TODO: add a column to track compression level used for each image, and later implement a way to (re)compress at a specific compression level.
26
  // TODO: integrate AGR, since it's "abandoned", but possibly using gifsicle for better GIFs.
27
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
28
  // TODO: on images without srscet, add 2x and 3x versions anyway.
 
 
 
29
  // TODO: can svg/use tags be exluded from all the things?
 
 
30
  // TODO: match Adaptive Images functionality with ExactDN.
31
+ // TODO: handle relative urls with ExactDN.
32
  if ( ! defined( 'ABSPATH' ) ) {
33
  exit;
34
  }
35
 
36
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '420.0' );
37
 
38
  // Initialize a couple globals.
39
  $ewww_debug = '';
175
  add_action( 'admin_bar_init', 'ewww_image_optimizer_admin_bar_init' );
176
  // Non-AJAX handler to delete the API key, and reroute back to the settings page.
177
  add_action( 'admin_action_ewww_image_optimizer_remove_cloud_key', 'ewww_image_optimizer_remove_cloud_key' );
178
+ // Non-AJAX handler to retest async/background mode.
179
+ add_action( 'admin_action_ewww_image_optimizer_retest_background_optimization', 'ewww_image_optimizer_retest_background_optimization' );
180
  // Non-AJAX handler to delete the debug log, and reroute back to the settings page.
181
  add_action( 'admin_action_ewww_image_optimizer_delete_debug_log', 'ewww_image_optimizer_delete_debug_log' );
182
  // Makes sure to flush out any scheduled jobs on deactivation.
222
  }
223
 
224
  /**
225
+ * Display a notice that PHP version 5.4 support is going away.
226
  */
227
+ function ewww_image_optimizer_php54_warning() {
228
+ echo '<div id="ewww-image-optimizer-notice-php54" class="notice notice-info is-dismissible"><p><a href="https://docs.ewww.io/article/55-upgrading-php" target="_blank" data-beacon-article="5ab2baa6042863478ea7c2ae">' . esc_html__( 'The next major release of EWWW Image Optimizer will require PHP 5.5 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</a></p></div>';
229
  }
230
 
231
  /**
656
  $html->encoding = 'utf-8';
657
  $home_url = get_site_url();
658
  ewwwio_debug_message( "home url: $home_url" );
659
+ if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
660
  global $exactdn;
661
  $exactdn_domain = $exactdn->get_exactdn_domain();
662
  $home_url_parts = $exactdn->parse_url( $home_url );
1073
  */
1074
  function ewww_image_optimizer_stl_check() {
1075
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 
 
 
1076
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_STL' ) && EWWW_IMAGE_OPTIMIZER_DISABLE_STL ) {
1077
  ewwwio_debug_message( 'stl disabled by user' );
1078
  return false;
1176
  ewww_image_optimizer_enable_background_optimization();
1177
  ewww_image_optimizer_install_table();
1178
  ewww_image_optimizer_set_defaults();
1179
+ // This will get re-enabled if things are too slow.
1180
+ ewww_image_optimizer_set_option( 'exactdn_prevent_db_queries', false );
1181
+ delete_option( 'ewww_image_optimizer_exactdn_verify_method' );
1182
+ delete_site_option( 'ewww_image_optimizer_exactdn_verify_method' );
1183
  if ( get_option( 'ewww_image_optimizer_version' ) < 297.5 ) {
1184
  // Cleanup background test mess.
1185
  wp_clear_scheduled_hook( 'wp_ewwwio_test_optimize_cron' );
1231
  ewww_image_optimizer_debug_log();
1232
  }
1233
 
1234
+ /**
1235
+ * Re-tests background optimization at a user's request.
1236
+ */
1237
+ function ewww_image_optimizer_retest_background_optimization() {
1238
+ $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' );
1239
+ if ( false === current_user_can( $permissions ) ) {
1240
+ wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
1241
+ }
1242
+ ewww_image_optimizer_enable_background_optimization();
1243
+ sleep( 10 );
1244
+ $sendback = wp_get_referer();
1245
+ wp_redirect( $sendback );
1246
+ exit;
1247
+ }
1248
+
1249
  /**
1250
  * Plugin initialization for admin area.
1251
  *
1432
  }
1433
  }
1434
  ewww_image_optimizer_ajax_compat_check();
1435
+ // Remove the false when the next bump is coming.
1436
+ if ( false && defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50500 ) {
1437
+ add_action( 'network_admin_notices', 'ewww_image_optimizer_php54_warning' );
1438
+ add_action( 'admin_notices', 'ewww_image_optimizer_php54_warning' );
1439
  }
1440
  ewwwio_memory( __FUNCTION__ );
1441
  }
2413
  wp_clear_scheduled_hook( 'ewww_image_optimizer_auto' );
2414
  wp_clear_scheduled_hook( 'ewww_image_optimizer_defer' );
2415
  // Un-configure Autoptimize CDN domain.
2416
+ if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && strpos( ewww_image_optimizer_get_option( 'autoptimize_cdn_url' ), 'exactdn' ) ) {
2417
+ ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '' );
2418
  }
2419
  restore_current_blog();
2420
  }
3337
  }
3338
  if ( empty( $old_type ) || $old_type == $new_type ) {
3339
  if ( rename( $image['path'] . '.tmp', $image['path'] ) ) {
3340
+ if ( is_file( $image['path'] . '.webp' ) && is_writable( $image['path'] . '.webp' ) ) {
3341
+ unlink( $image['path'] . '.webp' );
3342
+ }
3343
  // Set the results to nothing.
3344
  $ewwwdb->query( "UPDATE $ewwwdb->ewwwio_images SET results = '', image_size = 0, updates = 0, updated=updated, level = 0 WHERE id = {$image['id']}" );
3345
  return true;
7400
  * @global string $ewww_debug In memory debug log.
7401
  */
7402
  function ewww_image_optimizer_network_options() {
7403
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
7404
  add_filter( 'ewww_image_optimizer_settings', 'ewww_image_optimizer_filter_network_settings_page', 9 );
7405
  ewww_image_optimizer_options( 'network-multisite' );
7406
  }
7414
  * @global string $ewww_debug In memory debug log.
7415
  */
7416
  function ewww_image_optimizer_network_singlesite_options() {
7417
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
7418
  add_filter( 'ewww_image_optimizer_settings', 'ewww_image_optimizer_filter_network_singlesite_settings_page', 9 );
7419
  ewww_image_optimizer_options( 'network-singlesite' );
7420
  }
7518
  if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7519
  $status_output .= '<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>';
7520
  $collapsible = false;
7521
+ } elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7522
  $status_output .= '<p><b>ExactDN:</b> ';
7523
  global $exactdn;
7524
+ if ( $exactdn->get_exactdn_domain() && $exactdn->verify_domain( $exactdn->get_exactdn_domain() ) ) {
7525
  $status_output .= '<span style="color: green">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
7526
+ } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
7527
+ $status_output .= '<span style="color: orange">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
7528
+ $collapsible = false;
7529
+ } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'suspended' ) ) {
7530
+ $status_output .= '<span style="color: orange">' . esc_html__( 'Active, not yet verified.', 'ewww-image-optimizer' ) . ' </span>';
7531
+ $collapsible = false;
7532
  } else {
7533
+ ewwwio_debug_message( 'could not verify: ' . $exactdn->get_exactdn_domain() );
7534
  $status_output .= '<span style="color: red"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
7535
  $collapsible = false;
7536
  }
7537
  $status_output .= '</p>';
7538
+ } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7539
  $status_output .= '<p><b>ExactDN:</b> ' . esc_html__( 'Inactive, enable automatic resizing in the Resize Settings', 'ewww-image-optimizer' ) . '</p>';
7540
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
7541
  delete_option( 'ewww_image_optimizer_exactdn_failures' );
7542
+ delete_option( 'ewww_image_optimizer_exactdn_checkin' );
7543
+ delete_option( 'ewww_image_optimizer_exactdn_verified' );
7544
  delete_option( 'ewww_image_optimizer_exactdn_validation' );
7545
+ delete_option( 'ewww_image_optimizer_exactdn_suspended' );
7546
  delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
7547
  delete_site_option( 'ewww_image_optimizer_exactdn_failures' );
7548
+ delete_site_option( 'ewww_image_optimizer_exactdn_checkin' );
7549
+ delete_site_option( 'ewww_image_optimizer_exactdn_verified' );
7550
  delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
7551
+ delete_site_option( 'ewww_image_optimizer_exactdn_suspended' );
7552
  }
7553
  if ( ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7554
  list ( $jpegtran_src, $optipng_src, $gifsicle_src, $jpegtran_dst, $optipng_dst, $gifsicle_dst ) = ewww_image_optimizer_install_paths();
7646
  }
7647
  }
7648
  if ( ! ewww_image_optimizer_full_cloud() ) {
 
 
 
 
 
 
7649
  if ( ewww_image_optimizer_exec_check() ) {
7650
  $status_output .= 'exec(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Disabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7651
  $collapsible = false;
7757
  } elseif ( ! ewww_image_optimizer_function_exists( 'sleep' ) ) {
7758
  $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled, sleep function missing', 'ewww-image-optimizer' ) . '</span>';
7759
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
7760
+ $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled automatically, async requests blocked', 'ewww-image-optimizer' ) . " - <a href='admin.php?action=ewww_image_optimizer_retest_background_optimization'>" . esc_html__( 'Re-test', 'ewww-image-optimizer' ) . '</a><span>';
7761
  } elseif ( ewww_image_optimizer_detect_wpsf_location_lock() ) {
7762
+ $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( "Disabled by Shield's Lock to Location feature", 'ewww-image-optimizer' ) . '</span>';
7763
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ) {
7764
  $status_output .= '<span>' . esc_html__( 'Background mode active, enable Parallel Optimization in Advanced Settings', 'ewww-image-optimizer' ) . '</span>';
7765
  } else {
7780
  "<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7781
  "<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Conversion Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7782
  "<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7783
+ "<li class='ewww-tab ewww-overrides-nav'><span class='ewww-tab-hidden'><a href='https://docs.ewww.io/article/40-override-options' target='_blank' data-beacon-article='59710ce4042863033a1b45a6'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
7784
  "</ul>\n";
7785
  }
7786
  if ( 'network-multisite' == $network ) {
7797
  $output[] = "<div id='ewww-general-settings'>\n";
7798
  $output[] = "<table class='form-table'>\n";
7799
  if ( is_multisite() ) {
7800
+ if ( is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
7801
+ $output[] = "<tr class='network-only'><th><label for='ewww_image_optimizer_allow_multisite_override'>" . esc_html__( 'Allow Single-site Override', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_multisite_override' name='ewww_image_optimizer_allow_multisite_override' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow individual sites to configure their own settings and override all network options.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7802
+ }
7803
  if ( 'network-multisite' == $network && get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
7804
  $output[] = "<tr><th><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7805
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7817
  }
7818
  }
7819
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7820
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_notkey'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_notkey' name='ewww_image_optimizer_cloud_notkey' readonly='readonly' value='****************************" . substr( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ), 28 ) . "' size='32' /> <a href='admin.php?action=ewww_image_optimizer_remove_cloud_key'>" . esc_html__( 'Remove API key', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
 
7821
  $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7822
  } else {
7823
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_key'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='' size='32' /> " . esc_html__( 'API Key will be validated when you save your settings.', 'ewww-image-optimizer' ) . " <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Purchase an API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7986
  ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) == true ? 'on' : 'off' ) );
7987
  ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
7988
  ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) == true ? 'on' : 'off' ) );
7989
+ ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) == true ? 'off' : 'on' ) );
7990
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7991
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? 'on' : 'off' ) );
7992
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
ewww-image-optimizer.php CHANGED
@@ -14,7 +14,7 @@ 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: Shane Bishop
16
  Text Domain: ewww-image-optimizer
17
- Version: 4.1.3
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
@@ -37,7 +37,7 @@ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
37
  }
38
 
39
  // Check the PHP version.
40
- if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50300 ) {
41
  /**
42
  * This is the full system path to the plugin folder.
43
  *
@@ -132,7 +132,7 @@ if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
132
  * Display a notice that the PHP version is too old.
133
  */
134
  function ewww_image_optimizer_unsupported_php() {
135
- echo "<div id='ewww-image-optimizer-warning-php' class='error'><p><strong>" . esc_html__( 'EWWW Image Optimizer requires PHP 5.3 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</strong></p></div>';
136
  }
137
 
138
  /**
14
  Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Shane Bishop
16
  Text Domain: ewww-image-optimizer
17
+ Version: 4.2.0
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
37
  }
38
 
39
  // Check the PHP version.
40
+ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50400 ) {
41
  /**
42
  * This is the full system path to the plugin folder.
43
  *
132
  * Display a notice that the PHP version is too old.
133
  */
134
  function ewww_image_optimizer_unsupported_php() {
135
+ echo "<div id='ewww-image-optimizer-warning-php' class='error'><p><strong>" . esc_html__( 'EWWW Image Optimizer requires PHP 5.4 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</strong></p></div>';
136
  }
137
 
138
  /**
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: image, compress, optimize, optimization, lossless, lossy, seo, tinyjpg, tinypng, webp, wp-cli
5
  Requires at least: 4.6
6
  Tested up to: 4.9
7
- Requires PHP: 5.3
8
- Stable tag: 4.1.3
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
@@ -177,6 +177,24 @@ http://developer.yahoo.com/performance/rules.html#opt_images
177
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
178
  * 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/
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  = 4.1.3 =
181
  * fixed: infinite loop when removing invalid API key
182
  * fixed: img elements with incorrect attachment ID being replaced with wrong image src
@@ -216,73 +234,15 @@ http://developer.yahoo.com/performance/rules.html#opt_images
216
  * fixed: warnings when WP Offload S3 set to delete local files, props ianmjones
217
  * updated: pngquant version 2.11.7
218
 
219
- = 4.0.6 =
220
- * changed: dummy images have no args appended with exactdn except for ssl flag
221
- * fixed: resize_detection.js being combined with other scripts by Autoptimize
222
- * fixed: retina optimization not deferred in async mode
223
- * fixed: PDF files could trigger license exceeded message
224
- * fixed: binary detection not fully functional with MacOS and PHP 7.2
225
- * fixed: compatibility with Regenerate Thumbnails version 3
226
-
227
- = 4.0.5 =
228
- * added: enable lossy compression with ExactDN: https://docs.ewww.io/article/47-getting-more-from-exactdn
229
- * added: CSS/JS minification with ExactDN, see https://docs.ewww.io/article/47-getting-more-from-exactdn
230
- * added: disable WebP for specific files with ewww_image_optimizer_bypass_webp filter
231
- * added: ExactDN obeys focus point from Theia Smart Thumbnails plugin
232
- * added: admin-ajax requests for eddvbugm loader work with ExactDN
233
- * fixed: multisite settings would not save in certain circumstances
234
- * fixed: compression levels reset for API users on multisite after toggling single-site override on and off
235
- * fixed: media library items with non-local images rewritten incorrectly by ExactDN
236
- * fixed: restoring images throws errors on PHP 7.1
237
- * fixed: has_cap with invalid argument not recognizing utf8-mb4 v5.2
238
-
239
- = 4.0.4 =
240
- * fixed: ExactDN domain validation failing on length check for some domains
241
- * updated: PEL for better EXIF preservation
242
-
243
- = 4.0.3 =
244
- * added: support for additional ExactDN root domains
245
- * added: button to remove WebP rewrite rules
246
- * added: informational notice on thumbnail rebuild pages of how the plugins interact
247
- * changed: WebP rewrite rules removed automatically when ExactDN is enabled, use Alt WebP instead
248
- * changed: ExactDN now removes metadata if option is enabled
249
- * fixed: multisite settings set to defaults when single-site resize settings are submitted
250
-
251
- = 4.0.2 =
252
- * fixed: WooCommerce images still not working with Alt WebP in all cases
253
- * fixed: ob_clean() breaks AJAX actions when there is no buffer to clean
254
- * fixed: notice on NextCellent gallery management pages
255
- * fixed: missing JS for AJAX actions in NextCellent
256
-
257
- = 4.0.1 =
258
- * fixed: ExactDN option not disabled when verification fails too many times
259
- * fixed: theme scanner sometimes skipped images on PHP 5.3
260
- * fixed: invalid (float) width parameters for srcset attributes
261
- * fixed: Jetpack lightbox and carousel were not fully working with Alt WebP
262
- * fixed: WooCommerce lightbox and gallery not working with Alt WebP
263
- * fixed: incorrect message about scanning scope when selecting images from media library for bulk optimization
264
- * security: fixed wildcard LIKE queries to allow proper escaping
265
-
266
- = 4.0.0 =
267
- * added: ExactDN with CDN and automatic image resizing
268
- * added: image resize detection for admin users
269
- * changed: WP core, theme, and plugin images are excluded from lossy optimization
270
- * fixed: files fetched from S3 not detected by PHP in some cases
271
- * fixed: option override conflict preventing webp conversion
272
- * fixed: Alt WebP breaks Draw Attention image maps
273
- * fixed: customized WP_Background_Process class conflicts with other plugins using the same class
274
- * fixed: image deletion could cause deletion of images on source site after cloning database
275
- * fixed: WebP .htaccess rules using REQUEST_FILENAME instead of REQUEST_URI does not work on some servers
276
- * fixed: per-site resize settings hidden when API is active network-wide
277
- * fixed: network-wide settings not saving properly
278
- * fixed: notice of undefined index with some configurations of the Shield security plugin
279
- * deprecated: PHP 5.3 support will be removed by March 2018
280
-
281
  = Earlier versions =
282
  Please refer to the separate changelog.txt file.
283
 
284
  == Upgrade Notice ==
285
 
 
 
 
 
286
  = 4.1.0 =
287
  * Security update: gifsicle and optipng have been updated to resolve security flaws.
288
  * ExactDN now processes JS/CSS/Fonts for even more speed.
@@ -294,12 +254,6 @@ Please refer to the separate changelog.txt file.
294
  * API functions have been rewritten to use core WP detection for https capability, please report any errors right away.
295
  * Several options have been removed from the user interface, see the changelog for details.
296
 
297
- = 3.4.0 =
298
- * Multisite change: disabling resizes must be done on individual sites even when network activated, as those settings are heavily theme-specific.
299
-
300
- = 3.3.0 =
301
- * Requires PHP 5.3+. All sites hosted on Pantheon will now use "relative" paths. Existing Pantheon sites will need to update the ewwwio_images table to match (contact support for help), or disable this function by setting EWWW_IMAGE_OPTIMIZER_RELATIVE to false in wp-config.php.
302
-
303
  == Contact and Credits ==
304
 
305
  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 class based upon the Photon module from Jetpack.
4
  Tags: image, compress, optimize, optimization, lossless, lossy, seo, tinyjpg, tinypng, webp, wp-cli
5
  Requires at least: 4.6
6
  Tested up to: 4.9
7
+ Requires PHP: 5.4
8
+ Stable tag: 4.2.0
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
177
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
178
  * 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/
179
 
180
+ = 4.2.0 =
181
+ * added: disable ExactDN attachment ID queries if they take too long
182
+ * added: ExactDN compatibility with a3 Lazy Load
183
+ * added: ability to re-test async/background mode if it gets disabled
184
+ * changed: better compatibility between Autoptimize and ExactDN
185
+ * changed: .webp files removed when restoring original from API
186
+ * changed: Force re-optimize checkbox persists up to an hour if bulk optimizer is interrupted
187
+ * fixed: CSS, JS, and other resources could be skipped by ExactDN in certain circumstances
188
+ * fixed: Jupiter theme captcha incompatible with ExactDN
189
+ * fixed: prevent calls to php_uname when it is disabled
190
+ * fixed: MacOS X installer for PNGOUT
191
+ * fixed: prevent notices due to empty output from exec()
192
+ * fixed: ExactDN fails to crop when image_downsize() is called with explicit dimensions
193
+ * fixed: ExactDN breaks image resizing with Themify themes
194
+ * fixed: multi-site settings throws error during submission when ExactDN is active
195
+ * fixed: single-site override option displayed when plugin activated per-site
196
+ * removed: PHP 5.3 no longer supported
197
+
198
  = 4.1.3 =
199
  * fixed: infinite loop when removing invalid API key
200
  * fixed: img elements with incorrect attachment ID being replaced with wrong image src
234
  * fixed: warnings when WP Offload S3 set to delete local files, props ianmjones
235
  * updated: pngquant version 2.11.7
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  = Earlier versions =
238
  Please refer to the separate changelog.txt file.
239
 
240
  == Upgrade Notice ==
241
 
242
+ = 4.2.0 =
243
+ * ExactDN verification rewritten, please report any issues immediately.
244
+ * PHP 5.3 support discontinued, see https://docs.ewww.io/article/55-upgrading-php
245
+
246
  = 4.1.0 =
247
  * Security update: gifsicle and optipng have been updated to resolve security flaws.
248
  * ExactDN now processes JS/CSS/Fonts for even more speed.
254
  * API functions have been rewritten to use core WP detection for https capability, please report any errors right away.
255
  * Several options have been removed from the user interface, see the changelog for details.
256
 
 
 
 
 
 
 
257
  == Contact and Credits ==
258
 
259
  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 class based upon the Photon module from Jetpack.
unique.php CHANGED
@@ -162,8 +162,12 @@ function ewww_image_optimizer_install_paths() {
162
  $webp_dst = $tool_path . 'cwebp';
163
  }
164
  if ( PHP_OS == 'FreeBSD' ) {
165
- $arch_type = php_uname( 'm' );
166
- ewwwio_debug_message( "CPU architecture: $arch_type" );
 
 
 
 
167
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-fbsd';
168
  $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-fbsd';
169
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-fbsd';
@@ -176,8 +180,12 @@ function ewww_image_optimizer_install_paths() {
176
  $webp_dst = $tool_path . 'cwebp';
177
  }
178
  if ( PHP_OS == 'Linux' ) {
179
- $arch_type = php_uname( 'm' );
180
- ewwwio_debug_message( "CPU architecture: $arch_type" );
 
 
 
 
181
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-linux';
182
  $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-linux';
183
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-linux';
@@ -447,11 +455,6 @@ function ewww_image_optimizer_define_noexec() {
447
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
448
  ewwwio_debug_message( 'exec seems to be disabled' );
449
  ewww_image_optimizer_disable_tools();
450
- // Otherwise, query the php settings for safe mode.
451
- } elseif ( ewww_image_optimizer_safemode_check() ) {
452
- define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
453
- ewwwio_debug_message( 'safe mode appears to be enabled' );
454
- ewww_image_optimizer_disable_tools();
455
  } else {
456
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', false );
457
  }
@@ -477,18 +480,6 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
477
  ewwwio_debug_message( 'exec seems to be disabled' );
478
  ewww_image_optimizer_disable_tools();
479
  return;
480
- // Otherwise, query the php settings for safe mode.
481
- } elseif ( ewww_image_optimizer_safemode_check() ) {
482
- if ( 'quiet' !== $quiet ) {
483
- // Display a warning to the user.
484
- echo "<div id='ewww-image-optimizer-warning-safemode' class='error'><p>" . esc_html__( 'Safe Mode is turned on for PHP. This plugin cannot operate in Safe Mode unless you have an API key.', 'ewww-image-optimizer' ) . '</p></div>';
485
- }
486
- if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
487
- define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
488
- }
489
- ewwwio_debug_message( 'safe mode appears to be enabled' );
490
- ewww_image_optimizer_disable_tools();
491
- return;
492
  } else {
493
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
494
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', false );
@@ -603,26 +594,6 @@ function ewww_image_optimizer_exec_check() {
603
  return false;
604
  }
605
 
606
- /**
607
- * Checks if safe mode is on.
608
- *
609
- * @return bool True if safe mode is enabled.
610
- */
611
- function ewww_image_optimizer_safemode_check() {
612
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
613
- $safe_mode = ini_get( 'safe_mode' );
614
- ewwwio_debug_message( "safe_mode = $safe_mode" );
615
- switch ( strtolower( $safe_mode ) ) {
616
- case 'off':
617
- return false;
618
- case 'on':
619
- case true:
620
- return true;
621
- default:
622
- return false;
623
- }
624
- }
625
-
626
  /**
627
  * Sends each tool to the binary checker appropriate for the operating system.
628
  *
@@ -1099,64 +1070,6 @@ function ewww_image_optimizer_mimetype( $path, $case ) {
1099
  }
1100
  }
1101
  return false;
1102
- if ( function_exists( 'finfo_file' ) && defined( 'FILEINFO_MIME' ) ) {
1103
- // Create a finfo resource.
1104
- $finfo = finfo_open( FILEINFO_MIME );
1105
- // Retrieve the mimetype.
1106
- $type = explode( ';', finfo_file( $finfo, $path ) );
1107
- $type = $type[0];
1108
- finfo_close( $finfo );
1109
- ewwwio_debug_message( "finfo_file: $type" );
1110
- }
1111
- // See if we can use the getimagesize function.
1112
- if ( empty( $type ) && function_exists( 'getimagesize' ) && 'i' === $case && strpos( ewww_image_optimizer_quick_mimetype( $path ), 'pdf' ) === false ) {
1113
- // Run getimagesize on the file.
1114
- $type = getimagesize( $path );
1115
- // Make sure we have results.
1116
- if ( false !== $type ) {
1117
- // Store the mime-type.
1118
- $type = $type['mime'];
1119
- }
1120
- ewwwio_debug_message( "getimagesize: $type" );
1121
- }
1122
- // See if we can use mime_content_type.
1123
- if ( empty( $type ) && function_exists( 'mime_content_type' ) ) {
1124
- // Retrieve and store the mime-type.
1125
- $type = mime_content_type( $path );
1126
- ewwwio_debug_message( "mime_content_type: $type" );
1127
- }
1128
- // If nothing else has worked, try the 'file' command.
1129
- if ( ( empty( $type ) || 'application/x-executable' != $type ) && 'b' === $case ) {
1130
- // Find the 'file' command.
1131
- $file = ewww_image_optimizer_find_nix_binary( 'file', 'f' );
1132
- if ( $file ) {
1133
- // Run 'file' on the file in question.
1134
- exec( "$file $path", $filetype );
1135
- ewwwio_debug_message( "file command: {$filetype[0]}" );
1136
- // If we've found a proper binary.
1137
- if ( ( strpos( $filetype[0], 'ELF' ) && strpos( $filetype[0], 'executable' ) )
1138
- || false !== strpos( $filetype[0], 'Mach-O universal binary' )
1139
- || false !== strpos( $filetype[0], 'Mach-O fat file with' )
1140
- || false !== strpos( $filetype[0], 'Mach-O 64-bit x86_64 executable' )
1141
- ) {
1142
- $type = 'application/x-executable';
1143
- }
1144
- }
1145
- }
1146
- // If we are dealing with a binary, and found an executable.
1147
- if ( 'b' === $case && preg_match( '/executable|octet-stream|dosexec|x-mach-binary/', $type ) ) {
1148
- ewwwio_memory( __FUNCTION__ );
1149
- return $type;
1150
- // Otherwise, if we are dealing with an image.
1151
- } elseif ( 'i' === $case ) {
1152
- ewwwio_memory( __FUNCTION__ );
1153
- return $type;
1154
- // If all else fails, bail.
1155
- } else {
1156
- ewwwio_debug_message( 'no mime functions or not a binary' );
1157
- ewwwio_memory( __FUNCTION__ );
1158
- return false;
1159
- }
1160
  }
1161
 
1162
  /**
@@ -1184,8 +1097,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1184
  switch ( $tool ) {
1185
  case 'j': // jpegtran.
1186
  exec( $path . ' -v ' . EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'sample.jpg 2>&1', $jpegtran_version );
1187
- if ( ! empty( $jpegtran_version ) ) {
1188
  ewwwio_debug_message( "$path: {$jpegtran_version[0]}" );
 
 
 
1189
  }
1190
  foreach ( $jpegtran_version as $jout ) {
1191
  if ( preg_match( '/Independent JPEG Group/', $jout ) ) {
@@ -1210,8 +1126,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1210
  break;
1211
  case 'o': // optipng.
1212
  exec( $path . ' -v 2>&1', $optipng_version );
1213
- if ( ! empty( $optipng_version ) ) {
1214
  ewwwio_debug_message( "$path: {$optipng_version[0]}" );
 
 
 
1215
  }
1216
  if ( ! empty( $optipng_version ) && strpos( $optipng_version[0], 'OptiPNG' ) === 0 ) {
1217
  ewwwio_debug_message( 'optimizer found' );
@@ -1234,8 +1153,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1234
  break;
1235
  case 'g': // gifsicle.
1236
  exec( $path . ' --version 2>&1', $gifsicle_version );
1237
- if ( ! empty( $gifsicle_version ) ) {
1238
  ewwwio_debug_message( "$path: {$gifsicle_version[0]}" );
 
 
 
1239
  }
1240
  if ( ! empty( $gifsicle_version ) && strpos( $gifsicle_version[0], 'LCDF Gifsicle' ) === 0 ) {
1241
  ewwwio_debug_message( 'optimizer found' );
@@ -1258,8 +1180,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1258
  break;
1259
  case 'p': // pngout.
1260
  exec( "$path 2>&1", $pngout_version );
1261
- if ( ! empty( $pngout_version ) ) {
1262
  ewwwio_debug_message( "$path: {$pngout_version[0]}" );
 
 
 
1263
  }
1264
  if ( ! empty( $pngout_version ) && strpos( $pngout_version[0], 'PNGOUT' ) === 0 ) {
1265
  ewwwio_debug_message( 'optimizer found' );
@@ -1282,8 +1207,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1282
  break;
1283
  case 'q': // pngquant.
1284
  exec( $path . ' -V 2>&1', $pngquant_version );
1285
- if ( ! empty( $pngquant_version ) ) {
1286
  ewwwio_debug_message( "$path: {$pngquant_version[0]}" );
 
 
 
1287
  }
1288
  if ( ! empty( $pngquant_version ) && substr( $pngquant_version[0], 0, 3 ) >= 2.0 ) {
1289
  ewwwio_debug_message( 'optimizer found' );
@@ -1306,8 +1234,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1306
  break;
1307
  case 'i': // ImageMagick.
1308
  exec( "$path -version 2>&1", $convert_version );
1309
- if ( ! empty( $convert_version ) ) {
1310
  ewwwio_debug_message( "$path: {$convert_version[0]}" );
 
 
 
1311
  }
1312
  if ( ! empty( $convert_version ) && strpos( $convert_version[0], 'ImageMagick' ) ) {
1313
  ewwwio_debug_message( 'imagemagick found' );
@@ -1316,8 +1247,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1316
  break;
1317
  case 'f': // file.
1318
  exec( "$path -v 2>&1", $file_version );
1319
- if ( ! empty( $file_version[1] ) ) {
1320
  ewwwio_debug_message( "$path: {$file_version[1]}" );
 
 
 
1321
  }
1322
  if ( ! empty( $file_version[1] ) && preg_match( '/magic/', $file_version[1] ) ) {
1323
  ewwwio_debug_message( 'file binary found' );
@@ -1329,8 +1263,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1329
  break;
1330
  case 'n': // nice.
1331
  exec( "$path 2>&1", $nice_output );
1332
- if ( is_array( $nice_output ) && isset( $nice_output[0] ) ) {
1333
  ewwwio_debug_message( "$path: {$nice_output[0]}" );
 
 
 
1334
  }
1335
  if ( is_array( $nice_output ) && isset( $nice_output[0] ) && preg_match( '/usage/', $nice_output[0] ) ) {
1336
  ewwwio_debug_message( 'nice found' );
@@ -1342,8 +1279,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1342
  break;
1343
  case 't': // tar.
1344
  exec( "$path --version 2>&1", $tar_version );
1345
- if ( ! empty( $tar_version[0] ) ) {
1346
  ewwwio_debug_message( "$path: {$tar_version[0]}" );
 
 
 
1347
  }
1348
  if ( ! empty( $tar_version[0] ) && preg_match( '/bsdtar/', $tar_version[0] ) ) {
1349
  ewwwio_debug_message( 'tar found' );
@@ -1355,8 +1295,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1355
  break;
1356
  case 'w': // cwebp.
1357
  exec( "$path -version 2>&1", $webp_version );
1358
- if ( ! empty( $webp_version ) ) {
1359
  ewwwio_debug_message( "$path: {$webp_version[0]}" );
 
 
 
1360
  }
1361
  if ( ! empty( $webp_version ) && preg_match( '/0.\d.\d/', $webp_version[0] ) ) {
1362
  ewwwio_debug_message( 'optimizer found' );
@@ -2648,7 +2591,10 @@ function ewww_image_optimizer_install_pngout() {
2648
  if ( is_wp_error( $download_result ) ) {
2649
  $pngout_error = $download_result->get_error_message();
2650
  } else {
2651
- $arch_type = php_uname( 'm' );
 
 
 
2652
  exec( "$tar xzf $download_result -C " . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . ' pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' );
2653
  if ( file_exists( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2654
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
@@ -2673,7 +2619,7 @@ function ewww_image_optimizer_install_pngout() {
2673
  $pngout_error = $download_result->get_error_message();
2674
  } else {
2675
  exec( "$tar xzf $download_result -C " . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . ' pngout-' . $latest . '-darwin/pngout' );
2676
- if ( file_exists( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2677
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout', $tool_path . 'pngout-static' ) ) {
2678
  if ( empty( $pngout_error ) ) {
2679
  $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
162
  $webp_dst = $tool_path . 'cwebp';
163
  }
164
  if ( PHP_OS == 'FreeBSD' ) {
165
+ if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
166
+ $arch_type = php_uname( 'm' );
167
+ ewwwio_debug_message( "CPU architecture: $arch_type" );
168
+ } else {
169
+ ewwwio_debug_message( 'CPU architecture unknown, php_uname disabled' );
170
+ }
171
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-fbsd';
172
  $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-fbsd';
173
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-fbsd';
180
  $webp_dst = $tool_path . 'cwebp';
181
  }
182
  if ( PHP_OS == 'Linux' ) {
183
+ if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
184
+ $arch_type = php_uname( 'm' );
185
+ ewwwio_debug_message( "CPU architecture: $arch_type" );
186
+ } else {
187
+ ewwwio_debug_message( 'CPU architecture unknown, php_uname disabled' );
188
+ }
189
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-linux';
190
  $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-linux';
191
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-linux';
455
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
456
  ewwwio_debug_message( 'exec seems to be disabled' );
457
  ewww_image_optimizer_disable_tools();
 
 
 
 
 
458
  } else {
459
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', false );
460
  }
480
  ewwwio_debug_message( 'exec seems to be disabled' );
481
  ewww_image_optimizer_disable_tools();
482
  return;
 
 
 
 
 
 
 
 
 
 
 
 
483
  } else {
484
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
485
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', false );
594
  return false;
595
  }
596
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  /**
598
  * Sends each tool to the binary checker appropriate for the operating system.
599
  *
1070
  }
1071
  }
1072
  return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1073
  }
1074
 
1075
  /**
1097
  switch ( $tool ) {
1098
  case 'j': // jpegtran.
1099
  exec( $path . ' -v ' . EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'sample.jpg 2>&1', $jpegtran_version );
1100
+ if ( ewww_image_optimizer_iterable( $jpegtran_version ) ) {
1101
  ewwwio_debug_message( "$path: {$jpegtran_version[0]}" );
1102
+ } else {
1103
+ ewwwio_debug_message( "$path: invalid output" );
1104
+ break;
1105
  }
1106
  foreach ( $jpegtran_version as $jout ) {
1107
  if ( preg_match( '/Independent JPEG Group/', $jout ) ) {
1126
  break;
1127
  case 'o': // optipng.
1128
  exec( $path . ' -v 2>&1', $optipng_version );
1129
+ if ( ewww_image_optimizer_iterable( $optipng_version ) ) {
1130
  ewwwio_debug_message( "$path: {$optipng_version[0]}" );
1131
+ } else {
1132
+ ewwwio_debug_message( "$path: invalid output" );
1133
+ break;
1134
  }
1135
  if ( ! empty( $optipng_version ) && strpos( $optipng_version[0], 'OptiPNG' ) === 0 ) {
1136
  ewwwio_debug_message( 'optimizer found' );
1153
  break;
1154
  case 'g': // gifsicle.
1155
  exec( $path . ' --version 2>&1', $gifsicle_version );
1156
+ if ( ewww_image_optimizer_iterable( $gifsicle_version ) ) {
1157
  ewwwio_debug_message( "$path: {$gifsicle_version[0]}" );
1158
+ } else {
1159
+ ewwwio_debug_message( "$path: invalid output" );
1160
+ break;
1161
  }
1162
  if ( ! empty( $gifsicle_version ) && strpos( $gifsicle_version[0], 'LCDF Gifsicle' ) === 0 ) {
1163
  ewwwio_debug_message( 'optimizer found' );
1180
  break;
1181
  case 'p': // pngout.
1182
  exec( "$path 2>&1", $pngout_version );
1183
+ if ( ewww_image_optimizer_iterable( $pngout_version ) ) {
1184
  ewwwio_debug_message( "$path: {$pngout_version[0]}" );
1185
+ } else {
1186
+ ewwwio_debug_message( "$path: invalid output" );
1187
+ break;
1188
  }
1189
  if ( ! empty( $pngout_version ) && strpos( $pngout_version[0], 'PNGOUT' ) === 0 ) {
1190
  ewwwio_debug_message( 'optimizer found' );
1207
  break;
1208
  case 'q': // pngquant.
1209
  exec( $path . ' -V 2>&1', $pngquant_version );
1210
+ if ( ewww_image_optimizer_iterable( $pngquant_version ) ) {
1211
  ewwwio_debug_message( "$path: {$pngquant_version[0]}" );
1212
+ } else {
1213
+ ewwwio_debug_message( "$path: invalid output" );
1214
+ break;
1215
  }
1216
  if ( ! empty( $pngquant_version ) && substr( $pngquant_version[0], 0, 3 ) >= 2.0 ) {
1217
  ewwwio_debug_message( 'optimizer found' );
1234
  break;
1235
  case 'i': // ImageMagick.
1236
  exec( "$path -version 2>&1", $convert_version );
1237
+ if ( ewww_image_optimizer_iterable( $convert_version ) ) {
1238
  ewwwio_debug_message( "$path: {$convert_version[0]}" );
1239
+ } else {
1240
+ ewwwio_debug_message( "$path: invalid output" );
1241
+ break;
1242
  }
1243
  if ( ! empty( $convert_version ) && strpos( $convert_version[0], 'ImageMagick' ) ) {
1244
  ewwwio_debug_message( 'imagemagick found' );
1247
  break;
1248
  case 'f': // file.
1249
  exec( "$path -v 2>&1", $file_version );
1250
+ if ( ewww_image_optimizer_iterable( $file_version ) ) {
1251
  ewwwio_debug_message( "$path: {$file_version[1]}" );
1252
+ } else {
1253
+ ewwwio_debug_message( "$path: invalid output" );
1254
+ break;
1255
  }
1256
  if ( ! empty( $file_version[1] ) && preg_match( '/magic/', $file_version[1] ) ) {
1257
  ewwwio_debug_message( 'file binary found' );
1263
  break;
1264
  case 'n': // nice.
1265
  exec( "$path 2>&1", $nice_output );
1266
+ if ( ewww_image_optimizer_iterable( $nice_output ) && isset( $nice_output[0] ) ) {
1267
  ewwwio_debug_message( "$path: {$nice_output[0]}" );
1268
+ } else {
1269
+ ewwwio_debug_message( "$path: invalid output" );
1270
+ break;
1271
  }
1272
  if ( is_array( $nice_output ) && isset( $nice_output[0] ) && preg_match( '/usage/', $nice_output[0] ) ) {
1273
  ewwwio_debug_message( 'nice found' );
1279
  break;
1280
  case 't': // tar.
1281
  exec( "$path --version 2>&1", $tar_version );
1282
+ if ( ewww_image_optimizer_iterable( $tar_version ) ) {
1283
  ewwwio_debug_message( "$path: {$tar_version[0]}" );
1284
+ } else {
1285
+ ewwwio_debug_message( "$path: invalid output" );
1286
+ break;
1287
  }
1288
  if ( ! empty( $tar_version[0] ) && preg_match( '/bsdtar/', $tar_version[0] ) ) {
1289
  ewwwio_debug_message( 'tar found' );
1295
  break;
1296
  case 'w': // cwebp.
1297
  exec( "$path -version 2>&1", $webp_version );
1298
+ if ( ewww_image_optimizer_iterable( $webp_version ) ) {
1299
  ewwwio_debug_message( "$path: {$webp_version[0]}" );
1300
+ } else {
1301
+ ewwwio_debug_message( "$path: invalid output" );
1302
+ break;
1303
  }
1304
  if ( ! empty( $webp_version ) && preg_match( '/0.\d.\d/', $webp_version[0] ) ) {
1305
  ewwwio_debug_message( 'optimizer found' );
2591
  if ( is_wp_error( $download_result ) ) {
2592
  $pngout_error = $download_result->get_error_message();
2593
  } else {
2594
+ $arch_type = 'i686';
2595
+ if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
2596
+ $arch_type = php_uname( 'm' );
2597
+ }
2598
  exec( "$tar xzf $download_result -C " . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . ' pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' );
2599
  if ( file_exists( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2600
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
2619
  $pngout_error = $download_result->get_error_message();
2620
  } else {
2621
  exec( "$tar xzf $download_result -C " . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . ' pngout-' . $latest . '-darwin/pngout' );
2622
+ if ( file_exists( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout' ) ) {
2623
  if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout', $tool_path . 'pngout-static' ) ) {
2624
  if ( empty( $pngout_error ) ) {
2625
  $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );