WebP Express - Version 0.17.1

Version Description

(released: 3 Oct 2019)

  • Fixed NGINX rules in FAQ (added xdestination for the create webp upon request functionality)
  • Fixed issue with Alter HTML. Thanks to @jonathanernst for discovering issue and supplying the patch.
  • WebP Express now works on WP Engine. Check out the new "I am on WP Engine" section in the FAQ
  • Miscellaneous bug fixes

For more info, see the closed issues on the 0.17.1 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/27?closed=1

Download this release

Release Info

Developer rosell.dk
Plugin Icon 128x128 WebP Express
Version 0.17.1
Comparing to
See all releases

Code changes from version 0.17.0 to 0.17.1

README.md CHANGED
@@ -132,8 +132,7 @@ Don't fret - you have options!
132
  - You can try to get one of the local converters working. Check out [this page](https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters) on the webp-convert wiki. There is also this [test/troubleshooting script](https://github.com/rosell-dk/webp-convert/wiki/A-PHP-script-for-the-webhost) which is handy when messing around with this.
133
  - Finally, if you have access to another server and are comfortable with installing projects with composer, you can install [webp-convert-cloud-service](https://github.com/rosell-dk/webp-convert-cloud-service). It's open source.
134
 
135
- Of course, there is also the option of using another plugin altogether. I can recommend [Optimole](https://optimole.pxf.io/20b0M).
136
-
137
 
138
  ### It doesn't work - Although test conversions work, it still serves jpeg images.
139
  Actually, you might be mistaking, so first, make sure that you didn't make the very common mistake of thinking that something with the URL *example.com/image.jpg* must be a jpeg image. The plugin serves webp images on same URL as the original (unconverted) images, so do not let appearances fool you! Confused? See next FAQ item.
@@ -237,7 +236,7 @@ location ~* ^/?wp-content/.*\.(png|jpe?g)$ {
237
  location ~* ^/?wp-content/.*\.(png|jpe?g)\.webp$ {
238
  try_files
239
  $uri
240
- /wp-content/plugins/webp-express/wod/webp-realizer.php?wp-content=wp-content
241
  ;
242
  }
243
  # ------------------- (WebP Express rules ends here)
@@ -491,6 +490,20 @@ To make *WebP Express* work on a free Cloudflare account, you have the following
491
 
492
  3. You can switch operation mode to "CDN friendly" and use HTML altering.
493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  ### WebP Express / ShortPixel setup
495
  Here is a recipe for using WebP Express together with ShortPixel, such that WebP Express generates the webp's, and ShortPixel only is used to create `<picture>` tags, when it detects a webp image in the same folder as an original.
496
 
@@ -638,11 +651,22 @@ Here are my current plans ahead: 0.17 will probably be a file manager-like inter
638
 
639
  If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
640
 
 
 
 
 
 
 
 
 
 
 
641
  ## Changes in 0.17.0
642
  *(released: 27 sep 2019)*
643
 
644
  * Cwebp conversion method runs on more systems (not subject to open_basedir restrictions and also tries "pure" cwebp command). Thanks to cng11 for reaching out so I spotted this.
645
  * Ewww conversion method no longer does a remote api-key check for each conversion - so it is faster. If an ewww conversions fails due to a non-functional key, the key will not be tried again (until next time the options are saved)
 
646
 
647
  ## Changes in 0.16.0
648
  *(released: 24 sep 2019)*
132
  - You can try to get one of the local converters working. Check out [this page](https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters) on the webp-convert wiki. There is also this [test/troubleshooting script](https://github.com/rosell-dk/webp-convert/wiki/A-PHP-script-for-the-webhost) which is handy when messing around with this.
133
  - Finally, if you have access to another server and are comfortable with installing projects with composer, you can install [webp-convert-cloud-service](https://github.com/rosell-dk/webp-convert-cloud-service). It's open source.
134
 
135
+ Of course, there is also the option of using another plugin altogether. I can recommend Optimole. If you want to try that out and want to support me in the process, [follow this link](https://optimole.pxf.io/20b0M). It is an affiliate link and will give me a reward in case you decide to sign up.
 
136
 
137
  ### It doesn't work - Although test conversions work, it still serves jpeg images.
138
  Actually, you might be mistaking, so first, make sure that you didn't make the very common mistake of thinking that something with the URL *example.com/image.jpg* must be a jpeg image. The plugin serves webp images on same URL as the original (unconverted) images, so do not let appearances fool you! Confused? See next FAQ item.
236
  location ~* ^/?wp-content/.*\.(png|jpe?g)\.webp$ {
237
  try_files
238
  $uri
239
+ /wp-content/plugins/webp-express/wod/webp-realizer.php?xdestination=x$request_filename&wp-content=wp-content
240
  ;
241
  }
242
  # ------------------- (WebP Express rules ends here)
490
 
491
  3. You can switch operation mode to "CDN friendly" and use HTML altering.
492
 
493
+ ### I am on WP Engine
494
+ From version 0.17.1 on WebP Express works with WP engine and this combination will be tested before each release.
495
+
496
+ You can use the plugin both in "Varied image responses" mode and in "CDN friendly mode".
497
+
498
+ To make the redirection work, you must:
499
+ 1) Grab the nginx configuration found in the "I am on Nginx/OpenResty" section in this FAQ. Use the "try_files" variant.
500
+ 2) Contact help center and ask them to insert that configuration.
501
+ 3) Make sure the settings match this configuration. Follow the "beware" statements in the "I am on Nginx/OpenResty" section.
502
+
503
+ WebP Express tweaks the workings of "Redirect to converter" a bit for WP engine. That PHP script usually serves the webp directly, along with a Vary:Accept header. This header is however overwritten by the caching machinery on WP engine. As a work-around, I modified the response of the script for WP engine. Instead of serving the image, it serves a redirect to itself. As there now IS a corresponding webp, this repeated request will not be redirected to the PHP script, but directly to the webp. And headers are OK for those redirects. You can hit the "Live test" button next to "Enable redirection to converter?" to verify that this works as just described.
504
+
505
+ If you (contrary to this headline!) are in fact not on WP Engine, but might want to be, I have an affiliate link for you. It will give you 3 months free and it will give me a reward too, if you should decide to stay there. Here you go: [Get 3 months free when you sign up for WP Engine.](https://shareasale.com/r.cfm?b=1343154&u=2194916&m=41388&urllink=&afftrack=)
506
+
507
  ### WebP Express / ShortPixel setup
508
  Here is a recipe for using WebP Express together with ShortPixel, such that WebP Express generates the webp's, and ShortPixel only is used to create `<picture>` tags, when it detects a webp image in the same folder as an original.
509
 
651
 
652
  If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
653
 
654
+ ## Changes in 0.17.1
655
+ *(released: 3 Oct 2019)*
656
+
657
+ - Fixed NGINX rules in FAQ (added xdestination for the create webp upon request functionality)
658
+ - Fixed issue with Alter HTML. Thanks to @jonathanernst for discovering issue and supplying the patch.
659
+ - WebP Express now works on WP Engine. Check out the new "I am on WP Engine" section in the FAQ
660
+ - Miscellaneous bug fixes
661
+
662
+ For more info, see the closed issues on the 0.17.1 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/27?closed=1
663
+
664
  ## Changes in 0.17.0
665
  *(released: 27 sep 2019)*
666
 
667
  * Cwebp conversion method runs on more systems (not subject to open_basedir restrictions and also tries "pure" cwebp command). Thanks to cng11 for reaching out so I spotted this.
668
  * Ewww conversion method no longer does a remote api-key check for each conversion - so it is faster. If an ewww conversions fails due to a non-functional key, the key will not be tried again (until next time the options are saved)
669
+ * Updated cwebp binaries to version 1.0.3
670
 
671
  ## Changes in 0.16.0
672
  *(released: 24 sep 2019)*
README.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://ko-fi.com/rosell
4
  Tags: webp, images, performance
5
  Requires at least: 4.0
6
  Tested up to: 5.2
7
- Stable tag: 0.17.0
8
  Requires PHP: 5.6
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -134,7 +134,7 @@ Don't fret - you have options!
134
  - You can try to get one of the local converters working. Check out [this page](https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters) on the webp-convert wiki. There is also this [test/troubleshooting script](https://github.com/rosell-dk/webp-convert/wiki/A-PHP-script-for-the-webhost) which is handy when messing around with this.
135
  - Finally, if you have access to another server and are comfortable with installing projects with composer, you can install [webp-convert-cloud-service](https://github.com/rosell-dk/webp-convert-cloud-service). It's open source.
136
 
137
- Of course, there is also the option of using another plugin altogether. I can recommend [Optimole](https://optimole.pxf.io/20b0M).
138
 
139
  = It doesn't work - Although test conversions work, it still serves jpeg images =
140
  Actually, you might be mistaking, so first, make sure that you didn't make the very common mistake of thinking that something with the URL *example.com/image.jpg* must be a jpeg image. The plugin serves webp images on same URL as the original (unconverted) images, so do not let appearances fool you! Confused? See next FAQ item.
@@ -162,7 +162,7 @@ WebP Express has three ways of distributing webp to webp-enabled browsers while
162
  Can some of these go wrong?
163
  Yes. All!
164
 
165
- #### Method 1: Varied image responses
166
  The "Varied image responses" method adds rules to the `.htaccess` which redirects jpegs and pngs to the corresponding webps (if they exist). The rules have a condition that makes sure they only trigger for browsers supports webp images (this is established by examining the "accept" header).
167
 
168
  I the method "varied image responses" because the response on a given image URL *varies* (the webp is served on the same URL as the jpeg/png).
@@ -180,12 +180,12 @@ I do not believe it can go wrong in other ways. To be certain, please check out
180
 
181
  Since WebP Express 0.15.0 you can use the "Live test" button to check that browsers not supporting webp gets the original files and that the Vary:Accept header is returned. Note however that it may not detect CDN caching problems if the CDN doesn't cache a new image immediately - and across all its nodes.
182
 
183
- #### Method 2: Altering HTML to use picture tags
184
  IMG tags are replaced with PICTURE tags which has two sources. One of them points to the webp and has the "content-type" set to "image/webp". The other points to the original. The browser will select the webp source if it supports webp and the other source if it doesn't.
185
 
186
  Method 2 can go wrong on old browser that doesn't support the picture tag syntax. However, simply enable the "Dynamically load picturefill.js on older browsers" option, and it will take care of that issue.
187
 
188
- #### Method 3: Altering HTML to point directly to webps in webp enabled browsers
189
  In this solution, the URLs in the HTML are modified for browsers that supports webp. Again, this is determined by examining the "accept" header. So, actually the complete page HTML varies with this method.
190
 
191
  Method 3 can go wrong if you are using a page caching plugin if that plugin does not create a separate webp cache for webp-enabled browsers. The *Cache Enabler* plugin handles this. I don't believe there are other page caching plugins that does. There is a FAQ section in this FAQ describing how to set *Cache Enabler* up to work in tandem with WebP Express.
@@ -238,7 +238,7 @@ location ~* ^/?wp-content/.*\.(png|jpe?g)$ {
238
  location ~* ^/?wp-content/.*\.(png|jpe?g)\.webp$ {
239
  try_files
240
  $uri
241
- /wp-content/plugins/webp-express/wod/webp-realizer.php?wp-content=wp-content
242
  ;
243
  }
244
  &#35; ------------------- (WebP Express rules ends here)
@@ -432,7 +432,7 @@ You can also make it "work" on some CDN's by bypassing cache for images. But I r
432
  *Status of some CDN's*:
433
 
434
  - *KeyCDN*: Does not support varied image responses. I have added a feature request [here](https://community.keycdn.com/t/support-vary-accept-header-for-conditional-webp/1864). You can give it a +1 if you like!
435
- - *Cloudflare*: See the "I am on Cloudflare" item
436
  - *Cloudfront*: Works, but needs to be configured to forward the accept header. Go to *Distribution settings*, find the *Behavior tab*, select the Behavior and click the Edit button. Choose *Whitelist* from *Forward Headers* and then add the "Accept" header to the whitelist.
437
 
438
  I shall add more to the list. You are welcome to help out [here](https://wordpress.org/support/topic/which-cdns-works-in-standard-mode/).
@@ -490,7 +490,21 @@ To make *WebP Express* work on a free Cloudflare account, you have the following
490
 
491
  3. You can switch operation mode to "CDN friendly" and use HTML altering.
492
 
493
- ### WebP Express / ShortPixel setup
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  Here is a recipe for using WebP Express together with ShortPixel, such that WebP Express generates the webp's, and ShortPixel only is used to create `<picture>` tags, when it detects a webp image in the same folder as an original.
495
 
496
  **There is really no need to do this anymore, because WebP Express is now capable of replacing img tags with picture tags (check out the Alter HTML option)**
@@ -645,6 +659,16 @@ Easy enough! - [Go here!](https://ko-fi.com/rosell). Or [here](https://buymeacof
645
 
646
  == Changelog ==
647
 
 
 
 
 
 
 
 
 
 
 
648
  = 0.17.0 =
649
  *(released: 27 sep 2019)*
650
 
@@ -1026,6 +1050,9 @@ For older releases, check out changelog.txt
1026
 
1027
  == Upgrade Notice ==
1028
 
 
 
 
1029
  = 0.17.0 =
1030
  * Improved Cwebp availability and Ewww performance. And updated cwebp binaries to version 1.0.3
1031
 
4
  Tags: webp, images, performance
5
  Requires at least: 4.0
6
  Tested up to: 5.2
7
+ Stable tag: 0.17.1
8
  Requires PHP: 5.6
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
134
  - You can try to get one of the local converters working. Check out [this page](https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters) on the webp-convert wiki. There is also this [test/troubleshooting script](https://github.com/rosell-dk/webp-convert/wiki/A-PHP-script-for-the-webhost) which is handy when messing around with this.
135
  - Finally, if you have access to another server and are comfortable with installing projects with composer, you can install [webp-convert-cloud-service](https://github.com/rosell-dk/webp-convert-cloud-service). It's open source.
136
 
137
+ Of course, there is also the option of using another plugin altogether. I can recommend Optimole. If you want to try that out and want to support me in the process, [follow this link](https://optimole.pxf.io/20b0M). It is an affiliate link and will give me a reward in case you decide to sign up.
138
 
139
  = It doesn't work - Although test conversions work, it still serves jpeg images =
140
  Actually, you might be mistaking, so first, make sure that you didn't make the very common mistake of thinking that something with the URL *example.com/image.jpg* must be a jpeg image. The plugin serves webp images on same URL as the original (unconverted) images, so do not let appearances fool you! Confused? See next FAQ item.
162
  Can some of these go wrong?
163
  Yes. All!
164
 
165
+ **Method 1: Varied image responses**
166
  The "Varied image responses" method adds rules to the `.htaccess` which redirects jpegs and pngs to the corresponding webps (if they exist). The rules have a condition that makes sure they only trigger for browsers supports webp images (this is established by examining the "accept" header).
167
 
168
  I the method "varied image responses" because the response on a given image URL *varies* (the webp is served on the same URL as the jpeg/png).
180
 
181
  Since WebP Express 0.15.0 you can use the "Live test" button to check that browsers not supporting webp gets the original files and that the Vary:Accept header is returned. Note however that it may not detect CDN caching problems if the CDN doesn't cache a new image immediately - and across all its nodes.
182
 
183
+ **Method 2: Altering HTML to use picture tags**
184
  IMG tags are replaced with PICTURE tags which has two sources. One of them points to the webp and has the "content-type" set to "image/webp". The other points to the original. The browser will select the webp source if it supports webp and the other source if it doesn't.
185
 
186
  Method 2 can go wrong on old browser that doesn't support the picture tag syntax. However, simply enable the "Dynamically load picturefill.js on older browsers" option, and it will take care of that issue.
187
 
188
+ **Method 3: Altering HTML to point directly to webps in webp enabled browsers**
189
  In this solution, the URLs in the HTML are modified for browsers that supports webp. Again, this is determined by examining the "accept" header. So, actually the complete page HTML varies with this method.
190
 
191
  Method 3 can go wrong if you are using a page caching plugin if that plugin does not create a separate webp cache for webp-enabled browsers. The *Cache Enabler* plugin handles this. I don't believe there are other page caching plugins that does. There is a FAQ section in this FAQ describing how to set *Cache Enabler* up to work in tandem with WebP Express.
238
  location ~* ^/?wp-content/.*\.(png|jpe?g)\.webp$ {
239
  try_files
240
  $uri
241
+ /wp-content/plugins/webp-express/wod/webp-realizer.php?xdestination=x$request_filename&wp-content=wp-content
242
  ;
243
  }
244
  &#35; ------------------- (WebP Express rules ends here)
432
  *Status of some CDN's*:
433
 
434
  - *KeyCDN*: Does not support varied image responses. I have added a feature request [here](https://community.keycdn.com/t/support-vary-accept-header-for-conditional-webp/1864). You can give it a +1 if you like!
435
+ - *Cloudflare*: See the "I am on Cloudflare" section
436
  - *Cloudfront*: Works, but needs to be configured to forward the accept header. Go to *Distribution settings*, find the *Behavior tab*, select the Behavior and click the Edit button. Choose *Whitelist* from *Forward Headers* and then add the "Accept" header to the whitelist.
437
 
438
  I shall add more to the list. You are welcome to help out [here](https://wordpress.org/support/topic/which-cdns-works-in-standard-mode/).
490
 
491
  3. You can switch operation mode to "CDN friendly" and use HTML altering.
492
 
493
+ = I am on WP Engine =
494
+ From version 0.17.1 on WebP Express works with WP engine and this combination will be tested before each release.
495
+
496
+ You can use the plugin both in "Varied image responses" mode and in "CDN friendly mode".
497
+
498
+ To make the redirection work, you must:
499
+ 1) Grab the nginx configuration found in the "I am on Nginx/OpenResty" section in this FAQ. Use the "try_files" variant.
500
+ 2) Contact help center and ask them to insert that configuration.
501
+ 3) Make sure the settings match this configuration. Follow the "beware" statements in the "I am on Nginx/OpenResty" section.
502
+
503
+ WebP Express tweaks the workings of "Redirect to converter" a bit for WP engine. That PHP script usually serves the webp directly, along with a Vary:Accept header. This header is however overwritten by the caching machinery on WP engine. As a work-around, I modified the response of the script for WP engine. Instead of serving the image, it serves a redirect to itself. As there now IS a corresponding webp, this repeated request will not be redirected to the PHP script, but directly to the webp. And headers are OK for those redirects. You can hit the "Live test" button next to "Enable redirection to converter?" to verify that this works as just described.
504
+
505
+ If you (contrary to this headline!) are in fact not on WP Engine, but might want to be, I have an affiliate link for you. It will give you 3 months free and it will give me a reward too, if you should decide to stay there. Here you go: [Get 3 months free when you sign up for WP Engine.](https://shareasale.com/r.cfm?b=1343154&u=2194916&m=41388&urllink=&afftrack=)
506
+
507
+ = WebP Express / ShortPixel setup =
508
  Here is a recipe for using WebP Express together with ShortPixel, such that WebP Express generates the webp's, and ShortPixel only is used to create `<picture>` tags, when it detects a webp image in the same folder as an original.
509
 
510
  **There is really no need to do this anymore, because WebP Express is now capable of replacing img tags with picture tags (check out the Alter HTML option)**
659
 
660
  == Changelog ==
661
 
662
+ = 0.17.1 =
663
+ *(released: 3 Oct 2019)*
664
+
665
+ * Fixed NGINX rules in FAQ (added xdestination for the create webp upon request functionality)
666
+ * Fixed issue with Alter HTML. Thanks to @jonathanernst for discovering issue and supplying the patch.
667
+ * WebP Express now works on WP Engine. Check out the new "I am on WP Engine" section in the FAQ
668
+ * Miscellaneous bug fixes
669
+
670
+ For more info, see the closed issues on the 0.17.1 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/27?closed=1
671
+
672
  = 0.17.0 =
673
  *(released: 27 sep 2019)*
674
 
1050
 
1051
  == Upgrade Notice ==
1052
 
1053
+ = 0.17.1 =
1054
+ * Miscellaneous bug fixes. Including the NGINX rules in the FAQ (added "xdestination" argument to webp-realizer.php). Now works with WP Engine.
1055
+
1056
  = 0.17.0 =
1057
  * Improved Cwebp availability and Ewww performance. And updated cwebp binaries to version 1.0.3
1058
 
changelog.txt CHANGED
@@ -1,3 +1,13 @@
 
 
 
 
 
 
 
 
 
 
1
  = 0.17.0 =
2
  *(released: 27 sep 2019)*
3
 
1
+ = 0.17.1 =
2
+ *(released: 3 Oct 2019)*
3
+
4
+ * Fixed NGINX rules in FAQ (added xdestination for the create webp upon request functionality)
5
+ * Fixed issue with Alter HTML. Thanks to @jonathanernst for discovering issue and supplying the patch.
6
+ * WebP Express now works on WP Engine. Check out the new "I am on WP Engine" section in the FAQ
7
+ * Miscellaneous bug fixes
8
+
9
+ For more info, see the closed issues on the 0.17.1 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/27?closed=1
10
+
11
  = 0.17.0 =
12
  *(released: 27 sep 2019)*
13
 
lib/classes/AlterHtmlHelper.php CHANGED
@@ -208,6 +208,10 @@ class AlterHtmlHelper
208
  */
209
  public static function getWebPUrl($sourceUrl, $returnValueOnFail)
210
  {
 
 
 
 
211
 
212
  // Fail for webp-disabled browsers (when "only-for-webp-enabled-browsers" is set)
213
  if ((self::$options['only-for-webp-enabled-browsers']) && (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') === false)) {
@@ -219,11 +223,6 @@ class AlterHtmlHelper
219
  return $returnValueOnFail;
220
  }
221
 
222
- // Get the options
223
- if (!isset(self::$options)) {
224
- self::$options = json_decode(Option::getOption('webp-express-alter-html-options', null), true);
225
- }
226
-
227
  // Fail if the image type isn't enabled
228
  switch (self::$options['image-types']) {
229
  case 0:
208
  */
209
  public static function getWebPUrl($sourceUrl, $returnValueOnFail)
210
  {
211
+ // Get the options
212
+ if (!isset(self::$options)) {
213
+ self::$options = json_decode(Option::getOption('webp-express-alter-html-options', null), true);
214
+ }
215
 
216
  // Fail for webp-disabled browsers (when "only-for-webp-enabled-browsers" is set)
217
  if ((self::$options['only-for-webp-enabled-browsers']) && (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') === false)) {
223
  return $returnValueOnFail;
224
  }
225
 
 
 
 
 
 
226
  // Fail if the image type isn't enabled
227
  switch (self::$options['image-types']) {
228
  case 0:
lib/classes/Convert.php CHANGED
@@ -79,12 +79,12 @@ class Convert
79
  $checking = 'destination';
80
  $destination = self::getDestination($source, $config);
81
 
82
- $destination = SanityCheck::absPathIsInDocRoot($destination);
83
 
84
  // Check log dir
85
  // -------------------------------
86
  $checking = 'conversion log dir';
87
- $logDir = SanityCheck::absPathIsInDocRoot(Paths::getWebPExpressContentDirAbs() . '/log');
88
 
89
 
90
  } catch (\Exception $e) {
79
  $checking = 'destination';
80
  $destination = self::getDestination($source, $config);
81
 
82
+ $destination = SanityCheck::absPath($destination);
83
 
84
  // Check log dir
85
  // -------------------------------
86
  $checking = 'conversion log dir';
87
+ $logDir = SanityCheck::absPath(Paths::getWebPExpressContentDirAbs() . '/log');
88
 
89
 
90
  } catch (\Exception $e) {
lib/classes/ConvertHelperIndependent.php CHANGED
@@ -571,7 +571,7 @@ APACHE
571
  $text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
572
 
573
  // TODO: Put version number somewhere else. Ie \WebPExpress\VersionNumber::version
574
- $text = 'WebP Express 0.17.0. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
575
 
576
  $logFile = self::getLogFilename($source, $logDir);
577
 
571
  $text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
572
 
573
  // TODO: Put version number somewhere else. Ie \WebPExpress\VersionNumber::version
574
+ $text = 'WebP Express 0.17.1. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
575
 
576
  $logFile = self::getLogFilename($source, $logDir);
577
 
lib/classes/PlatformInfo.php CHANGED
@@ -11,10 +11,12 @@ class PlatformInfo
11
  return ( strpos( $server, 'microsoft-iis') !== false );
12
  }
13
 
 
 
 
14
  public static function isApache()
15
  {
16
- $server = strtolower($_SERVER['SERVER_SOFTWARE']);
17
- return ( strpos( $server, 'apache') !== false );
18
  }
19
 
20
  public static function isLiteSpeed()
11
  return ( strpos( $server, 'microsoft-iis') !== false );
12
  }
13
 
14
+ /**
15
+ * Check if Apache handles the PHP requests (Note that duel setups are possible and ie Nginx could be handling the image requests).
16
+ */
17
  public static function isApache()
18
  {
19
+ return (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false);
 
20
  }
21
 
22
  public static function isLiteSpeed()
lib/classes/SanityCheck.php CHANGED
@@ -12,7 +12,9 @@ class SanityCheck
12
  private static function fail($errorMsg, $input)
13
  {
14
  // sanitize input before calling error_log(), it might be sent to file, mail, syslog etc.
 
15
  error_log($errorMsg . '. input:' . Sanitize::removeNUL($input));
 
16
  //error_log(get_magic_quotes_gpc() ? 'on' :'off');
17
  throw new SanityException($errorMsg); // . '. Check debug.log for details (and make sure debugging is enabled)'
18
  }
@@ -268,7 +270,9 @@ class SanityCheck
268
 
269
 
270
  /**
271
- * Test that absolute path is in document root.
 
 
272
  *
273
  * TODO: Instead of this method, we shoud check
274
  *
@@ -279,26 +283,44 @@ class SanityCheck
279
  {
280
  self::absPath($input);
281
 
 
 
 
 
 
 
 
282
  $docRoot = self::absPath($_SERVER["DOCUMENT_ROOT"]);
283
  $docRoot = rtrim($docRoot, '/');
284
- $docRoot = self::absPathExistsAndIsDir($docRoot);
 
 
 
 
 
 
 
 
 
 
 
285
 
286
  // Use realpath to expand symbolic links and check if it exists
287
  $docRootSymLinksExpanded = @realpath($docRoot);
288
  if ($docRootSymLinksExpanded === false) {
289
- $errorMsg = 'Cannot find document root';
290
- self::fail($errorMsg, $input);
 
 
 
 
291
  }
292
  $docRootSymLinksExpanded = rtrim($docRootSymLinksExpanded, '/');
293
  $docRootSymLinksExpanded = self::absPathExists($docRootSymLinksExpanded, 'Document root does not exist!');
294
  $docRootSymLinksExpanded = self::absPathExistsAndIsDir($docRootSymLinksExpanded, 'Document root is not a directory!');
295
 
296
- try {
297
- // try without symlinks expanded
298
- self::pathBeginsWith($input, $docRoot . '/', $errorMsg);
299
- } catch (SanityException $e) {
300
- self::pathBeginsWithSymLinksExpanded($input, $docRootSymLinksExpanded . '/', $errorMsg);
301
- }
302
 
303
  return $input;
304
  }
12
  private static function fail($errorMsg, $input)
13
  {
14
  // sanitize input before calling error_log(), it might be sent to file, mail, syslog etc.
15
+ //error_log($errorMsg . '. input:' . Sanitize::removeNUL($input) . 'backtrace: ' . print_r(debug_backtrace(), true));
16
  error_log($errorMsg . '. input:' . Sanitize::removeNUL($input));
17
+
18
  //error_log(get_magic_quotes_gpc() ? 'on' :'off');
19
  throw new SanityException($errorMsg); // . '. Check debug.log for details (and make sure debugging is enabled)'
20
  }
270
 
271
 
272
  /**
273
+ * Test that path is an absolute path and it is in document root.
274
+ *
275
+ * If DOCUMENT_ROOT is not available, then only the absPath check will be done.
276
  *
277
  * TODO: Instead of this method, we shoud check
278
  *
283
  {
284
  self::absPath($input);
285
 
286
+ if (!isset($_SERVER["DOCUMENT_ROOT"])) {
287
+ return $input;
288
+ }
289
+ if ($_SERVER["DOCUMENT_ROOT"] == '') {
290
+ return $input;
291
+ }
292
+
293
  $docRoot = self::absPath($_SERVER["DOCUMENT_ROOT"]);
294
  $docRoot = rtrim($docRoot, '/');
295
+
296
+ try {
297
+ $docRoot = self::absPathExistsAndIsDir($docRoot);
298
+ } catch (SanityException $e) {
299
+ return $input;
300
+ }
301
+
302
+ // See if $filePath begins with $dirPath + '/'. If it does, we are done and OK!
303
+ if (strpos($input, $docRoot . '/') === 0) {
304
+ return $input;
305
+ }
306
+
307
 
308
  // Use realpath to expand symbolic links and check if it exists
309
  $docRootSymLinksExpanded = @realpath($docRoot);
310
  if ($docRootSymLinksExpanded === false) {
311
+ // probably outside open basedir restriction.
312
+ //$errorMsg = 'Cannot resolve document root';
313
+ //self::fail($errorMsg, $input);
314
+
315
+ // Cannot resolve document root, so cannot test if in document root
316
+ return $input;
317
  }
318
  $docRootSymLinksExpanded = rtrim($docRootSymLinksExpanded, '/');
319
  $docRootSymLinksExpanded = self::absPathExists($docRootSymLinksExpanded, 'Document root does not exist!');
320
  $docRootSymLinksExpanded = self::absPathExistsAndIsDir($docRootSymLinksExpanded, 'Document root is not a directory!');
321
 
322
+ $errorMsg = 'Path is outside resolved document root (' . $docRootSymLinksExpanded . ')';
323
+ self::pathBeginsWithSymLinksExpanded($input, $docRootSymLinksExpanded . '/', $errorMsg);
 
 
 
 
324
 
325
  return $input;
326
  }
lib/classes/SelfTestHelper.php CHANGED
@@ -50,22 +50,22 @@ class SelfTestHelper
50
 
51
  public static function copyFile($source, $destination)
52
  {
53
- $result = [];
54
  if (@copy($source, $destination)) {
55
- return [true, $result];
56
  } else {
57
- $result[] = 'Failed to copy *' . $source . '* to *' . $destination . '*';
58
  if (!@file_exists($source)) {
59
- $result[] = 'The source file was not found';
60
  } else {
61
  if (!@file_exists(dirname($destination))) {
62
- $result[] = 'The destination folder does not exist!';
63
  } else {
64
- $result[] = 'This is probably a permission issue. Check that your webserver has permission to ' .
65
  'write files in the directory (*' . dirname($destination) . '*)';
66
  }
67
  }
68
- return [false, $result];
69
  }
70
  }
71
 
@@ -84,7 +84,7 @@ class SelfTestHelper
84
  {
85
  // TODO: Copy to a subfolder instead
86
  // TODO: Use smaller jpeg / pngs please.
87
- $result = [];
88
  switch ($imageType) {
89
  case 'jpeg':
90
  $fileNameToCopy = 'very-small.jpg';
@@ -96,30 +96,30 @@ class SelfTestHelper
96
  $testSource = Paths::getPluginDirAbs() . '/webp-express/test/' . $fileNameToCopy;
97
  $filenameOfDestination = self::randomDigitsAndLetters(6) . '.' . strtoupper($imageType);
98
  //$filenameOfDestination = self::randomDigitsAndLetters(6) . '.' . $imageType;
99
- $result[] = 'Copying ' . strtoupper($imageType) . ' to ' . $rootId . ' folder (*webp-express-test-images/' . $filenameOfDestination . '*)';
100
 
101
  $destDir = Paths::getAbsDirById($rootId) . '/webp-express-test-images';
102
  $destination = $destDir . '/' . $filenameOfDestination;
103
 
104
  if (!@file_exists($destDir)) {
105
  if (!@mkdir($destDir)) {
106
- $result[count($result) - 1] .= '. FAILED';
107
- $result[] = 'Failed to create folder for test images: ' . $destDir;
108
- return [$result, false, ''];
109
  }
110
  }
111
 
112
  list($success, $errors) = self::copyFile($testSource, $destination);
113
  if (!$success) {
114
- $result[count($result) - 1] .= '. FAILED';
115
- $result = array_merge($result, $errors);
116
- return [$result, false, ''];
117
  } else {
118
- $result[count($result) - 1] .= '. ok!';
119
- $result[] = 'We now have a ' . $imageType . ' stored here:';
120
- $result[] = '*' . $destination . '*';
121
  }
122
- return [$result, true, $filenameOfDestination];
123
  }
124
 
125
  public static function copyTestImageToUploadFolder($imageType = 'jpeg')
@@ -129,25 +129,25 @@ class SelfTestHelper
129
 
130
  public static function copyDummyWebPToCacheFolder($rootId, $destinationFolder, $destinationExtension, $destinationStructure, $sourceFileName, $imageType = 'jpeg')
131
  {
132
- $result = [];
133
  $dummyWebP = Paths::getPluginDirAbs() . '/webp-express/test/test.jpg.webp';
134
 
135
- $result[] = 'Copying dummy webp to the cache root for ' . $rootId;
136
  $destDir = Paths::getCacheDirForImageRoot($destinationFolder, $destinationStructure, $rootId);
137
  if (!file_exists($destDir)) {
138
- $result[] = 'The folder did not exist. Creating folder at: ' . $destinationFolder;
139
  if (!mkdir($destDir, 0777, true)) {
140
- $result[] = 'Failed creating folder!';
141
- return [$result, false, ''];
142
  }
143
  }
144
  $destDir .= '/webp-express-test-images';
145
  if (!file_exists($destDir)) {
146
  if (!mkdir($destDir, 0755, false)) {
147
- $result[] = 'Failed creating the folder for the test images:';
148
- $result[] = $destDir;
149
- $result[] = 'To run this test, you must grant write permissions';
150
- return [$result, false, ''];
151
  }
152
  }
153
 
@@ -163,48 +163,84 @@ class SelfTestHelper
163
 
164
  list($success, $errors) = self::copyFile($dummyWebP, $destination);
165
  if (!$success) {
166
- $result[count($result) - 1] .= '. FAILED';
167
- $result = array_merge($result, $errors);
168
- return [$result, false, ''];
169
  } else {
170
- $result[count($result) - 1] .= '. ok!';
171
- $result[] = 'We now have a webp file stored here:';
172
- $result[] = '*' . $destination . '*';
173
- $result[] = '';
174
  }
175
- return [$result, true, $destination];
176
  }
177
 
178
- public static function remoteGet($requestUrl, $args = [])
 
 
 
 
 
 
 
 
 
 
 
 
179
  {
180
- $result = [];
181
- $return = wp_remote_get($requestUrl, $args);
182
- if (is_wp_error($return)) {
183
- $result[] = 'Request URL: ' . $requestUrl;
184
- $result[] = 'The remote request errored';
185
- return [false, $result, [], $return];
186
- }
187
- if ($return['response']['code'] != '200') {
188
- //$result[count($result) - 1] .= '. FAILED';
189
- $result[] = 'Request URL: ' . $requestUrl;
190
- $result[] = 'Response: ' . $return['response']['code'] . ' ' . $return['response']['message'];
191
-
192
- if (isset($return['headers'])) {
193
- $result = array_merge($result, SelfTestHelper::printHeaders($return['headers']));
194
- } else {
195
- $return['headers'] = [];
196
- }
197
- if (isset($return['headers']['content-type'])) {
198
- if (strpos($return['headers']['content-type'], 'text/html') !== false) {
199
- $result[] = 'Body:';
200
- $result[] = print_r($return['body'], true);
201
- }
202
 
 
 
 
 
 
 
203
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
- return [false, $result, $return['headers'], $return];
 
 
 
206
  }
207
- return [true, $result, $return['headers'], $return];
 
 
208
  }
209
 
210
  public static function hasHeaderContaining($headers, $headerToInspect, $containString)
@@ -265,23 +301,23 @@ class SelfTestHelper
265
 
266
  public static function flattenHeaders($headers)
267
  {
268
- $result = [];
269
  foreach ($headers as $headerName => $headerValue) {
270
  if (gettype($headerValue) == 'array') {
271
  foreach ($headerValue as $i => $value) {
272
- $result[] = [$headerName, $value];
273
  }
274
  } else {
275
- $result[] = [$headerName, $headerValue];
276
  }
277
  }
278
- return $result;
279
  }
280
 
281
  public static function printHeaders($headers)
282
  {
283
- $result = [];
284
- $result[] = '#### Response headers:';
285
 
286
  $headersFlat = self::flattenHeaders($headers);
287
  //
@@ -289,10 +325,10 @@ class SelfTestHelper
289
  if ($headerName == 'x-webp-express-error') {
290
  $headerValue = '**' . $headerValue . '**{: .error}';
291
  }
292
- $result[] = '- ' . $headerName . ': ' . $headerValue;
293
  }
294
- $result[] = '';
295
- return $result;
296
  }
297
 
298
  private static function trueFalseNullString($var)
@@ -308,109 +344,109 @@ class SelfTestHelper
308
 
309
  public static function systemInfo()
310
  {
311
- $result = [];
312
- $result[] = '#### System info:';
313
- $result[] = '- PHP version: ' . phpversion();
314
- $result[] = '- OS: ' . PHP_OS;
315
- $result[] = '- Server software: ' . $_SERVER["SERVER_SOFTWARE"];
316
- $result[] = '- Document Root status: ' . Paths::docRootStatusText();
317
  if (PathHelper::isDocRootAvailable()) {
318
- $result[] = '- Document Root: ' . $_SERVER['DOCUMENT_ROOT'];
319
  }
320
  if (PathHelper::isDocRootAvailableAndResolvable()) {
321
  if ($_SERVER['DOCUMENT_ROOT'] != realpath($_SERVER['DOCUMENT_ROOT'])) {
322
- $result[] = '- Document Root (symlinked resolved): ' . realpath($_SERVER['DOCUMENT_ROOT']);
323
  }
324
  }
325
 
326
- $result[] = '- Document Root: ' . Paths::docRootStatusText();
327
- $result[] = '- Apache module "mod_rewrite" enabled?: ' . self::trueFalseNullString(PlatformInfo::gotApacheModule('mod_rewrite'));
328
- $result[] = '- Apache module "mod_headers" enabled?: ' . self::trueFalseNullString(PlatformInfo::gotApacheModule('mod_headers'));
329
- return $result;
330
  }
331
 
332
  public static function wordpressInfo()
333
  {
334
- $result = [];
335
- $result[] = '#### Wordpress info:';
336
- $result[] = '- Version: ' . get_bloginfo('version');
337
- $result[] = '- Multisite?: ' . self::trueFalseNullString(is_multisite());
338
- $result[] = '- Is wp-content moved?: ' . self::trueFalseNullString(Paths::isWPContentDirMoved());
339
- $result[] = '- Is uploads moved out of wp-content?: ' . self::trueFalseNullString(Paths::isUploadDirMovedOutOfWPContentDir());
340
- $result[] = '- Is plugins moved out of wp-content?: ' . self::trueFalseNullString(Paths::isPluginDirMovedOutOfWpContent());
341
 
342
- $result[] = '';
343
 
344
- $result[] = '#### Image roots (absolute paths)';
345
  foreach (Paths::getImageRootIds() as $rootId) {
346
  $absDir = Paths::getAbsDirById($rootId);
347
 
348
  if (PathHelper::pathExistsAndIsResolvable($absDir) && ($absDir != realpath($absDir))) {
349
- $result[] = '*' . $rootId . '*: ' . $absDir . ' (resolved for symlinks: ' . realpath($absDir) . ')';
350
  } else {
351
- $result[] = '*' . $rootId . '*: ' . $absDir;
352
 
353
  }
354
  }
355
 
356
- $result[] = '#### Image roots (relative to document root)';
357
  foreach (Paths::getImageRootIds() as $rootId) {
358
  $absPath = Paths::getAbsDirById($rootId);
359
  if (PathHelper::canCalculateRelPathFromDocRootToDir($absPath)) {
360
- $result[] = '*' . $rootId . '*: ' . PathHelper::getRelPathFromDocRootToDirNoDirectoryTraversalAllowed($absPath);
361
  } else {
362
- $result[] = '*' . $rootId . '*: ' . 'n/a (not within document root)';
363
  }
364
  }
365
 
366
- $result[] = '#### Image roots (URLs)';
367
  foreach (Paths::getImageRootIds() as $rootId) {
368
  $url = Paths::getUrlById($rootId);
369
- $result[] = '*' . $rootId . '*: ' . $url;
370
  }
371
 
372
 
373
- return $result;
374
  }
375
 
376
  public static function configInfo($config)
377
  {
378
- $result = [];
379
- $result[] = '#### WebP Express configuration info:';
380
- $result[] = '- Destination folder: ' . $config['destination-folder'];
381
- $result[] = '- Destination extension: ' . $config['destination-extension'];
382
- $result[] = '- Destination structure: ' . $config['destination-structure'];
383
- //$result[] = 'Image types: ' . ;
384
- //$result[] = '';
385
- $result[] = '(To view all configuration, take a look at the config file, which is stored in *' . Paths::getConfigFileName() . '*)';
386
- return $result;
387
  }
388
 
389
  public static function htaccessInfo($config, $printRules = true)
390
  {
391
- $result = [];
392
- //$result[] = '*.htaccess info:*';
393
- //$result[] = '- Image roots with WebP Express rules: ' . implode(', ', HTAccess::getRootsWithWebPExpressRulesIn());
394
- $result[] = '#### .htaccess files that WebP Express have placed rules in the following files:';
395
  $rootIds = HTAccess::getRootsWithWebPExpressRulesIn();
396
  foreach ($rootIds as $imageRootId) {
397
- $result[] = '- ' . Paths::getAbsDirById($imageRootId) . '/.htaccess';
398
  }
399
 
400
  foreach ($rootIds as $imageRootId) {
401
- $result = array_merge($result, self::rulesInImageRoot($config, $imageRootId));
402
  }
403
 
404
- return $result;
405
  }
406
 
407
  public static function rulesInImageRoot($config, $imageRootId)
408
  {
409
- $result = [];
410
- $result[] = '#### WebP rules in *' . $imageRootId . '*:';
411
  $file = Paths::getAbsDirById($imageRootId) . '/.htaccess';
412
  if (!HTAccess::haveWeRulesInThisHTAccess($file)) {
413
- $result[] = '**NONE!**{: .warn}';
414
  } else {
415
  $weRules = HTAccess::extractWebPExpressRulesFromHTAccess($file);
416
  // remove unindented comments
@@ -423,9 +459,9 @@ class SelfTestHelper
423
  }
424
  $weRules = implode("\n", $weRulesArr);
425
 
426
- $result[] = '```' . $weRules . '```';
427
  }
428
- return $result;
429
  }
430
 
431
  public static function rulesInUpload($config)
@@ -435,117 +471,117 @@ class SelfTestHelper
435
 
436
  public static function allInfo($config)
437
  {
438
- $result = [];
439
- $result = array_merge($result, self::systemInfo());
440
- $result = array_merge($result, self::wordpressInfo());
441
- $result = array_merge($result, self::configInfo($config));
442
- $result = array_merge($result, self::capabilityTests($config));
443
- $result = array_merge($result, self::htaccessInfo($config, true));
444
- //$result = array_merge($result, self::rulesInImageRoot($config, 'upload'));
445
- //$result = array_merge($result, self::rulesInImageRoot($config, 'wp-content'));
446
- return $result;
447
  }
448
 
449
  public static function capabilityTests($config)
450
  {
451
  $capTests = $config['base-htaccess-on-these-capability-tests'];
452
- $result = [];
453
- $result[] = '#### Live tests of .htaccess capabilities:';
454
- /*$result[] = 'Exactly what you can do in a *.htaccess* depends on the server setup. WebP Express ' .
455
  'makes some live tests to verify if a certain feature in fact works. This is done by creating ' .
456
  'test files (*.htaccess* files and php files) in a dir inside the content dir and running these. ' .
457
  'These test results are used when creating the rewrite rules. Here are the results:';*/
458
 
459
- // $result[] = '';
460
- $result[] = '- mod_rewrite working?: ' . self::trueFalseNullString(CapabilityTest::modRewriteWorking());
461
- $result[] = '- mod_header working?: ' . self::trueFalseNullString($capTests['modHeaderWorking']);
462
- /*$result[] = '- pass variable from *.htaccess* to script through header working?: ' .
463
  self::trueFalseNullString($capTests['passThroughHeaderWorking']);*/
464
- $result[] = '- passing variables from *.htaccess* to PHP script through environment variable working?: ' . self::trueFalseNullString($capTests['passThroughEnvWorking']);
465
- return $result;
466
  }
467
 
468
  public static function diagnoseFailedRewrite($config)
469
  {
470
  if (($config['destination-structure'] == 'image-roots') && (!PathHelper::isDocRootAvailableAndResolvable())) {
471
- $result[] = 'The problem is probably this combination:';
472
  if (!PathHelper::isDocRootAvailable()) {
473
- $result[] = '1. Your document root isn`t available';
474
  } else {
475
- $result[] = '1. Your document root isn`t resolvable for symlinks (it is probably subject to open_basedir restriction)';
476
  }
477
- $result[] = '2. Your document root is symlinked';
478
- $result[] = '3. The wordpress function that tells the path of the uploads folder returns the symlink resolved path';
479
 
480
- $result[] = 'I cannot check if your document root is in fact symlinked (as document root isnt resolvable). ' .
481
  'But if it is, there you have it. The line beginning with "RewriteCond %{REQUEST_FILENAME}"" points to your resolved root, ' .
482
  'but it should point to your symlinked root. WebP Express cannot do that for you because it cannot discover what the symlink is. ' .
483
  'Try changing the line manually. When it works, you can move the rules outside the WebP Express block so they dont get ' .
484
  'overwritten. OR you can change your server configuration (document root / open_basedir restrictions)';
485
  }
486
 
487
- //$result[] = '## Diagnosing';
488
  if (PlatformInfo::isNginx()) {
489
  // Nginx
490
- $result[] = 'Notice that you are on Nginx and the rules that WebP Express stores in the *.htaccess* files probably does not ' .
491
  'have any effect. ';
492
- $result[] = 'Please read the "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
493
- $result[] = 'And did you remember to restart the nginx service after updating the configuration?';
494
 
495
- $result[] = 'PS: If you cannot get the redirect to work, you can simply rely on Alter HTML as described in the FAQ.';
496
- return $result;
497
  }
498
 
499
  $modRewriteWorking = CapabilityTest::modRewriteWorking();
500
  if ($modRewriteWorking !== null) {
501
- $result[] = 'Running a special designed capability test to test if rewriting works with *.htaccess* files';
502
  }
503
  if ($modRewriteWorking === true) {
504
- $result[] = 'Result: Yes, rewriting works.';
505
- $result[] = 'It seems something is wrong with the *.htaccess* rules then. You could try ' .
506
  'to change "Destination structure" - the rules there are quite different.';
507
- $result[] = 'It could also be that the server has cached the configuration a while. Some servers ' .
508
  'does that. In that case, simply give it a few minutes and try again.';
509
  } elseif ($modRewriteWorking === false) {
510
- $result[] = 'Result: No, rewriting does not seem to work within *.htaccess* rules.';
511
  if (PlatformInfo::definitelyNotGotModRewrite()) {
512
- $result[] = 'It actually seems "mod_write" is disabled on your server. ' .
513
  '**You must enable mod_rewrite on the server**';
514
  } elseif (PlatformInfo::definitelyGotApacheModule('mod_rewrite')) {
515
- $result[] = 'However, "mod_write" *is* enabled on your server. This seems to indicate that ' .
516
  '*.htaccess* files has been disabled for configuration on your server. ' .
517
  'In that case, you need to copy the WebP Express rules from the *.htaccess* files into your virtual host configuration files. ' .
518
  '(WebP Express generates multiple *.htaccess* files. Look in the upload folder, the wp-content folder, etc).';
519
- $result[] = 'It could however alse simply be that your server simply needs some time. ' .
520
  'Some servers caches the *.htaccess* rules for a bit. In that case, simply give it a few minutes and try again.';
521
  } else {
522
- $result[] = 'However, this could be due to your server being a bit slow on picking up changes in *.htaccess*.' .
523
  'Give it a few minutes and try again.';
524
  }
525
  } else {
526
  // The mod_rewrite test could not conclude anything.
527
  if (PlatformInfo::definitelyNotGotApacheModule('mod_rewrite')) {
528
- $result[] = 'It actually seems "mod_write" is disabled on your server. ' .
529
  '**You must enable mod_rewrite on the server**';
530
  } elseif (PlatformInfo::definitelyGotApacheModule('mod_rewrite')) {
531
- $result[] = '"mod_write" is enabled on your server, so rewriting ought to work. ' .
532
  'However, it could be that your server setup has disabled *.htaccess* files for configuration. ' .
533
  'In that case, you need to copy the WebP Express rules from the *.htaccess* files into your virtual host configuration files. ' .
534
  '(WebP Express generates multiple *.htaccess* files. Look in the upload folder, the wp-content folder, etc). ';
535
  } else {
536
- $result[] = 'It seems something is wrong with the *.htaccess* rules. ';
537
- $result[] = 'Or perhaps the server has cached the configuration a while. Some servers ' .
538
  'does that. In that case, simply give it a few minutes and try again.';
539
  }
540
  }
541
- $result[] = 'Note that if you cannot get redirection to work, you can switch to "CDN friendly" mode and ' .
542
  'rely on the "Alter HTML" functionality to point to the webp images. If you do a bulk conversion ' .
543
  'and make sure that "Convert upon upload" is activated, you should be all set. Alter HTML even handles ' .
544
  'inline css (unless you select "picture tag" syntax). It does however not handle images in external css or ' .
545
  'which is added dynamically with javascript.';
546
 
547
- $result[] = '## Info for manually diagnosing';
548
- $result = array_merge($result, self::allInfo($config));
549
- return $result;
550
  }
551
  }
50
 
51
  public static function copyFile($source, $destination)
52
  {
53
+ $log = [];
54
  if (@copy($source, $destination)) {
55
+ return [true, $log];
56
  } else {
57
+ $log[] = 'Failed to copy *' . $source . '* to *' . $destination . '*';
58
  if (!@file_exists($source)) {
59
+ $log[] = 'The source file was not found';
60
  } else {
61
  if (!@file_exists(dirname($destination))) {
62
+ $log[] = 'The destination folder does not exist!';
63
  } else {
64
+ $log[] = 'This is probably a permission issue. Check that your webserver has permission to ' .
65
  'write files in the directory (*' . dirname($destination) . '*)';
66
  }
67
  }
68
+ return [false, $log];
69
  }
70
  }
71
 
84
  {
85
  // TODO: Copy to a subfolder instead
86
  // TODO: Use smaller jpeg / pngs please.
87
+ $log = [];
88
  switch ($imageType) {
89
  case 'jpeg':
90
  $fileNameToCopy = 'very-small.jpg';
96
  $testSource = Paths::getPluginDirAbs() . '/webp-express/test/' . $fileNameToCopy;
97
  $filenameOfDestination = self::randomDigitsAndLetters(6) . '.' . strtoupper($imageType);
98
  //$filenameOfDestination = self::randomDigitsAndLetters(6) . '.' . $imageType;
99
+ $log[] = 'Copying ' . strtoupper($imageType) . ' to ' . $rootId . ' folder (*webp-express-test-images/' . $filenameOfDestination . '*)';
100
 
101
  $destDir = Paths::getAbsDirById($rootId) . '/webp-express-test-images';
102
  $destination = $destDir . '/' . $filenameOfDestination;
103
 
104
  if (!@file_exists($destDir)) {
105
  if (!@mkdir($destDir)) {
106
+ $log[count($log) - 1] .= '. FAILED';
107
+ $log[] = 'Failed to create folder for test images: ' . $destDir;
108
+ return [$log, false, ''];
109
  }
110
  }
111
 
112
  list($success, $errors) = self::copyFile($testSource, $destination);
113
  if (!$success) {
114
+ $log[count($log) - 1] .= '. FAILED';
115
+ $log = array_merge($log, $errors);
116
+ return [$log, false, ''];
117
  } else {
118
+ $log[count($log) - 1] .= '. ok!';
119
+ $log[] = 'We now have a ' . $imageType . ' stored here:';
120
+ $log[] = '*' . $destination . '*';
121
  }
122
+ return [$log, true, $filenameOfDestination];
123
  }
124
 
125
  public static function copyTestImageToUploadFolder($imageType = 'jpeg')
129
 
130
  public static function copyDummyWebPToCacheFolder($rootId, $destinationFolder, $destinationExtension, $destinationStructure, $sourceFileName, $imageType = 'jpeg')
131
  {
132
+ $log = [];
133
  $dummyWebP = Paths::getPluginDirAbs() . '/webp-express/test/test.jpg.webp';
134
 
135
+ $log[] = 'Copying dummy webp to the cache root for ' . $rootId;
136
  $destDir = Paths::getCacheDirForImageRoot($destinationFolder, $destinationStructure, $rootId);
137
  if (!file_exists($destDir)) {
138
+ $log[] = 'The folder did not exist. Creating folder at: ' . $destinationFolder;
139
  if (!mkdir($destDir, 0777, true)) {
140
+ $log[] = 'Failed creating folder!';
141
+ return [$log, false, ''];
142
  }
143
  }
144
  $destDir .= '/webp-express-test-images';
145
  if (!file_exists($destDir)) {
146
  if (!mkdir($destDir, 0755, false)) {
147
+ $log[] = 'Failed creating the folder for the test images:';
148
+ $log[] = $destDir;
149
+ $log[] = 'To run this test, you must grant write permissions';
150
+ return [$log, false, ''];
151
  }
152
  }
153
 
163
 
164
  list($success, $errors) = self::copyFile($dummyWebP, $destination);
165
  if (!$success) {
166
+ $log[count($log) - 1] .= '. FAILED';
167
+ $log = array_merge($log, $errors);
168
+ return [$log, false, ''];
169
  } else {
170
+ $log[count($log) - 1] .= '. ok!';
171
+ $log[] = 'We now have a webp file stored here:';
172
+ $log[] = '*' . $destination . '*';
173
+ $log[] = '';
174
  }
175
+ return [$log, true, $destination];
176
  }
177
 
178
+ /**
179
+ * Perform HTTP request.
180
+ *
181
+ * @param string $requestUrl URL
182
+ * @param array $args Args to pass to wp_remote_get. Note however that "redirection" is set to 0
183
+ * @param int $maxRedirects For internal use
184
+ * @return array The result
185
+ * $success (boolean): If we got a 200 response in the end (after max 2 redirects)
186
+ * $log (array) : Message log
187
+ * $results : Array of results from wp_remote_get. If no redirection occured, it will only contain one item.
188
+ *
189
+ */
190
+ public static function remoteGet($requestUrl, $args = [], $maxRedirects = 2)
191
  {
192
+ $log = [];
193
+ $args['redirection'] = 0;
194
+
195
+ $log[] = 'Request URL: ' . $requestUrl;
196
+
197
+ $results = [];
198
+ $wpResult = wp_remote_get($requestUrl, $args);
199
+ if (!isset($wpResult['headers'])) {
200
+ $wpResult['headers'] = [];
201
+ }
202
+ $results[] = $wpResult;
203
+ if (is_wp_error($wpResult)) {
204
+ $log[] = 'The remote request errored';
205
+ return [false, $log, $results];
206
+ }
207
+ $responseCode = $wpResult['response']['code'];
208
+
209
+ $log[] = 'Response: ' . $responseCode . ' ' . $wpResult['response']['message'];
210
+ $log = array_merge($log, SelfTestHelper::printHeaders($wpResult['headers']));
 
 
 
211
 
212
+ if (isset($wpResult['headers']['content-type'])) {
213
+ if (strpos($wpResult['headers']['content-type'], 'text/html') !== false) {
214
+ if (isset($wpResult['body']) && (!empty($wpResult['body']))) {
215
+ $log[] = 'Body:';
216
+ $log[] = print_r($wpResult['body'], true);
217
+ }
218
  }
219
+ }
220
+
221
+ if (($responseCode == '302') || ($responseCode == '301')) {
222
+ if ($maxRedirects > 0) {
223
+ if (isset($wpResult['headers']['location'])) {
224
+ $url = $wpResult['headers']['location'];
225
+ if (strpos($url, 'http') !== 0) {
226
+ $url = $requestUrl . $url;
227
+ }
228
+ $log[] = 'Following that redirect';
229
+
230
+ list($success, $newLog, $newResult) = self::remoteGet($url, $args, $maxRedirects - 1);
231
+ $log = array_merge($log, $newLog);
232
+ $results = array_merge($results, $newResult);
233
+
234
+ return [$success, $log, $results];
235
 
236
+ }
237
+ } else {
238
+ $log[] = 'Not following the redirect (max redirects exceeded)';
239
+ }
240
  }
241
+
242
+ $success = ($responseCode == '200');
243
+ return [$success, $log, $results];
244
  }
245
 
246
  public static function hasHeaderContaining($headers, $headerToInspect, $containString)
301
 
302
  public static function flattenHeaders($headers)
303
  {
304
+ $log = [];
305
  foreach ($headers as $headerName => $headerValue) {
306
  if (gettype($headerValue) == 'array') {
307
  foreach ($headerValue as $i => $value) {
308
+ $log[] = [$headerName, $value];
309
  }
310
  } else {
311
+ $log[] = [$headerName, $headerValue];
312
  }
313
  }
314
+ return $log;
315
  }
316
 
317
  public static function printHeaders($headers)
318
  {
319
+ $log = [];
320
+ $log[] = '#### Response headers:';
321
 
322
  $headersFlat = self::flattenHeaders($headers);
323
  //
325
  if ($headerName == 'x-webp-express-error') {
326
  $headerValue = '**' . $headerValue . '**{: .error}';
327
  }
328
+ $log[] = '- ' . $headerName . ': ' . $headerValue;
329
  }
330
+ $log[] = '';
331
+ return $log;
332
  }
333
 
334
  private static function trueFalseNullString($var)
344
 
345
  public static function systemInfo()
346
  {
347
+ $log = [];
348
+ $log[] = '#### System info:';
349
+ $log[] = '- PHP version: ' . phpversion();
350
+ $log[] = '- OS: ' . PHP_OS;
351
+ $log[] = '- Server software: ' . $_SERVER["SERVER_SOFTWARE"];
352
+ $log[] = '- Document Root status: ' . Paths::docRootStatusText();
353
  if (PathHelper::isDocRootAvailable()) {
354
+ $log[] = '- Document Root: ' . $_SERVER['DOCUMENT_ROOT'];
355
  }
356
  if (PathHelper::isDocRootAvailableAndResolvable()) {
357
  if ($_SERVER['DOCUMENT_ROOT'] != realpath($_SERVER['DOCUMENT_ROOT'])) {
358
+ $log[] = '- Document Root (symlinked resolved): ' . realpath($_SERVER['DOCUMENT_ROOT']);
359
  }
360
  }
361
 
362
+ $log[] = '- Document Root: ' . Paths::docRootStatusText();
363
+ $log[] = '- Apache module "mod_rewrite" enabled?: ' . self::trueFalseNullString(PlatformInfo::gotApacheModule('mod_rewrite'));
364
+ $log[] = '- Apache module "mod_headers" enabled?: ' . self::trueFalseNullString(PlatformInfo::gotApacheModule('mod_headers'));
365
+ return $log;
366
  }
367
 
368
  public static function wordpressInfo()
369
  {
370
+ $log = [];
371
+ $log[] = '#### Wordpress info:';
372
+ $log[] = '- Version: ' . get_bloginfo('version');
373
+ $log[] = '- Multisite?: ' . self::trueFalseNullString(is_multisite());
374
+ $log[] = '- Is wp-content moved?: ' . self::trueFalseNullString(Paths::isWPContentDirMoved());
375
+ $log[] = '- Is uploads moved out of wp-content?: ' . self::trueFalseNullString(Paths::isUploadDirMovedOutOfWPContentDir());
376
+ $log[] = '- Is plugins moved out of wp-content?: ' . self::trueFalseNullString(Paths::isPluginDirMovedOutOfWpContent());
377
 
378
+ $log[] = '';
379
 
380
+ $log[] = '#### Image roots (absolute paths)';
381
  foreach (Paths::getImageRootIds() as $rootId) {
382
  $absDir = Paths::getAbsDirById($rootId);
383
 
384
  if (PathHelper::pathExistsAndIsResolvable($absDir) && ($absDir != realpath($absDir))) {
385
+ $log[] = '*' . $rootId . '*: ' . $absDir . ' (resolved for symlinks: ' . realpath($absDir) . ')';
386
  } else {
387
+ $log[] = '*' . $rootId . '*: ' . $absDir;
388
 
389
  }
390
  }
391
 
392
+ $log[] = '#### Image roots (relative to document root)';
393
  foreach (Paths::getImageRootIds() as $rootId) {
394
  $absPath = Paths::getAbsDirById($rootId);
395
  if (PathHelper::canCalculateRelPathFromDocRootToDir($absPath)) {
396
+ $log[] = '*' . $rootId . '*: ' . PathHelper::getRelPathFromDocRootToDirNoDirectoryTraversalAllowed($absPath);
397
  } else {
398
+ $log[] = '*' . $rootId . '*: ' . 'n/a (not within document root)';
399
  }
400
  }
401
 
402
+ $log[] = '#### Image roots (URLs)';
403
  foreach (Paths::getImageRootIds() as $rootId) {
404
  $url = Paths::getUrlById($rootId);
405
+ $log[] = '*' . $rootId . '*: ' . $url;
406
  }
407
 
408
 
409
+ return $log;
410
  }
411
 
412
  public static function configInfo($config)
413
  {
414
+ $log = [];
415
+ $log[] = '#### WebP Express configuration info:';
416
+ $log[] = '- Destination folder: ' . $config['destination-folder'];
417
+ $log[] = '- Destination extension: ' . $config['destination-extension'];
418
+ $log[] = '- Destination structure: ' . $config['destination-structure'];
419
+ //$log[] = 'Image types: ' . ;
420
+ //$log[] = '';
421
+ $log[] = '(To view all configuration, take a look at the config file, which is stored in *' . Paths::getConfigFileName() . '*)';
422
+ return $log;
423
  }
424
 
425
  public static function htaccessInfo($config, $printRules = true)
426
  {
427
+ $log = [];
428
+ //$log[] = '*.htaccess info:*';
429
+ //$log[] = '- Image roots with WebP Express rules: ' . implode(', ', HTAccess::getRootsWithWebPExpressRulesIn());
430
+ $log[] = '#### .htaccess files that WebP Express have placed rules in the following files:';
431
  $rootIds = HTAccess::getRootsWithWebPExpressRulesIn();
432
  foreach ($rootIds as $imageRootId) {
433
+ $log[] = '- ' . Paths::getAbsDirById($imageRootId) . '/.htaccess';
434
  }
435
 
436
  foreach ($rootIds as $imageRootId) {
437
+ $log = array_merge($log, self::rulesInImageRoot($config, $imageRootId));
438
  }
439
 
440
+ return $log;
441
  }
442
 
443
  public static function rulesInImageRoot($config, $imageRootId)
444
  {
445
+ $log = [];
446
+ $log[] = '#### WebP rules in *' . $imageRootId . '*:';
447
  $file = Paths::getAbsDirById($imageRootId) . '/.htaccess';
448
  if (!HTAccess::haveWeRulesInThisHTAccess($file)) {
449
+ $log[] = '**NONE!**{: .warn}';
450
  } else {
451
  $weRules = HTAccess::extractWebPExpressRulesFromHTAccess($file);
452
  // remove unindented comments
459
  }
460
  $weRules = implode("\n", $weRulesArr);
461
 
462
+ $log[] = '```' . $weRules . '```';
463
  }
464
+ return $log;
465
  }
466
 
467
  public static function rulesInUpload($config)
471
 
472
  public static function allInfo($config)
473
  {
474
+ $log = [];
475
+ $log = array_merge($log, self::systemInfo());
476
+ $log = array_merge($log, self::wordpressInfo());
477
+ $log = array_merge($log, self::configInfo($config));
478
+ $log = array_merge($log, self::capabilityTests($config));
479
+ $log = array_merge($log, self::htaccessInfo($config, true));
480
+ //$log = array_merge($log, self::rulesInImageRoot($config, 'upload'));
481
+ //$log = array_merge($log, self::rulesInImageRoot($config, 'wp-content'));
482
+ return $log;
483
  }
484
 
485
  public static function capabilityTests($config)
486
  {
487
  $capTests = $config['base-htaccess-on-these-capability-tests'];
488
+ $log = [];
489
+ $log[] = '#### Live tests of .htaccess capabilities:';
490
+ /*$log[] = 'Exactly what you can do in a *.htaccess* depends on the server setup. WebP Express ' .
491
  'makes some live tests to verify if a certain feature in fact works. This is done by creating ' .
492
  'test files (*.htaccess* files and php files) in a dir inside the content dir and running these. ' .
493
  'These test results are used when creating the rewrite rules. Here are the results:';*/
494
 
495
+ // $log[] = '';
496
+ $log[] = '- mod_rewrite working?: ' . self::trueFalseNullString(CapabilityTest::modRewriteWorking());
497
+ $log[] = '- mod_header working?: ' . self::trueFalseNullString($capTests['modHeaderWorking']);
498
+ /*$log[] = '- pass variable from *.htaccess* to script through header working?: ' .
499
  self::trueFalseNullString($capTests['passThroughHeaderWorking']);*/
500
+ $log[] = '- passing variables from *.htaccess* to PHP script through environment variable working?: ' . self::trueFalseNullString($capTests['passThroughEnvWorking']);
501
+ return $log;
502
  }
503
 
504
  public static function diagnoseFailedRewrite($config)
505
  {
506
  if (($config['destination-structure'] == 'image-roots') && (!PathHelper::isDocRootAvailableAndResolvable())) {
507
+ $log[] = 'The problem is probably this combination:';
508
  if (!PathHelper::isDocRootAvailable()) {
509
+ $log[] = '1. Your document root isn`t available';
510
  } else {
511
+ $log[] = '1. Your document root isn`t resolvable for symlinks (it is probably subject to open_basedir restriction)';
512
  }
513
+ $log[] = '2. Your document root is symlinked';
514
+ $log[] = '3. The wordpress function that tells the path of the uploads folder returns the symlink resolved path';
515
 
516
+ $log[] = 'I cannot check if your document root is in fact symlinked (as document root isnt resolvable). ' .
517
  'But if it is, there you have it. The line beginning with "RewriteCond %{REQUEST_FILENAME}"" points to your resolved root, ' .
518
  'but it should point to your symlinked root. WebP Express cannot do that for you because it cannot discover what the symlink is. ' .
519
  'Try changing the line manually. When it works, you can move the rules outside the WebP Express block so they dont get ' .
520
  'overwritten. OR you can change your server configuration (document root / open_basedir restrictions)';
521
  }
522
 
523
+ //$log[] = '## Diagnosing';
524
  if (PlatformInfo::isNginx()) {
525
  // Nginx
526
+ $log[] = 'Notice that you are on Nginx and the rules that WebP Express stores in the *.htaccess* files probably does not ' .
527
  'have any effect. ';
528
+ $log[] = 'Please read the "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
529
+ $log[] = 'And did you remember to restart the nginx service after updating the configuration?';
530
 
531
+ $log[] = 'PS: If you cannot get the redirect to work, you can simply rely on Alter HTML as described in the FAQ.';
532
+ return $log;
533
  }
534
 
535
  $modRewriteWorking = CapabilityTest::modRewriteWorking();
536
  if ($modRewriteWorking !== null) {
537
+ $log[] = 'Running a special designed capability test to test if rewriting works with *.htaccess* files';
538
  }
539
  if ($modRewriteWorking === true) {
540
+ $log[] = 'Result: Yes, rewriting works.';
541
+ $log[] = 'It seems something is wrong with the *.htaccess* rules then. You could try ' .
542
  'to change "Destination structure" - the rules there are quite different.';
543
+ $log[] = 'It could also be that the server has cached the configuration a while. Some servers ' .
544
  'does that. In that case, simply give it a few minutes and try again.';
545
  } elseif ($modRewriteWorking === false) {
546
+ $log[] = 'Result: No, rewriting does not seem to work within *.htaccess* rules.';
547
  if (PlatformInfo::definitelyNotGotModRewrite()) {
548
+ $log[] = 'It actually seems "mod_write" is disabled on your server. ' .
549
  '**You must enable mod_rewrite on the server**';
550
  } elseif (PlatformInfo::definitelyGotApacheModule('mod_rewrite')) {
551
+ $log[] = 'However, "mod_write" *is* enabled on your server. This seems to indicate that ' .
552
  '*.htaccess* files has been disabled for configuration on your server. ' .
553
  'In that case, you need to copy the WebP Express rules from the *.htaccess* files into your virtual host configuration files. ' .
554
  '(WebP Express generates multiple *.htaccess* files. Look in the upload folder, the wp-content folder, etc).';
555
+ $log[] = 'It could however alse simply be that your server simply needs some time. ' .
556
  'Some servers caches the *.htaccess* rules for a bit. In that case, simply give it a few minutes and try again.';
557
  } else {
558
+ $log[] = 'However, this could be due to your server being a bit slow on picking up changes in *.htaccess*.' .
559
  'Give it a few minutes and try again.';
560
  }
561
  } else {
562
  // The mod_rewrite test could not conclude anything.
563
  if (PlatformInfo::definitelyNotGotApacheModule('mod_rewrite')) {
564
+ $log[] = 'It actually seems "mod_write" is disabled on your server. ' .
565
  '**You must enable mod_rewrite on the server**';
566
  } elseif (PlatformInfo::definitelyGotApacheModule('mod_rewrite')) {
567
+ $log[] = '"mod_write" is enabled on your server, so rewriting ought to work. ' .
568
  'However, it could be that your server setup has disabled *.htaccess* files for configuration. ' .
569
  'In that case, you need to copy the WebP Express rules from the *.htaccess* files into your virtual host configuration files. ' .
570
  '(WebP Express generates multiple *.htaccess* files. Look in the upload folder, the wp-content folder, etc). ';
571
  } else {
572
+ $log[] = 'It seems something is wrong with the *.htaccess* rules. ';
573
+ $log[] = 'Or perhaps the server has cached the configuration a while. Some servers ' .
574
  'does that. In that case, simply give it a few minutes and try again.';
575
  }
576
  }
577
+ $log[] = 'Note that if you cannot get redirection to work, you can switch to "CDN friendly" mode and ' .
578
  'rely on the "Alter HTML" functionality to point to the webp images. If you do a bulk conversion ' .
579
  'and make sure that "Convert upon upload" is activated, you should be all set. Alter HTML even handles ' .
580
  'inline css (unless you select "picture tag" syntax). It does however not handle images in external css or ' .
581
  'which is added dynamically with javascript.';
582
 
583
+ $log[] = '## Info for manually diagnosing';
584
+ $log = array_merge($log, self::allInfo($config));
585
+ return $log;
586
  }
587
  }
lib/classes/SelfTestRedirectToConverter.php CHANGED
@@ -10,175 +10,192 @@ class SelfTestRedirectToConverter extends SelfTestRedirectAbstract
10
  *
11
  * @param string $rootId (ie "uploads" or "themes")
12
  * @param string $imageType ("jpeg" or "png")
13
- * @return array [$success, $result, $createdTestFiles]
14
  */
15
  protected function runTestForImageType($rootId, $imageType)
16
  {
17
- $result = [];
18
  $createdTestFiles = false;
19
  $noWarningsYet = true;
20
 
21
  // Copy test image (jpeg)
22
  list($subResult, $success, $sourceFileName) = SelfTestHelper::copyTestImageToRoot($rootId, $imageType);
23
- $result = array_merge($result, $subResult);
24
  if (!$success) {
25
- $result[] = 'The test cannot be completed';
26
- return [false, $result, $createdTestFiles];
27
  }
28
  $createdTestFiles = true;
29
 
30
  $requestUrl = Paths::getUrlById($rootId) . '/webp-express-test-images/' . $sourceFileName;
31
 
32
- $result[] = '### Lets check that browsers supporting webp gets a freshly converted WEBP ' .
33
  'when the ' . $imageType . ' is requested';
34
- $result[] = 'Making a HTTP request for the test image (pretending to be a client that supports webp, by setting the "Accept" header to "image/webp")';
35
  $requestArgs = [
36
  'headers' => [
37
  'ACCEPT' => 'image/webp'
38
- ]
39
  ];
40
- list($success, $errors, $headers, $return) = SelfTestHelper::remoteGet($requestUrl, $requestArgs);
 
 
41
 
42
  if (!$success) {
43
- $result[count($result) - 1] .= '. FAILED';
44
- $result = array_merge($result, $errors);
45
- $result[] = 'The test cannot be completed';
46
- //$result[count($result) - 1] .= '. FAILED';
47
- return [false, $result, $createdTestFiles];
 
48
  }
49
- //$result[count($result) - 1] .= '. ok!';
50
- $result[] = '*' . $requestUrl . '*';
51
 
52
- $result = array_merge($result, SelfTestHelper::printHeaders($headers));
53
 
54
  if (!isset($headers['content-type'])) {
55
- $result[] = 'Bummer. There is no "content-type" response header. The test FAILED';
56
- return [false, $result, $createdTestFiles];
57
  }
58
 
59
  if ($headers['content-type'] == 'image/' . $imageType) {
60
- $result[] = 'Bummer. As the "content-type" header reveals, we got the ' . $imageType . '.';
61
- $result[] = 'The test **failed**{: .error}.';
62
- $result[] = 'Now, what went wrong?';
63
 
64
  if (isset($headers['x-webp-convert-log'])) {
65
- //$result[] = 'Inspect the "x-webp-convert-log" headers above, and you ' .
66
  // 'should have your answer (it is probably because you do not have any conversion methods working).';
67
  if (SelfTestHelper::hasHeaderContaining($headers, 'x-webp-convert-log', 'Performing fail action: original')) {
68
- $result[] = 'The answer lies in the "x-convert-log" response headers: ' .
69
  '**The conversion failed**{: .error}. ';
70
  }
71
  } else {
72
- $result[] = 'Well, there is indication that the redirection isnt working. ' .
73
  'The PHP script should set "x-webp-convert-log" response headers, but there are none. ';
74
  'While these headers could have been eaten in a Cloudflare-like setup, the problem is ';
75
  'probably that the redirection simply failed';
76
 
77
- $result[] = '### Diagnosing redirection problems';
78
- $result = array_merge($result, SelfTestHelper::diagnoseFailedRewrite($this->config));
79
  }
80
- return [false, $result, $createdTestFiles];
81
  }
82
 
83
  if ($headers['content-type'] != 'image/webp') {
84
- $result[] = 'However. As the "content-type" header reveals, we did not get a webp' .
85
  'Surprisingly we got: "' . $headers['content-type'] . '"';
86
- $result[] = 'The test FAILED.';
87
- if (strpos($headers['content-type'], 'text/html') !== false) {
88
- $result[] = 'Body:';
89
- $result[] = print_r($return['body'], true);
90
- }
91
- return [false, $result, $createdTestFiles];
92
  }
93
 
94
- $result[] = 'Alrighty. We got a webp, and we got it from the PHP script. **Great!**{: .ok}';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
97
- $result[count($result) - 1] .= '. **BUT!**';
98
- $result[] = '**Warning: We did not receive a Vary:Accept header. ' .
99
  'That header should be set in order to tell proxies that the response varies depending on the ' .
100
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
101
  $noWarningsYet = false;
102
  }
103
  if (!SelfTestHelper::hasCacheControlOrExpiresHeader($headers)) {
104
- $result[] = '**Notice: No cache-control or expires header has been set. ' .
105
  'It is recommended to do so. Set it nice and big once you are sure the webps have a good quality/compression compromise.**{: .warn}';
106
  }
107
- $result[] = '';
108
 
109
 
110
  // Check browsers NOT supporting webp
111
  // -----------------------------------
112
- $result[] = '### Now lets check that browsers *not* supporting webp gets the ' . strtoupper($imageType);
113
- $result[] = 'Making a HTTP request for the test image (without setting the "Accept" header)';
114
- list($success, $errors, $headers) = SelfTestHelper::remoteGet($requestUrl);
 
 
115
 
116
  if (!$success) {
117
- $result[count($result) - 1] .= '. FAILED';
118
- $result = array_merge($result, $errors);
119
- $result[] = 'The test cannot be completed';
120
- //$result[count($result) - 1] .= '. FAILED';
121
- return [false, $result, $createdTestFiles];
122
  }
123
- //$result[count($result) - 1] .= '. ok!';
124
- $result[] = '*' . $requestUrl . '*';
125
 
126
- $result = array_merge($result, SelfTestHelper::printHeaders($headers));
127
 
128
  if (!isset($headers['content-type'])) {
129
- $result[] = 'Bummer. There is no "content-type" response header. The test FAILED';
130
- return [false, $result, $createdTestFiles];
131
  }
132
 
133
  if ($headers['content-type'] == 'image/webp') {
134
- $result[] = '**Bummer**{: .error}. As the "content-type" header reveals, we got the webp. ' .
135
  'So even browsers not supporting webp gets webp. Not good!';
136
- $result[] = 'The test FAILED.';
137
 
138
- $result[] = '### What to do now?';
139
  // TODO: We could examine the headers for common CDN responses
140
 
141
- $result[] = 'First, examine the response headers above. Is there any indication that ' .
142
  'the image is returned from a CDN cache? ' .
143
- $result[] = 'If there is: Check out the ' .
144
  '*How do I configure my CDN in “Varied image responses” operation mode?* section in the FAQ ' .
145
  '(https://wordpress.org/plugins/webp-express/)';
146
 
147
  if (PlatformInfo::isApache()) {
148
- $result[] = 'If not: please report this in the forum, as it seems the .htaccess rules ';
149
- $result[] = 'just arent working on your system.';
150
  } elseif (PlatformInfo::isNginx()) {
151
- $result[] = 'Also, as you are on Nginx, check out the ' .
152
  ' "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
153
  } else {
154
- $result[] = 'If not: please report this in the forum, as it seems that there is something ' .
155
  'in the *.htaccess* rules generated by WebP Express that are not working.';
156
  }
157
 
158
- $result[] = '### System info (for manual diagnosing):';
159
- $result = array_merge($result, SelfTestHelper::allInfo($this->config));
160
 
161
 
162
- return [false, $result, $createdTestFiles];
163
  }
164
 
165
  if ($headers['content-type'] != 'image/' . $imageType) {
166
- $result[] = 'Bummer. As the "content-type" header reveals, we did not get the ' . $imageType .
167
  'Surprisingly we got: "' . $headers['content-type'] . '"';
168
- $result[] = 'The test FAILED.';
169
- return [false, $result, $createdTestFiles];
170
  }
171
- $result[] = 'Alrighty. We got the ' . $imageType . '. **Great!**{: .ok}.';
172
 
173
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
174
- $result[count($result) - 1] .= '. **BUT!**';
175
- $result[] = '**We did not receive a Vary:Accept header. ' .
176
  'That header should be set in order to tell proxies that the response varies depending on the ' .
177
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
178
  $noWarningsYet = false;
179
  }
180
 
181
- return [$noWarningsYet, $result, $createdTestFiles];
182
  }
183
 
184
  protected function getSuccessMessage()
@@ -190,12 +207,12 @@ class SelfTestRedirectToConverter extends SelfTestRedirectAbstract
190
 
191
  public function startupTests()
192
  {
193
- $result[] = '# Testing redirection to converter';
194
  if (!$this->config['enable-redirection-to-converter']) {
195
- $result[] = 'Turned off, nothing to test (if you just turned it on without saving, remember: this is a live test so you need to save settings)';
196
- return [false, $result];
197
  }
198
- return [true, $result];
199
  }
200
 
201
  public static function runTest()
10
  *
11
  * @param string $rootId (ie "uploads" or "themes")
12
  * @param string $imageType ("jpeg" or "png")
13
+ * @return array [$success, $log, $createdTestFiles]
14
  */
15
  protected function runTestForImageType($rootId, $imageType)
16
  {
17
+ $log = [];
18
  $createdTestFiles = false;
19
  $noWarningsYet = true;
20
 
21
  // Copy test image (jpeg)
22
  list($subResult, $success, $sourceFileName) = SelfTestHelper::copyTestImageToRoot($rootId, $imageType);
23
+ $log = array_merge($log, $subResult);
24
  if (!$success) {
25
+ $log[] = 'The test cannot be completed';
26
+ return [false, $log, $createdTestFiles];
27
  }
28
  $createdTestFiles = true;
29
 
30
  $requestUrl = Paths::getUrlById($rootId) . '/webp-express-test-images/' . $sourceFileName;
31
 
32
+ $log[] = '### Lets check that browsers supporting webp gets a freshly converted WEBP ' .
33
  'when the ' . $imageType . ' is requested';
34
+ $log[] = 'Making a HTTP request for the test image (pretending to be a client that supports webp, by setting the "Accept" header to "image/webp")';
35
  $requestArgs = [
36
  'headers' => [
37
  'ACCEPT' => 'image/webp'
38
+ ],
39
  ];
40
+ list($success, $remoteGetLog, $results) = SelfTestHelper::remoteGet($requestUrl, $requestArgs);
41
+ $headers = $results[count($results)-1]['headers'];
42
+ $log = array_merge($log, $remoteGetLog);
43
 
44
  if (!$success) {
45
+ //$log[count($log) - 1] .= '. FAILED';
46
+ $log[] = 'The request FAILED';
47
+ //$log = array_merge($log, $remoteGetLog);
48
+ $log[] = 'The test cannot be completed';
49
+ //$log[count($log) - 1] .= '. FAILED';
50
+ return [false, $log, $createdTestFiles];
51
  }
52
+ //$log[count($log) - 1] .= '. ok!';
53
+ //$log[] = '*' . $requestUrl . '*';
54
 
55
+ //$log = array_merge($log, SelfTestHelper::printHeaders($headers));
56
 
57
  if (!isset($headers['content-type'])) {
58
+ $log[] = 'Bummer. There is no "content-type" response header. The test FAILED';
59
+ return [false, $log, $createdTestFiles];
60
  }
61
 
62
  if ($headers['content-type'] == 'image/' . $imageType) {
63
+ $log[] = 'Bummer. As the "content-type" header reveals, we got the ' . $imageType . '.';
64
+ $log[] = 'The test **failed**{: .error}.';
65
+ $log[] = 'Now, what went wrong?';
66
 
67
  if (isset($headers['x-webp-convert-log'])) {
68
+ //$log[] = 'Inspect the "x-webp-convert-log" headers above, and you ' .
69
  // 'should have your answer (it is probably because you do not have any conversion methods working).';
70
  if (SelfTestHelper::hasHeaderContaining($headers, 'x-webp-convert-log', 'Performing fail action: original')) {
71
+ $log[] = 'The answer lies in the "x-convert-log" response headers: ' .
72
  '**The conversion failed**{: .error}. ';
73
  }
74
  } else {
75
+ $log[] = 'Well, there is indication that the redirection isnt working. ' .
76
  'The PHP script should set "x-webp-convert-log" response headers, but there are none. ';
77
  'While these headers could have been eaten in a Cloudflare-like setup, the problem is ';
78
  'probably that the redirection simply failed';
79
 
80
+ $log[] = '### Diagnosing redirection problems';
81
+ $log = array_merge($log, SelfTestHelper::diagnoseFailedRewrite($this->config));
82
  }
83
+ return [false, $log, $createdTestFiles];
84
  }
85
 
86
  if ($headers['content-type'] != 'image/webp') {
87
+ $log[] = 'However. As the "content-type" header reveals, we did not get a webp' .
88
  'Surprisingly we got: "' . $headers['content-type'] . '"';
89
+ $log[] = 'The test FAILED.';
90
+ return [false, $log, $createdTestFiles];
 
 
 
 
91
  }
92
 
93
+ if (isset($headers['x-webp-convert-log'])) {
94
+ $log[] = 'Alrighty. We got a webp, and we got it from the PHP script. **Great!**{: .ok}';
95
+ } else {
96
+ if (count($results) > 1) {
97
+ if (isset($results[0]['headers']['x-webp-convert-log'])) {
98
+ $log[] = '**Great!**{: .ok}. The PHP script created a webp and redirected the image request ' .
99
+ 'back to itself. A refresh, if you wish. The refresh got us the webp (relying on there being ' .
100
+ 'a rule which redirect images to existing converted images for webp-enabled browsers - which there is!). ' .
101
+ (SelfTestHelper::hasVaryAcceptHeader($headers) ? 'And we got the Vary:Accept header set too. **Super!**{: .ok}!' : '');
102
+ }
103
+ } else {
104
+ $log[] = 'We got a webp. However, it seems we did not get it from the PHP script.';
105
+
106
+ }
107
+
108
+ //$log[] = print_r($return, true);
109
+ //error_log(print_r($return, true));
110
+ }
111
 
112
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
113
+ $log[count($log) - 1] .= '. **BUT!**';
114
+ $log[] = '**Warning: We did not receive a Vary:Accept header. ' .
115
  'That header should be set in order to tell proxies that the response varies depending on the ' .
116
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
117
  $noWarningsYet = false;
118
  }
119
  if (!SelfTestHelper::hasCacheControlOrExpiresHeader($headers)) {
120
+ $log[] = '**Notice: No cache-control or expires header has been set. ' .
121
  'It is recommended to do so. Set it nice and big once you are sure the webps have a good quality/compression compromise.**{: .warn}';
122
  }
123
+ $log[] = '';
124
 
125
 
126
  // Check browsers NOT supporting webp
127
  // -----------------------------------
128
+ $log[] = '### Now lets check that browsers *not* supporting webp gets the ' . strtoupper($imageType);
129
+ $log[] = 'Making a HTTP request for the test image (without setting the "Accept" header)';
130
+ list($success, $remoteGetLog, $results) = SelfTestHelper::remoteGet($requestUrl);
131
+ $headers = $results[count($results)-1]['headers'];
132
+ $log = array_merge($log, $remoteGetLog);
133
 
134
  if (!$success) {
135
+ $log[] = 'The request FAILED';
136
+ $log[] = 'The test cannot be completed';
137
+ //$log[count($log) - 1] .= '. FAILED';
138
+ return [false, $log, $createdTestFiles];
 
139
  }
140
+ //$log[count($log) - 1] .= '. ok!';
141
+ //$log[] = '*' . $requestUrl . '*';
142
 
143
+ //$log = array_merge($log, SelfTestHelper::printHeaders($headers));
144
 
145
  if (!isset($headers['content-type'])) {
146
+ $log[] = 'Bummer. There is no "content-type" response header. The test FAILED';
147
+ return [false, $log, $createdTestFiles];
148
  }
149
 
150
  if ($headers['content-type'] == 'image/webp') {
151
+ $log[] = '**Bummer**{: .error}. As the "content-type" header reveals, we got the webp. ' .
152
  'So even browsers not supporting webp gets webp. Not good!';
153
+ $log[] = 'The test FAILED.';
154
 
155
+ $log[] = '### What to do now?';
156
  // TODO: We could examine the headers for common CDN responses
157
 
158
+ $log[] = 'First, examine the response headers above. Is there any indication that ' .
159
  'the image is returned from a CDN cache? ' .
160
+ $log[] = 'If there is: Check out the ' .
161
  '*How do I configure my CDN in “Varied image responses” operation mode?* section in the FAQ ' .
162
  '(https://wordpress.org/plugins/webp-express/)';
163
 
164
  if (PlatformInfo::isApache()) {
165
+ $log[] = 'If not: please report this in the forum, as it seems the .htaccess rules ';
166
+ $log[] = 'just arent working on your system.';
167
  } elseif (PlatformInfo::isNginx()) {
168
+ $log[] = 'Also, as you are on Nginx, check out the ' .
169
  ' "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
170
  } else {
171
+ $log[] = 'If not: please report this in the forum, as it seems that there is something ' .
172
  'in the *.htaccess* rules generated by WebP Express that are not working.';
173
  }
174
 
175
+ $log[] = '### System info (for manual diagnosing):';
176
+ $log = array_merge($log, SelfTestHelper::allInfo($this->config));
177
 
178
 
179
+ return [false, $log, $createdTestFiles];
180
  }
181
 
182
  if ($headers['content-type'] != 'image/' . $imageType) {
183
+ $log[] = 'Bummer. As the "content-type" header reveals, we did not get the ' . $imageType .
184
  'Surprisingly we got: "' . $headers['content-type'] . '"';
185
+ $log[] = 'The test FAILED.';
186
+ return [false, $log, $createdTestFiles];
187
  }
188
+ $log[] = 'Alrighty. We got the ' . $imageType . '. **Great!**{: .ok}.';
189
 
190
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
191
+ $log[count($log) - 1] .= '. **BUT!**';
192
+ $log[] = '**We did not receive a Vary:Accept header. ' .
193
  'That header should be set in order to tell proxies that the response varies depending on the ' .
194
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
195
  $noWarningsYet = false;
196
  }
197
 
198
+ return [$noWarningsYet, $log, $createdTestFiles];
199
  }
200
 
201
  protected function getSuccessMessage()
207
 
208
  public function startupTests()
209
  {
210
+ $log[] = '# Testing redirection to converter';
211
  if (!$this->config['enable-redirection-to-converter']) {
212
+ $log[] = 'Turned off, nothing to test (if you just turned it on without saving, remember: this is a live test so you need to save settings)';
213
+ return [false, $log];
214
  }
215
+ return [true, $log];
216
  }
217
 
218
  public static function runTest()
lib/classes/SelfTestRedirectToExisting.php CHANGED
@@ -9,26 +9,26 @@ class SelfTestRedirectToExisting extends SelfTestRedirectAbstract
9
  *
10
  * @param string $rootId (ie "uploads" or "themes")
11
  * @param string $imageType ("jpeg" or "png")
12
- * @return array [$success, $result, $createdTestFiles]
13
  */
14
  protected function runTestForImageType($rootId, $imageType)
15
  {
16
- $result = [];
17
  $createdTestFiles = false;
18
  $noWarningsYet = true;
19
 
20
- $result[] = '### Copying files for testing';
21
 
22
  // Copy test image
23
  list($subResult, $success, $sourceFileName) = SelfTestHelper::copyTestImageToRoot($rootId, $imageType);
24
- $result = array_merge($result, $subResult);
25
  if (!$success) {
26
- $result[] = 'The test cannot be completed';
27
- return [false, $result, $createdTestFiles];
28
  }
29
  $createdTestFiles = true;
30
 
31
- $result[] = '';
32
 
33
  // Copy dummy webp
34
  list($subResult, $success, $destinationFile) = SelfTestHelper::copyDummyWebPToCacheFolder(
@@ -39,191 +39,188 @@ class SelfTestRedirectToExisting extends SelfTestRedirectAbstract
39
  $sourceFileName,
40
  $imageType
41
  );
42
- $result = array_merge($result, $subResult);
43
  if (!$success) {
44
- $result[] = 'The test cannot be completed';
45
- return [false, $result, $createdTestFiles];
46
  }
47
 
48
  $requestUrl = Paths::getUrlById($rootId) . '/webp-express-test-images/' . $sourceFileName;
49
- $result[] = '### Lets check that browsers supporting webp gets the WEBP when the ' . strtoupper($imageType) . ' is requested';
50
- $result[] = 'Making a HTTP request for the test image (pretending to be a client that supports webp, by setting the "Accept" header to "image/webp")';
51
  $requestArgs = [
52
  'headers' => [
53
  'ACCEPT' => 'image/webp'
54
  ]
55
  ];
56
- list($success, $errors, $headers, $return) = SelfTestHelper::remoteGet($requestUrl, $requestArgs);
 
 
 
57
 
58
  if (!$success) {
59
- $result[count($result) - 1] .= '. FAILED';
60
- $result = array_merge($result, $errors);
61
- $result[] = 'The test cannot be completed';
62
- //$result[count($result) - 1] .= '. FAILED';
63
- return [false, $result, $createdTestFiles];
64
  }
65
- //$result[count($result) - 1] .= '. ok!';
66
- $result[] = '*' . $requestUrl . '*';
67
 
68
- $result = array_merge($result, SelfTestHelper::printHeaders($headers));
69
 
70
  if (!isset($headers['content-type'])) {
71
- $result[] = 'Bummer. There is no "content-type" response header. The test FAILED';
72
- return [false, $result, $createdTestFiles];
73
  }
74
 
75
  if ($headers['content-type'] != 'image/webp') {
76
 
77
  if ($headers['content-type'] == 'image/' . $imageType) {
78
- $result[] = 'Bummer. As the "content-type" header reveals, we got the ' . $imageType . '. ';
79
  } else {
80
- $result[] = 'Bummer. As the "content-type" header reveals, we did not get a webp' .
81
  'Surprisingly we got: "' . $headers['content-type'] . '"';
82
- if (strpos($headers['content-type'], 'text/html') !== false) {
83
- $result[] = 'Body:';
84
- $result[] = print_r($return['body'], true);
85
- }
86
  }
87
 
88
  if (isset($headers['content-length'])) {
89
  if ($headers['content-length'] == '6964') {
90
- $result[] = 'However, the content-length reveals that we actually GOT the webp ' .
91
  '(we know that the file we put is exactly 6964 bytes). ' .
92
  'So it is "just" the content-type header that was not set correctly.';
93
 
94
  if (PlatformInfo::isNginx()) {
95
- $result[] = 'As you are on Nginx, you probably need to add the following line ' .
96
  'in your *mime.types* configuration file: ';
97
- $result[] = '```image/webp webp;```';
98
  } else {
99
- $result[] = 'Perhaps you dont have *mod_mime* installed, or the following lines are not in a *.htaccess* ' .
100
  'in the folder containing the webp (or a parent):';
101
- $result[] = "```<IfModule mod_mime.c>\n AddType image/webp .webp\n</IfModule>```";
102
 
103
- $result[] = '### .htaccess status';
104
- $result = array_merge($result, SelfTestHelper::htaccessInfo($this->config, true));
105
  }
106
 
107
- $result[] = 'The test **FAILED**{: .error}.';
108
  } else {
109
- $result[] = 'Additionally, the content-length reveals that we did not get the webp ' .
110
  '(we know that the file we put is exactly 6964 bytes). ' .
111
  'So we can conclude that the rewrite did not happen';
112
- $result[] = 'The test **FAILED**{: .error}.';
113
- $result[] = '#### Diagnosing rewrites';
114
- $result = array_merge($result, SelfTestHelper::diagnoseFailedRewrite($this->config));
115
  }
116
  } else {
117
- $result[] = 'In addition, we did not get a *content-length* header either.' .
118
- $result[] = 'It seems we can conclude that the rewrite did not happen.';
119
- $result[] = 'The test **FAILED**{: .error}.';
120
- $result[] = '#### Diagnosing rewrites';
121
- $result = array_merge($result, SelfTestHelper::diagnoseFailedRewrite($this->config));
122
  }
123
 
124
- return [false, $result, $createdTestFiles];
125
  }
126
 
127
  if (isset($headers['x-webp-convert-log'])) {
128
- $result[] = 'Bummer. Although we did get a webp, we did not get it as a result of a direct ' .
129
  'redirection. This webp was returned by the PHP script. Although this works, it takes more ' .
130
  'resources to ignite the PHP engine for each image request than redirecting directly to the image.';
131
- $result[] = 'The test FAILED.';
132
 
133
- $result[] = 'It seems something went wrong with the redirection.';
134
- $result[] = '#### Diagnosing redirects';
135
- $result = array_merge($result, SelfTestHelper::diagnoseFailedRewrite($this->config));
136
 
137
- return [false, $result, $createdTestFiles];
138
  } else {
139
- $result[] = 'Alrighty. We got a webp. Just what we wanted. **Great!**{: .ok}';
140
  }
141
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
142
- $result[count($result) - 1] .= '. **BUT!**';
143
- $result[] = '**Warning: We did not receive a Vary:Accept header. ' .
144
  'That header should be set in order to tell proxies that the response varies depending on the ' .
145
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
146
  $noWarningsYet = false;
147
  }
148
  if (!SelfTestHelper::hasCacheControlOrExpiresHeader($headers)) {
149
- $result[] = '**Notice: No cache-control or expires header has been set. ' .
150
  'It is recommended to do so. Set it nice and big once you are sure the webps have a good quality/compression compromise.**{: .warn}';
151
  }
152
- $result[] = '';
153
 
154
 
155
  // Check browsers NOT supporting webp
156
  // -----------------------------------
157
- $result[] = '### Now lets check that browsers *not* supporting webp gets the ' . strtoupper($imageType);
158
- $result[] = 'Making a HTTP request for the test image (without setting the "Accept" header)';
159
- list($success, $errors, $headers) = SelfTestHelper::remoteGet($requestUrl);
 
 
160
 
161
  if (!$success) {
162
- $result[count($result) - 1] .= '. FAILED';
163
- $result = array_merge($result, $errors);
164
- $result[] = 'The test cannot be completed';
165
- //$result[count($result) - 1] .= '. FAILED';
166
- return [false, $result, $createdTestFiles];
167
  }
168
- //$result[count($result) - 1] .= '. ok!';
169
- $result[] = '*' . $requestUrl . '*';
170
 
171
- $result = array_merge($result, SelfTestHelper::printHeaders($headers));
172
 
173
  if (!isset($headers['content-type'])) {
174
- $result[] = 'Bummer. There is no "content-type" response header. The test FAILED';
175
- return [false, $result, $createdTestFiles];
176
  }
177
 
178
  if ($headers['content-type'] == 'image/webp') {
179
- $result[] = '**Bummer**{: .error}. As the "content-type" header reveals, we got the webp. ' .
180
  'So even browsers not supporting webp gets webp. Not good!';
181
- $result[] = 'The test FAILED.';
182
 
183
- $result[] = '#### What to do now?';
184
  // TODO: We could examine the headers for common CDN responses
185
 
186
- $result[] = 'First, examine the response headers above. Is there any indication that ' .
187
  'the image is returned from a CDN cache? ' .
188
- $result[] = 'If there is: Check out the ' .
189
  '*How do I configure my CDN in “Varied image responses” operation mode?* section in the FAQ ' .
190
  '(https://wordpress.org/plugins/webp-express/)';
191
 
192
  if (PlatformInfo::isApache()) {
193
- $result[] = 'If not: please report this in the forum, as it seems the .htaccess rules ';
194
- $result[] = 'just arent working on your system.';
195
  } elseif (PlatformInfo::isNginx()) {
196
- $result[] = 'Also, as you are on Nginx, check out the ' .
197
  ' "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
198
  } else {
199
- $result[] = 'If not: please report this in the forum, as it seems that there is something ' .
200
  'in the *.htaccess* rules generated by WebP Express that are not working.';
201
  }
202
 
203
- $result[] = '### System info (for manual diagnosing):';
204
- $result = array_merge($result, SelfTestHelper::allInfo($this->config));
205
 
206
 
207
- return [false, $result, $createdTestFiles];
208
  }
209
 
210
  if ($headers['content-type'] != 'image/' . $imageType) {
211
- $result[] = 'Bummer. As the "content-type" header reveals, we did not get the ' . $imageType .
212
  'Surprisingly we got: "' . $headers['content-type'] . '"';
213
- $result[] = 'The test FAILED.';
214
- return [false, $result, $createdTestFiles];
215
  }
216
- $result[] = 'Alrighty. We got the ' . $imageType . '. **Great!**{: .ok}.';
217
 
218
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
219
- $result[count($result) - 1] .= '. **BUT!**';
220
- $result[] = '**We did not receive a Vary:Accept header. ' .
221
  'That header should be set in order to tell proxies that the response varies depending on the ' .
222
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
223
  $noWarningsYet = false;
224
  }
225
 
226
- return [$noWarningsYet, $result, $createdTestFiles];
227
  }
228
 
229
  protected function getSuccessMessage()
@@ -236,12 +233,12 @@ class SelfTestRedirectToExisting extends SelfTestRedirectAbstract
236
 
237
  public function startupTests()
238
  {
239
- $result[] = '# Testing redirection to existing webp';
240
  if (!$this->config['redirect-to-existing-in-htaccess']) {
241
- $result[] = 'Turned off, nothing to test (if you just turned it on without saving, remember: this is a live test so you need to save settings)';
242
- return [false, $result];
243
  }
244
- return [true, $result];
245
  }
246
 
247
  public static function runTest()
9
  *
10
  * @param string $rootId (ie "uploads" or "themes")
11
  * @param string $imageType ("jpeg" or "png")
12
+ * @return array [$success, $log, $createdTestFiles]
13
  */
14
  protected function runTestForImageType($rootId, $imageType)
15
  {
16
+ $log = [];
17
  $createdTestFiles = false;
18
  $noWarningsYet = true;
19
 
20
+ $log[] = '### Copying files for testing';
21
 
22
  // Copy test image
23
  list($subResult, $success, $sourceFileName) = SelfTestHelper::copyTestImageToRoot($rootId, $imageType);
24
+ $log = array_merge($log, $subResult);
25
  if (!$success) {
26
+ $log[] = 'The test cannot be completed';
27
+ return [false, $log, $createdTestFiles];
28
  }
29
  $createdTestFiles = true;
30
 
31
+ $log[] = '';
32
 
33
  // Copy dummy webp
34
  list($subResult, $success, $destinationFile) = SelfTestHelper::copyDummyWebPToCacheFolder(
39
  $sourceFileName,
40
  $imageType
41
  );
42
+ $log = array_merge($log, $subResult);
43
  if (!$success) {
44
+ $log[] = 'The test cannot be completed';
45
+ return [false, $log, $createdTestFiles];
46
  }
47
 
48
  $requestUrl = Paths::getUrlById($rootId) . '/webp-express-test-images/' . $sourceFileName;
49
+ $log[] = '### Lets check that browsers supporting webp gets the WEBP when the ' . strtoupper($imageType) . ' is requested';
50
+ $log[] = 'Making a HTTP request for the test image (pretending to be a client that supports webp, by setting the "Accept" header to "image/webp")';
51
  $requestArgs = [
52
  'headers' => [
53
  'ACCEPT' => 'image/webp'
54
  ]
55
  ];
56
+
57
+ list($success, $remoteGetLog, $results) = SelfTestHelper::remoteGet($requestUrl, $requestArgs);
58
+ $headers = $results[count($results)-1]['headers'];
59
+ $log = array_merge($log, $remoteGetLog);
60
 
61
  if (!$success) {
62
+ $log[] = 'The request FAILED';
63
+ $log[] = 'The test cannot be completed';
64
+ return [false, $log, $createdTestFiles];
 
 
65
  }
66
+ //$log[count($log) - 1] .= '. ok!';
67
+ //$log[] = '*' . $requestUrl . '*';
68
 
69
+ //$log = array_merge($log, SelfTestHelper::printHeaders($headers));
70
 
71
  if (!isset($headers['content-type'])) {
72
+ $log[] = 'Bummer. There is no "content-type" response header. The test FAILED';
73
+ return [false, $log, $createdTestFiles];
74
  }
75
 
76
  if ($headers['content-type'] != 'image/webp') {
77
 
78
  if ($headers['content-type'] == 'image/' . $imageType) {
79
+ $log[] = 'Bummer. As the "content-type" header reveals, we got the ' . $imageType . '. ';
80
  } else {
81
+ $log[] = 'Bummer. As the "content-type" header reveals, we did not get a webp' .
82
  'Surprisingly we got: "' . $headers['content-type'] . '"';
 
 
 
 
83
  }
84
 
85
  if (isset($headers['content-length'])) {
86
  if ($headers['content-length'] == '6964') {
87
+ $log[] = 'However, the content-length reveals that we actually GOT the webp ' .
88
  '(we know that the file we put is exactly 6964 bytes). ' .
89
  'So it is "just" the content-type header that was not set correctly.';
90
 
91
  if (PlatformInfo::isNginx()) {
92
+ $log[] = 'As you are on Nginx, you probably need to add the following line ' .
93
  'in your *mime.types* configuration file: ';
94
+ $log[] = '```image/webp webp;```';
95
  } else {
96
+ $log[] = 'Perhaps you dont have *mod_mime* installed, or the following lines are not in a *.htaccess* ' .
97
  'in the folder containing the webp (or a parent):';
98
+ $log[] = "```<IfModule mod_mime.c>\n AddType image/webp .webp\n</IfModule>```";
99
 
100
+ $log[] = '### .htaccess status';
101
+ $log = array_merge($log, SelfTestHelper::htaccessInfo($this->config, true));
102
  }
103
 
104
+ $log[] = 'The test **FAILED**{: .error}.';
105
  } else {
106
+ $log[] = 'Additionally, the content-length reveals that we did not get the webp ' .
107
  '(we know that the file we put is exactly 6964 bytes). ' .
108
  'So we can conclude that the rewrite did not happen';
109
+ $log[] = 'The test **FAILED**{: .error}.';
110
+ $log[] = '#### Diagnosing rewrites';
111
+ $log = array_merge($log, SelfTestHelper::diagnoseFailedRewrite($this->config));
112
  }
113
  } else {
114
+ $log[] = 'In addition, we did not get a *content-length* header either.' .
115
+ $log[] = 'It seems we can conclude that the rewrite did not happen.';
116
+ $log[] = 'The test **FAILED**{: .error}.';
117
+ $log[] = '#### Diagnosing rewrites';
118
+ $log = array_merge($log, SelfTestHelper::diagnoseFailedRewrite($this->config));
119
  }
120
 
121
+ return [false, $log, $createdTestFiles];
122
  }
123
 
124
  if (isset($headers['x-webp-convert-log'])) {
125
+ $log[] = 'Bummer. Although we did get a webp, we did not get it as a result of a direct ' .
126
  'redirection. This webp was returned by the PHP script. Although this works, it takes more ' .
127
  'resources to ignite the PHP engine for each image request than redirecting directly to the image.';
128
+ $log[] = 'The test FAILED.';
129
 
130
+ $log[] = 'It seems something went wrong with the redirection.';
131
+ $log[] = '#### Diagnosing redirects';
132
+ $log = array_merge($log, SelfTestHelper::diagnoseFailedRewrite($this->config));
133
 
134
+ return [false, $log, $createdTestFiles];
135
  } else {
136
+ $log[] = 'Alrighty. We got a webp. Just what we wanted. **Great!**{: .ok}';
137
  }
138
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
139
+ $log[count($log) - 1] .= '. **BUT!**';
140
+ $log[] = '**Warning: We did not receive a Vary:Accept header. ' .
141
  'That header should be set in order to tell proxies that the response varies depending on the ' .
142
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
143
  $noWarningsYet = false;
144
  }
145
  if (!SelfTestHelper::hasCacheControlOrExpiresHeader($headers)) {
146
+ $log[] = '**Notice: No cache-control or expires header has been set. ' .
147
  'It is recommended to do so. Set it nice and big once you are sure the webps have a good quality/compression compromise.**{: .warn}';
148
  }
149
+ $log[] = '';
150
 
151
 
152
  // Check browsers NOT supporting webp
153
  // -----------------------------------
154
+ $log[] = '### Now lets check that browsers *not* supporting webp gets the ' . strtoupper($imageType);
155
+ $log[] = 'Making a HTTP request for the test image (without setting the "Accept" header)';
156
+ list($success, $remoteGetLog, $results) = SelfTestHelper::remoteGet($requestUrl);
157
+ $headers = $results[count($results)-1]['headers'];
158
+ $log = array_merge($log, $remoteGetLog);
159
 
160
  if (!$success) {
161
+ $log[] = 'The request FAILED';
162
+ $log[] = 'The test cannot be completed';
163
+ return [false, $log, $createdTestFiles];
 
 
164
  }
165
+ //$log[count($log) - 1] .= '. ok!';
166
+ //$log[] = '*' . $requestUrl . '*';
167
 
168
+ //$log = array_merge($log, SelfTestHelper::printHeaders($headers));
169
 
170
  if (!isset($headers['content-type'])) {
171
+ $log[] = 'Bummer. There is no "content-type" response header. The test FAILED';
172
+ return [false, $log, $createdTestFiles];
173
  }
174
 
175
  if ($headers['content-type'] == 'image/webp') {
176
+ $log[] = '**Bummer**{: .error}. As the "content-type" header reveals, we got the webp. ' .
177
  'So even browsers not supporting webp gets webp. Not good!';
178
+ $log[] = 'The test FAILED.';
179
 
180
+ $log[] = '#### What to do now?';
181
  // TODO: We could examine the headers for common CDN responses
182
 
183
+ $log[] = 'First, examine the response headers above. Is there any indication that ' .
184
  'the image is returned from a CDN cache? ' .
185
+ $log[] = 'If there is: Check out the ' .
186
  '*How do I configure my CDN in “Varied image responses” operation mode?* section in the FAQ ' .
187
  '(https://wordpress.org/plugins/webp-express/)';
188
 
189
  if (PlatformInfo::isApache()) {
190
+ $log[] = 'If not: please report this in the forum, as it seems the .htaccess rules ';
191
+ $log[] = 'just arent working on your system.';
192
  } elseif (PlatformInfo::isNginx()) {
193
+ $log[] = 'Also, as you are on Nginx, check out the ' .
194
  ' "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
195
  } else {
196
+ $log[] = 'If not: please report this in the forum, as it seems that there is something ' .
197
  'in the *.htaccess* rules generated by WebP Express that are not working.';
198
  }
199
 
200
+ $log[] = '### System info (for manual diagnosing):';
201
+ $log = array_merge($log, SelfTestHelper::allInfo($this->config));
202
 
203
 
204
+ return [false, $log, $createdTestFiles];
205
  }
206
 
207
  if ($headers['content-type'] != 'image/' . $imageType) {
208
+ $log[] = 'Bummer. As the "content-type" header reveals, we did not get the ' . $imageType .
209
  'Surprisingly we got: "' . $headers['content-type'] . '"';
210
+ $log[] = 'The test FAILED.';
211
+ return [false, $log, $createdTestFiles];
212
  }
213
+ $log[] = 'Alrighty. We got the ' . $imageType . '. **Great!**{: .ok}.';
214
 
215
  if (!SelfTestHelper::hasVaryAcceptHeader($headers)) {
216
+ $log[count($log) - 1] .= '. **BUT!**';
217
+ $log[] = '**We did not receive a Vary:Accept header. ' .
218
  'That header should be set in order to tell proxies that the response varies depending on the ' .
219
  'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
220
  $noWarningsYet = false;
221
  }
222
 
223
+ return [$noWarningsYet, $log, $createdTestFiles];
224
  }
225
 
226
  protected function getSuccessMessage()
233
 
234
  public function startupTests()
235
  {
236
+ $log[] = '# Testing redirection to existing webp';
237
  if (!$this->config['redirect-to-existing-in-htaccess']) {
238
+ $log[] = 'Turned off, nothing to test (if you just turned it on without saving, remember: this is a live test so you need to save settings)';
239
+ return [false, $log];
240
  }
241
+ return [true, $log];
242
  }
243
 
244
  public static function runTest()
lib/classes/SelfTestRedirectToWebPRealizer.php CHANGED
@@ -10,20 +10,20 @@ class SelfTestRedirectToWebPRealizer extends SelfTestRedirectAbstract
10
  *
11
  * @param string $rootId (ie "uploads" or "themes")
12
  * @param string $imageType ("jpeg" or "png")
13
- * @return array [$success, $result, $createdTestFiles]
14
  */
15
  protected function runTestForImageType($rootId, $imageType)
16
  {
17
- $result = [];
18
  $createdTestFiles = false;
19
  $noWarningsYet = true;
20
 
21
  // Copy test image
22
  list($subResult, $success, $sourceFileName) = SelfTestHelper::copyTestImageToRoot($rootId, $imageType);
23
- $result = array_merge($result, $subResult);
24
  if (!$success) {
25
- $result[] = 'The test cannot be completed';
26
- return [false, $result, $createdTestFiles];
27
  }
28
  $createdTestFiles = true;
29
 
@@ -47,149 +47,147 @@ class SelfTestRedirectToWebPRealizer extends SelfTestRedirectAbstract
47
  );
48
 
49
 
50
- $result[] = '### Lets check that browsers supporting webp gets a freshly converted WEBP ' .
51
  'when a non-existing WEBP is requested, which has a corresponding source';
52
- $result[] = 'Making a HTTP request for the test image (pretending to be a client that supports webp, by setting the "Accept" header to "image/webp")';
53
  $requestArgs = [
54
  'headers' => [
55
  'ACCEPT' => 'image/webp'
56
  ]
57
  ];
58
- list($success, $errors, $headers, $return) = SelfTestHelper::remoteGet($requestUrl, $requestArgs);
 
 
59
 
60
  if (!$success) {
61
- //$result[count($result) - 1] .= '. FAILED';
62
- //$result[] = '*' . $requestUrl . '*';
63
 
64
- $result = array_merge($result, $errors);
65
- $result[] = 'The test **failed**{: .error}';
66
 
67
- $result[] = 'Why did it fail? It could either be that the redirection rule did not trigger ' .
68
  'or it could be that the PHP script could not locate a source image corresponding to the destination URL. ' .
69
  'Currently, this analysis cannot dertermine which was the case and it cannot be helpful ' .
70
  'if the latter is the case (sorry!). However, if the redirection rules are the problem, here is some info:';
71
 
72
- $result[] = '### Diagnosing redirection problems (presuming it is the redirection to the script that is failing)';
73
- $result = array_merge($result, SelfTestHelper::diagnoseFailedRewrite($this->config));
74
 
75
 
76
- //$result[count($result) - 1] .= '. FAILED';
77
- return [false, $result, $createdTestFiles];
78
  }
79
- //$result[count($result) - 1] .= '. ok!';
80
- $result[] = '*' . $requestUrl . '*';
81
 
82
- $result = array_merge($result, SelfTestHelper::printHeaders($headers));
83
 
84
  if (!isset($headers['content-type'])) {
85
- $result[] = 'Bummer. There is no "content-type" response header. The test FAILED';
86
- return [false, $result, $createdTestFiles];
87
  }
88
 
89
  if ($headers['content-type'] == 'image/' . $imageType) {
90
- $result[] = 'Bummer. As the "content-type" header reveals, we got the ' . $imageType . '.';
91
- $result[] = 'The test **failed**{: .error}.';
92
- $result[] = 'Now, what went wrong?';
93
 
94
  if (isset($headers['x-webp-convert-log'])) {
95
- //$result[] = 'Inspect the "x-webp-convert-log" headers above, and you ' .
96
  // 'should have your answer (it is probably because you do not have any conversion methods working).';
97
  if (SelfTestHelper::hasHeaderContaining($headers, 'x-webp-convert-log', 'Performing fail action: original')) {
98
- $result[] = 'The answer lies in the "x-convert-log" response headers: ' .
99
  '**The conversion failed**{: .error}. ';
100
  }
101
  } else {
102
- $result[] = 'Well, there is indication that the redirection isnt working. ' .
103
  'The PHP script should set "x-webp-convert-log" response headers, but there are none. ';
104
  'While these headers could have been eaten in a Cloudflare-like setup, the problem is ';
105
  'probably that the redirection simply failed';
106
 
107
- $result[] = '### Diagnosing redirection problems';
108
- $result = array_merge($result, SelfTestHelper::diagnoseFailedRewrite($this->config));
109
  }
110
- return [false, $result, $createdTestFiles];
111
  }
112
 
113
  if ($headers['content-type'] != 'image/webp') {
114
- $result[] = 'However. As the "content-type" header reveals, we did not get a webp' .
115
  'Surprisingly we got: "' . $headers['content-type'] . '"';
116
- $result[] = 'The test FAILED.';
117
- if (strpos($headers['content-type'], 'text/html') !== false) {
118
- $result[] = 'Body:';
119
- $result[] = print_r($return['body'], true);
120
- }
121
- return [false, $result, $createdTestFiles];
122
  }
123
 
124
- $result[] = '**Alrighty**{: .ok}. We got a webp.';
125
  if (isset($headers['x-webp-convert-log'])) {
126
- $result[] = 'The "x-webp-convert-log" headers reveals we got the webp from the PHP script. **Great!**{: .ok}';
127
  } else {
128
- $result[] = 'Interestingly, there are no "x-webp-convert-log" headers even though ' .
129
  'the PHP script always produces such. Could it be you have some weird setup that eats these headers?';
130
  }
131
 
132
  if (SelfTestHelper::hasVaryAcceptHeader($headers)) {
133
- $result[] = 'All is however not super-duper:';
134
 
135
- $result[] = '**Notice: We received a Vary:Accept header. ' .
136
  'That header need not to be set. Actually, it is a little bit bad for performance ' .
137
  'as proxies are currently doing a bad job maintaining several caches (in many cases they simply do not)**{: .warn}';
138
  $noWarningsYet = false;
139
  }
140
  if (!SelfTestHelper::hasCacheControlOrExpiresHeader($headers)) {
141
- $result[] = '**Notice: No cache-control or expires header has been set. ' .
142
  'It is recommended to do so. Set it nice and big once you are sure the webps have a good quality/compression compromise.**{: .warn}';
143
  }
144
- $result[] = '';
145
 
146
- return [$noWarningsYet, $result, $createdTestFiles];
147
  }
148
 
149
  /*
150
  private static function doRunTest($this->config)
151
  {
152
- $result = [];
153
- $result[] = '# Testing redirection to converter';
154
 
155
  $createdTestFiles = false;
156
  if (!file_exists(Paths::getConfigFileName())) {
157
- $result[] = 'Hold on. You need to save options before you can run this test. There is no config file yet.';
158
- return [true, $result, $createdTestFiles];
159
  }
160
 
161
 
162
  if ($this->config['image-types'] == 0) {
163
- $result[] = 'No image types have been activated, nothing to test';
164
- return [true, $result, $createdTestFiles];
165
  }
166
 
167
  if ($this->config['image-types'] & 1) {
168
  list($success, $subResult, $createdTestFiles) = self::runTestForImageType($this->config, 'jpeg');
169
- $result = array_merge($result, $subResult);
170
 
171
  if ($success) {
172
  if ($this->config['image-types'] & 2) {
173
- $result[] = '### Performing same tests for PNG';
174
  list($success, $subResult, $createdTestFiles2) = self::runTestForImageType($this->config, 'png');
175
  $createdTestFiles = $createdTestFiles || $createdTestFiles2;
176
  if ($success) {
177
- //$result[count($result) - 1] .= '. **ok**{: .ok}';
178
- $result[] .= 'All tests passed for PNG as well.';
179
- $result[] = '(I shall spare you for the report, which is almost identical to the one above)';
180
  } else {
181
- $result = array_merge($result, $subResult);
182
  }
183
  }
184
  }
185
  } else {
186
  list($success, $subResult, $createdTestFiles) = self::runTestForImageType($this->config, 'png');
187
- $result = array_merge($result, $subResult);
188
  }
189
 
190
  if ($success) {
191
- $result[] = '### Conclusion';
192
- $result[] = 'Everything **seems to work**{: .ok} as it should. ' .
193
  'However, notice that this test only tested an image which was placed in the *uploads* folder. ' .
194
  'The rest of the image roots (such as theme images) have not been tested (it is on the TODO). ' .
195
  'Also on the TODO: If one image type is disabled, check that it does not redirect to the conversion script. ' .
@@ -197,7 +195,7 @@ class SelfTestRedirectToWebPRealizer extends SelfTestRedirectAbstract
197
  }
198
 
199
 
200
- return [true, $result, $createdTestFiles];
201
  }*/
202
 
203
  protected function getSuccessMessage()
@@ -209,12 +207,12 @@ class SelfTestRedirectToWebPRealizer extends SelfTestRedirectAbstract
209
 
210
  public function startupTests()
211
  {
212
- $result[] = '# Testing "WebP Realizer" functionality';
213
  if (!$this->config['enable-redirection-to-webp-realizer']) {
214
- $result[] = 'Turned off, nothing to test (if you just turned it on without saving, remember: this is a live test so you need to save settings)';
215
- return [false, $result];
216
  }
217
- return [true, $result];
218
  }
219
 
220
  public static function runTest()
10
  *
11
  * @param string $rootId (ie "uploads" or "themes")
12
  * @param string $imageType ("jpeg" or "png")
13
+ * @return array [$success, $log, $createdTestFiles]
14
  */
15
  protected function runTestForImageType($rootId, $imageType)
16
  {
17
+ $log = [];
18
  $createdTestFiles = false;
19
  $noWarningsYet = true;
20
 
21
  // Copy test image
22
  list($subResult, $success, $sourceFileName) = SelfTestHelper::copyTestImageToRoot($rootId, $imageType);
23
+ $log = array_merge($log, $subResult);
24
  if (!$success) {
25
+ $log[] = 'The test cannot be completed';
26
+ return [false, $log, $createdTestFiles];
27
  }
28
  $createdTestFiles = true;
29
 
47
  );
48
 
49
 
50
+ $log[] = '### Lets check that browsers supporting webp gets a freshly converted WEBP ' .
51
  'when a non-existing WEBP is requested, which has a corresponding source';
52
+ $log[] = 'Making a HTTP request for the test image (pretending to be a client that supports webp, by setting the "Accept" header to "image/webp")';
53
  $requestArgs = [
54
  'headers' => [
55
  'ACCEPT' => 'image/webp'
56
  ]
57
  ];
58
+ list($success, $remoteGetLog, $results) = SelfTestHelper::remoteGet($requestUrl, $requestArgs);
59
+ $headers = $results[count($results)-1]['headers'];
60
+ $log = array_merge($log, $remoteGetLog);
61
 
62
  if (!$success) {
63
+ //$log[count($log) - 1] .= '. FAILED';
64
+ //$log[] = '*' . $requestUrl . '*';
65
 
66
+ $log = array_merge($log, $errors);
67
+ $log[] = 'The test **failed**{: .error}';
68
 
69
+ $log[] = 'Why did it fail? It could either be that the redirection rule did not trigger ' .
70
  'or it could be that the PHP script could not locate a source image corresponding to the destination URL. ' .
71
  'Currently, this analysis cannot dertermine which was the case and it cannot be helpful ' .
72
  'if the latter is the case (sorry!). However, if the redirection rules are the problem, here is some info:';
73
 
74
+ $log[] = '### Diagnosing redirection problems (presuming it is the redirection to the script that is failing)';
75
+ $log = array_merge($log, SelfTestHelper::diagnoseFailedRewrite($this->config));
76
 
77
 
78
+ //$log[count($log) - 1] .= '. FAILED';
79
+ return [false, $log, $createdTestFiles];
80
  }
81
+ //$log[count($log) - 1] .= '. ok!';
82
+ //$log[] = '*' . $requestUrl . '*';
83
 
84
+ //$log = array_merge($log, SelfTestHelper::printHeaders($headers));
85
 
86
  if (!isset($headers['content-type'])) {
87
+ $log[] = 'Bummer. There is no "content-type" response header. The test FAILED';
88
+ return [false, $log, $createdTestFiles];
89
  }
90
 
91
  if ($headers['content-type'] == 'image/' . $imageType) {
92
+ $log[] = 'Bummer. As the "content-type" header reveals, we got the ' . $imageType . '.';
93
+ $log[] = 'The test **failed**{: .error}.';
94
+ $log[] = 'Now, what went wrong?';
95
 
96
  if (isset($headers['x-webp-convert-log'])) {
97
+ //$log[] = 'Inspect the "x-webp-convert-log" headers above, and you ' .
98
  // 'should have your answer (it is probably because you do not have any conversion methods working).';
99
  if (SelfTestHelper::hasHeaderContaining($headers, 'x-webp-convert-log', 'Performing fail action: original')) {
100
+ $log[] = 'The answer lies in the "x-convert-log" response headers: ' .
101
  '**The conversion failed**{: .error}. ';
102
  }
103
  } else {
104
+ $log[] = 'Well, there is indication that the redirection isnt working. ' .
105
  'The PHP script should set "x-webp-convert-log" response headers, but there are none. ';
106
  'While these headers could have been eaten in a Cloudflare-like setup, the problem is ';
107
  'probably that the redirection simply failed';
108
 
109
+ $log[] = '### Diagnosing redirection problems';
110
+ $log = array_merge($log, SelfTestHelper::diagnoseFailedRewrite($this->config));
111
  }
112
+ return [false, $log, $createdTestFiles];
113
  }
114
 
115
  if ($headers['content-type'] != 'image/webp') {
116
+ $log[] = 'However. As the "content-type" header reveals, we did not get a webp' .
117
  'Surprisingly we got: "' . $headers['content-type'] . '"';
118
+ $log[] = 'The test FAILED.';
119
+ return [false, $log, $createdTestFiles];
 
 
 
 
120
  }
121
 
122
+ $log[] = '**Alrighty**{: .ok}. We got a webp.';
123
  if (isset($headers['x-webp-convert-log'])) {
124
+ $log[] = 'The "x-webp-convert-log" headers reveals we got the webp from the PHP script. **Great!**{: .ok}';
125
  } else {
126
+ $log[] = 'Interestingly, there are no "x-webp-convert-log" headers even though ' .
127
  'the PHP script always produces such. Could it be you have some weird setup that eats these headers?';
128
  }
129
 
130
  if (SelfTestHelper::hasVaryAcceptHeader($headers)) {
131
+ $log[] = 'All is however not super-duper:';
132
 
133
+ $log[] = '**Notice: We received a Vary:Accept header. ' .
134
  'That header need not to be set. Actually, it is a little bit bad for performance ' .
135
  'as proxies are currently doing a bad job maintaining several caches (in many cases they simply do not)**{: .warn}';
136
  $noWarningsYet = false;
137
  }
138
  if (!SelfTestHelper::hasCacheControlOrExpiresHeader($headers)) {
139
+ $log[] = '**Notice: No cache-control or expires header has been set. ' .
140
  'It is recommended to do so. Set it nice and big once you are sure the webps have a good quality/compression compromise.**{: .warn}';
141
  }
142
+ $log[] = '';
143
 
144
+ return [$noWarningsYet, $log, $createdTestFiles];
145
  }
146
 
147
  /*
148
  private static function doRunTest($this->config)
149
  {
150
+ $log = [];
151
+ $log[] = '# Testing redirection to converter';
152
 
153
  $createdTestFiles = false;
154
  if (!file_exists(Paths::getConfigFileName())) {
155
+ $log[] = 'Hold on. You need to save options before you can run this test. There is no config file yet.';
156
+ return [true, $log, $createdTestFiles];
157
  }
158
 
159
 
160
  if ($this->config['image-types'] == 0) {
161
+ $log[] = 'No image types have been activated, nothing to test';
162
+ return [true, $log, $createdTestFiles];
163
  }
164
 
165
  if ($this->config['image-types'] & 1) {
166
  list($success, $subResult, $createdTestFiles) = self::runTestForImageType($this->config, 'jpeg');
167
+ $log = array_merge($log, $subResult);
168
 
169
  if ($success) {
170
  if ($this->config['image-types'] & 2) {
171
+ $log[] = '### Performing same tests for PNG';
172
  list($success, $subResult, $createdTestFiles2) = self::runTestForImageType($this->config, 'png');
173
  $createdTestFiles = $createdTestFiles || $createdTestFiles2;
174
  if ($success) {
175
+ //$log[count($log) - 1] .= '. **ok**{: .ok}';
176
+ $log[] .= 'All tests passed for PNG as well.';
177
+ $log[] = '(I shall spare you for the report, which is almost identical to the one above)';
178
  } else {
179
+ $log = array_merge($log, $subResult);
180
  }
181
  }
182
  }
183
  } else {
184
  list($success, $subResult, $createdTestFiles) = self::runTestForImageType($this->config, 'png');
185
+ $log = array_merge($log, $subResult);
186
  }
187
 
188
  if ($success) {
189
+ $log[] = '### Conclusion';
190
+ $log[] = 'Everything **seems to work**{: .ok} as it should. ' .
191
  'However, notice that this test only tested an image which was placed in the *uploads* folder. ' .
192
  'The rest of the image roots (such as theme images) have not been tested (it is on the TODO). ' .
193
  'Also on the TODO: If one image type is disabled, check that it does not redirect to the conversion script. ' .
195
  }
196
 
197
 
198
+ return [true, $log, $createdTestFiles];
199
  }*/
200
 
201
  protected function getSuccessMessage()
207
 
208
  public function startupTests()
209
  {
210
+ $log[] = '# Testing "WebP Realizer" functionality';
211
  if (!$this->config['enable-redirection-to-webp-realizer']) {
212
+ $log[] = 'Turned off, nothing to test (if you just turned it on without saving, remember: this is a live test so you need to save settings)';
213
+ return [false, $log];
214
  }
215
+ return [true, $log];
216
  }
217
 
218
  public static function runTest()
lib/classes/WebPOnDemand.php CHANGED
@@ -17,6 +17,7 @@ use \WebPExpress\SanityException;
17
  use \WebPExpress\ValidateException;
18
  use \WebPExpress\Validate;
19
  use \WebPExpress\WodConfigLoader;
 
20
 
21
  class WebPOnDemand extends WodConfigLoader
22
  {
@@ -82,7 +83,7 @@ class WebPOnDemand extends WodConfigLoader
82
  // Check querystring (full path)
83
  // - But only on Nginx (our Apache .htaccess rules never passes absolute url)
84
  if (
85
- (stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') !== false) &&
86
  (isset($_GET['source']) || isset($_GET['xsource']))
87
  ) {
88
  self::$checking = 'source (passed as absolute path on nginx)';
@@ -206,6 +207,39 @@ class WebPOnDemand extends WodConfigLoader
206
  }
207
  //echo $source . '<br>' . $destination; exit;
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  ConvertHelperIndependent::serveConverted(
210
  $source,
211
  $destination,
17
  use \WebPExpress\ValidateException;
18
  use \WebPExpress\Validate;
19
  use \WebPExpress\WodConfigLoader;
20
+ use WebPConvert\Loggers\EchoLogger;
21
 
22
  class WebPOnDemand extends WodConfigLoader
23
  {
83
  // Check querystring (full path)
84
  // - But only on Nginx (our Apache .htaccess rules never passes absolute url)
85
  if (
86
+ (self::isNginxHandlingImages()) &&
87
  (isset($_GET['source']) || isset($_GET['xsource']))
88
  ) {
89
  self::$checking = 'source (passed as absolute path on nginx)';
207
  }
208
  //echo $source . '<br>' . $destination; exit;
209
 
210
+ /*
211
+ // No caching!
212
+ // - perhaps this will solve it for WP engine.
213
+ // but no... Perhaps a 302 redirect to self then? (if redirect to existing is activated).
214
+ // TODO: try!
215
+ //$serveOptions['serve-image']['headers']['vary-accept'] = false;
216
+
217
+ */
218
+ /*
219
+ include_once __DIR__ . '/../../vendor/autoload.php';
220
+ $convertLogger = new \WebPConvert\Loggers\BufferLogger();
221
+ \WebPConvert\WebPConvert::convert($source, $destination, $serveOptions['convert'], $convertLogger);
222
+ header('Location: ?fresh' , 302);
223
+ */
224
+
225
+ if (isset($_SERVER['WPENGINE_ACCOUNT'])) {
226
+ // Redirect to self rather than serve directly for WP Engine.
227
+ // This overcomes that Vary:Accept header set from PHP is lost on WP Engine.
228
+ // To prevent endless loop in case "redirect to existing webp" isn't set up correctly,
229
+ // only activate when destination is missing.
230
+ // (actually it does not prevent anything on wpengine as the first request is cached!
231
+ // -even though we try to prevent it:)
232
+ // Well well. Those users better set up "redirect to existing webp" as well!
233
+ $serveOptions['serve-image']['headers']['cache-control'] = true;
234
+ $serveOptions['serve-image']['headers']['expires'] = false;
235
+ $serveOptions['serve-image']['cache-control-header'] = 'no-store, no-cache, must-revalidate, max-age=0';
236
+ //header("Pragma: no-cache", true);
237
+
238
+ if (!@file_exists($destination)) {
239
+ $serveOptions['redirect-to-self-instead-of-serving'] = true;
240
+ }
241
+ }
242
+
243
  ConvertHelperIndependent::serveConverted(
244
  $source,
245
  $destination,
lib/classes/WebPRealizer.php CHANGED
@@ -39,21 +39,30 @@ class WebPRealizer extends WodConfigLoader
39
 
40
  // Check querystring (full path)
41
  // - But only on Nginx (our Apache .htaccess rules never passes absolute url)
42
- if (
43
- (stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') !== false) &&
44
- (isset($_GET['destination']) || isset($_GET['xdestination']))
45
- ) {
46
  if (isset($_GET['destination'])) {
47
- $destination = SanityCheck::absPathIsInDocRoot($_GET['destination']);
48
- } else {
 
49
  $xdest = SanityCheck::noControlChars($_GET['xdestination']);
50
- $destination = SanityCheck::absPathIsInDocRoot(substr($xdest, 1));
51
  }
52
  }
53
 
54
  // Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
55
- // correct result in all setups (ie "folder method 1")
 
56
  $destRel = SanityCheck::pathWithoutDirectoryTraversal(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
 
 
 
 
 
 
 
 
 
 
57
  $destination = SanityCheck::absPath($docRoot . $destRel);
58
  return SanityCheck::absPathIsInDocRoot($destination);
59
  }
39
 
40
  // Check querystring (full path)
41
  // - But only on Nginx (our Apache .htaccess rules never passes absolute url)
42
+ if (self::isNginxHandlingImages()) {
 
 
 
43
  if (isset($_GET['destination'])) {
44
+ return SanityCheck::absPathIsInDocRoot($_GET['destination']);
45
+ }
46
+ if (isset($_GET['xdestination'])) {
47
  $xdest = SanityCheck::noControlChars($_GET['xdestination']);
48
+ return SanityCheck::absPathIsInDocRoot(substr($xdest, 1));
49
  }
50
  }
51
 
52
  // Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
53
+ // correct result in all setups (ie "folder method 1").
54
+ // On nginx, it can even return the path to webp-realizer.php. TODO: Handle that better than now
55
  $destRel = SanityCheck::pathWithoutDirectoryTraversal(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
56
+ if ($destRel) {
57
+ if (preg_match('#webp-realizer\.php$#', $destRel)) {
58
+ throw new \Exception(
59
+ 'webp-realizer.php need to know the file path and cannot simply use $_SERVER["REQUEST_URI"] ' .
60
+ 'as that points to itself rather than the image requested. ' .
61
+ 'On Nginx, please add: "&xdestination=x$request_filename" to the URL in the rules in the nginx config ' .
62
+ '(sorry, the parameter was missing in the rules in the README for a while, but it is back)'
63
+ );
64
+ }
65
+ }
66
  $destination = SanityCheck::absPath($docRoot . $destRel);
67
  return SanityCheck::absPathIsInDocRoot($destination);
68
  }
lib/classes/WodConfigLoader.php CHANGED
@@ -35,6 +35,42 @@ class WodConfigLoader
35
  exit;
36
  }
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  /**
39
  * Get environment variable set with mod_rewrite module
40
  * Return false if the environment variable isn't found
35
  exit;
36
  }
37
 
38
+ /**
39
+ * Check if Apache handles the PHP requests (Note that duel setups are possible and ie Nginx could be handling the image requests).
40
+ */
41
+ public static function isApache()
42
+ {
43
+ return (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false);
44
+ }
45
+
46
+ protected static function isNginxHandlingImages()
47
+ {
48
+ if (stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') !== false) {
49
+ return true;
50
+ }
51
+
52
+ // On WP Engine, SERVER_SOFTWARE is "Apache", but images are handled by NGINX.
53
+ if (isset($_SERVER['WPENGINE_ACCOUNT'])) {
54
+ return true;
55
+ };
56
+ return false;
57
+ }
58
+
59
+ public static function preventDirectAccess($filename)
60
+ {
61
+ // Protect against directly accessing webp-on-demand.php
62
+ // Only protect on Apache. We know for sure that the method is not reliable on nginx.
63
+ // We have not tested on litespeed yet, so we dare not.
64
+ if (self::isApache() && (!self::isNginxHandlingImages())) {
65
+ if (strpos($_SERVER['REQUEST_URI'], $filename) !== false) {
66
+ self::exitWithError(
67
+ 'It seems you are visiting this file (plugins/webp-express/wod/' . $filename . ') directly. We do not allow this.'
68
+ );
69
+ exit;
70
+ }
71
+ }
72
+ }
73
+
74
  /**
75
  * Get environment variable set with mod_rewrite module
76
  * Return false if the environment variable isn't found
lib/options/page-welcome.php CHANGED
@@ -35,8 +35,10 @@ if ($weKnowThereAreNoWorkingConverters) {
35
  '<li>You can try to meet the server requirements of cwebp, imagick, vips, gmagick or gd. Check out <a target="_blank" href="https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters">this wiki page</a> on how to do that</li>' .
36
  '</ol>' .
37
  '<p>Of course, there is also the option of using another plugin altogether. ' .
38
- 'I can recommend ' .
39
- '<a href="https://optimole.pxf.io/20b0M">Optimole</a>. ' .
 
 
40
  '</p>' .
41
  "<p>Btw, don't worry, your images still works. The rewrite rules will not be saved until you click the " .
42
  '"Save settings" button.</p>';
35
  '<li>You can try to meet the server requirements of cwebp, imagick, vips, gmagick or gd. Check out <a target="_blank" href="https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters">this wiki page</a> on how to do that</li>' .
36
  '</ol>' .
37
  '<p>Of course, there is also the option of using another plugin altogether. ' .
38
+ 'I can recommend <i>Optimole</i>. ' .
39
+ 'If you want to try that out and want to support me in the process, ' .
40
+ '<a href="https://optimole.pxf.io/20b0M">follow this link</a> ' .
41
+ '(it will give me a reward in case you decide to sign up).' .
42
  '</p>' .
43
  "<p>Btw, don't worry, your images still works. The rewrite rules will not be saved until you click the " .
44
  '"Save settings" button.</p>';
vendor/rosell-dk/webp-convert/src/Serve/ServeConvertedWebP.php CHANGED
@@ -49,6 +49,8 @@ class ServeConvertedWebP
49
  new BooleanOption('serve-original', false),
50
  new BooleanOption('show-report', false),
51
  new BooleanOption('suppress-warnings', true),
 
 
52
  new ArrayOption('serve-image', []),
53
  new SensitiveArrayOption('convert', [])
54
  );
@@ -180,6 +182,12 @@ class ServeConvertedWebP
180
  self::serveOriginal($source, $options['serve-image']);
181
  }
182
 
 
 
 
 
 
 
183
  $filesizeDestination = @filesize($destination);
184
  $filesizeSource = @filesize($source);
185
  if (($filesizeSource !== false) &&
@@ -189,7 +197,14 @@ class ServeConvertedWebP
189
  self::serveOriginal($source, $options['serve-image']);
190
  }
191
 
192
- Header::addLogHeader('Serving converted file', $serveLogger);
193
- self::serveDestination($destination, $options['serve-image']);
 
 
 
 
 
 
 
194
  }
195
  }
49
  new BooleanOption('serve-original', false),
50
  new BooleanOption('show-report', false),
51
  new BooleanOption('suppress-warnings', true),
52
+ new BooleanOption('redirect-to-self-instead-of-serving', false),
53
+ //new BooleanOption('redirect-to-self-instead-of-serving-destination', false),
54
  new ArrayOption('serve-image', []),
55
  new SensitiveArrayOption('convert', [])
56
  );
182
  self::serveOriginal($source, $options['serve-image']);
183
  }
184
 
185
+ if ($options['redirect-to-self-instead-of-serving']) {
186
+ Header::addLogHeader('Redirecting to self! (hope you got redirection to existing webps set up, otherwise you will get a loop!)', $serveLogger);
187
+ header('Location: ?fresh' , 302);
188
+ return;
189
+ }
190
+
191
  $filesizeDestination = @filesize($destination);
192
  $filesizeSource = @filesize($source);
193
  if (($filesizeSource !== false) &&
197
  self::serveOriginal($source, $options['serve-image']);
198
  }
199
 
200
+ /*if ($options['redirect-to-self-instead-of-serving-destination']) {
201
+ Header::addLogHeader('Redirecting to self! (hope you got redirection to existing webps set up, otherwise you will get a loop!)', $serveLogger);
202
+ header('Location: ?fresh' , 302);
203
+ } else {*/
204
+ Header::addLogHeader('Serving converted file', $serveLogger);
205
+ self::serveDestination($destination, $options['serve-image']);
206
+ //}
207
+
208
+
209
  }
210
  }
webp-express.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WebP Express
4
  * Plugin URI: https://github.com/rosell-dk/webp-express
5
  * Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
6
- * Version: 0.17.0
7
  * Author: Bjørn Rosell
8
  * Author URI: https://www.bitwise-it.dk
9
  * License: GPL2
@@ -52,55 +52,9 @@ if (Option::getOption('webp-express-alter-html', false)) {
52
  \WebPExpress\AlterHtmlInit::setHooks();
53
  }
54
 
55
- /*
56
- $filters = [];
57
- add_action('all', function() {
58
- global $filters;
59
- $filter = current_filter();
60
- if (!in_array($filter, $filters)) {
61
- $filters[] = $filter;
62
- error_log($filter);
63
- }
64
- });
65
- */
66
-
67
  // When images are uploaded with Gutenberg, is_admin() returns false, so, hook needs to be added here
68
  add_filter('wp_handle_upload', array('\WebPExpress\HandleUploadHooks', 'handleUpload'), 10, 2);
69
  add_filter('image_make_intermediate_size', array('\WebPExpress\HandleUploadHooks', 'handleMakeIntermediateSize'), 10, 1);
70
  add_filter('wp_delete_file', array('\WebPExpress\HandleDeleteFileHook', 'deleteAssociatedWebP'), 10, 2);
71
 
72
- /*
73
- add_action('wp_handle_upload', function($a) {
74
- error_log('yes, it is called'. (is_admin() ? 'admin' : 'not admin'));
75
- \WebPExpress\HandleUploadHooks::handleUpload($a, true);
76
- return $a;
77
- });*/
78
-
79
-
80
- /*
81
- function webpexpress_addWebPJs() {
82
- $url = plugins_url('webpjs/webpjs-0.0.2.min.js', __FILE__);
83
- $script = <<<EOD
84
- <script>
85
- (function(){
86
- var WebP=new Image();
87
- WebP.onload=WebP.onerror=function(){
88
- if(WebP.height!=2){
89
- var sc=document.createElement('script');
90
- sc.type='text/javascript';
91
- sc.async=true;
92
- var s=document.getElementsByTagName('script')[0];
93
- sc.src='$url';
94
- s.parentNode.insertBefore(sc,s);
95
- }
96
- };
97
- WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
98
- })();
99
- </script>
100
- EOD;
101
- echo $script;
102
- }
103
-
104
- add_action( 'wp_head', 'webpexpress_addWebPJs');
105
- */
106
  //add_action( 'template_redirect', 'webp_express_template_redirect' );
3
  * Plugin Name: WebP Express
4
  * Plugin URI: https://github.com/rosell-dk/webp-express
5
  * Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
6
+ * Version: 0.17.1
7
  * Author: Bjørn Rosell
8
  * Author URI: https://www.bitwise-it.dk
9
  * License: GPL2
52
  \WebPExpress\AlterHtmlInit::setHooks();
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  // When images are uploaded with Gutenberg, is_admin() returns false, so, hook needs to be added here
56
  add_filter('wp_handle_upload', array('\WebPExpress\HandleUploadHooks', 'handleUpload'), 10, 2);
57
  add_filter('image_make_intermediate_size', array('\WebPExpress\HandleUploadHooks', 'handleMakeIntermediateSize'), 10, 1);
58
  add_filter('wp_delete_file', array('\WebPExpress\HandleDeleteFileHook', 'deleteAssociatedWebP'), 10, 2);
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  //add_action( 'template_redirect', 'webp_express_template_redirect' );
wod/.htaccess CHANGED
@@ -1,3 +1,4 @@
 
1
  <FilesMatch "(webp-on-demand|webp-realizer)\.php$">
2
  <IfModule !mod_authz_core.c>
3
  Order deny,allow
1
+ # Grant access to webp-on-demand.php and webp-realizer.php
2
  <FilesMatch "(webp-on-demand|webp-realizer)\.php$">
3
  <IfModule !mod_authz_core.c>
4
  Order deny,allow
wod/autoloader.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ define('WOD_DIR', __DIR__);
3
+ function webpexpress_autoloader($class) {
4
+ if (strpos($class, 'WebPExpress\\') === 0) {
5
+ require_once WOD_DIR . '/../lib/classes/' . substr($class, 12) . '.php';
6
+ }
7
+ }
8
+ spl_autoload_register('webpexpress_autoloader');
wod/webp-on-demand.php CHANGED
@@ -1,25 +1,8 @@
1
  <?php
2
 
3
- use \WebPExpress\WebPOnDemand;
4
 
5
- // Protect against directly accessing webp-on-demand.php
6
- // Only protect on Apache. We know for sure that the method is not reliable on nginx. We have not tested on litespeed yet, so we dare not.
7
- if (stripos($_SERVER["SERVER_SOFTWARE"], 'apache') !== false && stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') === false) {
8
- if (strpos($_SERVER['REQUEST_URI'], 'webp-on-demand.php') !== false) {
9
- WebPOnDemand::exitWithError(
10
- 'It seems you are visiting this file (plugins/webp-express/wod/webp-on-demand.php) directly. We do not allow this.'
11
- );
12
- exit;
13
- }
14
- }
15
-
16
- define('WOD_DIR', __DIR__);
17
-
18
- function webpexpress_autoloader($class) {
19
- if (strpos($class, 'WebPExpress\\') === 0) {
20
- require_once WOD_DIR . '/../lib/classes/' . substr($class, 12) . '.php';
21
- }
22
- }
23
- spl_autoload_register('webpexpress_autoloader');
24
 
 
25
  WebPOnDemand::processRequest();
1
  <?php
2
 
3
+ namespace WebPExpress;
4
 
5
+ include 'autoloader.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ WebPOnDemand::preventDirectAccess('webp-on-demand.php');
8
  WebPOnDemand::processRequest();
wod/webp-realizer.php CHANGED
@@ -1,25 +1,8 @@
1
  <?php
2
 
3
- use \WebPExpress\WebPRealizer;
4
 
5
- // Protect against directly accessing webp-on-demand.php
6
- // Only protect on Apache. We know for sure that the method is not reliable on nginx. We have not tested on litespeed yet, so we dare not.
7
- if (stripos($_SERVER["SERVER_SOFTWARE"], 'apache') !== false && stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') === false) {
8
- if (strpos($_SERVER['REQUEST_URI'], 'webp-realizer.php') !== false) {
9
- WebPOnDemand::exitWithError(
10
- 'It seems you are visiting this file (plugins/webp-express/wod/webp-realizer.php) directly. We do not allow this.'
11
- );
12
- exit;
13
- }
14
- }
15
-
16
- define('WOD_DIR', __DIR__);
17
-
18
- function webpexpress_autoloader($class) {
19
- if (strpos($class, 'WebPExpress\\') === 0) {
20
- require_once WOD_DIR . '/../lib/classes/' . substr($class, 12) . '.php';
21
- }
22
- }
23
- spl_autoload_register('webpexpress_autoloader');
24
 
 
25
  WebPRealizer::processRequest();
1
  <?php
2
 
3
+ namespace WebPExpress;
4
 
5
+ include 'autoloader.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ WebPRealizer::preventDirectAccess('webp-realizer.php');
8
  WebPRealizer::processRequest();