WebP Express - Version 0.11.3

Version Description

  • Fixed bug: Alter HTML caused media library not to display images on some systems. Alter HTML is now disabled in admin mode.
  • Alter HTML (picture tags) could produce the source tags with "src" attribute. But source tags inside picture tags must use "srcset" attribute. Fixed.
  • Alter HTML (image urls): srcsets containing "x" descriptors wasn't handled (ie, srcset="image.jpg 1x")
  • Fixed rewrite rules when placed in root so they are confined to wp-content and uploads. In particular, they no longer apply in wp-admin area, which might have caused problems, ie with media library.
  • Added warning when rules are placed in root and "Convert non-existing webp-files upon request" feature is enabled and WebP Express rules are to be placed below Wordpress rules
  • Fixed bug: The code that determined if WebP Express had placed rules in a .htaccess failed in "CDN friendly" mode. The effect was that these rules was not cleaned up upon plugin deactivation
Download this release

Release Info

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

Code changes from version 0.11.2 to 0.11.3

README.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: rosell.dk
3
  Donate link: https://ko-fi.com/rosell
4
  Tags: webp, images, performance
5
  Requires at least: 4.0
6
- Tested up to: 5.0
7
- Stable tag: 0.11.2
8
  Requires PHP: 5.6
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -550,11 +550,12 @@ In a webp-enabled browser, the HTML may look like this: `<img src="image.webp">`
550
  = Does it work with lazy loaded images? =
551
  No plugins/frameworks has yet been discovered, which does not work with *WebP Express*.
552
 
553
- The most common way of lazy-loading is by setting a *data-src* attribute on the image and let javascript use that value for setten the *src* attribute. That method works, as the image request, seen from the server side, is indistinguishable from any other image request. It could however be that some obscure lazy load implementation would load the image with an XHR request. In that case, the *Accept* header will not contain 'image/webp', but '*/*', and a jpeg will be served, even though the browser supports webp.
554
 
555
  The following lazy load plugins/frameworks has been tested and works with *WebP Express*:
