EWWW Image Optimizer - Version 4.1.3

Version Description

  • fixed: infinite loop when removing invalid API key
  • fixed: img elements with incorrect attachment ID being replaced with wrong image src
  • fixed: ExactDN CSS and JS parsing incompatible with Autoptimize
Download this release

Release Info

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

Code changes from version 4.0.6 to 4.1.3

aux-optimize.php CHANGED
@@ -703,7 +703,7 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
703
  ewwwio_memory( __FUNCTION__ );
704
  /* translators: %d: number of images */
705
  $ready_msg = sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $image_count, 'ewww-image-optimizer' ) ), $image_count )
706
- . ' <a href="http://docs.ewww.io/article/20-why-do-i-have-so-many-images-on-my-site" target="_blank" data-beacon-article="58598744c697912ffd6c3eb4">' . esc_html__( 'Why are there so many images?', 'ewww-image-optimizer' ) . '</a>';
707
  ewwwio_ob_clean();
708
  die( json_encode( array(
709
  'ready' => $image_count,
703
  ewwwio_memory( __FUNCTION__ );
704
  /* translators: %d: number of images */
705
  $ready_msg = sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $image_count, 'ewww-image-optimizer' ) ), $image_count )
706
+ . ' <a href="https://docs.ewww.io/article/20-why-do-i-have-so-many-images-on-my-site" target="_blank" data-beacon-article="58598744c697912ffd6c3eb4">' . esc_html__( 'Why are there so many images?', 'ewww-image-optimizer' ) . '</a>';
707
  ewwwio_ob_clean();
