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