556
  - [BJ Lazy Load](https://da.wordpress.org/plugins/bj-lazy-load/)
557
  - [Owl Carousel 2](https://owlcarousel2.github.io/OwlCarousel2/)
 
558
 
559
  I have only tested the above in *Varied image responses* mode, but it should also work in *CDN friendly* mode. Both *Alter HTML* options have been designed to work with standard lazy load attributes.
560
 
@@ -573,6 +574,14 @@ Easy enough! - [Go here!](https://ko-fi.com/rosell). Or [here](https://buymeacof
573
  1. WebP Express settings
574
 
575
  == Changelog ==
 
 
 
 
 
 
 
 
576
  = 0.11.2 =
577
  * Fixed bug which caused Alter HTML to fail miserably on some setups
578
  * AlterHTML now also looks for lazy load attributes in DIV and LI tags.
@@ -673,6 +682,9 @@ For older releases, check out changelog.txt
673
 
674
  == Upgrade Notice ==
675
 
 
 
 
676
  = 0.11.0 =
677
  WebP Express can now alter HTML to either point to webp images directly or by using the picture tag syntax. Also, non-existing webp-files can be converted upon request (means you can reference the converted webp files before they are actually converted!)
678
 
3
  Donate link: https://ko-fi.com/rosell
4
  Tags: webp, images, performance
5
  Requires at least: 4.0
6
+ Tested up to: 5.1
7
+ Stable tag: 0.11.3
8
  Requires PHP: 5.6
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
550
  = Does it work with lazy loaded images? =
551
  No plugins/frameworks has yet been discovered, which does not work with *WebP Express*.
552
 
553
+ The most common way of lazy-loading is by setting a *data-src* attribute on the image and let javascript use that value for setting the *src* attribute. That method works, as the image request, seen from the server side, is indistinguishable from any other image request. It could however be that some obscure lazy load implementation would load the image with an XHR request. In that case, the *Accept* header will not contain 'image/webp', but '*/*', and a jpeg will be served, even though the browser supports webp.
554
 
555
  The following lazy load plugins/frameworks has been tested and works with *WebP Express*:
556
  - [BJ Lazy Load](https://da.wordpress.org/plugins/bj-lazy-load/)
557
  - [Owl Carousel 2](https://owlcarousel2.github.io/OwlCarousel2/)
558
+ - [Lazy Load by WP Rocket](https://wordpress.org/plugins/rocket-lazy-load/)
559
 
560
  I have only tested the above in *Varied image responses* mode, but it should also work in *CDN friendly* mode. Both *Alter HTML* options have been designed to work with standard lazy load attributes.
561
 
574
  1. WebP Express settings
575
 
576
  == Changelog ==
577
+ = 0.11.3 =
578
+ * Fixed bug: Alter HTML caused media library not to display images on some systems. Alter HTML is now disabled in admin mode.
579
+ * Alter HTML (picture tags) could produce the source tags with "src" attribute. But source tags inside picture tags must use "srcset" attribute. Fixed.
580
+ * Alter HTML (image urls): srcsets containing "x" descriptors wasn't handled (ie, srcset="image.jpg 1x")
581
+ * Fixed rewrite rules when placed in root so they are confined to wp-content and uploads. In particular, they no longer apply in wp-admin area, which might have caused problems, ie with media library.
582
+ * Added warning when rules are placed in root and "Convert non-existing webp-files upon request" feature is enabled and WebP Express rules are to be placed below Wordpress rules
583
+ * Fixed bug: The code that determined if WebP Express had placed rules in a .htaccess failed in "CDN friendly" mode. The effect was that these rules was not cleaned up upon plugin deactivation
584
+
585
  = 0.11.2 =
586
  * Fixed bug which caused Alter HTML to fail miserably on some setups
587
  * AlterHTML now also looks for lazy load attributes in DIV and LI tags.
682
 
683
  == Upgrade Notice ==
684
 
685
+ = 0.11.3 =
686
+ Fixed several bugs. You should update :)
687
+
688
  = 0.11.0 =
689
  WebP Express can now alter HTML to either point to webp images directly or by using the picture tag syntax. Also, non-existing webp-files can be converted upon request (means you can reference the converted webp files before they are actually converted!)
690
 
changelog.txt CHANGED
@@ -1,3 +1,11 @@
 
 
 
 
 
 
 
 
1
  = 0.11.2 =
2
  * Fixed bug which caused Alter HTML to fail miserably on some setups
3
  * AlterHTML now also looks for lazy load attributes in DIV and LI tags.
1
+ = 0.11.3 =
2
+ * Fixed bug: Alter HTML caused media library not to display images on some systems. Alter HTML is now disabled in admin mode.
3
+ * Alter HTML (picture tags) could produce the source tags with "src" attribute. But source tags inside picture tags must use "srcset" attribute. Fixed.
4
+ * Alter HTML (image urls): srcsets containing "x" descriptors wasn't handled (ie, srcset="image.jpg 1x")
5
+ * Fixed rewrite rules when placed in root so they are confined to wp-content and uploads. In particular, they no longer apply in wp-admin area, which might have caused problems, ie with media library.
6
+ * Added warning when rules are placed in root and "Convert non-existing webp-files upon request" feature is enabled and WebP Express rules are to be placed below Wordpress rules
7
+ * Fixed bug: The code that determined if WebP Express had placed rules in a .htaccess failed in "CDN friendly" mode. The effect was that these rules was not cleaned up upon plugin deactivation
8
+
9
  = 0.11.2 =
10
  * Fixed bug which caused Alter HTML to fail miserably on some setups
11
  * AlterHTML now also looks for lazy load attributes in DIV and LI tags.
lib/admin.php CHANGED
@@ -2,16 +2,15 @@
2
  use \WebPExpress\State;
3
 
4
  // When an update requires a migration, the number should be increased
5
- define('WEBPEXPRESS_MIGRATION_VERSION', '5');
6
-
7
- //update_option('webp-express-migration-version', '4');
8
 
9
  if (WEBPEXPRESS_MIGRATION_VERSION != get_option('webp-express-migration-version', 0)) {
10
  // run migration logic
11
  include __DIR__ . '/migrate/migrate.php';
12
  }
13
 
14
- // include __DIR__ . '/migrate/migrate3.php'; // test-running a migration
 
15
 
16
  // uncomment next line to debug an error during activation
17
  //include __DIR__ . "/debug.php";
2
  use \WebPExpress\State;
3
 
4
  // When an update requires a migration, the number should be increased
5
+ define('WEBPEXPRESS_MIGRATION_VERSION', '6');
 
 
6
 
7
  if (WEBPEXPRESS_MIGRATION_VERSION != get_option('webp-express-migration-version', 0)) {
8
  // run migration logic
9
  include __DIR__ . '/migrate/migrate.php';
10
  }
11
 
12
+ // uncomment next line to test-run a migration
13
+ // include __DIR__ . '/migrate/migrate6.php';
14
 
15
  // uncomment next line to debug an error during activation
16
  //include __DIR__ . "/debug.php";
lib/classes/AlterHtmlInit.php CHANGED
@@ -23,14 +23,15 @@ class AlterHtmlInit
23
  return $content;
24
  }
25
 
 
 
 
 
26
  if (get_option('webp-express-alter-html-replacement') == 'picture') {
27
  if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
28
  //for AMP pages the <picture> tag is not allowed
29
  return $content;
30
  }
31
- /*if (is_admin() ) {
32
- return $content;
33
- }*/
34
  }
35
 
36
  if (!isset(self::$options)) {
23
  return $content;
24
  }
25
 
26
+ if (is_admin() ) {
27
+ return $content;
28
+ }
29
+
30
  if (get_option('webp-express-alter-html-replacement') == 'picture') {
31
  if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
32
  //for AMP pages the <picture> tag is not allowed
33
  return $content;
34
  }
 
 
 
35
  }
36
 
37
  if (!isset(self::$options)) {
lib/classes/HTAccess.php CHANGED
@@ -125,6 +125,33 @@ class HTAccess
125
 
126
 
127
  /* Build rules */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  $rules = '';
129
 
130
 
@@ -178,10 +205,11 @@ class HTAccess
178
 
179
  if ($config['destination-extension'] == 'append') {
180
  $rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $htaccessDirRel . "/$1.$2.webp -f\n";
181
- $rules .= " RewriteRule ^(.+)\.(" . $fileExt . ")$ $1.$2.webp [T=image/webp,E=EXISTING:1,L]\n\n";
182
  } else {
183
  $rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $htaccessDirRel . "/$1.webp -f\n";
184
- $rules .= " RewriteRule ^(.+)\.(" . $fileExt . ")$ $1.webp [T=image/webp,E=EXISTING:1,L]\n\n";
 
185
  }
186
  }
187
 
@@ -189,7 +217,8 @@ class HTAccess
189
  $rules .= " RewriteCond %{HTTP_ACCEPT} image/webp\n";
190
  $rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
191
  $rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $cacheDirRel . "/" . $htaccessDirRel . "/$1.$2.webp -f\n";
192
- $rules .= " RewriteRule ^\/?(.*)\.(" . $fileExt . ")$ /" . $cacheDirRel . "/" . $htaccessDirRel . "/$1.$2.webp [NC,T=image/webp,E=EXISTING:1,L]\n\n";
 
193
 
194
  $rules .= $ccRules;
195
 
@@ -227,7 +256,7 @@ class HTAccess
227
 
228
  $rules .= " # Pass REQUEST_FILENAME to webp-realizer.php in request header\n";
229
  $rules .= $basicConditionsRealizer;
230
- $rules .= " RewriteRule ^(.*)\.(webp)$ - [E=REQFN:%{REQUEST_FILENAME}]\n" .
231
  " <IfModule mod_headers.c>\n" .
232
  " RequestHeader set REQFN \"%{REQFN}e\" env=REQFN\n" .
233
  " </IfModule>\n\n";
@@ -235,7 +264,7 @@ class HTAccess
235
  $rules .= " # WebP Realizer: Redirect non-existing webp images to webp-realizer.php, which will locate corresponding jpg/png, convert it, and deliver the webp (if possible) \n";
236
  $rules .= $basicConditionsRealizer;
237
 
238
- $rules .= " RewriteRule ^(.*)\.(webp)$ " .
239
  "/" . Paths::getWebPRealizerUrlPath() .
240
  ($passSourceInQSRealizer ? "?xdestination=x%{SCRIPT_FILENAME}&" : "?") .
241
  "wp-content=" . Paths::getContentDirRel() .
@@ -297,14 +326,15 @@ class HTAccess
297
  // Add "NE" flag?
298
  // https://github.com/rosell-dk/webp-convert/issues/95
299
  // (and try testing spaces in directory paths)
300
- $rules .= " RewriteRule ^(.*)\.(" . $fileExt . ")$ " .
 
 
301
  "/" . Paths::getWodUrlPath() .
302
  ($passSourceInQS ? "?xsource=x%{SCRIPT_FILENAME}&" : "?") .
303
  "wp-content=" . Paths::getContentDirRel() .
304
  ($config['forward-query-string'] ? '&%1' : '') .
305
  " [NC,L]\n"; // E=WOD:1
306
 
307
-
308
  $rules .= "\n <IfModule mod_headers.c>\n";
309
  $rules .= " <IfModule mod_setenvif.c>\n";
310
 
@@ -444,50 +474,34 @@ class HTAccess
444
  /**
445
  * Must be parsed ie "wp-content", "index", etc. Not real dirs
446
  */
447
- public static function addToActiveHTAccessDirsArray($whichDir)
448
  {
449
  $activeHtaccessDirs = State::getState('active-htaccess-dirs', []);
450
- if (!in_array($whichDir, $activeHtaccessDirs)) {
451
- $activeHtaccessDirs[] = $whichDir;
452
  State::setState('active-htaccess-dirs', array_values($activeHtaccessDirs));
453
  }
454
  }
455
 
456
- public static function removeFromActiveHTAccessDirsArray($whichDir)
457
  {
458
  $activeHtaccessDirs = State::getState('active-htaccess-dirs', []);
459
- if (in_array($whichDir, $activeHtaccessDirs)) {
460
- $activeHtaccessDirs = array_diff($activeHtaccessDirs, [$whichDir]);
461
  State::setState('active-htaccess-dirs', array_values($activeHtaccessDirs));
462
  }
463
  }
464
 
465
- public static function isInActiveHTAccessDirsArray($whichDir)
466
  {
467
  $activeHtaccessDirs = State::getState('active-htaccess-dirs', []);
468
- return (in_array($whichDir, $activeHtaccessDirs));
469
- }
470
-
471
- public static function whichHTAccessDirIsThis($dir) {
472
- switch ($dir) {
473
- case Paths::getContentDirAbs():
474
- return 'wp-content';
475
- case Paths::getIndexDirAbs():
476
- return 'index';
477
- case Paths::getHomeDirAbs():
478
- return 'home';
479
- case Paths::getPluginDirAbs():
480
- return 'plugins';
481
- case Paths::getUploadDirAbs():
482
- return 'uploads';
483
- }
484
- return '';
485
  }
486
 
487
  public static function hasRecordOfSavingHTAccessToDir($dir) {
488
- $whichDir = self::whichHTAccessDirIsThis($dir);
489
- if ($whichDir != '') {
490
- return self::isInActiveHTAccessDirsArray($whichDir);
491
  }
492
  return false;
493
  }
@@ -504,7 +518,20 @@ class HTAccess
504
  if ($content === false) {
505
  return null;
506
  }
507
- return (strpos($content, '# Redirect images to webp-on-demand.php') != false);
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  } else {
509
  // the .htaccess isn't even there. So there are no rules.
510
  return false;
@@ -572,15 +599,16 @@ class HTAccess
572
  if ($success) {
573
  State::setState('htaccess-rules-saved-at-some-point', true);
574
 
575
- $containsRules = (strpos(implode('',$rules), '# Redirect images to webp-on-demand.php') != false);
 
576
 
577
  $dir = FileHelper::dirName($filename);
578
- $whichDir = self::whichHTAccessDirIsThis($dir);
579
- if ($whichDir != '') {
580
  if ($containsRules) {
581
- self::addToActiveHTAccessDirsArray($whichDir);
582
  } else {
583
- self::removeFromActiveHTAccessDirsArray($whichDir);
584
  }
585
  }
586
  }
125
 
126
 
127
  /* Build rules */
128
+
129
+ /* When .htaccess is placed in root (index), the rules needs to be confined only to work in
130
+ content folder (if uploads folder is moved, perhaps also that)
131
+ Rules needs to start with ie "^/?(wp-content/.+)" rather than "^/?(.+)"
132
+ In the case that upload folder is in root too, rules needs to apply to both.
133
+ We do it like this: "^/?((?:wp-content|uploads)/.+)" (using non capturing group)
134
+ */
135
+
136
+ $rewriteRuleStart = '^/?(.+)';
137
+ if ($htaccessDir == 'index') {
138
+ // Get relative path between index dir and wp-content dir / uploads
139
+ // Because we want to restrict the rule so it doesn't work on wp-admin, but only those two.
140
+
141
+ $wpContentRel = PathHelper::getRelDir(Paths::getIndexDirAbs(), Paths::getContentDirAbs());
142
+ $uploadsRel = PathHelper::getRelDir(Paths::getIndexDirAbs(), Paths::getUploadDirAbs());
143
+
144
+ //$rules .= '# rel: ' . $uploadsRel . "\n";
145
+ if (strpos($wpContentRel, '.') !== 0) {
146
+
147
+ if (strpos($uploadsRel, $wpContentRel) === 0) {
148
+ $rewriteRuleStart = '^/?(' . $wpContentRel . '/.+)';
149
+ } else {
150
+ $rewriteRuleStart = '^/?((?:' . $wpContentRel . '|' . $uploadsRel . '/.+)';
151
+ }
152
+ }
153
+ }
154
+
155
  $rules = '';
156
 
157
 
205
 
206
  if ($config['destination-extension'] == 'append') {
207
  $rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $htaccessDirRel . "/$1.$2.webp -f\n";
208
+ $rules .= " RewriteRule " . $rewriteRuleStart . "\.(" . $fileExt . ")$ $1.$2.webp [T=image/webp,E=EXISTING:1,L]\n\n";
209
  } else {
210
  $rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $htaccessDirRel . "/$1.webp -f\n";
211
+ $rules .= " RewriteRule " . $rewriteRuleStart . "\.(" . $fileExt . ")$ $1.webp [T=image/webp,E=EXISTING:1,L]\n\n";
212
+ //$rules .= " RewriteRule ^(.+)\.(" . $fileExt . ")$ $1.webp [T=image/webp,E=EXISTING:1,L]\n\n";
213
  }
214
  }
215
 
217
  $rules .= " RewriteCond %{HTTP_ACCEPT} image/webp\n";
218
  $rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
219
  $rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $cacheDirRel . "/" . $htaccessDirRel . "/$1.$2.webp -f\n";
220
+ $rules .= " RewriteRule " . $rewriteRuleStart . "\.(" . $fileExt . ")$ /" . $cacheDirRel . "/" . $htaccessDirRel . "/$1.$2.webp [NC,T=image/webp,E=EXISTING:1,L]\n\n";
221
+ //$rules .= " RewriteRule ^\/?(.*)\.(" . $fileExt . ")$ /" . $cacheDirRel . "/" . $htaccessDirRel . "/$1.$2.webp [NC,T=image/webp,E=EXISTING:1,L]\n\n";
222
 
223
  $rules .= $ccRules;
224
 
256
 
257
  $rules .= " # Pass REQUEST_FILENAME to webp-realizer.php in request header\n";
258
  $rules .= $basicConditionsRealizer;
259
+ $rules .= " RewriteRule " . $rewriteRuleStart . "\.(webp)$ - [E=REQFN:%{REQUEST_FILENAME}]\n" .
260
  " <IfModule mod_headers.c>\n" .
261
  " RequestHeader set REQFN \"%{REQFN}e\" env=REQFN\n" .
262
  " </IfModule>\n\n";
264
  $rules .= " # WebP Realizer: Redirect non-existing webp images to webp-realizer.php, which will locate corresponding jpg/png, convert it, and deliver the webp (if possible) \n";
265
  $rules .= $basicConditionsRealizer;
266
 
267
+ $rules .= " RewriteRule " . $rewriteRuleStart . "\.(webp)$ " .
268
  "/" . Paths::getWebPRealizerUrlPath() .
269
  ($passSourceInQSRealizer ? "?xdestination=x%{SCRIPT_FILENAME}&" : "?") .
270
  "wp-content=" . Paths::getContentDirRel() .
326
  // Add "NE" flag?
327
  // https://github.com/rosell-dk/webp-convert/issues/95
328
  // (and try testing spaces in directory paths)
329
+
330
+ // TODO: When $rewriteRuleStart is empty, we don't need the .*, do we? - test
331
+ $rules .= " RewriteRule " . $rewriteRuleStart . "\.(" . $fileExt . ")$ " .
332
  "/" . Paths::getWodUrlPath() .
333
  ($passSourceInQS ? "?xsource=x%{SCRIPT_FILENAME}&" : "?") .
334
  "wp-content=" . Paths::getContentDirRel() .
335
  ($config['forward-query-string'] ? '&%1' : '') .
336
  " [NC,L]\n"; // E=WOD:1
337
 
 
338
  $rules .= "\n <IfModule mod_headers.c>\n";
339
  $rules .= " <IfModule mod_setenvif.c>\n";
340
 
474
  /**
475
  * Must be parsed ie "wp-content", "index", etc. Not real dirs
476
  */
477
+ public static function addToActiveHTAccessDirsArray($dirId)
478
  {
479
  $activeHtaccessDirs = State::getState('active-htaccess-dirs', []);
480
+ if (!in_array($dirId, $activeHtaccessDirs)) {
481
+ $activeHtaccessDirs[] = $dirId;
482
  State::setState('active-htaccess-dirs', array_values($activeHtaccessDirs));
483
  }
484
  }
485
 
486
+ public static function removeFromActiveHTAccessDirsArray($dirId)
487
  {
488
  $activeHtaccessDirs = State::getState('active-htaccess-dirs', []);
489
+ if (in_array($dirId, $activeHtaccessDirs)) {
490
+ $activeHtaccessDirs = array_diff($activeHtaccessDirs, [$dirId]);
491
  State::setState('active-htaccess-dirs', array_values($activeHtaccessDirs));
492
  }
493
  }
494
 
495
+ public static function isInActiveHTAccessDirsArray($dirId)
496
  {
497
  $activeHtaccessDirs = State::getState('active-htaccess-dirs', []);
498
+ return (in_array($dirId, $activeHtaccessDirs));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  }
500
 
501
  public static function hasRecordOfSavingHTAccessToDir($dir) {
502
+ $dirId = Paths::getAbsDirId($dir);
503
+ if ($dirId !== false) {
504
+ return self::isInActiveHTAccessDirsArray($dirId);
505
  }
506
  return false;
507
  }
518
  if ($content === false) {
519
  return null;
520
  }
521
+
522
+ $pos1 = strpos($content, '# BEGIN WebP Express');
523
+ if ($pos1 === false) {
524
+ return false;
525
+ }
526
+ $pos2 = strrpos($content, '# END WebP Express');
527
+ if ($pos2 === false) {
528
+ return false;
529
+ }
530
+
531
+ $weRules = substr($content, $pos1, $pos2 - $pos1);
532
+
533
+ return (strpos($weRules, '<IfModule mod_rewrite.c>') !== false);
534
+
535
  } else {
536
  // the .htaccess isn't even there. So there are no rules.
537
  return false;
599
  if ($success) {
600
  State::setState('htaccess-rules-saved-at-some-point', true);
601
 
602
+ //$containsRules = (strpos(implode('',$rules), '# Redirect images to webp-on-demand.php') != false);
603
+ $containsRules = (strpos(implode('',$rules), '<IfModule mod_rewrite.c>') !== false);
604
 
605
  $dir = FileHelper::dirName($filename);
606
+ $dirId = Paths::getAbsDirId($dir);
607
+ if ($dirId !== false) {
608
  if ($containsRules) {
609
+ self::addToActiveHTAccessDirsArray($dirId);
610
  } else {
611
+ self::removeFromActiveHTAccessDirsArray($dirId);
612
  }
613
  }
614
  }
lib/classes/Paths.php CHANGED
@@ -277,6 +277,38 @@ APACHE
277
  return untrailingslashit(WEBPEXPRESS_PLUGIN_DIR);
278
  }
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
  // ------------------------------------
