LiteSpeed Cache - Version 4.6

Version Description

  • Mar 29 2022 =
  • Page Optimize Improved compatibility for JS Delay.
  • Page Optimize Fixed an issue for network subsites that occurred when only CSS/JS Minify are enabled.
  • Localization Added query string compatibility for Resource URLs.
  • Vary Fixed a potential PHP warning when server variable REQUEST_METHOD is not detected.
  • Cache Guest Mode now respects Cache Excludes settings.
  • GUI Added warning notice when enabling Localize Resources feature; each localized JS resource requires thorough testing!
  • GUI Fixed a PHP Deprecated warning that occurred with the Mobile Cache User Agent setting on PHP v8.1+. (jrmora)
  • Conf Removed Google related scripts from default Localization Files value.
  • Media WordPress core Lazy Load feature is now automatically disabled when LiteSpeed Lazy Load Images option is enabled. (VR51 #Issue440)
  • API Filter litespeed_ucss_per_pagetype for UCSS now also applies to CSS Combine to avoid UCSS failure. (Ankit)
  • API Added a filter litespeed_media_ignore_remote_missing_sizes to disable auto detection for remote images that are missing dimensions. (Lucas)
Download this release

Release Info

Developer LiteSpeedTech
Plugin Icon 128x128 LiteSpeed Cache
Version 4.6
Comparing to
See all releases

Code changes from version 4.5.0.1 to 4.6

assets/js/js_delay.js CHANGED
@@ -6,87 +6,100 @@ const litespeed_ui_events = [
6
  "touchmove",
7
  "touchstart",
8
  ];
9
- var litespeed_delay_i=0;
10
  var urlCreator = window.URL || window.webkitURL;
11
 
12
  // const litespeed_js_delay_timer = setTimeout( litespeed_load_delayed_js, 70 );
13
 
14
- litespeed_ui_events.forEach( function( e ) {
15
- window.addEventListener( e, litespeed_load_delayed_js_forced, { passive: true } );
16
  } );
17
 
18
- function litespeed_load_delayed_js_forced() {
19
  console.log( '[LiteSpeed] Start Load JS Delayed' );
20
  // clearTimeout( litespeed_js_delay_timer );
21
- litespeed_ui_events.forEach( function( e ) {
22
- window.removeEventListener( e, litespeed_load_delayed_js_forced, { passive: true } );
23
  } );
24
- litespeed_load_delayed_js( true );
25
 
26
- document.querySelectorAll( 'iframe[data-litespeed-src]' ).forEach( function( e ) {
27
- e.setAttribute( 'src', e.getAttribute( 'data-litespeed-src' ) );
28
  } );
29
- }
30
 
31
- function litespeed_load_delayed_js( is_forced ) {
32
- if ( is_forced ) {
33
- console.log( '[LiteSpeed] Force running delayed JS' );
34
  }
35
-
36
- litespeed_load_one();
37
- }
38
-
39
- function litespeed_inline2src( data ) {
40
- try {
41
- var src = urlCreator.createObjectURL( new Blob( [ data.replace( /^(?:<!--)?(.*?)(?:-->)?$/gm, "$1" ) ], {
42
- type: "text/javascript"
43
- }));
44
- } catch (e) {
45
- var src = "data:text/javascript;base64," + btoa( data.replace( /^(?:<!--)?(.*?)(?:-->)?$/gm, "$1" ) );
46
  }
47
-
48
- return src;
49
  }
50
 
51
- function litespeed_load_one() {
52
- litespeed_delay_i ++;
53
- var e = document.querySelector( 'script[type="litespeed/javascript"][data-i="'+litespeed_delay_i+'"]' );
54
- if ( ! e ) {
55
- console.log( '[LiteSpeed] All loaded!' );
56
- return;
 
 
 
 
57
  }
58
 
59
- console.log( '[LiteSpeed] Load i=' + e.getAttribute( 'data-i' ), '-----',e );
 
 
 
60
 
61
- var e2 = document.createElement( 'script' );
 
 
 
 
62
 
63
- e2.addEventListener( 'load', function(){
64
- console.log('[LiteSpeed] loaded --- ' + e2.getAttribute('data-i'));
65
- litespeed_load_one();
66
- }, { passive: true } );
67
 
68
- e2.addEventListener( 'error', function(){
69
- console.log('[LiteSpeed] loaded error! --- ' + e2.getAttribute('data-i'));
70
- litespeed_load_one();
71
- }, { passive: true } );
72
 
73
  var attrs = e.getAttributeNames();
74
-
75
- attrs.forEach( function( aname ) {
76
- if ( aname == 'type') return;
77
- e2.setAttribute( aname == 'data-src' ? 'src' : aname, e.getAttribute( aname ) );
78
  } );
79
  e2.type = 'text/javascript';
 
 
 
80
  if ( ! e2.src && e.textContent ) {
81
- e2.src = litespeed_inline2src( e.textContent );
82
  // e2.textContent = e.textContent;
 
83
  }
84
- // setTimeout(function(){
85
- e.after( e2 );
86
- // document.head.appendChild(e2);
87
- e.remove();
88
- // },0);
89
  // e2 = e.cloneNode(true)
90
  // e2.setAttribute( 'type', 'text/javascript' );
91
  // e2.setAttribute( 'data-delayed', '1' );
92
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  "touchmove",
7
  "touchstart",
8
  ];
 
9
  var urlCreator = window.URL || window.webkitURL;
10
 
11
  // const litespeed_js_delay_timer = setTimeout( litespeed_load_delayed_js, 70 );
12
 
13
+ litespeed_ui_events.forEach( e => {
14
+ window.addEventListener(e, litespeed_load_delayed_js_force, {passive: true}); // Use passive to save GPU in interaction
15
  } );
16
 
17
+ function litespeed_load_delayed_js_force() {
18
  console.log( '[LiteSpeed] Start Load JS Delayed' );
19
  // clearTimeout( litespeed_js_delay_timer );
20
+ litespeed_ui_events.forEach( e => {
21
+ window.removeEventListener(e, litespeed_load_delayed_js_force, {passive: true});
22
  } );
 
23
 
24
+ document.querySelectorAll('iframe[data-litespeed-src]').forEach( e => {
25
+ e.setAttribute('src', e.getAttribute('data-litespeed-src'));
26
  } );
 
27
 
28
+ // Prevent early loading
29
+ if ( document.readyState == 'loading' ) {
30
+ window.addEventListener('DOMContentLoaded', litespeed_load_delayed_js);
31
  }
32
+ else {
33
+ litespeed_load_delayed_js();
 
 
 
 
 
 
 
 
 
34
  }
 
 
35
  }
36
 
37
+ async function litespeed_load_delayed_js() {
38
+ let js_list = [];
39
+ // Prepare all JS
40
+ document.querySelectorAll('script[type="litespeed/javascript"]').forEach( e => {
41
+ js_list.push(e);
42
+ } );
43
+
44
+ // Load by sequence
45
+ for ( let script in js_list ) {
46
+ await new Promise(resolve => litespeed_load_one(js_list[script], resolve));
47
  }
48
 
49
+ // Simulate doc.loaded
50
+ document.dispatchEvent(new Event('DOMContentLiteSpeedLoaded'));
51
+ window.dispatchEvent(new Event('DOMContentLiteSpeedLoaded'));
52
+ }
53
 
54
+ /**
55
+ * Load one JS synchronously
56
+ */
57
+ function litespeed_load_one(e, resolve) {
58
+ console.log('[LiteSpeed] Load ', e);
59
 
60
+ var e2 = document.createElement('script');
 
 
 
61
 
62
+ e2.addEventListener('load', resolve);
63
+ e2.addEventListener('error', resolve);
 
 
64
 
65
  var attrs = e.getAttributeNames();
66
+ attrs.forEach( aname => {
67
+ if ( aname == 'type' ) return;
68
+ e2.setAttribute(aname == 'data-src' ? 'src' : aname, e.getAttribute(aname));
 
69
  } );
70
  e2.type = 'text/javascript';
71
+
72
+ let is_inline = false;
73
+ // Inline script
74
  if ( ! e2.src && e.textContent ) {
75
+ e2.src = litespeed_inline2src(e.textContent);
76
  // e2.textContent = e.textContent;
77
+ is_inline = true;
78
  }
79
+
80
+ // Deploy to dom
81
+ e.after(e2);
82
+ e.remove();
83
+ // document.head.appendChild(e2);
84
  // e2 = e.cloneNode(true)
85
  // e2.setAttribute( 'type', 'text/javascript' );
86
  // e2.setAttribute( 'data-delayed', '1' );
87
+
88
+ // Kick off resolve for inline
89
+ if ( is_inline ) resolve();
90
+ }
91
+
92
+ /**
93
+ * Prepare inline script
94
+ */
95
+ function litespeed_inline2src( data ) {
96
+ try {
97
+ var src = urlCreator.createObjectURL( new Blob( [ data.replace( /^(?:<!--)?(.*?)(?:-->)?$/gm, "$1" ) ], {
98
+ type: "text/javascript"
99
+ }));
100
+ } catch (e) {
101
+ var src = "data:text/javascript;base64," + btoa( data.replace( /^(?:<!--)?(.*?)(?:-->)?$/gm, "$1" ) );
102
+ }
103
+
104
+ return src;
105
+ }
assets/js/js_delay.min.js CHANGED
@@ -1 +1 @@
1
- const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var litespeed_delay_i=0,urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_forced(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(function(e){window.removeEventListener(e,litespeed_load_delayed_js_forced,{passive:!0})}),litespeed_load_delayed_js(!0),document.querySelectorAll("iframe[data-litespeed-src]").forEach(function(e){e.setAttribute("src",e.getAttribute("data-litespeed-src"))})}function litespeed_load_delayed_js(e){e&&console.log("[LiteSpeed] Force running delayed JS"),litespeed_load_one()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}function litespeed_load_one(){litespeed_delay_i++;var t,d=document.querySelector('script[type="litespeed/javascript"][data-i="'+litespeed_delay_i+'"]');d?(console.log("[LiteSpeed] Load i="+d.getAttribute("data-i"),"-----",d),(t=document.createElement("script")).addEventListener("load",function(){console.log("[LiteSpeed] loaded --- "+t.getAttribute("data-i")),litespeed_load_one()},{passive:!0}),t.addEventListener("error",function(){console.log("[LiteSpeed] loaded error! --- "+t.getAttribute("data-i")),litespeed_load_one()},{passive:!0}),d.getAttributeNames().forEach(function(e){"type"!=e&&t.setAttribute("data-src"==e?"src":e,d.getAttribute(e))}),t.type="text/javascript",!t.src&&d.textContent&&(t.src=litespeed_inline2src(d.textContent)),d.after(t),d.remove()):console.log("[LiteSpeed] All loaded!")}litespeed_ui_events.forEach(function(e){window.addEventListener(e,litespeed_load_delayed_js_forced,{passive:!0})});
1
+ const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}
data/const.default.ini CHANGED
@@ -459,10 +459,6 @@ optm-localize = false
459
  ; O_OPTM_LOCALIZE_DOMAINS