708
  die( json_encode( array(
709
  'ready' => $image_count,
binaries/gifsicle-fbsd CHANGED
Binary file
binaries/gifsicle-linux CHANGED
Binary file
binaries/gifsicle-mac CHANGED
Binary file
binaries/gifsicle-sol CHANGED
Binary file
binaries/gifsicle.exe CHANGED
Binary file
binaries/optipng-fbsd CHANGED
Binary file
binaries/optipng-linux CHANGED
Binary file
binaries/optipng-mac CHANGED
Binary file
binaries/optipng-sol CHANGED
Binary file
binaries/optipng.exe CHANGED
Binary file
binaries/pngquant-fbsd CHANGED
Binary file
binaries/pngquant-linux CHANGED
Binary file
binaries/pngquant-mac CHANGED
Binary file
binaries/pngquant-sol CHANGED
Binary file
binaries/pngquant.exe CHANGED
Binary file
bulk.php CHANGED
@@ -473,7 +473,7 @@ function ewww_image_optimizer_bulk_script( $hook ) {
473
  'time_remaining' => esc_html__( 'remaining', 'ewww-image-optimizer' ),
474
  'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
475
  'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
476
- 'bulk_fail_more' => '<a href="http://docs.ewww.io/article/39-bulk-optimizer-failure" target="_blank" data-beacon-article="596f84f72c7d3a73488b3ca7">' . esc_html__( 'more...', 'ewww-image-optimizer' ) . '</a>',
477
  ) );
478
  // Load the stylesheet for the jquery progressbar.
479
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
@@ -967,7 +967,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
967
  foreach ( $attachment_images as $size => $file_path ) {
968
  ewwwio_debug_message( "here is a path $file_path" );
969
  ewww_image_optimizer_debug_log();
970
- if ( ! $remote_file && strpos( $file_path, 's3' ) !== 0 && ! defined( 'EWWW_IMAGE_OPTIMIZER_RELATIVE_FOLDER' ) ) {
971
  $file_path = realpath( $file_path );
972
  }
973
  if ( empty( $file_path ) ) {
473
  'time_remaining' => esc_html__( 'remaining', 'ewww-image-optimizer' ),
474
  'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
475
  'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
476
+ 'bulk_fail_more' => '<a href="https://docs.ewww.io/article/39-bulk-optimizer-failure" target="_blank" data-beacon-article="596f84f72c7d3a73488b3ca7">' . esc_html__( 'more...', 'ewww-image-optimizer' ) . '</a>',
477
  ) );
478
  // Load the stylesheet for the jquery progressbar.
479
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
967
  foreach ( $attachment_images as $size => $file_path ) {
968
  ewwwio_debug_message( "here is a path $file_path" );
969
  ewww_image_optimizer_debug_log();
970
+ if ( ! $remote_file && strpos( $file_path, 's3' ) !== 0 && ! defined( 'EWWW_IMAGE_OPTIMIZER_RELATIVE' ) ) {
971
  $file_path = realpath( $file_path );
972
  }
973
  if ( empty( $file_path ) ) {
changelog.txt CHANGED
@@ -1,3 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.0.6 =
2
  * changed: dummy images have no args appended with exactdn except for ssl flag
3
  * fixed: resize_detection.js being combined with other scripts by Autoptimize
@@ -7,8 +46,8 @@
7
  * fixed: compatibility with Regenerate Thumbnails version 3
8
 
9
  = 4.0.5 =
10
- * added: enable lossy compression with ExactDN: http://docs.ewww.io/article/47-getting-more-from-exactdn
11
- * added: CSS/JS minification with ExactDN, see http://docs.ewww.io/article/47-getting-more-from-exactdn
12
  * added: disable WebP for specific files with ewww_image_optimizer_bypass_webp filter
13
  * added: ExactDN obeys focus point from Theia Smart Thumbnails plugin
14
  * added: admin-ajax requests for eddvbugm loader work with ExactDN
@@ -66,7 +105,7 @@
66
 
67
  = 3.6.0 =
68
  In an effort to simplify the settings page and make room for new features, many settings have been "hidden" and/or rearranged. It is my hope that this will make it easier for new users to get going with EWWW IO.
69
- You can find more information about overriding options in the [Documentation](http://docs.ewww.io)
70
  * added: ability to override any boolean/integer options by defining constant of the same name
71
  * added: debug information included automatically with help beacon requests when debugging is enabled
72
  * added: use wp_raise_memory_limit (WP 4.6+) to avoid memory issues
@@ -94,7 +133,7 @@ You can find more information about overriding options in the [Documentation](ht
94
  * added: optional help beacons on bulk and settings pages
95
  * added: disable deferring of WP Offload S3 uploads with EWWW_IMAGE_OPTIMIZER_NO_DEFER_S3
96
  * added: override use of wp_add_inline_script with non-standard jQuery by defining EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK
97
- * fixed: javascript for bulk optimizers in NextGEN, NextCellent and FlaGallery
98
 
99
  = 3.5.0 =
100
  * added: compatibility with S3 Uploads by Human Made
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
4
+ * fixed: ExactDN CSS and JS parsing incompatible with Autoptimize
5
+
6
+ = 4.1.2 =
7
+ * added: detect WP Fastest Cache WebP rewrite rules
8
+ * added: notice if WebP conversion enabled but mod_rewrite or mod_headers is missing
9
+ * added: better debugging when background/async mode is blocked
10
+ * changed: CSS/JS files are filtered pre-emptively by ExactDN to avoid quirks with emoji scripts
11
+ * fixed: warning during wp_cron for undefined constant
12
+ * fixed: invalid or expired keys would still attempt optimization
13
+ * fixed: WebP files are orphaned when using Media File Renamer
14
+ * deprecated: PHP 5.3 will no longer be supported in 4.2
15
+ * deprecated: PHP 5.4 support will be removed by July 2018
16
+ * deprecated: PHP 5.5 support will be removed by October 2018
17
+
18
+ = 4.1.1 =
19
+ * added: reduce ExactDN load time by suppressing db queries with EXACTDN_PREVENT_DB_QUERIES
20
+ * added: $fullsize indicator added to pre/post optimization hooks, props Schweinepriester
21
+ * fixed: missing www preventing rewrites for ExactDN
22
+ * fixed: Alt WebP compatibility with Tatsu page builder
23
+ * fixed: relative path support not working properly for Pantheon users
24
+ * fixed: missing directories prevent optimization of S3 files
25
+
26
+ = 4.1.0 =
27
+ * SECURITY: gifsicle and optipng have been updated to address security flaws
28
+ * added: full compatibility with Image Watermark plugin
29
+ * added: dummy images for Essential Grid and Layer Slider whitelisted with ExactDN
30
+ * added: compatibility with Visual Composer and Essential Grid async/AJAX loaders
31
+ * added: compatibility with Media File Renamer
32
+ * changed: ExactDN rewrites all wp-content and wp-includes urls by default
33
+ * changed: mime-type detection function does not rely on fileinfo extension anymore
34
+ * changed: Solaris/SunOS binary builds use OpenIndiana 2017.10, let me know if they break
35
+ * fixed: wp-emoji script not rewritten by EXACTDN_ALL_THE_THINGS
36
+ * fixed: resize detection script throws error when admin bar is hidden
37
+ * fixed: warnings when WP Offload S3 set to delete local files, props ianmjones
38
+ * updated: pngquant version 2.11.7
39
+
40
  = 4.0.6 =
41
  * changed: dummy images have no args appended with exactdn except for ssl flag
42
  * fixed: resize_detection.js being combined with other scripts by Autoptimize
46
  * fixed: compatibility with Regenerate Thumbnails version 3
47
 
48
  = 4.0.5 =
49
+ * added: enable lossy compression with ExactDN: https://docs.ewww.io/article/47-getting-more-from-exactdn
50
+ * added: CSS/JS minification with ExactDN, see https://docs.ewww.io/article/47-getting-more-from-exactdn
51
  * added: disable WebP for specific files with ewww_image_optimizer_bypass_webp filter
52
  * added: ExactDN obeys focus point from Theia Smart Thumbnails plugin
53
  * added: admin-ajax requests for eddvbugm loader work with ExactDN
105
 
106
  = 3.6.0 =
107
  In an effort to simplify the settings page and make room for new features, many settings have been "hidden" and/or rearranged. It is my hope that this will make it easier for new users to get going with EWWW IO.
108
+ You can find more information about overriding options in the [Documentation](https://docs.ewww.io)
109
  * added: ability to override any boolean/integer options by defining constant of the same name
110
  * added: debug information included automatically with help beacon requests when debugging is enabled
111
  * added: use wp_raise_memory_limit (WP 4.6+) to avoid memory issues
133
  * added: optional help beacons on bulk and settings pages
134
  * added: disable deferring of WP Offload S3 uploads with EWWW_IMAGE_OPTIMIZER_NO_DEFER_S3
135
  * added: override use of wp_add_inline_script with non-standard jQuery by defining EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK
136
+ * fixed: javascript for bulk optimizers in NextGEN, NextCellent and FlaGallery
137
 
138
  = 3.5.0 =
139
  * added: compatibility with S3 Uploads by Human Made
classes/class-ewww-image.php CHANGED
@@ -929,8 +929,11 @@ class EWWW_Image {
929
  $type = ewww_image_optimizer_quick_mimetype( $this->file );
930
  $image_size = ( empty( $this->opt_size ) ? $this->orig_size : $this->opt_size );
931
  if ( empty( $image_size ) ) {
932
- $this->orig_size = filesize( $this->file );
933
  $image_size = $this->orig_size;
 
 
 
934
  }
935
  switch ( $type ) {
936
  case 'image/jpeg':
929
  $type = ewww_image_optimizer_quick_mimetype( $this->file );
930
  $image_size = ( empty( $this->opt_size ) ? $this->orig_size : $this->opt_size );
931
  if ( empty( $image_size ) ) {
932
+ $this->orig_size = ewww_image_optimizer_filesize( $this->file );
933
  $image_size = $this->orig_size;
934
+ if ( ! $image_size ) {
935
+ return 5;
936
+ }
937
  }
938
  switch ( $type ) {
939
  case 'image/jpeg':
classes/class-ewwwio-background-process.php CHANGED
@@ -459,7 +459,7 @@ if ( ! class_exists( 'EWWWIO_Background_Process' ) ) {
459
  $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
460
 
461
  if ( property_exists( $this, 'cron_interval' ) ) {
462
- $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval_identifier );
463
  }
464
 
465
  // Adds every 5 minutes to the existing schedules.
459
  $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
460
 
461
  if ( property_exists( $this, 'cron_interval' ) ) {
462
+ $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
463
  }
464
 
465
  // Adds every 5 minutes to the existing schedules.
classes/class-ewwwio-tracking.php CHANGED
@@ -328,6 +328,7 @@ class EWWWIO_Tracking {
328
  return;
329
  }
330
  if (
 
331
  stristr( network_site_url( '/' ), 'dev' ) !== false ||
332
  stristr( network_site_url( '/' ), 'localhost' ) !== false ||
333
  stristr( network_site_url( '/' ), ':8888' ) !== false // This is common with MAMP on OS X.
@@ -340,7 +341,7 @@ class EWWWIO_Tracking {
340
  echo '<div class="updated"><p>';
341
  /* translators: %s: admin email as configured in settings */
342
  printf( esc_html__( 'Allow EWWW Image Optimizer to track plugin usage? Opt-in to tracking and receive 500 free image credits in your admin email: %s. No sensitive data is tracked.', 'ewww-image-optimizer' ), $admin_email );
343
- echo '&nbsp;<a href="http://docs.ewww.io/article/23-usage-tracking" target="_blank" data-beacon-article="591f3a8e2c7d3a057f893d91">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a>';
344
  echo '<a href="' . esc_url( $optin_url ) . '" class="button-secondary" style="margin-left:5px;">' . esc_html__( 'Allow', 'ewww-image-optimizer' ) . '</a>';
345
  echo '<a href="' . esc_url( $optout_url ) . '" class="button-secondary" style="margin-left:5px">' . esc_html__( 'Do not allow', 'ewww-image-optimizer' ) . '</a>';
346
  echo '</p></div>';
328
  return;
329
  }
330
  if (
331
+ stristr( network_site_url( '/' ), '.local' ) !== false ||
332
  stristr( network_site_url( '/' ), 'dev' ) !== false ||
333
  stristr( network_site_url( '/' ), 'localhost' ) !== false ||
334
  stristr( network_site_url( '/' ), ':8888' ) !== false // This is common with MAMP on OS X.
341
  echo '<div class="updated"><p>';
342
  /* translators: %s: admin email as configured in settings */
343
  printf( esc_html__( 'Allow EWWW Image Optimizer to track plugin usage? Opt-in to tracking and receive 500 free image credits in your admin email: %s. No sensitive data is tracked.', 'ewww-image-optimizer' ), $admin_email );
344
+ echo '&nbsp;<a href="https://docs.ewww.io/article/23-usage-tracking" target="_blank" data-beacon-article="591f3a8e2c7d3a057f893d91">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a>';
345
  echo '<a href="' . esc_url( $optin_url ) . '" class="button-secondary" style="margin-left:5px;">' . esc_html__( 'Allow', 'ewww-image-optimizer' ) . '</a>';
346
  echo '<a href="' . esc_url( $optout_url ) . '" class="button-secondary" style="margin-left:5px">' . esc_html__( 'Do not allow', 'ewww-image-optimizer' ) . '</a>';
347
  echo '</p></div>';
classes/class-exactdn.php CHANGED
@@ -69,6 +69,14 @@ class ExactDN {
69
  */
70
  private $exactdn_domain = false;
71
 
 
 
 
 
 
 
 
 
72
  /**
73
  * Allow us to track how much overhead ExactDN introduces.
74
  *
@@ -92,6 +100,15 @@ class ExactDN {
92
  return;
93
  }
94
 
 
 
 
 
 
 
 
 
 
95
  // Images in post content and galleries.
96
  add_filter( 'the_content', array( $this, 'filter_the_content' ), 999999 );
97
  // Start an output buffer before any output starts.
@@ -121,11 +138,30 @@ class ExactDN {
121
  add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ), 9 );
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
 
124
  // Find the "local" domain.
125
  $upload_dir = wp_upload_dir( null, false );
126
  $this->upload_domain = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $this->parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
127
  ewwwio_debug_message( "allowing images from here: $this->upload_domain" );
128
  $this->allowed_domains[] = $this->upload_domain;
 
 
 
 
 
 
 
 
129
  }
130
 
131
  /**
@@ -515,7 +551,11 @@ class ExactDN {
515
  if ( preg_match( '#width=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $width_string ) ) {
516
  $width = $width_string[1];
517
  }
518
-
 
 
 
 
519
  if ( preg_match( '#height=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $height_string ) ) {
520
  $height = $height_string[1];
521
  }
@@ -543,10 +583,12 @@ class ExactDN {
543
  list( $filename_width, $filename_height ) = $this->parse_dimensions_from_filename( $src );
544
  // WP Attachment ID, if uploaded to this site.
545
  preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id );
546
- if ( empty( $attachment_id ) ) {
 
547
  $attachment_id = array( attachment_url_to_postid( $src ) );
548
  }
549
- if ( ! empty( $attachment_id ) ) {
 
550
  $attachment_id = intval( array_pop( $attachment_id ) );
551
 
552
  if ( $attachment_id ) {
@@ -557,7 +599,24 @@ class ExactDN {
557
  if ( is_object( $attachment ) && ! is_wp_error( $attachment ) && 'attachment' == $attachment->post_type ) {
558
  $src_per_wp = wp_get_attachment_image_src( $attachment_id, 'full' );
559
 
560
- if ( $this->validate_image_url( $src_per_wp[0] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  ewwwio_debug_message( "detected $width filenamew $filename_width" );
562
  if ( $resize_existing || ( $width && $filename_width != $width ) ) {
563
  ewwwio_debug_message( 'resizing existing or width does not match' );
@@ -611,7 +670,7 @@ class ExactDN {
611
  }
612
 
613
  // Detect if image source is for a custom-cropped thumbnail and prevent further URL manipulation.
614
- if ( ! $fullsize_url && preg_match_all( '#-e[a-z0-9]+(-\d+x\d+)?\.(' . implode( '|', $this->extensions ) . '){1}$#i', basename( $src ), $filename ) ) {
615
  $fullsize_url = true;
616
  }
617
 
@@ -634,7 +693,10 @@ class ExactDN {
634
  $src = $this->strip_image_dimensions_maybe( $src );
635
  }
636
 
637
- $args = $this->maybe_smart_crop( $args, $attachment_id );
 
 
 
638
 
639
  /**
640
  * Filter the array of ExactDN arguments added to an image.
@@ -744,7 +806,7 @@ class ExactDN {
744
  }
745
  } // End if().
746
  } // End foreach().
747
- if ( $this->filtering_the_page && defined( 'EXACTDN_ALL_THE_THINGS' ) && EXACTDN_ALL_THE_THINGS ) {
748
  ewwwio_debug_message( 'rewriting all other wp_content urls' );
749
  if ( $this->exactdn_domain && $this->upload_domain ) {
750
  $escaped_upload_domain = str_replace( '.', '\.', $this->upload_domain );
@@ -779,6 +841,12 @@ class ExactDN {
779
  if ( ! empty( $_POST['action'] ) && 'eddvbugm_viewport_downloads' == $_POST['action'] ) {
780
  return true;
781
  }
 
 
 
 
 
 
782
  return $allow;
783
  }
784
 
@@ -1348,8 +1416,7 @@ class ExactDN {
1348
  */
1349
  protected function validate_image_url( $url, $exactdn_is_valid = false ) {
1350
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1351
- $parsed_url = parse_url( $url );
1352
- // TODO: add a parameter to allow validation of exactdn urls.
1353
  if ( ! $parsed_url ) {
1354
  ewwwio_debug_message( 'could not parse' );
1355
  return false;
@@ -1536,9 +1603,68 @@ class ExactDN {
1536
  if ( strpos( $image_url, 'lazy_placeholder.gif' ) ) {
1537
  return array();
1538
  }
 
 
 
 
 
 
1539
  return $args;
1540
  }
1541
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1542
  /**
1543
  * Generates an ExactDN URL.
1544
  *
@@ -1552,11 +1678,7 @@ class ExactDN {
1552
  $image_url = trim( $image_url );
1553
 
1554
  if ( is_null( $scheme ) ) {
1555
- $site_url = get_home_url();
1556
- $scheme = 'http';
1557
- if ( strpos( $site_url, 'https://' ) !== false ) {
1558
- $scheme = 'https';
1559
- }
1560
  }
1561
 
1562
  /**
69
  */
70
  private $exactdn_domain = false;
71
 
72
+ /**
73
+ * The detected site scheme (http/https).
74
+ *
75
+ * @access private
76
+ * @var string $scheme
77
+ */
78
+ private $scheme = false;
79
+
80
  /**
81
  * Allow us to track how much overhead ExactDN introduces.
82
  *
100
  return;
101
  }
102
 
103
+ if ( ! $this->scheme ) {
104
+ $site_url = get_home_url();
105
+ $scheme = 'http';
106
+ if ( strpos( $site_url, 'https://' ) !== false ) {
107
+ $scheme = 'https';
108
+ }
109
+ $this->scheme = $scheme;
110
+ }
111
+
112
  // Images in post content and galleries.
113
  add_filter( 'the_content', array( $this, 'filter_the_content' ), 999999 );
114
  // Start an output buffer before any output starts.
138
  add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ), 9 );
139
  }
140
 
141
+ // Get all the script/css urls and rewrite them (if enabled).
142
+ if ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
143
+ add_filter( 'style_loader_src', array( $this, 'parse_enqueue' ) );
144
+ add_filter( 'script_loader_src', array( $this, 'parse_enqueue' ) );
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.
153
  $upload_dir = wp_upload_dir( null, false );
154
  $this->upload_domain = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $this->parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
155
  ewwwio_debug_message( "allowing images from here: $this->upload_domain" );
156
  $this->allowed_domains[] = $this->upload_domain;
157
+ if ( strpos( $this->upload_domain, 'www' ) === false ) {
158
+ $this->allowed_domains[] = 'www.' . $this->upload_domain;
159
+ } else {
160
+ $nonwww = ltrim( 'www.', $this->upload_domain );
161
+ if ( $nonwww !== $this->upload_domain ) {
162
+ $this->allowed_domains[] = $nonwww;
163
+ }
164
+ }
165
  }
166
 
167
  /**
551
  if ( preg_match( '#width=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $width_string ) ) {
552
  $width = $width_string[1];
553
  }
554
+ if ( preg_match( '#max-width:\s?(\d+)px#', $images['img_tag'][ $index ], $max_width_string ) ) {
555
+ if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
556
+ $width = $max_width_string[1];
557
+ }
558
+ }
559
  if ( preg_match( '#height=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $height_string ) ) {
560
  $height = $height_string[1];
561
  }
583
  list( $filename_width, $filename_height ) = $this->parse_dimensions_from_filename( $src );
584
  // WP Attachment ID, if uploaded to this site.
585
  preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id );
586
+ if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && empty( $attachment_id ) ) {
587
+ ewwwio_debug_message( 'looking for attachment id' );
588
  $attachment_id = array( attachment_url_to_postid( $src ) );
589
  }
590
+ if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
591
+ ewwwio_debug_message( 'using attachment id to get source image' );
592
  $attachment_id = intval( array_pop( $attachment_id ) );
593
 
594
  if ( $attachment_id ) {
599
  if ( is_object( $attachment ) && ! is_wp_error( $attachment ) && 'attachment' == $attachment->post_type ) {
600
  $src_per_wp = wp_get_attachment_image_src( $attachment_id, 'full' );
601
 
602
+ if ( $src_per_wp && is_array( $src_per_wp ) ) {
603
+ ewwwio_debug_message( "src retrieved from db: {$src_per_wp[0]}, checking for match" );
604
+ $fullsize_url_path = $this->parse_url( $src_per_wp[0], PHP_URL_PATH );
605
+ if ( is_null( $fullsize_url_path ) ) {
606
+ $src_per_wp = false;
607
+ } elseif ( $fullsize_url_path ) {
608
+ $fullsize_url_basename = pathinfo( $fullsize_url_path, PATHINFO_FILENAME );
609
+ ewwwio_debug_message( "looking for $fullsize_url_basename in $src" );
610
+ if ( strpos( wp_basename( $src ), $fullsize_url_basename ) === false ) {
611
+ ewwwio_debug_message( 'fullsize url does not match' );
612
+ $src_per_wp = false;
613
+ }
614
+ } else {
615
+ $src_per_wp = false;
616
+ }
617
+ }
618
+
619
+ if ( $src_per_wp && $this->validate_image_url( $src_per_wp[0] ) ) {
620
  ewwwio_debug_message( "detected $width filenamew $filename_width" );
621
  if ( $resize_existing || ( $width && $filename_width != $width ) ) {
622
  ewwwio_debug_message( 'resizing existing or width does not match' );
670
  }
671
 
672
  // Detect if image source is for a custom-cropped thumbnail and prevent further URL manipulation.
673
+ if ( ! $fullsize_url && preg_match_all( '#-e[a-z0-9]+(-\d+x\d+)?\.(' . implode( '|', $this->extensions ) . '){1}$#i', wp_basename( $src ), $filename ) ) {
674
  $fullsize_url = true;
675
  }
676
 
693
  $src = $this->strip_image_dimensions_maybe( $src );
694
  }
695
 
696
+ if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
697
+ ewwwio_debug_message( 'using attachment id to check smart crop' );
698
+ $args = $this->maybe_smart_crop( $args, $attachment_id );
699
+ }
700
 
701
  /**
702
  * Filter the array of ExactDN arguments added to an image.
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 );
841
  if ( ! empty( $_POST['action'] ) && 'eddvbugm_viewport_downloads' == $_POST['action'] ) {
842
  return true;
843
  }
844
+ if ( ! empty( $_POST['action'] ) && 'vc_get_vc_grid_data' == $_POST['action'] ) {
845
+ return true;
846
+ }
847
+ if ( ! empty( $_POST['action'] ) && 'Essential_Grid_Front_request_ajax' == $_POST['action'] ) {
848
+ return true;
849
+ }
850
  return $allow;
851
  }
852
 
1416
  */
1417
  protected function validate_image_url( $url, $exactdn_is_valid = false ) {
1418
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1419
+ $parsed_url = $this->parse_url( $url );
 
1420
  if ( ! $parsed_url ) {
1421
  ewwwio_debug_message( 'could not parse' );
1422
  return false;
1603
  if ( strpos( $image_url, 'lazy_placeholder.gif' ) ) {
1604
  return array();
1605
  }
1606
+ if ( strpos( $image_url, 'essential-grid/public/assets/images/' ) ) {
1607
+ return array();
1608
+ }
1609
+ if ( strpos( $image_url, 'LayerSlider/static/img' ) ) {
1610
+ return array();
1611
+ }
1612
  return $args;
1613
  }
1614
 
1615
+ /**
1616
+ * Converts a local script/css url to use ExactDN.
1617
+ *
1618
+ * @param string $url URL to the resource being parsed.
1619
+ * @return string The ExactDN version of the resource, if it was local.
1620
+ */
1621
+ function parse_enqueue( $url ) {
1622
+ if ( is_admin() ) {
1623
+ return $url;
1624
+ }
1625
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1626
+ $parsed_url = $this->parse_url( $url );
1627
+
1628
+ // Unable to parse.
1629
+ if ( ! $parsed_url || ! is_array( $parsed_url ) || empty( $parsed_url['host'] ) || empty( $parsed_url['path'] ) ) {
1630
+ ewwwio_debug_message( 'src url no good' );
1631
+ return $url;
1632
+ }
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
+
1640
+ // Figure out which CDN (sub)domain to use.
1641
+ if ( empty( $this->exactdn_domain ) ) {
1642
+ ewwwio_debug_message( 'no exactdn domain configured' );
1643
+ return $url;
1644
+ }
1645
+
1646
+ // You can't run an ExactDN URL through again because query strings are stripped.
1647
+ // So if the image is already an ExactDN URL, append the new arguments to the existing URL.
1648
+ if ( $this->exactdn_domain === $parsed_url['host'] ) {
1649
+ ewwwio_debug_message( 'url already has exactdn domain' );
1650
+ return $url;
1651
+ }
1652
+
1653
+ // If a resource doesn't have a version string, we add one to help with cache-busting.
1654
+ if ( empty( $parsed_url['query'] ) ) {
1655
+ /**
1656
+ * Allows a custom version string for resources that are missing one.
1657
+ *
1658
+ * @param string EWWW IO version.
1659
+ */
1660
+ $parsed_url['query'] = apply_filters( 'exactdn_version_string', EWWW_IMAGE_OPTIMIZER_VERSION );
1661
+ }
1662
+
1663
+ $exactdn_url = '//' . $this->exactdn_domain . '/' . ltrim( $parsed_url['path'], '/' ) . '?' . $parsed_url['query'];
1664
+ ewwwio_debug_message( "exactdn css/script url: $exactdn_url" );
1665
+ return $exactdn_url;
1666
+ }
1667
+
1668
  /**
1669
  * Generates an ExactDN URL.
1670
  *
1678
  $image_url = trim( $image_url );
1679
 
1680
  if ( is_null( $scheme ) ) {
1681
+ $scheme = $this->scheme;
 
 
 
 
1682
  }
1683
 
1684
  /**
common.php CHANGED
@@ -18,7 +18,6 @@
18
  // TODO: might be able to use the Custom Bulk Actions in 4.7 to support the bulk optimize drop-down menu.
19
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
20
  // TODO: implement a search for the bulk table, or maybe we should just move it to it's own page?
21
- // TODO: port bulk changes to NextGEN and FlaGallery.
22
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
23
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
24
  // TODO: write some conversion tests.
@@ -28,14 +27,18 @@
28
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
29
  // TODO: on images without srscet, add 2x and 3x versions anyway.
30
  // TODO: check what happens to WebP images when restoring original from backups.
31
- // TODO: use got_mod_rewrite to warn folks not to bother with webp htaccess.
32
  // TODO: fix ExactDN failure after multisite save settings.
33
  // TODO: add ExactDN compat with A3 lazy.
 
 
 
 
 
34
  if ( ! defined( 'ABSPATH' ) ) {
35
  exit;
36
  }
37
 
38
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '406.0' );
39
 
40
  // Initialize a couple globals.
41
  $ewww_debug = '';
@@ -155,6 +158,8 @@ add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_media_scripts' );
155
  add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_settings_script' );
156
  // Enables scheduled optimization via wp-cron.
157
  add_action( 'ewww_image_optimizer_auto', 'ewww_image_optimizer_auto' );
 
 
158
  // Correct any records in the table created during retina generation.
159
  add_action( 'wr2x_retina_file_added', 'ewww_image_optimizer_retina', 20, 2 );
160
  // AJAX action hook for inserting WebP rewrite rules into .htaccess.
@@ -190,6 +195,11 @@ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
190
  * ExactDN class for parsing image urls and rewriting them.
191
  */
192
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-exactdn.php' );
 
 
 
 
 
193
  }
194
  // If Alt WebP Rewriting is enabled.
195
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ) {
@@ -214,6 +224,13 @@ if ( defined( 'WP_CLI' ) && WP_CLI ) {
214
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-cli.php' );
215
  }
216
 
 
 
 
 
 
 
 
217
  /**
218
  * Skips optimization when a file is within EWWW IO's own folder.
219
  *
@@ -260,6 +277,34 @@ function ewww_image_optimizer_ce_webp_enabled() {
260
  return false;
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  /**
264
  * Starts an output buffer and registers the callback function to do WebP replacement.
265
  */
@@ -555,12 +600,18 @@ function ewww_image_optimizer_filter_webp_page_output( $buffer ) {
555
  }
556
  $uri = $_SERVER['REQUEST_URI'];
557
  // Based on the uri, if this is a cornerstone editing page, don't filter the response.
558
- if ( strpos( $uri, '&cornerstone=1' ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
559
  return $buffer;
560
  }
561
  if ( ! empty( $_GET['et_fb'] ) ) {
562
  return $buffer;
563
  }
 
 
 
 
 
 
564
  // Modify buffer here, and then return the updated code.
565
  if ( class_exists( 'DOMDocument' ) ) {
566
  // If this is XML (not XHTML), don't modify the page.
@@ -1146,6 +1197,9 @@ function ewww_image_optimizer_upgrade() {
1146
  if ( get_option( 'ewww_image_optimizer_version' ) < 280 ) {
1147
  ewww_image_optimizer_migrate_settings_to_levels();
1148
  }
 
 
 
1149
  ewww_image_optimizer_remove_obsolete_settings();
1150
  update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
1151
  }
@@ -1365,6 +1419,10 @@ function ewww_image_optimizer_admin_init() {
1365
  }
1366
  }
1367
  ewww_image_optimizer_ajax_compat_check();
 
 
 
 
1368
  ewwwio_memory( __FUNCTION__ );
1369
  }
1370
 
@@ -1425,6 +1483,17 @@ function ewww_image_optimizer_ajax_compat_check() {
1425
  return;
1426
  }
1427
  }
 
 
 
 
 
 
 
 
 
 
 
1428
  // Check for other MLP actions, including multi-regen.
1429
  if ( ! empty( $_REQUEST['action'] ) && class_exists( 'MaxGalleriaMediaLib' ) && ( 'regen_mlp_thumbnails' == $_REQUEST['action'] || 'move_media' == $_REQUEST['action'] || 'copy_media' == $_REQUEST['action'] || 'maxgalleria_rename_image' == $_REQUEST['action'] ) ) {
1430
  ewwwio_debug_message( 'doing regen_mlp_thumbnails' );
@@ -1439,6 +1508,89 @@ function ewww_image_optimizer_ajax_compat_check() {
1439
  }
1440
  }
1441
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1442
  if ( ! function_exists( 'wp_doing_ajax' ) ) {
1443
  /**
1444
  * Checks to see if this is an AJAX request.
@@ -1760,7 +1912,7 @@ function ewww_image_optimizer_network_settings_saved() {
1760
  */
1761
  function ewww_image_optimizer_thumbnail_regen_notice() {
1762
  echo "<div id='ewww-image-optimizer-thumb-regen-notice' class='notice notice-info is-dismissible'><p><strong>" . esc_html__( 'New thumbnails will be optimized by the EWWW Image Optimizer as they are generated. You may wish to disable the plugin and run a bulk optimize later to speed up the process.', 'ewww-image-optimizer' ) . '</strong>';
1763
- echo '&nbsp;<a href="http://docs.ewww.io/article/49-regenerate-thumbnails" target="_blank" data-beacon-article="5a0f84ed2c7d3a272c0dc801">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a></p></div>';
1764
  }
1765
 
1766
  /**
@@ -1812,9 +1964,15 @@ function ewww_image_optimizer_notice_reoptimization() {
1812
  function ewww_image_optimizer_load_editor( $editors ) {
1813
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1814
  if ( ! class_exists( 'EWWWIO_GD_Editor' ) && ! class_exists( 'EWWWIO_Imagick_Editor' ) ) {
1815
- require_once( plugin_dir_path( __FILE__ ) . '/classes/class-ewwwio-gd-editor.php' );
1816
- require_once( plugin_dir_path( __FILE__ ) . '/classes/class-ewwwio-imagick-editor.php' );
1817
- require_once( plugin_dir_path( __FILE__ ) . '/classes/class-ewwwio-gmagick-editor.php' );
 
 
 
 
 
 
1818
  }
1819
  if ( ! in_array( 'EWWWIO_GD_Editor', $editors ) ) {
1820
  array_unshift( $editors, 'EWWWIO_GD_Editor' );
@@ -1918,6 +2076,44 @@ function ewww_image_optimizer_pte_check( $data ) {
1918
  return $data;
1919
  }
1920
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1921
  /**
1922
  * Wraps around the retina generation function to prevent premature optimization.
1923
  *
@@ -2191,6 +2387,10 @@ function ewww_image_optimizer_network_deactivate( $network_wide ) {
2191
  global $wpdb;
2192
  wp_clear_scheduled_hook( 'ewww_image_optimizer_auto' );
2193
  wp_clear_scheduled_hook( 'ewww_image_optimizer_defer' );
 
 
 
 
2194
  if ( $network_wide ) {
2195
  $blogs = $wpdb->get_results( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = %d", $wpdb->siteid ), ARRAY_A );
2196
  if ( ewww_image_optimizer_iterable( $blogs ) ) {
@@ -2198,6 +2398,10 @@ function ewww_image_optimizer_network_deactivate( $network_wide ) {
2198
  switch_to_blog( $blog['blog_id'] );
2199
  wp_clear_scheduled_hook( 'ewww_image_optimizer_auto' );
2200
  wp_clear_scheduled_hook( 'ewww_image_optimizer_defer' );
 
 
 
 
2201
  restore_current_blog();
2202
  }
2203
  }
@@ -3266,6 +3470,9 @@ function ewww_image_optimizer_cloud_key_sanitize( $key ) {
3266
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
3267
  ewwwio_debug_message( print_r( $_REQUEST, true ) );
3268
  }
 
 
 
3269
  if ( ewww_image_optimizer_cloud_verify( false, $key ) ) {
3270
  add_settings_error( 'ewww_image_optimizer_cloud_key', 'ewwwio-cloud-key', esc_html__( 'Successfully validated API key, happy optimizing!', 'ewww-image-optimizer' ), 'updated' );
3271
  ewwwio_debug_message( 'sanitize (verification) successful' );
@@ -3330,6 +3537,10 @@ function ewww_image_optimizer_cloud_useragent( $useragent ) {
3330
  */
3331
  function ewww_image_optimizer_cloud_verify( $cache = true, $api_key = '' ) {
3332
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 
 
 
 
3333
  if ( empty( $api_key ) && ! ( ! empty( $_REQUEST['option_page'] ) && 'ewww_image_optimizer_options' == $_REQUEST['option_page'] ) ) {
3334
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3335
  } elseif ( empty( $api_key ) && ! empty( $_POST['ewww_image_optimizer_cloud_key'] ) ) {
@@ -3391,8 +3602,14 @@ function ewww_image_optimizer_cloud_verify( $cache = true, $api_key = '' ) {
3391
  if ( preg_match( '/exceeded/', $verified ) ) {
3392
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', time() + 300 );
3393
  }
 
 
 
3394
  ewwwio_debug_message( "verification success via: $url" );
3395
  } else {
 
 
 
3396
  ewwwio_debug_message( "verification failed via: $url" );
3397
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
3398
  ewwwio_debug_message( print_r( $result, true ) );
@@ -3618,8 +3835,11 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3618
  ewwwio_debug_message( "jpg fill: $jpg_fill" );
3619
  ewwwio_debug_message( "jpg quality: $jpg_quality" );
3620
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3621
- $url = 'http://optimize.exactlywww.com/v2/';
3622
- $ssl = wp_http_supports( array( 'ssl' ) );
 
 
 
3623
  if ( $ssl ) {
3624
  $url = set_url_scheme( $url, 'https' );
3625
  }
@@ -3687,7 +3907,10 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3687
  $newsize = $orig_size;
3688
  $converted = false;
3689
  $msg = '';
3690
- if ( 100 > strlen( $response['body'] ) && preg_match( '/exceeded/', $response['body'] ) ) {
 
 
 
3691
  ewwwio_debug_message( 'License Exceeded' );
3692
  set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', 3600 );
3693
  $msg = 'exceeded';
@@ -3752,8 +3975,11 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3752
  ewwwio_debug_message( "file: $file " );
3753
  ewwwio_debug_message( "type: $type" );
3754
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3755
- $url = 'http://optimize.exactlywww.com/rotate/';
3756
- $ssl = wp_http_supports( array( 'ssl' ) );
 
 
 
3757
  if ( $ssl ) {
3758
  $url = set_url_scheme( $url, 'https' );
3759
  }
@@ -4312,6 +4538,9 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4312
  ewwwio_debug_message( "unfiltered fullsize path: $filename" );
4313
  $temp_file = download_url( $full_url );
4314
  if ( ! is_wp_error( $temp_file ) ) {
 
 
 
4315
  rename( $temp_file, $filename );
4316
  }
4317
  // Resized versions, so we'll grab those too.
@@ -4348,6 +4577,9 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4348
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4349
  $temp_file = download_url( $resize_url );
4350
  if ( ! is_wp_error( $temp_file ) ) {
 
 
 
4351
  rename( $temp_file, $resize_path );
4352
  }
4353
  }
@@ -4364,6 +4596,9 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4364
  ewwwio_debug_message( "fullsize path: $filename" );
4365
  $temp_file = download_url( $full_url );
4366
  if ( ! is_wp_error( $temp_file ) ) {
 
 
 
4367
  rename( $temp_file, $filename );
4368
  }
4369
  // Resized versions, so we'll grab those too.
@@ -4402,6 +4637,9 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4402
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4403
  $temp_file = download_url( $resize_url );
4404
  if ( ! is_wp_error( $temp_file ) ) {
 
 
 
4405
  rename( $temp_file, $resize_path );
4406
  }
4407
  }
@@ -5947,6 +6185,8 @@ function ewww_image_optimizer_quick_mimetype( $path ) {
5947
  return 'image/png';
5948
  case 'gif':
5949
  return 'image/gif';
 
 
5950
  case 'pdf':
5951
  return 'application/pdf';
5952
  default:
@@ -6604,7 +6844,7 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
6604
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
6605
  if ( ! is_file( $file_path ) && ( class_exists( 'WindowsAzureStorageUtil' ) || class_exists( 'Amazon_S3_And_CloudFront' ) ) ) {
6606
  // Construct a $file_path and proceed IF a supported CDN plugin is installed.
6607
- $file_path = get_attached_file( $selected_id );
6608
  if ( ! $file_path ) {
6609
  ewwwio_debug_message( 'no file found for remote attachment' );
6610
  // $meta = ewww_image_optimizer_clean_meta( $meta );
@@ -6987,6 +7227,9 @@ function ewww_image_optimizer_webp_rewrite_verify() {
6987
  insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' );
6988
  }
6989
  }
 
 
 
6990
  $current_rules = ewwwio_extract_from_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO' );
6991
  $ewww_rules = array(
6992
  '<IfModule mod_rewrite.c>',
@@ -7002,7 +7245,9 @@ function ewww_image_optimizer_webp_rewrite_verify() {
7002
  '</IfModule>',
7003
  'AddType image/webp .webp',
7004
  );
7005
- ewwwio_debug_message( print_r( $current_rules, true ) );
 
 
7006
  if ( empty( $current_rules ) ||
7007
  ! ewww_image_optimizer_array_search( '{HTTP_ACCEPT} image/webp', $current_rules ) ||
7008
  ! ewww_image_optimizer_array_search( '{REQUEST_FILENAME}.webp', $current_rules ) ||
@@ -7202,7 +7447,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7202
  $output[] = "<h1>EWWW Image Optimizer</h1>\n";
7203
  $output[] = "<div id='ewww-container-left' style='float: left; margin-right: 225px;'>\n";
7204
  $output[] = "<p><a href='https://ewww.io/'>" . esc_html__( 'Plugin Home Page', 'ewww-image-optimizer' ) . '</a> | ' .
7205
- "<a href='http://docs.ewww.io/'>" . esc_html__( 'Documentation', 'ewww-image-optimizer' ) . '</a> | ' .
7206
  "<a href='https://ewww.io/contact-us/'>" . esc_html__( 'Plugin Support', 'ewww-image-optimizer' ) . '</a> | ' .
7207
  "<a href='https://ewww.io/status/'>" . esc_html__( 'Cloud Status', 'ewww-image-optimizer' ) . '</a> | ' .
7208
  "<a href='https://ewww.io/downloads/s3-image-optimizer/'>" . esc_html__( 'S3 Image Optimizer', 'ewww-image-optimizer' ) . "</a></p>\n";
@@ -7470,14 +7715,15 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7470
  } elseif ( $file_command_check ) {
7471
  $collapsible = false;
7472
  }
7473
- if ( 'getimagesize' == $mimetype_tool && ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) ) {
7474
  $collapsible = false;
7475
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
7476
  } elseif ( $mimetype_tool ) {
7477
  $mimetype_output = str_replace( 'color: red', 'color: gray', $mimetype_output );
7478
  }
7479
  ewwwio_debug_message( "mimetype function in use: $mimetype_tool" );
7480
- $status_output .= $mimetype_output;
 
7481
  $status_output .= $extra_tool_output;
7482
  $status_output .= '<strong>' . esc_html( 'Background and Parallel optimization (faster uploads):', 'ewww-image-optimizer' ) . '</strong><br>';
7483
  if ( defined( 'EWWW_DISABLE_ASYNC' ) && EWWW_DISABLE_ASYNC ) {
@@ -7489,7 +7735,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7489
  } elseif ( ewww_image_optimizer_detect_wpsf_location_lock() ) {
7490
  $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( "Disabled by Shield's Lock to Location feature", 'ewww-image-optimizer' ) . '</p>';
7491
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ) {
7492
- $status_output .= '<span>' . esc_html__( 'Enable Parallel Optimization in Advanced Settings', 'ewww-image-optimizer' ) . '</span>';
7493
  } else {
7494
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Fully Enabled', 'ewww-image-optimizer' ) . '</span>';
7495
  }
@@ -7587,7 +7833,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7587
  "</select></td></tr>\n";
7588
  ewwwio_debug_message( 'gif level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) );
7589
  $disable_pdf_level = $disable_level;
7590
- if ( 'getimagesize' == $mimetype_tool ) {
7591
  $disable_pdf_level = "disabled='disabled'";
7592
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>";
7593
  $output[] = "<p class='$network_class description'>" . esc_html__( '*PDF optimization cannot be enabled because the fileinfo extension is missing.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
@@ -7619,6 +7865,45 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7619
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_parallel_optimization'>" . esc_html__( 'Parallel optimization', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_parallel_optimization' name='ewww_image_optimizer_parallel_optimization' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'All resizes generated from a single upload are optimized in parallel for faster optimization. If this is causing performance issues, disable parallel optimization to reduce the load on your server.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7620
  ewwwio_debug_message( 'parallel optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? 'on' : 'off' ) );
7621
  ewwwio_debug_message( 'background optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) == true ? 'on' : 'off' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7622
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_auto'>" . esc_html__( 'Scheduled optimization', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_auto' name='ewww_image_optimizer_auto' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will enable scheduled optimization of unoptimized images for your theme, buddypress, and any additional folders you have configured below. Runs hourly: wp_cron only runs when your site is visited, so it may be even longer between optimizations.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7623
  ewwwio_debug_message( 'scheduled optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? 'on' : 'off' ) );
7624
  $media_include_disable = '';
@@ -7667,9 +7952,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7667
  esc_html__( 'Retina Support, use WP Retina 2x for best results', 'ewww-image-optimizer' ) . '<br>' .
7668
  esc_html__( 'Maximum Lossless Compression', 'ewww-image-optimizer' ) . '<br>' .
7669
  esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
7670
- '<a href="http://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about ExactDN', 'ewww-image-optimizer' ) . '</a>' .
7671
  "</p></td></tr>\n";
7672
  ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
 
 
 
7673
  $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";
7674
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? 'on' : 'off' ) );
7675
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
@@ -7770,6 +8058,16 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7770
  ewww_image_optimizer_webp_rewrite_verify();
7771
  }
7772
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
 
 
 
 
 
 
 
 
 
 
7773
  $output[] = "<form id='ewww-webp-rewrite'>\n";
7774
  $output[] = '<p>' . esc_html__( 'There are many ways to serve WebP images to visitors with supported browsers. You may choose any you wish, but it is recommended to serve them with an .htaccess file using mod_rewrite and mod_headers. The plugin can insert the rules for you if the file is writable, or you can edit .htaccess yourself.', 'ewww-image-optimizer' ) . "</p>\n";
7775
  if ( ! ewww_image_optimizer_webp_rewrite_verify() ) {
@@ -7963,18 +8261,27 @@ function ewww_image_optimizer_filter_network_singlesite_settings_page( $input )
7963
 
7964
  /**
7965
  * Removes the API key currently installed.
 
 
7966
  */
7967
- function ewww_image_optimizer_remove_cloud_key() {
7968
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' );
7969
- if ( false === current_user_can( $permissions ) ) {
7970
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
7971
  }
7972
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', '' );
 
 
 
 
7973
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
7974
- ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 10 );
7975
  }
7976
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) != 40 ) {
7977
- ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 10 );
 
 
 
7978
  }
7979
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
7980
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
@@ -7982,9 +8289,11 @@ function ewww_image_optimizer_remove_cloud_key() {
7982
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', 0 );
7983
  delete_transient( 'ewww_image_optimizer_cloud_status' );
7984
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_backup_files', '' );
7985
- $sendback = wp_get_referer();
7986
- wp_redirect( esc_url_raw( $sendback ) );
7987
- exit;
 
 
7988
  }
7989
 
7990
  /**
@@ -8157,6 +8466,11 @@ function ewwwio_debug_version_info() {
8157
  if ( ! empty( $_ENV['PANTHEON_ENVIRONMENT'] ) && in_array( $_ENV['PANTHEON_ENVIRONMENT'], array( 'test', 'live', 'dev' ) ) ) {
8158
  $ewww_debug .= "detected pantheon env: {$_ENV['PANTHEON_ENVIRONMENT']}<br>";
8159
  }
 
 
 
 
 
8160
  }
8161
 
8162
  /**
18
  // TODO: might be able to use the Custom Bulk Actions in 4.7 to support the bulk optimize drop-down menu.
19
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
20
  // TODO: implement a search for the bulk table, or maybe we should just move it to it's own page?
 
21
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
22
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
23
  // TODO: write some conversion tests.
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 = '';
158
  add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_settings_script' );
159
  // Enables scheduled optimization via wp-cron.
160
  add_action( 'ewww_image_optimizer_auto', 'ewww_image_optimizer_auto' );
161
+ // Correct records for files renamed by MFR.
162
+ add_action( 'mfrh_path_renamed', 'ewww_image_optimizer_path_renamed', 10, 3 );
163
  // Correct any records in the table created during retina generation.
164
  add_action( 'wr2x_retina_file_added', 'ewww_image_optimizer_retina', 20, 2 );
165
  // AJAX action hook for inserting WebP rewrite rules into .htaccess.
195
  * ExactDN class for parsing image urls and rewriting them.
196
  */
197
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-exactdn.php' );
198
+ } else {
199
+ // Un-configure Autoptimize CDN domain.
200
+ if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && strpos( ewww_image_optimizer_get_option( 'autoptimize_cdn_url' ), 'exactdn' ) ) {
201
+ ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '' );
202
+ }
203
  }
204
  // If Alt WebP Rewriting is enabled.
205
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ) {
224
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-cli.php' );
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
  /**
235
  * Skips optimization when a file is within EWWW IO's own folder.
236
  *
277
  return false;
278
  }
279
 
280
+ /**
281
+ * Checks to see if the WebP rules from WPFC are enabled.
282
+ *
283
+ * @return bool True if the WebP rules from WPFC are found.
284
+ */
285
+ function ewww_image_optimizer_wpfc_webp_enabled() {
286
+ if ( class_exists( 'WpFastestCache' ) ) {
287
+ $wpfc_abspath = get_home_path() . '.htaccess';
288
+ ewwwio_debug_message( "looking for WPFC rules in $wpfc_abspath" );
289
+ $wpfc_rules = ewwwio_extract_from_markers( $wpfc_abspath, 'WEBPWpFastestCache' );
290
+ if ( empty( $wpfc_rules ) ) {
291
+ $wpfc_abspath = ABSPATH . '.htaccess';
292
+ ewwwio_debug_message( "looking for WPFC rules in $wpfc_abspath" );
293
+ $wpfc_rules = ewwwio_extract_from_markers( $wpfc_abspath, 'WEBPWpFastestCache' );
294
+ }
295
+ if ( ! empty( $wpfc_rules ) ) {
296
+ ewwwio_debug_message( 'WPFC webp rules enabled' );
297
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
298
+ ewwwio_debug_message( 'removing htaccess webp to prevent ExactDN problems' );
299
+ insert_with_markers( $wpfc_abspath, 'WEBPWpFastestCache', '' );
300
+ return false;
301
+ }
302
+ return true;
303
+ }
304
+ }
305
+ return false;
306
+ }
307
+
308
  /**
309
  * Starts an output buffer and registers the callback function to do WebP replacement.
310
  */
600
  }
601
  $uri = $_SERVER['REQUEST_URI'];
602
  // Based on the uri, if this is a cornerstone editing page, don't filter the response.
603
+ if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
604
  return $buffer;
605
  }
606
  if ( ! empty( $_GET['et_fb'] ) ) {
607
  return $buffer;
608
  }
609
+ if ( ! empty( $_GET['tatsu'] ) ) {
610
+ return $buffer;
611
+ }
612
+ if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) {
613
+ return $buffer;
614
+ }
615
  // Modify buffer here, and then return the updated code.
616
  if ( class_exists( 'DOMDocument' ) ) {
617
  // If this is XML (not XHTML), don't modify the page.
1197
  if ( get_option( 'ewww_image_optimizer_version' ) < 280 ) {
1198
  ewww_image_optimizer_migrate_settings_to_levels();
1199
  }
1200
+ if ( get_option( 'ewww_image_optimizer_version' ) < 407 ) {
1201
+ add_site_option( 'exactdn_all_the_things', true );
1202
+ }
1203
  ewww_image_optimizer_remove_obsolete_settings();
1204
  update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
1205
  }
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
  }
1428
 
1483
  return;
1484
  }
1485
  }
1486
+ // Check for Image Watermark plugin.
1487
+ if ( ! empty( $_POST['iw-action'] ) ) {
1488
+ $action = $_POST['iw-action'];
1489
+ ewwwio_debug_message( "doing $action" );
1490
+ remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
1491
+ if ( 'applywatermark' === $action ) {
1492
+ remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
1493
+ add_action( 'iw_after_apply_watermark', 'ewww_image_optimizer_single_size_optimize', 10, 2 );
1494
+ }
1495
+ return;
1496
+ }
1497
  // Check for other MLP actions, including multi-regen.
1498
  if ( ! empty( $_REQUEST['action'] ) && class_exists( 'MaxGalleriaMediaLib' ) && ( 'regen_mlp_thumbnails' == $_REQUEST['action'] || 'move_media' == $_REQUEST['action'] || 'copy_media' == $_REQUEST['action'] || 'maxgalleria_rename_image' == $_REQUEST['action'] ) ) {
1499
  ewwwio_debug_message( 'doing regen_mlp_thumbnails' );
1508
  }
1509
  }
1510
 
1511
+ /**
1512
+ * Optimize a single image from an attachment, based on the size and ID.
1513
+ *
1514
+ * @param int $id The attachment ID number.
1515
+ * @param string $size The slug/name of the image size.
1516
+ */
1517
+ function ewww_image_optimizer_single_size_optimize( $id, $size ) {
1518
+ // TODO: may be able to bring in a meta or filename param from IW eventually.
1519
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1520
+ session_write_close();
1521
+ $meta = wp_get_attachment_metadata( $id );
1522
+ global $wpdb;
1523
+ if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
1524
+ ewww_image_optimizer_db_init();
1525
+ global $ewwwdb;
1526
+ } else {
1527
+ $ewwwdb = $wpdb;
1528
+ }
1529
+ list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
1530
+ ewwwio_debug_message( "retrieved file path: $file_path" );
1531
+ $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
1532
+ $supported_types = array(
1533
+ 'image/jpeg',
1534
+ 'image/png',
1535
+ 'image/gif',
1536
+ 'application/pdf',
1537
+ );
1538
+ if ( ! in_array( $type, $supported_types ) ) {
1539
+ ewwwio_debug_message( "mimetype not supported: $id" );
1540
+ return;
1541
+ }
1542
+ if ( 'full' == $size ) {
1543
+ $ewww_image = new EWWW_Image( $id, 'media', $file_path );
1544
+ $ewww_image->resize = 'full';
1545
+
1546
+ // Run the optimization and store the results.
1547
+ ewww_image_optimizer( $file_path, 4, false, false, true );
1548
+ return;
1549
+ }
1550
+ // Resized version, continue.
1551
+ if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'][ $size ] ) ) {
1552
+ $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
1553
+ ewwwio_debug_message( "processing size: $size" );
1554
+ $base_dir = trailingslashit( dirname( $file_path ) );
1555
+ $data = $meta['sizes'][ $size ];
1556
+ if ( strpos( $size, 'webp' ) === 0 ) {
1557
+ return;
1558
+ }
1559
+ if ( ! empty( $disabled_sizes[ $size ] ) ) {
1560
+ return;
1561
+ }
1562
+ if ( ! empty( $disabled_sizes['pdf-full'] ) && 'full' == $size ) {
1563
+ return;
1564
+ }
1565
+ if ( empty( $data['file'] ) ) {
1566
+ return;
1567
+ }
1568
+ // If this is a unique size.
1569
+ $resize_path = $base_dir . $data['file'];
1570
+ if ( 'application/pdf' == $type && 'full' == $size ) {
1571
+ $size = 'pdf-full';
1572
+ ewwwio_debug_message( 'processing full size pdf preview' );
1573
+ }
1574
+ $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
1575
+ $ewww_image->resize = $size;
1576
+ // Run the optimization and store the results.
1577
+ ewww_image_optimizer( $resize_path );
1578
+ // Optimize retina images, if they exist.
1579
+ if ( function_exists( 'wr2x_get_retina' ) ) {
1580
+ $retina_path = wr2x_get_retina( $resize_path );
1581
+ } else {
1582
+ $retina_path = false;
1583
+ }
1584
+ if ( $retina_path && is_file( $retina_path ) ) {
1585
+ $ewww_image = new EWWW_Image( $id, 'media', $retina_path );
1586
+ $ewww_image->resize = $size . '-retina';
1587
+ ewww_image_optimizer( $retina_path );
1588
+ } else {
1589
+ ewww_image_optimizer_hidpi_optimize( $resize_path );
1590
+ }
1591
+ } // End if().
1592
+ }
1593
+
1594
  if ( ! function_exists( 'wp_doing_ajax' ) ) {
1595
  /**
1596
  * Checks to see if this is an AJAX request.
1912
  */
1913
  function ewww_image_optimizer_thumbnail_regen_notice() {
1914
  echo "<div id='ewww-image-optimizer-thumb-regen-notice' class='notice notice-info is-dismissible'><p><strong>" . esc_html__( 'New thumbnails will be optimized by the EWWW Image Optimizer as they are generated. You may wish to disable the plugin and run a bulk optimize later to speed up the process.', 'ewww-image-optimizer' ) . '</strong>';
1915
+ echo '&nbsp;<a href="https://docs.ewww.io/article/49-regenerate-thumbnails" target="_blank" data-beacon-article="5a0f84ed2c7d3a272c0dc801">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a></p></div>';
1916
  }
1917
 
1918
  /**
1964
  function ewww_image_optimizer_load_editor( $editors ) {
1965
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1966
  if ( ! class_exists( 'EWWWIO_GD_Editor' ) && ! class_exists( 'EWWWIO_Imagick_Editor' ) ) {
1967
+ if ( class_exists( 'WP_Image_Editor_GD' ) ) {
1968
+ require_once( plugin_dir_path( __FILE__ ) . '/classes/class-ewwwio-gd-editor.php' );
1969
+ }
1970
+ if ( class_exists( 'WP_Image_Editor_Imagick' ) ) {
1971
+ require_once( plugin_dir_path( __FILE__ ) . '/classes/class-ewwwio-imagick-editor.php' );
1972
+ }
1973
+ if ( class_exists( 'WP_Image_Editor_Gmagick' ) ) {
1974
+ require_once( plugin_dir_path( __FILE__ ) . '/classes/class-ewwwio-gmagick-editor.php' );
1975
+ }
1976
  }
1977
  if ( ! in_array( 'EWWWIO_GD_Editor', $editors ) ) {
1978
  array_unshift( $editors, 'EWWWIO_GD_Editor' );
2076
  return $data;
2077
  }
2078
 
2079
+ /**
2080
+ * Updates paths in the database after Media File Rename has run.
2081
+ *
2082
+ * @param array $post The post information for the image attachment.
2083
+ * @param string $old_filepath The previous filename of the image.
2084
+ * @param string $new_filepath The new filename of the image.
2085
+ */
2086
+ function ewww_image_optimizer_path_renamed( $post, $old_filepath, $new_filepath ) {
2087
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2088
+ $optimized_query = ewww_image_optimizer_find_already_optimized( $old_filepath );
2089
+ if ( is_array( $optimized_query ) && ! empty( $optimized_query['id'] ) ) {
2090
+ global $wpdb;
2091
+ if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
2092
+ ewww_image_optimizer_db_init();
2093
+ global $ewwwdb;
2094
+ } else {
2095
+ $ewwwdb = $wpdb;
2096
+ }
2097
+ ewwwio_debug_message( "$old_filepath changed to $new_filepath" );
2098
+ // Replace the 'temp' path in the database with the real path.
2099
+ $ewwwdb->update( $ewwwdb->ewwwio_images,
2100
+ array(
2101
+ 'path' => ewww_image_optimizer_relative_path_remove( $new_filepath ),
2102
+ ),
2103
+ array(
2104
+ 'id' => $optimized_query['id'],
2105
+ )
2106
+ );
2107
+ }
2108
+ // Look for WebP variants and rename them.
2109
+ $old_webp = $old_filepath . '.webp';
2110
+ $new_webp = $new_filepath . '.webp';
2111
+ if ( is_file( $old_webp ) && ! is_file( $new_webp ) ) {
2112
+ ewwwio_debug_message( "renaming $old_webp to $new_webp" );
2113
+ rename( $old_webp, $new_webp );
2114
+ }
2115
+ }
2116
+
2117
  /**
2118
  * Wraps around the retina generation function to prevent premature optimization.
2119
  *
2387
  global $wpdb;
2388
  wp_clear_scheduled_hook( 'ewww_image_optimizer_auto' );
2389
  wp_clear_scheduled_hook( 'ewww_image_optimizer_defer' );
2390
+ // Un-configure Autoptimize CDN domain.
2391
+ if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && strpos( ewww_image_optimizer_get_option( 'autoptimize_cdn_url' ), 'exactdn' ) ) {
2392
+ ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '' );
2393
+ }
2394
  if ( $network_wide ) {
2395
  $blogs = $wpdb->get_results( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = %d", $wpdb->siteid ), ARRAY_A );
2396
  if ( ewww_image_optimizer_iterable( $blogs ) ) {
2398
  switch_to_blog( $blog['blog_id'] );
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
  }
2407
  }
3470
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
3471
  ewwwio_debug_message( print_r( $_REQUEST, true ) );
3472
  }
3473
+ if ( empty( $key ) ) {
3474
+ return '';
3475
+ }
3476
  if ( ewww_image_optimizer_cloud_verify( false, $key ) ) {
3477
  add_settings_error( 'ewww_image_optimizer_cloud_key', 'ewwwio-cloud-key', esc_html__( 'Successfully validated API key, happy optimizing!', 'ewww-image-optimizer' ), 'updated' );
3478
  ewwwio_debug_message( 'sanitize (verification) successful' );
3537
  */
3538
  function ewww_image_optimizer_cloud_verify( $cache = true, $api_key = '' ) {
3539
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3540
+ $sanitize = false;
3541
+ if ( ! empty( $api_key ) ) {
3542
+ $sanitize = true;
3543
+ }
3544
  if ( empty( $api_key ) && ! ( ! empty( $_REQUEST['option_page'] ) && 'ewww_image_optimizer_options' == $_REQUEST['option_page'] ) ) {
3545
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3546
  } elseif ( empty( $api_key ) && ! empty( $_POST['ewww_image_optimizer_cloud_key'] ) ) {
3602
  if ( preg_match( '/exceeded/', $verified ) ) {
3603
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', time() + 300 );
3604
  }
3605
+ if ( ! $sanitize && false !== strpos( $result['body'], 'expired' ) ) {
3606
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', '' );
3607
+ }
3608
  ewwwio_debug_message( "verification success via: $url" );
3609
  } else {
3610
+ if ( ! $sanitize && ! empty( $result['body'] ) && false !== strpos( $result['body'], 'invalid' ) ) {
3611
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', '' );
3612
+ }
3613
  ewwwio_debug_message( "verification failed via: $url" );
3614
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
3615
  ewwwio_debug_message( print_r( $result, true ) );
3835
  ewwwio_debug_message( "jpg fill: $jpg_fill" );
3836
  ewwwio_debug_message( "jpg quality: $jpg_quality" );
3837
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3838
+ if ( empty( $api_key ) ) {
3839
+ return array( $file, false, 'key verification failed', 0, '' );
3840
+ }
3841
+ $url = 'http://optimize.exactlywww.com/v2/';
3842
+ $ssl = wp_http_supports( array( 'ssl' ) );
3843
  if ( $ssl ) {
3844
  $url = set_url_scheme( $url, 'https' );
3845
  }
3907
  $newsize = $orig_size;
3908
  $converted = false;
3909
  $msg = '';
3910
+ if ( 100 > strlen( $response['body'] ) && strpos( $response['body'], 'invalid' ) ) {
3911
+ ewwwio_debug_message( 'License Invalid' );
3912
+ ewww_image_optimizer_remove_cloud_key( 'none' );
3913
+ } elseif ( 100 > strlen( $response['body'] ) && strpos( $response['body'], 'exceeded' ) ) {
3914
  ewwwio_debug_message( 'License Exceeded' );
3915
  set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', 3600 );
3916
  $msg = 'exceeded';
3975
  ewwwio_debug_message( "file: $file " );
3976
  ewwwio_debug_message( "type: $type" );
3977
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3978
+ if ( empty( $api_key ) ) {
3979
+ return false;
3980
+ }
3981
+ $url = 'http://optimize.exactlywww.com/rotate/';
3982
+ $ssl = wp_http_supports( array( 'ssl' ) );
3983
  if ( $ssl ) {
3984
  $url = set_url_scheme( $url, 'https' );
3985
  }
4538
  ewwwio_debug_message( "unfiltered fullsize path: $filename" );
4539
  $temp_file = download_url( $full_url );
4540
  if ( ! is_wp_error( $temp_file ) ) {
4541
+ if ( ! is_dir( dirname( $filename ) ) ) {
4542
+ wp_mkdir_p( dirname( $filename ) );
4543
+ }
4544
  rename( $temp_file, $filename );
4545
  }
4546
  // Resized versions, so we'll grab those too.
4577
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4578
  $temp_file = download_url( $resize_url );
4579
  if ( ! is_wp_error( $temp_file ) ) {
4580
+ if ( ! is_dir( dirname( $resize_path ) ) ) {
4581
+ wp_mkdir_p( dirname( $resize_path ) );
4582
+ }
4583
  rename( $temp_file, $resize_path );
4584
  }
4585
  }
4596
  ewwwio_debug_message( "fullsize path: $filename" );
4597
  $temp_file = download_url( $full_url );
4598
  if ( ! is_wp_error( $temp_file ) ) {
4599
+ if ( ! is_dir( dirname( $filename ) ) ) {
4600
+ wp_mkdir_p( dirname( $filename ) );
4601
+ }
4602
  rename( $temp_file, $filename );
4603
  }
4604
  // Resized versions, so we'll grab those too.
4637
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4638
  $temp_file = download_url( $resize_url );
4639
  if ( ! is_wp_error( $temp_file ) ) {
4640
+ if ( ! is_dir( dirname( $resize_path ) ) ) {
4641
+ wp_mkdir_p( dirname( $resize_path ) );
4642
+ }
4643
  rename( $temp_file, $resize_path );
4644
  }
4645
  }
6185
  return 'image/png';
6186
  case 'gif':
6187
  return 'image/gif';
6188
+ case 'webp':
6189
+ return 'image/webp';
6190
  case 'pdf':
6191
  return 'application/pdf';
6192
  default:
6844
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
6845
  if ( ! is_file( $file_path ) && ( class_exists( 'WindowsAzureStorageUtil' ) || class_exists( 'Amazon_S3_And_CloudFront' ) ) ) {
6846
  // Construct a $file_path and proceed IF a supported CDN plugin is installed.
6847
+ $file_path = get_attached_file( $id );
6848
  if ( ! $file_path ) {
6849
  ewwwio_debug_message( 'no file found for remote attachment' );
6850
  // $meta = ewww_image_optimizer_clean_meta( $meta );
7227
  insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' );
7228
  }
7229
  }
7230
+ if ( ewww_image_optimizer_wpfc_webp_enabled() ) {
7231
+ return;
7232
+ }
7233
  $current_rules = ewwwio_extract_from_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO' );
7234
  $ewww_rules = array(
7235
  '<IfModule mod_rewrite.c>',
7245
  '</IfModule>',
7246
  'AddType image/webp .webp',
7247
  );
7248
+ if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
7249
+ ewwwio_debug_message( print_r( $current_rules, true ) );
7250
+ }
7251
  if ( empty( $current_rules ) ||
7252
  ! ewww_image_optimizer_array_search( '{HTTP_ACCEPT} image/webp', $current_rules ) ||
7253
  ! ewww_image_optimizer_array_search( '{REQUEST_FILENAME}.webp', $current_rules ) ||
7447
  $output[] = "<h1>EWWW Image Optimizer</h1>\n";
7448
  $output[] = "<div id='ewww-container-left' style='float: left; margin-right: 225px;'>\n";
7449
  $output[] = "<p><a href='https://ewww.io/'>" . esc_html__( 'Plugin Home Page', 'ewww-image-optimizer' ) . '</a> | ' .
7450
+ "<a href='https://docs.ewww.io/'>" . esc_html__( 'Documentation', 'ewww-image-optimizer' ) . '</a> | ' .
7451
  "<a href='https://ewww.io/contact-us/'>" . esc_html__( 'Plugin Support', 'ewww-image-optimizer' ) . '</a> | ' .
7452
  "<a href='https://ewww.io/status/'>" . esc_html__( 'Cloud Status', 'ewww-image-optimizer' ) . '</a> | ' .
7453
  "<a href='https://ewww.io/downloads/s3-image-optimizer/'>" . esc_html__( 'S3 Image Optimizer', 'ewww-image-optimizer' ) . "</a></p>\n";
7715
  } elseif ( $file_command_check ) {
7716
  $collapsible = false;
7717
  }
7718
+ if ( false && 'getimagesize' == $mimetype_tool && ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) ) {
7719
  $collapsible = false;
7720
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
7721
  } elseif ( $mimetype_tool ) {
7722
  $mimetype_output = str_replace( 'color: red', 'color: gray', $mimetype_output );
7723
  }
7724
  ewwwio_debug_message( "mimetype function in use: $mimetype_tool" );
7725
+ // The whole mimetype section can go away when we're comfortable that nothing has broken.
7726
+ /* $status_output .= $mimetype_output; */
7727
  $status_output .= $extra_tool_output;
7728
  $status_output .= '<strong>' . esc_html( 'Background and Parallel optimization (faster uploads):', 'ewww-image-optimizer' ) . '</strong><br>';
7729
  if ( defined( 'EWWW_DISABLE_ASYNC' ) && EWWW_DISABLE_ASYNC ) {
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 {
7740
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Fully Enabled', 'ewww-image-optimizer' ) . '</span>';
7741
  }
7833
  "</select></td></tr>\n";
7834
  ewwwio_debug_message( 'gif level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) );
7835
  $disable_pdf_level = $disable_level;
7836
+ if ( false && 'getimagesize' == $mimetype_tool ) {
7837
  $disable_pdf_level = "disabled='disabled'";
7838
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>";
7839
  $output[] = "<p class='$network_class description'>" . esc_html__( '*PDF optimization cannot be enabled because the fileinfo extension is missing.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7865
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_parallel_optimization'>" . esc_html__( 'Parallel optimization', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_parallel_optimization' name='ewww_image_optimizer_parallel_optimization' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'All resizes generated from a single upload are optimized in parallel for faster optimization. If this is causing performance issues, disable parallel optimization to reduce the load on your server.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7866
  ewwwio_debug_message( 'parallel optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? 'on' : 'off' ) );
7867
  ewwwio_debug_message( 'background optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) == true ? 'on' : 'off' ) );
7868
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
7869
+ $admin_ajax_url = admin_url( 'admin-ajax.php' );
7870
+ if ( strpos( $admin_ajax_url, 'admin-ajax.php' ) ) {
7871
+ ewwwio_debug_message( "admin ajax url: $admin_ajax_url" );
7872
+ $admin_ajax_host = parse_url( $admin_ajax_url, PHP_URL_HOST );
7873
+ ewwwio_debug_message( "admin ajax hostname: $admin_ajax_host" );
7874
+ $resolved = gethostbyname( $admin_ajax_host . '.' );
7875
+ ewwwio_debug_message( "resolved to $resolved" );
7876
+ if ( $resolved == $admin_ajax_host . '.' ) {
7877
+ ewwwio_debug_message( 'DNS lookup failed' );
7878
+ } else {
7879
+ $admin_ajax_url = add_query_arg(
7880
+ array(
7881
+ 'action' => 'wp_ewwwio_test_optimize',
7882
+ 'nonce' => wp_create_nonce( 'wp_ewwwio_test_optimize' ),
7883
+ ),
7884
+ $admin_ajax_url
7885
+ );
7886
+ ewwwio_debug_message( "admin ajax POST url: $admin_ajax_url" );
7887
+ $async_post_args = array(
7888
+ 'body' => array(
7889
+ 'ewwwio_test_verify' => '949c34123cf2a4e4ce2f985135830df4a1b2adc24905f53d2fd3f5df5b16293245',
7890
+ ),
7891
+ 'sslverify' => false,
7892
+ );
7893
+ $async_response = wp_remote_post( esc_url_raw( $admin_ajax_url ), $async_post_args );
7894
+ if ( is_wp_error( $async_response ) ) {
7895
+ $error_message = $async_response->get_error_message();
7896
+ ewwwio_debug_message( "async test failed: $error_message" );
7897
+ } elseif ( is_array( $async_response ) && isset( $async_response['body'] ) ) {
7898
+ ewwwio_debug_message( 'async success, possibly: ' . $async_response['body'] );
7899
+ } else {
7900
+ ewwwio_debug_message( 'no async error, but no body either' );
7901
+ }
7902
+ }
7903
+ } else {
7904
+ ewwwio_debug_message( "invalid admin ajax url: $admin_ajax_url" );
7905
+ }
7906
+ }
7907
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_auto'>" . esc_html__( 'Scheduled optimization', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_auto' name='ewww_image_optimizer_auto' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will enable scheduled optimization of unoptimized images for your theme, buddypress, and any additional folders you have configured below. Runs hourly: wp_cron only runs when your site is visited, so it may be even longer between optimizations.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7908
  ewwwio_debug_message( 'scheduled optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? 'on' : 'off' ) );
7909
  $media_include_disable = '';
7952
  esc_html__( 'Retina Support, use WP Retina 2x for best results', 'ewww-image-optimizer' ) . '<br>' .
7953
  esc_html__( 'Maximum Lossless Compression', 'ewww-image-optimizer' ) . '<br>' .
7954
  esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
7955
+ '<a href="https://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about ExactDN', 'ewww-image-optimizer' ) . '</a>' .
7956
  "</p></td></tr>\n";
7957
  ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
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' ) ) {
8058
  ewww_image_optimizer_webp_rewrite_verify();
8059
  }
8060
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
8061
+ if ( ! apache_mod_loaded( 'mod_rewrite' ) ) {
8062
+ ewwwio_debug_message( 'webp missing mod_rewrite' );
8063
+ /* translators: %s: mod_rewrite or mod_headers */
8064
+ $output[] = '<p><strong>' . sprintf( esc_html( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.' ), 'mod_rewrite' ) . "</strong></p>\n";
8065
+ }
8066
+ if ( ! apache_mod_loaded( 'mod_headers' ) ) {
8067
+ /* translators: %s: mod_rewrite or mod_headers */
8068
+ $output[] = '<p><strong>' . sprintf( esc_html( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.' ), 'mod_headers' ) . "</strong></p>\n";
8069
+ ewwwio_debug_message( 'webp missing mod_headers' );
8070
+ }
8071
  $output[] = "<form id='ewww-webp-rewrite'>\n";
8072
  $output[] = '<p>' . esc_html__( 'There are many ways to serve WebP images to visitors with supported browsers. You may choose any you wish, but it is recommended to serve them with an .htaccess file using mod_rewrite and mod_headers. The plugin can insert the rules for you if the file is writable, or you can edit .htaccess yourself.', 'ewww-image-optimizer' ) . "</p>\n";
8073
  if ( ! ewww_image_optimizer_webp_rewrite_verify() ) {
8261
 
8262
  /**
8263
  * Removes the API key currently installed.
8264
+ *
8265
+ * @param boolean|string $redirect Should the plugin do a silent redirect back to the referring page? Default true.
8266
  */
8267
+ function ewww_image_optimizer_remove_cloud_key( $redirect = true ) {
8268
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' );
8269
+ if ( 'none' !== $redirect && false === current_user_can( $permissions ) ) {
8270
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
8271
  }
8272
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', '' );
8273
+ $default_level = 10;
8274
+ if ( defined( 'EWWW_IO_CLOUD_PLUGIN' ) && EWWW_IO_CLOUD_PLUGIN ) {
8275
+ $default_level = 0;
8276
+ }
8277
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
8278
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', $default_level );
8279
  }
8280
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) != 40 ) {
8281
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', $default_level );
8282
+ }
8283
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) > 0 ) {
8284
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_gif_level', $default_level );
8285
  }
8286
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
8287
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
8289
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', 0 );
8290
  delete_transient( 'ewww_image_optimizer_cloud_status' );
8291
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_backup_files', '' );
8292
+ if ( 'none' !== $redirect ) {
8293
+ $sendback = wp_get_referer();
8294
+ wp_redirect( esc_url_raw( $sendback ) );
8295
+ exit;
8296
+ }
8297
  }
8298
 
8299
  /**
8466
  if ( ! empty( $_ENV['PANTHEON_ENVIRONMENT'] ) && in_array( $_ENV['PANTHEON_ENVIRONMENT'], array( 'test', 'live', 'dev' ) ) ) {
8467
  $ewww_debug .= "detected pantheon env: {$_ENV['PANTHEON_ENVIRONMENT']}<br>";
8468
  }
8469
+ if ( defined( 'EWWW_IO_CLOUD_PLUGIN' ) && EWWW_IO_CLOUD_PLUGIN ) {
8470
+ $ewww_debug .= 'cloud plugin<br>';
8471
+ } else {
8472
+ $ewww_debug .= 'core plugin<br>';
8473
+ }
8474
  }
8475
 
8476
  /**
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.0.6
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
@@ -22,6 +22,11 @@ License: GPLv3
22
  if ( ! defined( 'ABSPATH' ) ) {
23
  exit;
24
  }
 
 
 
 
 
25
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
26
  /**
27
  * The folder where we install optimization tools - MUST have a trailing slash.
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
  */
22
  if ( ! defined( 'ABSPATH' ) ) {
23
  exit;
24
  }
25
+
26
+ if ( ! defined( 'EWWW_IO_CLOUD_PLUGIN' ) ) {
27
+ define( 'EWWW_IO_CLOUD_PLUGIN', false );
28
+ }
29
+
30
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
31
  /**
32
  * The folder where we install optimization tools - MUST have a trailing slash.
includes/resize_detection.js CHANGED
@@ -3,9 +3,12 @@
3
 
4
  window.onload = function() {
5
  checkImageSizes();
6
- document.getElementById('wp-admin-bar-resize-detection').onclick = function() {
7
- checkImageSizes();
8
- };
 
 
 
9
  }
10
  function checkImageSizes() {
11
  // Find images which have width or height different than their natural
@@ -23,7 +26,6 @@ function checkImageSizes() {
23
  if (wrongWidth || wrongHeight) {
24
  img.style.border = "3px #3eadc9 dotted";
25
  img.style.margin = "-3px";
26
- img.style.background = "black";
27
  img.title = "Forced to wrong size: " +
28
  img.width + "x" + img.height + ", natural is " +
29
  img.naturalWidth + "x" + img.naturalHeight + "!";
3
 
4
  window.onload = function() {
5
  checkImageSizes();
6
+ var adminBarButton = document.getElementById('wp-admin-bar-resize-detection');
7
+ if (adminBarButton) {
8
+ adminBarButton.onclick = function() {
9
+ checkImageSizes();
10
+ };
11
+ }
12
  }
13
  function checkImageSizes() {
14
  // Find images which have width or height different than their natural
26
  if (wrongWidth || wrongHeight) {
27
  img.style.border = "3px #3eadc9 dotted";
28
  img.style.margin = "-3px";
 
29
  img.title = "Forced to wrong size: " +
30
  img.width + "x" + img.height + ", natural is " +
31
  img.naturalWidth + "x" + img.naturalHeight + "!";
readme.txt CHANGED
@@ -1,11 +1,11 @@
1
  === EWWW Image Optimizer ===
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
4
- Tags: image, compress, optimize, optimization, lossless, lossy, seo, jpegmini, 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.0.6
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.
@@ -63,7 +63,7 @@ Can generate WebP versions of your images, and enables you to serve even smaller
63
 
64
  = WP-CLI =
65
 
66
- Allows you to run all Bulk Optimization processes from your command line, instead of the web interface. It is much faster, and allows you to do things like run it in 'screen' or via regular cron (instead of wp-cron, which can be unpredictable on low-traffic sites). Install WP-CLI from wp-cli.org, and run 'wp-cli.phar help ewwwio optimize' for more information or see the [Docs](http://docs.ewww.io/article/25-optimizing-with-wp-cli).
67
 
68
  = FooGallery =
69
 
@@ -111,21 +111,21 @@ To receive updates when new strings are available for translation, you can signu
111
  1. *Recommended* Visit the settings page to enable/disable specific tools and turn on advanced optimization features.
112
  1. Done!
113
 
114
- If these steps do not work, additional documentation is available at http://docs.ewww.io. If you need further assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/). The forums are community supported only.
115
 
116
  = Webhosts =
117
 
118
- To find out if your webhost works with the EWWW Image Optimizer, you can check the [official list](http://docs.ewww.io/article/43-supported-web-hosts).
119
 
120
  == Frequently Asked Questions ==
121
 
122
  = Google Pagespeed says my images need compressing or resizing, but I already optimized all my images. What do I do? =
123
 
124
- Try this for starters: http://docs.ewww.io/article/5-pagespeed-says-my-images-need-more-work
125
 
126
  = The plugin complains that I'm missing something, what do I do? =
127
 
128
- This article will walk you through installing the required tools (and the alternatives if installation does not work): http://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something
129
 
130
  = Does the plugin replace existing images? =
131
 
@@ -137,7 +137,7 @@ Yes, you can, set it up on the Resize tab.
137
 
138
  = Can I lower the compression setting for JPGs to save more space? =
139
 
140
- The lossy JPG optimization using TinyJPG and JPEGmini will determine the ideal quality setting and give you the best results, but you can also adjust the default quality for conversion and resizing. More information: http://docs.ewww.io/article/12-jpq-quality-and-wordpress
141
 
142
  = The bulk optimizer doesn't seem to be working, what can I do? =
143
 
@@ -150,7 +150,7 @@ I've tested it on Windows (with Apache), Linux, Mac OSX, FreeBSD 9, and Solaris
150
 
151
  = How are JPGs optimized? =
152
 
153
- Lossless optimization is done with the command *jpegtran -copy all -optimize -progressive -outfile optimized-file original-file*. Optionally, the -copy switch gets the 'none' parameter if you choose to strip metadata from your JPGs on the options page. Lossy optimization is done using the outstanding TinyJPG and JPEGmini utilities.
154
 
155
  = How are PNGs optimized? =
156
 
@@ -166,8 +166,6 @@ That's not a question, but since I made it up, I'll answer it. See these resourc
166
  https://developers.google.com/speed/docs/insights/OptimizeImages
167
  http://developer.yahoo.com/performance/rules.html#opt_images
168
 
169
- Pngout, TinyJPG/TinyPNG, JPEGmini, and Pngquant were recommended by EWWW IO users. Pngout (usually) optimizes better than Optipng, and best when they are used together. TinyJPG is the best lossy compression tool that I have found for JPG images. Pngquant is an excellent lossy optimizer for PNGs, and is one of the tools used by TinyPNG.
170
-
171
  == Screenshots ==
172
 
173
  1. Plugin settings page.
@@ -179,6 +177,45 @@ Pngout, TinyJPG/TinyPNG, JPEGmini, and Pngquant were recommended by EWWW IO user
179
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
180
  * 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/
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  = 4.0.6 =
183
  * changed: dummy images have no args appended with exactdn except for ssl flag
184
  * fixed: resize_detection.js being combined with other scripts by Autoptimize
@@ -188,8 +225,8 @@ Pngout, TinyJPG/TinyPNG, JPEGmini, and Pngquant were recommended by EWWW IO user
188
  * fixed: compatibility with Regenerate Thumbnails version 3
189
 
190
  = 4.0.5 =
191
- * added: enable lossy compression with ExactDN: http://docs.ewww.io/article/47-getting-more-from-exactdn
192
- * added: CSS/JS minification with ExactDN, see http://docs.ewww.io/article/47-getting-more-from-exactdn
193
  * added: disable WebP for specific files with ewww_image_optimizer_bypass_webp filter
194
  * added: ExactDN obeys focus point from Theia Smart Thumbnails plugin
195
  * added: admin-ajax requests for eddvbugm loader work with ExactDN
@@ -246,6 +283,10 @@ Please refer to the separate changelog.txt file.
246
 
247
  == Upgrade Notice ==
248
 
 
 
 
 
249
  = 4.0.0 =
250
  * Introduced new ExactDN with CDN and automatic image resizing.
251
 
1
  === EWWW Image Optimizer ===
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
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.
63
 
64
  = WP-CLI =
65
 
66
+ Allows you to run all Bulk Optimization processes from your command line, instead of the web interface. It is much faster, and allows you to do things like run it in 'screen' or via regular cron (instead of wp-cron, which can be unpredictable on low-traffic sites). Install WP-CLI from wp-cli.org, and run 'wp-cli.phar help ewwwio optimize' for more information or see the [Docs](https://docs.ewww.io/article/25-optimizing-with-wp-cli).
67
 
68
  = FooGallery =
69
 
111
  1. *Recommended* Visit the settings page to enable/disable specific tools and turn on advanced optimization features.
112
  1. Done!
113
 
114
+ If these steps do not work, additional documentation is available at https://docs.ewww.io. If you need further assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/). The forums are community supported only.
115
 
116
  = Webhosts =
117
 
118
+ To find out if your webhost works with the EWWW Image Optimizer, you can check the [official list](https://docs.ewww.io/article/43-supported-web-hosts).
119
 
120
  == Frequently Asked Questions ==
121
 
122
  = Google Pagespeed says my images need compressing or resizing, but I already optimized all my images. What do I do? =
123
 
124
+ Try this for starters: https://docs.ewww.io/article/5-pagespeed-says-my-images-need-more-work
125
 
126
  = The plugin complains that I'm missing something, what do I do? =
127
 
128
+ This article will walk you through installing the required tools (and the alternatives if installation does not work): https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something
129
 
130
  = Does the plugin replace existing images? =
131
 
137
 
138
  = Can I lower the compression setting for JPGs to save more space? =
139
 
140
+ The lossy JPG optimization using the API will determine the ideal quality setting and give you the best results, but you can also adjust the default quality for conversion and resizing. More information: https://docs.ewww.io/article/12-jpq-quality-and-wordpress
141
 
142
  = The bulk optimizer doesn't seem to be working, what can I do? =
143
 
150
 
151
  = How are JPGs optimized? =
152
 
153
+ Lossless optimization is done with the command *jpegtran -copy all -optimize -progressive -outfile optimized-file original-file*. Optionally, the -copy switch gets the 'none' parameter if you choose to strip metadata from your JPGs on the options page.
154
 
155
  = How are PNGs optimized? =
156
 
166
  https://developers.google.com/speed/docs/insights/OptimizeImages
167
  http://developer.yahoo.com/performance/rules.html#opt_images
168
 
 
 
169
  == Screenshots ==
170
 
171
  1. Plugin settings page.
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
183
+ * fixed: ExactDN CSS and JS parsing incompatible with Autoptimize
184
+
185
+ = 4.1.2 =
186
+ * added: detect WP Fastest Cache WebP rewrite rules
187
+ * added: notice if WebP conversion enabled but mod_rewrite or mod_headers is missing
188
+ * added: better debugging when background/async mode is blocked
189
+ * changed: CSS/JS files are filtered pre-emptively by ExactDN to avoid quirks with emoji scripts
190
+ * fixed: warning during wp_cron for undefined constant
191
+ * fixed: invalid or expired keys would still attempt optimization
192
+ * fixed: WebP files are orphaned when using Media File Renamer
193
+ * deprecated: PHP 5.3 will no longer be supported in 4.2
194
+ * deprecated: PHP 5.4 support will be removed by July 2018
195
+ * deprecated: PHP 5.5 support will be removed by October 2018
196
+
197
+ = 4.1.1 =
198
+ * added: reduce ExactDN load time by suppressing db queries with EXACTDN_PREVENT_DB_QUERIES
199
+ * added: $fullsize indicator added to pre/post optimization hooks, props Schweinepriester
200
+ * fixed: missing www preventing rewrites for ExactDN
201
+ * fixed: Alt WebP compatibility with Tatsu page builder
202
+ * fixed: relative path support not working properly for Pantheon users
203
+ * fixed: missing directories prevent optimization of S3 files
204
+
205
+ = 4.1.0 =
206
+ * SECURITY: gifsicle and optipng have been updated to address security flaws
207
+ * added: full compatibility with Image Watermark plugin
208
+ * added: dummy images for Essential Grid and Layer Slider whitelisted with ExactDN
209
+ * added: compatibility with Visual Composer and Essential Grid async/AJAX loaders
210
+ * added: compatibility with Media File Renamer
211
+ * changed: ExactDN rewrites all wp-content and wp-includes urls by default
212
+ * changed: mime-type detection function does not rely on fileinfo extension anymore
213
+ * changed: Solaris/SunOS binary builds use OpenIndiana 2017.10, let me know if they break
214
+ * fixed: wp-emoji script not rewritten by EXACTDN_ALL_THE_THINGS
215
+ * fixed: resize detection script throws error when admin bar is hidden
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
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
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.
289
+
290
  = 4.0.0 =
291
  * Introduced new ExactDN with CDN and automatic image resizing.
292
 
tests/test-optimize.php CHANGED
@@ -334,7 +334,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
334
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
335
  update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
336
  $results = $this->optimize_png();
337
- $this->assertEquals( 38082, filesize( $results[0] ) );
338
  unlink( $results[0] );
339
  }
340
 
@@ -368,7 +368,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
368
  $results = $this->optimize_png();
369
  update_option( 'ewww_image_optimizer_cloud_key', '' );
370
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
371
- $this->assertEquals( 37697, filesize( $results[0] ) );
372
  unlink( $results[0] );
373
  }
374
 
334
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
335
  update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
336
  $results = $this->optimize_png();
337
+ $this->assertEquals( 37428, filesize( $results[0] ) );
338
  unlink( $results[0] );
339
  }
340
 
368
  $results = $this->optimize_png();
369
  update_option( 'ewww_image_optimizer_cloud_key', '' );
370
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
371
+ $this->assertEquals( 37557, filesize( $results[0] ) );
372
  unlink( $results[0] );
373
  }
374
 
unique.php CHANGED
@@ -242,7 +242,7 @@ function ewww_image_optimizer_tool_folder_permissions_notice() {
242
  sprintf( esc_html__( 'EWWW Image Optimizer could not install tools in %s', 'ewww-image-optimizer' ), htmlentities( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) . '.</strong> ' .
243
  esc_html__( 'Please adjust permissions or create the folder. If you have installed the tools elsewhere on your system, check the option to Use System Paths.', 'ewww-image-optimizer' ) . ' ' .
244
  /* translators: 1: Settings Page (link) 2: Installation Instructions (link) */
245
- sprintf( esc_html__( 'For more details, visit the %1$s or the %2$s.', 'ewww-image-optimizer' ), "<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>', "<a href='http://docs.ewww.io/'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>' ) . '</p></div>';
246
  }
247
 
248
  /**
@@ -263,7 +263,7 @@ function ewww_image_optimizer_tool_installation_failed_notice() {
263
  sprintf( esc_html__( 'EWWW Image Optimizer could not install tools in %s', 'ewww-image-optimizer' ), htmlentities( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) . '.</strong> ' .
264
  esc_html__( 'Please adjust permissions or create the folder. If you have installed the tools elsewhere on your system, check the option to Use System Paths.', 'ewww-image-optimizer' ) . ' ' .
265
  /* translators: 1: Settings Page (link) 2: Installation Instructions (link) */
266
- sprintf( esc_html__( 'For more details, visit the %1$s or the %2$s.', 'ewww-image-optimizer' ), "<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>', "<a href='http://docs.ewww.io/'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>' ) . '</p></div>';
267
  }
268
 
269
  /**
@@ -585,7 +585,7 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
585
  }
586
  echo "<div id='ewww-image-optimizer-warning-opt-missing' class='error'><p>" .
587
  /* translators: 1-6: jpegtran, optipng, pngout, pngquant, gifsicle, and cwebp (links) 7: Settings Page (link) 8: Installation Instructions (link) */
588
- sprintf( esc_html__( 'EWWW Image Optimizer uses %1$s, %2$s, %3$s, %4$s, %5$s, and %6$s. You are missing: %7$s. Please install via the %8$s or the %9$s.', 'ewww-image-optimizer' ), "<a href='http://jpegclub.org/jpegtran/'>jpegtran</a>", "<a href='http://optipng.sourceforge.net/'>optipng</a>", "<a href='http://advsys.net/ken/utils.htm'>pngout</a>", "<a href='http://pngquant.org/'>pngquant</a>", "<a href='http://www.lcdf.org/gifsicle/'>gifsicle</a>", "<a href='https://developers.google.com/speed/webp/'>cwebp</a>", $msg, "<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>', "<a href='http://docs.ewww.io/'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>' ) . '</p></div>';
589
  ewwwio_memory( __FUNCTION__ );
590
  }
591
  }
@@ -643,6 +643,7 @@ function ewww_image_optimizer_path_check( $j = true, $o = true, $g = true, $p =
643
  $pngout = false;
644
  $pngquant = false;
645
  $webp = false;
 
646
  if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
647
  return array(
648
  'JPEGTRAN' => false,
@@ -866,6 +867,11 @@ function ewww_image_optimizer_md5check( $path ) {
866
  'd4f11e96733aed64a72e744843dcd0929e144a7fc97f40d405a034a72eb9bbc6', // optipng-mac 0.7.6, EWWW 2.8.0.
867
  '1ed9343194cfca0a1c32677c974192746adfd48cb4cea6a2df668452df0e68f7', // optipng-sol 0.7.6, EWWW 2.8.0.
868
  '03b86ce2c08e2cc78d76d3d3dd173986b498b055c3c19e13a97a7c3c674772c6', // optipng.exe 0.7.6, EWWW 2.8.0.
 
 
 
 
 
869
  // end optipng.
870
  'a2292c0085863a65c99cb41ff8418ce63033e162906df72e8fdde52f0633579b', // gifsicle linux 1.67, EWWW 1.2.0.
871
  'd7f9609b6fd0000b2eaad2bd0c3cb85476988b18705762e915bda3f2e6007801', // gifsicle-linux 1.68, EWWW 1.3.0.
@@ -892,6 +898,11 @@ function ewww_image_optimizer_md5check( $path ) {
892
  '3966e01474601059c6a13aefbe4f313c6cb6d49c799f7850966950892a9ab45a', // gifsicle-sol 1.87, EWWW 2.4.4.
893
  '40b86b2ea6642f4c921152923af1e631922b624f7d23189f53c659506c7179b5', // gifsicle.exe 1.87, EWWW 2.4.4.
894
  '3da9e1a764a459d78dc1468ba60d882ff042050a86f82d895777b172b50f2f19', // gifsicle.exe 1.87, EWWW 2.4.5.
 
 
 
 
 
895
  // end gifsicle.
896
  'bdea95497d6e60aae8938cae8e999ef74a255ad603531bf523dcdb531f61fc8f', // 20110722-bsd/i686/pngout.
897
  '57c09b3ebd7d4623d16f6056efd7951e8f98e2362a27993a7d865af677875c00', // 20110722-bsd-static/i686/pngout-static.
@@ -941,6 +952,11 @@ function ewww_image_optimizer_md5check( $path ) {
941
  '65dc20f05af588d948fc6f4df37c294f4a3a1c1ad207a8b56d13e6829773165a', // pngquant-mac 2.9.1, EWWW 3.4.0.
942
  'dbc9e12d5bb3e806aaf5e2c3d30d122d569069027a633485761cbf072cf2236d', // pngquant-sol 2.9.1, EWWW 3.4.0.
943
  '84e63e6f9f9630a1a0c3e782609349c12b8df9ea9d02c5a29230819379e56b3c', // pngquant.exe 2.8.1, EWWW 3.4.0.
 
 
 
 
 
944
  // end pngquant.
945
  'bf0e12f996802dc114a864e5150647ce41089a5a2b5e36c3a270ac848b655c26', // cwebp-fbsd 0.4.1, EWWW 2.0.0.
946
  '5349646072c3ef5f8b4588bbee8635e882c245439e2d86b863f04b7e27f4fafe', // cwebp-fbsd64 0.4.1, EWWW 2.0.0.
@@ -1012,13 +1028,77 @@ function ewww_image_optimizer_mimetype( $path, $case ) {
1012
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1013
  ewwwio_debug_message( "testing mimetype: $path" );
1014
  $type = false;
1015
- if ( 'i' === $case && preg_match( '/^RIFF.+WEBPVP8/', file_get_contents( $path, null, null, 0, 16 ) ) ) {
1016
- return 'image/webp';
1017
- }
1018
  // For S3 images/files, don't attempt to read the file, just use the quick (filename) mime check.
1019
  if ( 'i' === $case && strpos( $path, 's3' ) === 0 ) {
1020
  return ewww_image_optimizer_quick_mimetype( $path );
1021
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1022
  if ( function_exists( 'finfo_file' ) && defined( 'FILEINFO_MIME' ) ) {
1023
  // Create a finfo resource.
1024
  $finfo = finfo_open( FILEINFO_MIME );
@@ -1689,7 +1769,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1689
  // Toggle the convert process to ON.
1690
  $convert = true;
1691
  // Allow other plugins to mangle the image however they like prior to optimization.
1692
- do_action( 'ewww_image_optimizer_pre_optimization', $file, $type );
1693
  // Run the appropriate optimization/conversion for the mime-type.
1694
  switch ( $type ) {
1695
  case 'image/jpeg':
@@ -2432,7 +2512,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2432
  } // End switch().
2433
  // Allow other plugins to run operations on the images after optimization.
2434
  // NOTE: it is recommended to do any image modifications prior to optimization, otherwise you risk un-optimizing your images here.
2435
- do_action( 'ewww_image_optimizer_post_optimization', $file, $type );
2436
  // If their cloud api license limit has been exceeded.
2437
  if ( 'exceeded' == $result ) {
2438
  if ( strpos( $file, 's3' ) !== 0 && strpos( $file, 's3-uploads' ) === false && $s3_uploads_image && is_file( $file ) ) {
@@ -2443,8 +2523,10 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2443
  }
2444
  if ( ! empty( $new_size ) ) {
2445
  // Set correct file permissions.
2446
- $stat = stat( dirname( $file ) );
 
2447
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
 
2448
  chmod( $file, $perms );
2449
 
2450
  $results_msg = ewww_image_optimizer_update_table( $file, $new_size, $orig_size, $original, $backup_hash );
242
  sprintf( esc_html__( 'EWWW Image Optimizer could not install tools in %s', 'ewww-image-optimizer' ), htmlentities( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) . '.</strong> ' .
243
  esc_html__( 'Please adjust permissions or create the folder. If you have installed the tools elsewhere on your system, check the option to Use System Paths.', 'ewww-image-optimizer' ) . ' ' .
244
  /* translators: 1: Settings Page (link) 2: Installation Instructions (link) */
245
+ sprintf( esc_html__( 'For more details, visit the %1$s or the %2$s.', 'ewww-image-optimizer' ), "<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>', "<a href='https://docs.ewww.io/'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>' ) . '</p></div>';
246
  }
247
 
248
  /**
263
  sprintf( esc_html__( 'EWWW Image Optimizer could not install tools in %s', 'ewww-image-optimizer' ), htmlentities( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) . '.</strong> ' .
264
  esc_html__( 'Please adjust permissions or create the folder. If you have installed the tools elsewhere on your system, check the option to Use System Paths.', 'ewww-image-optimizer' ) . ' ' .
265
  /* translators: 1: Settings Page (link) 2: Installation Instructions (link) */
266
+ sprintf( esc_html__( 'For more details, visit the %1$s or the %2$s.', 'ewww-image-optimizer' ), "<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>', "<a href='https://docs.ewww.io/'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>' ) . '</p></div>';
267
  }
268
 
269
  /**
585
  }
586
  echo "<div id='ewww-image-optimizer-warning-opt-missing' class='error'><p>" .
587
  /* translators: 1-6: jpegtran, optipng, pngout, pngquant, gifsicle, and cwebp (links) 7: Settings Page (link) 8: Installation Instructions (link) */
588
+ sprintf( esc_html__( 'EWWW Image Optimizer uses %1$s, %2$s, %3$s, %4$s, %5$s, and %6$s. You are missing: %7$s. Please install via the %8$s or the %9$s.', 'ewww-image-optimizer' ), "<a href='http://jpegclub.org/jpegtran/'>jpegtran</a>", "<a href='http://optipng.sourceforge.net/'>optipng</a>", "<a href='http://advsys.net/ken/utils.htm'>pngout</a>", "<a href='http://pngquant.org/'>pngquant</a>", "<a href='http://www.lcdf.org/gifsicle/'>gifsicle</a>", "<a href='https://developers.google.com/speed/webp/'>cwebp</a>", $msg, "<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>', "<a href='https://docs.ewww.io/'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>' ) . '</p></div>';
589
  ewwwio_memory( __FUNCTION__ );
590
  }
591
  }
643
  $pngout = false;
644
  $pngquant = false;
645
  $webp = false;
646
+ ewww_image_optimizer_define_noexec();
647
  if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
648
  return array(
649
  'JPEGTRAN' => false,
867
  'd4f11e96733aed64a72e744843dcd0929e144a7fc97f40d405a034a72eb9bbc6', // optipng-mac 0.7.6, EWWW 2.8.0.
868
  '1ed9343194cfca0a1c32677c974192746adfd48cb4cea6a2df668452df0e68f7', // optipng-sol 0.7.6, EWWW 2.8.0.
869
  '03b86ce2c08e2cc78d76d3d3dd173986b498b055c3c19e13a97a7c3c674772c6', // optipng.exe 0.7.6, EWWW 2.8.0.
870
+ 'f01cba0ab658e08738315843ee635be273726bf102ae448416b3d8956843d864', // optipng-fbsd 0.7.7 EWWW 4.1.0.
871
+ '4404076a4f9119d4dfbb7acb00eb65345e804186a019c7136d8f8e87fb0cb997', // optipng-linux 0.7.7 EWWW 4.1.0.
872
+ '36535c1b262e0c457bbb0ed2bc71e812a49e26a6cada63b6acbd8d809c68a5a1', // optipng-mac 0.7.7 EWWW 4.1.0.
873
+ '41a4c78e6c97ea26836f4b021157b34f1812a9e5c2341502aad8cde942b18576', // optipng-sol 0.7.7 EWWW 4.1.0.
874
+ '6a321e07eca8e28fa8a969b5db3c1d3cc008a2064d636cf74762bbe4364b7b14', // optipng.exe 0.7.7 EWWW 4.1.0.
875
  // end optipng.
876
  'a2292c0085863a65c99cb41ff8418ce63033e162906df72e8fdde52f0633579b', // gifsicle linux 1.67, EWWW 1.2.0.
877
  'd7f9609b6fd0000b2eaad2bd0c3cb85476988b18705762e915bda3f2e6007801', // gifsicle-linux 1.68, EWWW 1.3.0.
898
  '3966e01474601059c6a13aefbe4f313c6cb6d49c799f7850966950892a9ab45a', // gifsicle-sol 1.87, EWWW 2.4.4.
899
  '40b86b2ea6642f4c921152923af1e631922b624f7d23189f53c659506c7179b5', // gifsicle.exe 1.87, EWWW 2.4.4.
900
  '3da9e1a764a459d78dc1468ba60d882ff042050a86f82d895777b172b50f2f19', // gifsicle.exe 1.87, EWWW 2.4.5.
901
+ '327c21635ea8c789e3e9533210e6baf372db27c7bbed3791881d74a7dd41cef9', // gifsicle-fbsd 1.91, EWWW 4.1.0.
902
+ '566f058b2043c4f3c8c049b0507bfa78dcb33dac52b132cade5f67bbb62d91e4', // gifsicle-linux 1.91, EWWW 4.1.0.
903
+ '03602b141432af2211882fc079ba15a773a7ec782c92755cb31279eb6d8b99d4', // gifsicle-mac 1.91, EWWW 4.1.0.
904
+ '5fcdd102146984e41b01a160d072dd36852d7be14ab569a323c47e7e56916d0d', // gifsicle-sol 1.91, EWWW 4.x.
905
+ '7156bfe16dc5e33af7facdc6847d268154ffeb75c0217517e4e188b58b293c6a', // gifsicle.exe 1.91, EWWW 4.1.0.
906
  // end gifsicle.
907
  'bdea95497d6e60aae8938cae8e999ef74a255ad603531bf523dcdb531f61fc8f', // 20110722-bsd/i686/pngout.
908
  '57c09b3ebd7d4623d16f6056efd7951e8f98e2362a27993a7d865af677875c00', // 20110722-bsd-static/i686/pngout-static.
952
  '65dc20f05af588d948fc6f4df37c294f4a3a1c1ad207a8b56d13e6829773165a', // pngquant-mac 2.9.1, EWWW 3.4.0.
953
  'dbc9e12d5bb3e806aaf5e2c3d30d122d569069027a633485761cbf072cf2236d', // pngquant-sol 2.9.1, EWWW 3.4.0.
954
  '84e63e6f9f9630a1a0c3e782609349c12b8df9ea9d02c5a29230819379e56b3c', // pngquant.exe 2.8.1, EWWW 3.4.0.
955
+ 'd6433dc6ecf6a0fdedf754782e6d5c9e494ddec762426a6d0b1896a220bd6d3f', // pngquant-fbsd 2.11.7 EWWW 4.1.0.
956
+ '40b0860abba39342fb64612a612e0f24571d259b6b83d7483af9a1d586950d79', // pngquant-linux 2.11.7 EWWW 4.1.0.
957
+ 'c924e11d9a3166afd5ed19165193c1351ff4a2cc993498f1f28c7daee829ca76', // pngquant-mac 2.11.7 EWWW 4.1.0.
958
+ '34534e69929e7fe267f77c55f487e419f76cc1d24e41fdb642f9671383012c56', // pngquant-sol 2.11.7 EWWW 4.1.0.
959
+ 'af7598aa09ba519ad15305a56011949db19c5b2176187662640bc0ebc4ddd19a', // pngquant.exe 2.11.7 EWWW 4.1.0.
960
  // end pngquant.
961
  'bf0e12f996802dc114a864e5150647ce41089a5a2b5e36c3a270ac848b655c26', // cwebp-fbsd 0.4.1, EWWW 2.0.0.
962
  '5349646072c3ef5f8b4588bbee8635e882c245439e2d86b863f04b7e27f4fafe', // cwebp-fbsd64 0.4.1, EWWW 2.0.0.
1028
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1029
  ewwwio_debug_message( "testing mimetype: $path" );
1030
  $type = false;
 
 
 
1031
  // For S3 images/files, don't attempt to read the file, just use the quick (filename) mime check.
1032
  if ( 'i' === $case && strpos( $path, 's3' ) === 0 ) {
1033
  return ewww_image_optimizer_quick_mimetype( $path );
1034
  }
1035
+ if ( 'i' === $case && preg_match( '/^RIFF.+WEBPVP8/', file_get_contents( $path, null, null, 0, 16 ) ) ) {
1036
+ /* return 'image/webp'; */
1037
+ }
1038
+ if ( 'i' === $case ) {
1039
+ $fhandle = fopen( $path, 'rb' );
1040
+ if ( $fhandle ) {
1041
+ // Read first 12 bytes, which equates to 24 hex characters.
1042
+ $magic = bin2hex( fread( $fhandle, 12 ) );
1043
+ if ( 0 === strpos( $magic, '52494646' ) && 16 === strpos( $magic, '57454250' ) ) {
1044
+ $type = 'image/webp';
1045
+ ewwwio_debug_message( "ewwwio type: $type" );
1046
+ return $type;
1047
+ }
1048
+ if ( 'ffd8ff' === substr( $magic, 0, 6 ) ) {
1049
+ $type = 'image/jpeg';
1050
+ ewwwio_debug_message( "ewwwio type: $type" );
1051
+ return $type;
1052
+ }
1053
+ if ( '89504e470d0a1a0a' === substr( $magic, 0, 16 ) ) {
1054
+ $type = 'image/png';
1055
+ ewwwio_debug_message( "ewwwio type: $type" );
1056
+ return $type;
1057
+ }
1058
+ if ( '474946383761' === substr( $magic, 0, 12 ) || '474946383961' === substr( $magic, 0, 12 ) ) {
1059
+ $type = 'image/gif';
1060
+ ewwwio_debug_message( "ewwwio type: $type" );
1061
+ return $type;
1062
+ }
1063
+ if ( '25504446' === substr( $magic, 0, 8 ) ) {
1064
+ $type = 'application/pdf';
1065
+ ewwwio_debug_message( "ewwwio type: $type" );
1066
+ return $type;
1067
+ }
1068
+ ewwwio_debug_message( "match not found for image: $magic" );
1069
+ } else {
1070
+ ewwwio_debug_message( 'could not open for reading' );
1071
+ }
1072
+ }
1073
+ if ( 'b' === $case ) {
1074
+ $fhandle = fopen( $path, 'rb' );
1075
+ if ( $fhandle ) {
1076
+ // Read first 4 bytes, which equates to 8 hex characters.
1077
+ $magic = bin2hex( fread( $fhandle, 4 ) );
1078
+ // Mac (Mach-O) binary.
1079
+ if ( 'cffaedfe' === $magic || 'feedface' === $magic || 'feedfacf' === $magic || 'cefaedfe' === $magic || 'cafebabe' === $magic ) {
1080
+ $type = 'application/x-executable';
1081
+ ewwwio_debug_message( "ewwwio type: $type" );
1082
+ return $type;
1083
+ }
1084
+ // ELF (Linux or BSD) binary.
1085
+ if ( '7f454c46' === $magic ) {
1086
+ $type = 'application/x-executable';
1087
+ ewwwio_debug_message( "ewwwio type: $type" );
1088
+ return $type;
1089
+ }
1090
+ // MS (DOS) binary.
1091
+ if ( '4d5a9000' === $magic ) {
1092
+ $type = 'application/x-executable';
1093
+ ewwwio_debug_message( "ewwwio type: $type" );
1094
+ return $type;
1095
+ }
1096
+ ewwwio_debug_message( "match not found for binary: $magic" );
1097
+ } else {
1098
+ ewwwio_debug_message( 'could not open for reading' );
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 );
1769
  // Toggle the convert process to ON.
1770
  $convert = true;
1771
  // Allow other plugins to mangle the image however they like prior to optimization.
1772
+ do_action( 'ewww_image_optimizer_pre_optimization', $file, $type, $fullsize );
1773
  // Run the appropriate optimization/conversion for the mime-type.
1774
  switch ( $type ) {
1775
  case 'image/jpeg':
2512
  } // End switch().
2513
  // Allow other plugins to run operations on the images after optimization.
2514
  // NOTE: it is recommended to do any image modifications prior to optimization, otherwise you risk un-optimizing your images here.
2515
+ do_action( 'ewww_image_optimizer_post_optimization', $file, $type, $fullsize );
2516
  // If their cloud api license limit has been exceeded.
2517
  if ( 'exceeded' == $result ) {
2518
  if ( strpos( $file, 's3' ) !== 0 && strpos( $file, 's3-uploads' ) === false && $s3_uploads_image && is_file( $file ) ) {
2523
  }
2524
  if ( ! empty( $new_size ) ) {
2525
  // Set correct file permissions.
2526
+ $stat = stat( dirname( $file ) );
2527
+ ewwwio_debug_message( 'folder mode: ' . $stat['mode'] );
2528
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2529
+ ewwwio_debug_message( "attempting chmod with $perms" );
2530
  chmod( $file, $perms );
2531
 
2532
  $results_msg = ewww_image_optimizer_update_table( $file, $new_size, $orig_size, $original, $backup_hash );