282
  // --------- Url paths ----------
277
  return untrailingslashit(WEBPEXPRESS_PLUGIN_DIR);
278
  }
279
 
280
+ public static function getAbsDirId($absDir) {
281
+ switch ($absDir) {
282
+ case self::getContentDirAbs():
283
+ return 'wp-content';
284
+ case self::getIndexDirAbs():
285
+ return 'index';
286
+ case self::getHomeDirAbs():
287
+ return 'home';
288
+ case self::getPluginDirAbs():
289
+ return 'plugins';
290
+ case self::getUploadDirAbs():
291
+ return 'uploads';
292
+ }
293
+ return false;
294
+ }
295
+
296
+ public static function getAbsDirById($dirId) {
297
+ switch ($dirId) {
298
+ case 'wp-content':
299
+ return self::getContentDirAbs();
300
+ case 'index':
301
+ return self::getIndexDirAbs();
302
+ case 'home':
303
+ return self::getHomeDirAbs();
304
+ case 'plugins':
305
+ return self::getPluginDirAbs();
306
+ case 'uploads':
307
+ return self::getUploadDirAbs();
308
+ }
309
+ return false;
310
+ }
311
+
312
 
313
  // ------------------------------------
314
  // --------- Url paths ----------
lib/migrate/migrate6.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebPExpress;
4
+
5
+
6
+ include_once __DIR__ . '/../classes/Config.php';
7
+ use \WebPExpress\Config;
8
+
9
+ include_once __DIR__ . '/../classes/Messenger.php';
10
+ use \WebPExpress\Messenger;
11
+
12
+ include_once __DIR__ . '/../classes/HTAccess.php';
13
+ use \WebPExpress\HTAccess;
14
+
15
+ include_once __DIR__ . '/../classes/Paths.php';
16
+ use \WebPExpress\Paths;
17
+
18
+ /**
19
+ * Fix records - if possible
20
+ */
21
+ function webpexpress_migrate6_fixHtaccessRecordsForDir($dirId) {
22
+ $haveRules = HTAccess::haveWeRulesInThisHTAccess(Paths::getAbsDirById($dirId) . '/.htaccess');
23
+
24
+ // PS: $haveRules may be null, meaning "maybe"
25
+ if ($haveRules === true) {
26
+ HTAccess::addToActiveHTAccessDirsArray($dirId);
27
+ }
28
+ if ($haveRules === false) {
29
+ HTAccess::removeFromActiveHTAccessDirsArray($dirId);
30
+ }
31
+ }
32
+
33
+ function webpexpress_migrate6() {
34
+
35
+ // Regenerate .htaccess file if placed in root (so rewrites does not apply in wp-admin area)
36
+ if (HTAccess::isInActiveHTAccessDirsArray('index')) {
37
+ if (Config::isConfigFileThere()) {
38
+ $config = Config::loadConfigAndFix();
39
+
40
+ $rules = HTAccess::generateHTAccessRulesFromConfigObj($config, 'index');
41
+ $success = (HTAccess::saveHTAccessRulesToFile(Paths::getIndexDirAbs() . '/.htaccess', $rules, true));
42
+
43
+ if ($success) {
44
+ Messenger::addMessage(
45
+ 'info',
46
+ 'Fixed .htaccess rules in root (the old rules were also applying to wp-admin folder. In some cases this resulted in problems with the media library).'
47
+ );
48
+ } else {
49
+ Messenger::addMessage(
50
+ 'warning',
51
+ 'Tried to fix .htaccess rules in root folder (the old rules applied to wp-admin, which in some cases resulted in problems with media library). However, the attempt failed.'
52
+ );
53
+ }
54
+ }
55
+ }
56
+
57
+ // The records about which .htaccess files that contains rules were not correct.
58
+ // Correct them if possible (haveWeRulesInThisHTAccess() may return null, if we cannot determine)
59
+ // https://github.com/rosell-dk/webp-express/issues/169
60
+
61
+ $dirsToFix = [
62
+ 'index',
63
+ 'home',
64
+ 'wp-content',
65
+ 'plugins',
66
+ 'uploads'
67
+ ];
68
+ foreach ($dirsToFix as $dirId) {
69
+ webpexpress_migrate6_fixHtaccessRecordsForDir($dirId);
70
+ }
71
+
72
+ update_option('webp-express-migration-version', '6');
73
+ }
74
+
75
+ webpexpress_migrate6();
lib/options/page-messages.php CHANGED
@@ -77,10 +77,10 @@ if (Config::isConfigFileThere()) {
77
  }