460
  optm-localize_domains = '### Popular scripts ###
461
  https://platform.twitter.com/widgets.js
462
- https://www.google.com/recaptcha/api.js
463
- https://www.google-analytics.com/analytics.js
464
- https://www.googletagmanager.com/gtm.js
465
- https://www.googletagservices.com/tag/js/gpt.js
466
  https://connect.facebook.net/en_US/fbevents.js'
467
 
468
 
459
  ; O_OPTM_LOCALIZE_DOMAINS
460
  optm-localize_domains = '### Popular scripts ###
461
  https://platform.twitter.com/widgets.js
 
 
 
 
462
  https://connect.facebook.net/en_US/fbevents.js'
463
 
464
 
litespeed-cache.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: LiteSpeed Cache
4
  * Plugin URI: https://www.litespeedtech.com/products/cache-plugins/wordpress-acceleration
5
  * Description: High-performance page caching and site optimization from LiteSpeed
6
- * Version: 4.5.0.1
7
  * Author: LiteSpeed Technologies
8
  * Author URI: https://www.litespeedtech.com
9
  * License: GPLv3
@@ -33,7 +33,7 @@ if ( defined( 'LSCWP_V' ) ) {
33
  return;
34
  }
35
 
36
- ! defined( 'LSCWP_V' ) && define( 'LSCWP_V', '4.5.0.1' );
37
 
38
  ! defined( 'LSCWP_CONTENT_DIR' ) && define( 'LSCWP_CONTENT_DIR', WP_CONTENT_DIR ) ;
39
  ! defined( 'LSCWP_DIR' ) && define( 'LSCWP_DIR', __DIR__ . '/' ) ;// Full absolute path '/var/www/html/***/wp-content/plugins/litespeed-cache/' or MU
3
  * Plugin Name: LiteSpeed Cache
4
  * Plugin URI: https://www.litespeedtech.com/products/cache-plugins/wordpress-acceleration
5
  * Description: High-performance page caching and site optimization from LiteSpeed
6
+ * Version: 4.6
7
  * Author: LiteSpeed Technologies
8
  * Author URI: https://www.litespeedtech.com
9
  * License: GPLv3
33
  return;
34
  }
35
 
36
+ ! defined( 'LSCWP_V' ) && define( 'LSCWP_V', '4.6' );
37
 
38
  ! defined( 'LSCWP_CONTENT_DIR' ) && define( 'LSCWP_CONTENT_DIR', WP_CONTENT_DIR ) ;
39
  ! defined( 'LSCWP_DIR' ) && define( 'LSCWP_DIR', __DIR__ . '/' ) ;// Full absolute path '/var/www/html/***/wp-content/plugins/litespeed-cache/' or MU
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: LiteSpeedTech
3
  Tags: caching, optimize, performance, pagespeed, core web vitals, seo, speed, image optimize, compress, object cache, redis, memcached, database cleaner
4
  Requires at least: 4.0
5
- Tested up to: 5.9.1
6
- Stable tag: 4.5.0.1
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
 
@@ -250,6 +250,19 @@ The vast majority of plugins and themes are compatible with LiteSpeed Cache. The
250
 
251
  == Changelog ==
252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  = 4.5.0.1 - Feb 24 2022 =
254
  * 🔥🐞**Media** Fixed an issue where lazy-loaded images would disappear when using custom CSS image loading effects.
255
 
2
  Contributors: LiteSpeedTech
3
  Tags: caching, optimize, performance, pagespeed, core web vitals, seo, speed, image optimize, compress, object cache, redis, memcached, database cleaner
4
  Requires at least: 4.0
5
+ Tested up to: 5.9.2
6
+ Stable tag: 4.6
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
 
250
 
251
  == Changelog ==
252
 