78
  }
79
 
80
- if (
81
- HTAccess::haveWeRulesInThisHTAccessBestGuess(Paths::getIndexDirAbs() . '/.htaccess') &&
82
- HTAccess::haveWeRulesInThisHTAccessBestGuess(Paths::getContentDirAbs() . '/.htaccess')
83
- ) {
84
  if (!HTAccess::saveHTAccessRulesToFile(Paths::getIndexDirAbs() . '/.htaccess', '# WebP Express has placed its rules in your wp-content dir. Go there.', false)) {
85
  Messenger::printMessage(
86
  'warning',
@@ -89,3 +89,22 @@ if (
89
  );
90
  }
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
78
  }
79
 
80
+ $haveRulesInIndexDir = HTAccess::haveWeRulesInThisHTAccessBestGuess(Paths::getIndexDirAbs() . '/.htaccess');
81
+ $haveRulesInContentDir = HTAccess::haveWeRulesInThisHTAccessBestGuess(Paths::getContentDirAbs() . '/.htaccess');
82
+
83
+ if ($haveRulesInIndexDir && $haveRulesInContentDir) {
84
  if (!HTAccess::saveHTAccessRulesToFile(Paths::getIndexDirAbs() . '/.htaccess', '# WebP Express has placed its rules in your wp-content dir. Go there.', false)) {
85
  Messenger::printMessage(
86
  'warning',
89
  );
90
  }
91
  }
92
+
93
+ $ht = FileHelper::loadFile(Paths::getIndexDirAbs() . '/.htaccess');
94
+ if ($ht !== false) {
95
+ $posWe = strpos($ht, '# BEGIN WebP Express');
96
+ $posWo = strpos($ht, '# BEGIN WordPress');
97
+ if (($posWe !== false) && ($posWo !== false) && ($posWe > $posWo)) {
98
+
99
+ $haveRulesInIndexDir = HTAccess::haveWeRulesInThisHTAccessBestGuess(Paths::getIndexDirAbs() . '/.htaccess');
100
+ if ($haveRulesInIndexDir) {
101
+ Messenger::printMessage(
102
+ 'warning',
103
+ 'Problem detected. ' .
104
+ 'In order for the "Convert non-existing webp-files upon request" functionality to work, you need to either:<br>' .
105
+ '- Move the WebP Express rules above the Wordpress rules in the .htaccess file located in your root dir<br>' .
106
+ '- Grant the webserver permission to your wp-content dir, so it can create its rules there instead.'
107
+ );
108
+ }
109
+ }
110
+ }
webp-express.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WebP Express
4
  * Plugin URI: https://github.com/rosell-dk/webp-express
5
  * Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
6
- * Version: 0.11.2
7
  * Author: Bjørn Rosell
8
  * Author URI: https://www.bitwise-it.dk
9
  * License: GPL2
3
  * Plugin Name: WebP Express
4
  * Plugin URI: https://github.com/rosell-dk/webp-express
5
  * Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
6
+ * Version: 0.11.3
7
  * Author: Bjørn Rosell
8
  * Author URI: https://www.bitwise-it.dk
9
  * License: GPL2