253
+ = 4.6 - Mar 29 2022 =
254
+ * **Page Optimize** Improved compatibility for JS Delay.
255
+ * 🐞**Page Optimize** Fixed an issue for network subsites that occurred when only CSS/JS Minify are enabled.
256
+ * **Localization** Added query string compatibility for Resource URLs.
257
+ * **Vary** Fixed a potential PHP warning when server variable `REQUEST_METHOD` is not detected.
258
+ * **Cache** Guest Mode now respects Cache Excludes settings.
259
+ * **GUI** Added warning notice when enabling `Localize Resources` feature; each localized JS resource requires thorough testing!
260
+ * **GUI** Fixed a PHP Deprecated warning that occurred with the Mobile Cache User Agent setting on PHP v8.1+. (jrmora)
261
+ * **Conf** Removed Google related scripts from default `Localization Files` value.
262
+ * **Media** WordPress core Lazy Load feature is now automatically disabled when LiteSpeed Lazy Load Images option is enabled. (VR51 #Issue440)
263
+ * 🐞**API** Filter `litespeed_ucss_per_pagetype` for UCSS now also applies to CSS Combine to avoid UCSS failure. (Ankit)
264
+ * **API** Added a filter `litespeed_media_ignore_remote_missing_sizes` to disable auto detection for remote images that are missing dimensions. (Lucas)
265
+
266
  = 4.5.0.1 - Feb 24 2022 =
267
  * 🔥🐞**Media** Fixed an issue where lazy-loaded images would disappear when using custom CSS image loading effects.
268
 
src/control.cls.php CHANGED
@@ -298,7 +298,7 @@ class Control extends Root {
298
  */
299
  public static function is_private() {
300
  if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
301
- return false;
302
  }
303
 
304
  return self::$_control & self::BM_PRIVATE && ! self::is_public_forced();
@@ -398,7 +398,7 @@ class Control extends Root {
398
 
399
  // Guest mode always cacheable
400
  if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
401
- return true;
402
  }
403
 
404
  // If its forced public cacheable
@@ -544,25 +544,25 @@ class Control extends Root {
544
  }
545
 
546
  // Guest mode directly return cacheable result
547
- if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
548
- // If is POST, no cache
549
- if ( defined( 'LSCACHE_NO_CACHE' ) && LSCACHE_NO_CACHE ) {
550
- Debug2::debug( "[Ctrl] ❌ forced no cache [reason] LSCACHE_NO_CACHE const" );
551
- $hdr .= 'no-cache';
552
- }
553
- else if( $_SERVER[ 'REQUEST_METHOD' ] !== 'GET' ) {
554
- Debug2::debug( "[Ctrl] ❌ forced no cache [reason] req not GET" );
555
- $hdr .= 'no-cache';
556
- }
557
- else {
558
- $hdr .= 'public';
559
- $hdr .= ',max-age=' . $this->get_ttl();
560
- }
561
-
562
- $hdr .= $esi_hdr;
563
-
564
- return $hdr;
565
- }
566
 
567
  // Fix cli `uninstall --deactivate` fatal err
568
 
@@ -597,7 +597,7 @@ class Control extends Root {
597
  */
598
  public function finalize() {
599
  if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
600
- return;
601
  }
602
 
603
  // Check if URI is forced public cache
298
  */
299
  public static function is_private() {
300
  if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
301
+ // return false;
302
  }
303
 
304
  return self::$_control & self::BM_PRIVATE && ! self::is_public_forced();
398
 
399
  // Guest mode always cacheable
400
  if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
401
+ // return true;
402
  }
403
 
404
  // If its forced public cacheable
544
  }
545
 
546
  // Guest mode directly return cacheable result
547
+ // if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
548
+ // // If is POST, no cache
549
+ // if ( defined( 'LSCACHE_NO_CACHE' ) && LSCACHE_NO_CACHE ) {
550
+ // Debug2::debug( "[Ctrl] ❌ forced no cache [reason] LSCACHE_NO_CACHE const" );
551
+ // $hdr .= 'no-cache';
552
+ // }
553
+ // else if( $_SERVER[ 'REQUEST_METHOD' ] !== 'GET' ) {
554
+ // Debug2::debug( "[Ctrl] ❌ forced no cache [reason] req not GET" );
555
+ // $hdr .= 'no-cache';
556
+ // }
557
+ // else {
558
+ // $hdr .= 'public';
559
+ // $hdr .= ',max-age=' . $this->get_ttl();
560
+ // }
561
+
562
+ // $hdr .= $esi_hdr;
563
+
564
+ // return $hdr;
565
+ // }
566
 
567
  // Fix cli `uninstall --deactivate` fatal err
568
 
597
  */
598
  public function finalize() {
599
  if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
600
+ // return;
601
  }
602
 
603
  // Check if URI is forced public cache
src/localization.cls.php CHANGED
@@ -27,7 +27,7 @@ class Localization extends Base {
27
  * @since 3.3
28
  */
29
  public function serve_static( $uri ) {
30
- $url = 'https://' . $uri;
31
 
32
  if ( ! $this->conf( self::O_OPTM_LOCALIZE ) ) {
33
  // wp_redirect( $url );
@@ -36,7 +36,7 @@ class Localization extends Base {
36
 
37
  if ( substr( $url, -3 ) !== '.js' ) {
38
  // wp_redirect( $url );
39
- exit( 'Not supported' );
40
  }
41
 
42
  $match = false;
@@ -65,7 +65,8 @@ class Localization extends Base {
65
  continue;
66
  }
67
 
68
- if ( strpos( $url, $domain ) !== 0 ) {
 
69
  continue;
70
  }
71
 
@@ -75,7 +76,7 @@ class Localization extends Base {
75
 
76
  if ( ! $match ) {
77
  // wp_redirect( $url );
78
- exit( 'Not supported' );
79
  }
80
 
81
  header( 'Content-Type: application/javascript' );
@@ -181,7 +182,7 @@ class Localization extends Base {
181
  continue;
182
  }
183
 
184
- $content = str_replace( $domain, LITESPEED_STATIC_URL . '/localres/' . substr( $domain, 8 ), $content );
185
  }
186
 
187
  return $content;
27
  * @since 3.3
28
  */
29
  public function serve_static( $uri ) {
30
+ $url = base64_decode( $uri );
31
 
32
  if ( ! $this->conf( self::O_OPTM_LOCALIZE ) ) {
33
  // wp_redirect( $url );
36
 
37
  if ( substr( $url, -3 ) !== '.js' ) {
38
  // wp_redirect( $url );
39
+ // exit( 'Not supported ' . $uri );
40
  }
41
 
42
  $match = false;
65
  continue;
66
  }
67
 
68
+ // if ( strpos( $url, $domain ) !== 0 ) {
69
+ if ( $url != $domain ) {
70
  continue;
71
  }
72
 
76
 
77
  if ( ! $match ) {
78
  // wp_redirect( $url );
79
+ exit( 'Not supported2' );
80
  }
81
 
82
  header( 'Content-Type: application/javascript' );
182
  continue;
183
  }
184
 
185
+ $content = str_replace( $domain, LITESPEED_STATIC_URL . '/localres/' . base64_encode( $domain ), $content );
186
  }
187
 
188
  return $content;
src/media.cls.php CHANGED
@@ -53,6 +53,10 @@ class Media extends Root {
53
  }
54
  }
55
 
 
 
 
 
56
  /**
57
  * Replace gravatar
58
  * @since 3.0
@@ -650,6 +654,9 @@ class Media extends Root {
650
  if ( $pathinfo = Utility::is_internal_file( $src ) ) {
651
  $src = $pathinfo[ 0 ];
652
  }
 
 
 
653
 
654
  $sizes = getimagesize( $src );
655
 
53
  }
54
  }
55
 
56
+ if ( $this->conf( Base::O_MEDIA_LAZY ) ) {
57
+ add_filter( 'wp_lazy_loading_enabled', '__return_false' );
58
+ }
59
+
60
  /**
61
  * Replace gravatar
62
  * @since 3.0
654
  if ( $pathinfo = Utility::is_internal_file( $src ) ) {
655
  $src = $pathinfo[ 0 ];
656
  }
657
+ elseif ( apply_filters( 'litespeed_media_ignore_remote_missing_sizes', false ) ) {
658
+ return false;
659
+ }
660
 
661
  $sizes = getimagesize( $src );
662
 
src/optimize.cls.php CHANGED
@@ -43,8 +43,6 @@ class Optimize extends Base {
43
  private $_var_preserve_js = array();
44
  private $_request_url;
45
 
46
- private $i2 = 0;
47
-
48
  /**
49
  * Constructor
50
  * @since 4.0
@@ -76,6 +74,15 @@ class Optimize extends Base {
76
  if ( defined( 'LITESPEED_GUEST_OPTM' ) ) {
77
  $this->cfg_js_defer = 2;
78
  }
 
 
 
 
 
 
 
 
 
79
 
80
  // To remove emoji from WP
81
  if ( $this->conf( self::O_OPTM_EMOJI_RM ) ) {
@@ -479,7 +486,7 @@ class Optimize extends Base {
479
  */
480
  private function _build_js_tag( $src ) {
481
  if ( $this->cfg_js_defer === 2 ) {
482
- return '<script data-optimized="1" type="litespeed/javascript" data-i="' . ++$this->i2 . '" data-src="' . $src . '"></script>';
483
  }
484
 
485
  if ( $this->cfg_js_defer ) {
@@ -734,14 +741,16 @@ class Optimize extends Base {
734
 
735
  $content = $this->__optimizer->optm_snippet( $content, $file_type, ! $is_min, $src );
736
 
 
 
737
  // Save to file
738
- $filename = $file_type . '/' . md5( $this->remove_query_strings( $src ) ) . '.' . $file_type;
739
- $static_file = LITESPEED_STATIC_DIR . '/' . $filename;
740
  File::save( $static_file, $content, true );
741
 
742
  // QS is required as $src may contains version info
743
  $qs_hash = substr( md5( $src ), -5 );
744
- return LITESPEED_STATIC_URL . "/$filename?ver=$qs_hash";
745
  }
746
 
747
  /**
@@ -775,7 +784,7 @@ class Optimize extends Base {
775
  // Add cache tag in case later file deleted to avoid lscache served stale non-existed files @since 4.4.1
776
  Tag::add( Tag::TYPE_MIN . '.' . $filename );
777
 
778
- $qs_hash = substr( md5( self::get_option( self::ITEM_TIMESTAMP_PURGE_CSS ) ), -5 );
779
  // As filename is alreay realted to filecon md5, no need QS anymore
780
  $filepath_prefix = $this->_build_filepath_prefix( $type );
781
  return LITESPEED_STATIC_URL . $filepath_prefix . $filename . '?ver=' . $qs_hash;
@@ -829,7 +838,7 @@ class Optimize extends Base {
829
  if ( $js_excluded || $ext_excluded || ! $is_file ) {
830
  // Maybe defer
831
  if ( $this->cfg_js_defer ) {
832
- $deferred = $this->_js_defer( $match[ 0 ], $attrs[ 'src' ] ); // todo: this can't follow the i2 order
833
  if ( $deferred ) {
834
  $this->content = str_replace( $match[ 0 ], $deferred, $this->content );
835
  }
@@ -920,8 +929,10 @@ class Optimize extends Base {
920
  if ( strpos( $attrs, ' type=' ) !== false ) {
921
  $attrs = preg_replace( '# type=([\'"])([^\1]+)\1#isU', '', $attrs );
922
  }
923
- return '<script' . $attrs . ' type="litespeed/javascript" data-i="' . ++$this->i2 . '">' . $con . '</script>';
924
- // return '<script' . $attrs . ' type="litespeed/javascript" data-i="' . $this->i2 . '" src="data:text/javascript;base64,' . base64_encode( $con ) . '"></script>';
 
 
925
  // return '<script' . $attrs . ' type="litespeed/javascript">' . $con . '</script>';
926
  }
927
 
@@ -1157,7 +1168,7 @@ class Optimize extends Base {
1157
  if ( strpos( $ori, ' type=' ) !== false ) {
1158
  $ori = preg_replace( '# type=([\'"])([^\1]+)\1#isU', '', $ori );
1159
  }
1160
- return str_replace( ' src=', ' type="litespeed/javascript" data-i="' . ++$this->i2 . '" data-src=', $ori );
1161
  }
1162
 
1163
  return str_replace( '></script>', ' defer data-deferred="1"></script>', $ori );
43
  private $_var_preserve_js = array();
44
  private $_request_url;
45
 
 
 
46
  /**
47
  * Constructor
48
  * @since 4.0
74
  if ( defined( 'LITESPEED_GUEST_OPTM' ) ) {
75
  $this->cfg_js_defer = 2;
76
  }
77
+ if ( $this->cfg_js_defer == 2 ) {
78
+ add_filter( 'litespeed_optm_cssjs', function( $con, $file_type ){
79
+ if ( $file_type == 'js' ) {
80
+ $con = str_replace( 'DOMContentLoaded', 'DOMContentLiteSpeedLoaded', $con );
81
+ // $con = str_replace( 'addEventListener("load"', 'addEventListener("litespeedLoad"', $con );
82
+ }
83
+ return $con;
84
+ }, 20, 2 );
85
+ }
86
 
87
  // To remove emoji from WP
88
  if ( $this->conf( self::O_OPTM_EMOJI_RM ) ) {
486
  */
487
  private function _build_js_tag( $src ) {
488
  if ( $this->cfg_js_defer === 2 ) {
489
+ return '<script data-optimized="1" type="litespeed/javascript" data-src="' . $src . '"></script>';
490
  }
491
 
492
  if ( $this->cfg_js_defer ) {
741
 
742
  $content = $this->__optimizer->optm_snippet( $content, $file_type, ! $is_min, $src );
743
 
744
+ $filepath_prefix = $this->_build_filepath_prefix( $file_type );
745
+
746
  // Save to file
747
+ $filename = $filepath_prefix . md5( $this->remove_query_strings( $src ) ) . '.' . $file_type;
748
+ $static_file = LITESPEED_STATIC_DIR . $filename;
749
  File::save( $static_file, $content, true );
750
 
751
  // QS is required as $src may contains version info
752
  $qs_hash = substr( md5( $src ), -5 );
753
+ return LITESPEED_STATIC_URL . "$filename?ver=$qs_hash";
754
  }
755
 
756
  /**
784
  // Add cache tag in case later file deleted to avoid lscache served stale non-existed files @since 4.4.1
785
  Tag::add( Tag::TYPE_MIN . '.' . $filename );
786
 
787
+ $qs_hash = substr( md5( self::get_option( self::ITEM_TIMESTAMP_PURGE_CSS) ), -5 );//xx
788
  // As filename is alreay realted to filecon md5, no need QS anymore
789
  $filepath_prefix = $this->_build_filepath_prefix( $type );
790
  return LITESPEED_STATIC_URL . $filepath_prefix . $filename . '?ver=' . $qs_hash;
838
  if ( $js_excluded || $ext_excluded || ! $is_file ) {
839
  // Maybe defer
840
  if ( $this->cfg_js_defer ) {
841
+ $deferred = $this->_js_defer( $match[ 0 ], $attrs[ 'src' ] );
842
  if ( $deferred ) {
843
  $this->content = str_replace( $match[ 0 ], $deferred, $this->content );
844
  }
929
  if ( strpos( $attrs, ' type=' ) !== false ) {
930
  $attrs = preg_replace( '# type=([\'"])([^\1]+)\1#isU', '', $attrs );
931
  }
932
+ // Replace DOMContentLoaded
933
+ $con = str_replace( 'DOMContentLoaded', 'DOMContentLiteSpeedLoaded', $con );
934
+ return '<script' . $attrs . ' type="litespeed/javascript">' . $con . '</script>';
935
+ // return '<script' . $attrs . ' type="litespeed/javascript" src="data:text/javascript;base64,' . base64_encode( $con ) . '"></script>';
936
  // return '<script' . $attrs . ' type="litespeed/javascript">' . $con . '</script>';
937
  }
938
 
1168
  if ( strpos( $ori, ' type=' ) !== false ) {
1169
  $ori = preg_replace( '# type=([\'"])([^\1]+)\1#isU', '', $ori );
1170
  }
1171
+ return str_replace( ' src=', ' type="litespeed/javascript" data-src=', $ori );
1172
  }
1173
 
1174
  return str_replace( '></script>', ' defer data-deferred="1"></script>', $ori );
src/optimizer.cls.php CHANGED
@@ -77,7 +77,16 @@ class Optimizer extends Root {
77
  // Before generated, don't know the contented hash filename yet, so used url hash as tmp filename
78
  $file_path_prefix = $this->_build_filepath_prefix( $file_type );
79
 
80
- $static_file = LITESPEED_STATIC_DIR . $file_path_prefix . ( is_404() ? '404' : md5( $request_url ) ) . '.' . $file_type;
 
 
 
 
 
 
 
 
 
81
 
82
  // Create tmp file to avoid conflict
83
  $tmp_static_file = $static_file . '.tmp';
@@ -123,7 +132,7 @@ class Optimizer extends Root {
123
 
124
  $vary = $this->cls( 'Vary' )->finalize_full_varies();
125
  Debug2::debug2( "[Optmer] Save URL to file for [file_type] $file_type [file] $filecon_md5 [vary] $vary " );
126
- $this->cls( 'Data' )->save_url( is_404() ? '404' : $request_url, $vary, $file_type, $filecon_md5, dirname( $realfile ) );
127
 
128
  return array( $filecon_md5 . '.' . $file_type, $file_type );
129
  }
77
  // Before generated, don't know the contented hash filename yet, so used url hash as tmp filename
78
  $file_path_prefix = $this->_build_filepath_prefix( $file_type );
79
 
80
+ $url_tag = $request_url;
81
+ $url_tag_for_file = md5( $request_url );
82
+ if ( is_404() ) {
83
+ $url_tag_for_file = $url_tag = '404';
84
+ }
85
+ elseif ( $file_type == 'css' && apply_filters( 'litespeed_ucss_per_pagetype', false ) ) {
86
+ $url_tag_for_file = $url_tag = Utility::page_type();
87
+ }
88
+
89
+ $static_file = LITESPEED_STATIC_DIR . $file_path_prefix . $url_tag_for_file . '.' . $file_type;
90
 
91
  // Create tmp file to avoid conflict
92
  $tmp_static_file = $static_file . '.tmp';
132
 
133
  $vary = $this->cls( 'Vary' )->finalize_full_varies();
134
  Debug2::debug2( "[Optmer] Save URL to file for [file_type] $file_type [file] $filecon_md5 [vary] $vary " );
135
+ $this->cls( 'Data' )->save_url( $url_tag, $vary, $file_type, $filecon_md5, dirname( $realfile ) );
136
 
137
  return array( $filecon_md5 . '.' . $file_type, $file_type );
138
  }
src/utility.cls.php CHANGED
@@ -21,20 +21,7 @@ class Utility extends Root {
21
  * @return bool True for valid rules, false otherwise.
22
  */
23
  public static function syntax_checker( $rules ) {
24
- $success = true;
25
-
26
- set_error_handler( 'litespeed_exception_handler' );
27
-
28
- try {
29
- preg_match( self::arr2regex( $rules ), null );
30
- }
31
- catch ( \ErrorException $e ) {
32
- $success = false;
33
- }
34
-
35
- restore_error_handler();
36
-
37
- return $success;
38
  }
39
 
40
  /**
21
  * @return bool True for valid rules, false otherwise.
22
  */
23
  public static function syntax_checker( $rules ) {
24
+ return preg_match( self::arr2regex( $rules ), '' ) !== false;
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
26
 
27
  /**
src/vary.cls.php CHANGED
@@ -347,7 +347,7 @@ class Vary extends Root {
347
  * POST request can set vary to fix #820789 login "loop" guest cache issue
348
  * @since 1.6.5
349
  */
350
- if ( $_SERVER["REQUEST_METHOD"] !== 'GET' && $_SERVER["REQUEST_METHOD"] !== 'POST' ) {
351
  Debug2::debug( '[Vary] can_change_vary bypassed due to method not get/post' );
352
  return false;
353
  }
347
  * POST request can set vary to fix #820789 login "loop" guest cache issue
348
  * @since 1.6.5
349
  */
350
+ if ( isset( $_SERVER["REQUEST_METHOD"] ) && $_SERVER["REQUEST_METHOD"] !== 'GET' && $_SERVER["REQUEST_METHOD"] !== 'POST' ) {
351
  Debug2::debug( '[Vary] can_change_vary bypassed due to method not get/post' );
352
  return false;
353
  }
tpl/page_optm/settings_localization.tpl.php CHANGED
@@ -93,6 +93,10 @@ $avatar_queue = Avatar::cls()->queue_count();
93
  <div class="litespeed-desc">
94
  <?php echo __( 'Localize external resources.', 'litespeed-cache' ); ?>
95
  <?php Doc::learn_more( 'https://docs.litespeedtech.com/lscache/lscwp/pageopt/#localize' ); ?>
 
 
 
 
96
  </div>
97
  </td>
98
  </tr>
@@ -120,10 +124,13 @@ $avatar_queue = Avatar::cls()->queue_count();
120
 
121
  <br /><?php echo sprintf( __( 'Comments are supported. Start a line with a %s to turn it into a comment line.', 'litespeed-cache' ), '<code>#</code>' ); ?>
122
 
123
- <br /><?php echo __( 'Non-`.js` file extensions will be ignored.', 'litespeed-cache' ); ?>
124
- <?php echo __( 'Example', 'litespeed-cache' ); ?>: <code>https://www.example.com/one.js</code>
125
  <?php Doc::learn_more( 'https://docs.litespeedtech.com/lscache/lscwp/pageopt/#localization-files' ); ?>
126
 
 
 
 
 
127
  </div>
128
  </td>
129
  </tr>
93
  <div class="litespeed-desc">
94
  <?php echo __( 'Localize external resources.', 'litespeed-cache' ); ?>
95
  <?php Doc::learn_more( 'https://docs.litespeedtech.com/lscache/lscwp/pageopt/#localize' ); ?>
96
+
97
+ <br /><font class="litespeed-danger">
98
+ 🚨 <?php echo sprintf( __( 'Please thoroughly test all items in %s to ensure they function as expected.', 'litespeed-cache' ), '<code>' . Lang::title( Base::O_OPTM_LOCALIZE_DOMAINS ) . '</code>' ); ?>
99
+ </font>
100
  </div>
101
  </td>
102
  </tr>
124
 
125
  <br /><?php echo sprintf( __( 'Comments are supported. Start a line with a %s to turn it into a comment line.', 'litespeed-cache' ), '<code>#</code>' ); ?>
126
 
127
+ <br /><?php echo __( 'Example', 'litespeed-cache' ); ?>: <code>https://www.example.com/one.js</code>
 
128
  <?php Doc::learn_more( 'https://docs.litespeedtech.com/lscache/lscwp/pageopt/#localization-files' ); ?>
129
 
130
+ <br /><font class="litespeed-danger">
131
+ 🚨 <?php echo __( 'Please thoroughly test each JS file you add to ensure it functions as expected.', 'litespeed-cache' ); ?>
132
+ </font>
133
+
134
  </div>
135
  </td>
136
  </tr>
tpl/toolbox/beta_test.tpl.php CHANGED
@@ -4,6 +4,8 @@ defined( 'WPINC' ) || exit;
4
 
5
  // Existing public version list
6
  $v_list = array(
 
 
7
  '4.4.7',
8
  '4.4.5',
9
  '4.4.4',
4
 
5
  // Existing public version list
6
  $v_list = array(
7
+ '4.6',
8
+ '4.5.0.1',
9
  '4.4.7',
10
  '4.4.5',
11
  '4.4.4',
tpl/toolbox/purge.tpl.php CHANGED
@@ -113,7 +113,7 @@ if ( $this->has_cache_folder( 'avatar' ) ) {
113
 
114
  $_panels[] = array(
115
  'title' => __( 'Purge All', 'litespeed-cache' ),
116
- 'desc' => __( 'Purge the cache entries created by this plugin except for Critical CSS & LQIP caches', 'litespeed-cache' ),
117
  'icon' => 'purge-all',
118
  'title_cls' => 'litespeed-warning',
119
  'newline' => true,
113
 
114
  $_panels[] = array(
115
  'title' => __( 'Purge All', 'litespeed-cache' ),
116
+ 'desc' => __( 'Purge the cache entries created by this plugin except for Critical CSS & Unique CSS & LQIP caches', 'litespeed-cache' ),
117
  'icon' => 'purge-all',
118
  'title_cls' => 'litespeed-warning',
119
  'newline' => true,