diff --git a/assets/css/litespeed.css b/assets/css/litespeed.css index d04573829..0269e3c52 100644 --- a/assets/css/litespeed.css +++ b/assets/css/litespeed.css @@ -218,6 +218,7 @@ input[type='checkbox'].litespeed-tiny-toggle:checked:after { .litespeed-width-3-10 { width: 100%; + padding: 0; } } @@ -464,9 +465,20 @@ button.litespeed-form-action:hover { margin: 10px 20px 0 2px; } -.litespeed-wrap .nav-tab-wrapper { - display: flex; - flex-wrap: wrap-reverse; +@media screen and (max-width: 600px) { + .litespeed-wrap h2 .nav-tab { + border-bottom: 1px solid #c3c4c7; + margin: 10px 10px 0 0; + } + + .litespeed-wrap .nav-tab-wrapper { + margin-bottom: 15px; + } + + .litespeed-desc a, + .litespeed-body p > a:not(.button) { + word-break: break-word; + } } .litespeed-wrap .nav-tab { @@ -494,8 +506,10 @@ button.litespeed-form-action:hover { padding: 1px 20px 20px 20px; } -.litespeed-header + .litespeed-body { - border-top: none; +@media screen and (min-width: 681px) { + .litespeed-header + .litespeed-body { + border-top: none; + } } .litespeed-body table { @@ -542,14 +556,30 @@ td > .litespeed-desc:first-child { margin: 2px 0; } -.litespeed-div { - display: inline-block; - min-width: 100px; +.litespeed-div .submit { + margin-top: 0; } -.litespeed-div .submit { - margin: 5px; - padding: 5px; +@media screen and (min-width: 681px) { + .litespeed-div { + display: inline-block; + min-width: 100px; + } + + .litespeed-div .submit { + margin: 5px; + padding: 5px; + } +} + +@media screen and (max-width: 680px) { + .litespeed-desc + .litespeed-desc.litespeed-left20 { + margin-left: 0 !important; + } + + .litespeed-desc .litespeed-callout.notice-warning.inline { + word-break: break-word; + } } .litespeed-h1 { @@ -768,6 +798,16 @@ h3 .litespeed-learn-more { margin-bottom: 0; } +@media screen and (max-width: 600px) { + .litespeed-block { + flex-direction: column; + } + + .litespeed-block .litespeed-col { + padding-right: 0; + } +} + /* ======================================= CARDS LINKS ======================================= */ @@ -1756,6 +1796,12 @@ ul.litespeed-shell-body { line-height: 1.4; } +@media screen and (max-width: 782px) { + .litespeed-radio-row { + padding-left: 2rem; + } +} + /* ======================================= FORM - layout ======================================= */ @@ -1803,6 +1849,16 @@ ul.litespeed-shell-body { width: 45px; } +@media screen and (max-width: 680px) { + .litespeed-input-short2 { + width: 160px; + } + + .litespeed-input-short { + width: 50px; + } +} + /* ======================================= FORM - elements ======================================= */ @@ -1889,6 +1945,16 @@ input.litespeed-input-warning { padding: 18px 0 5px 12px; } + .litespeed-body .litespeed-table td { + display: block; + max-width: 100%; + } + + .litespeed-body .litespeed-table textarea, + .litespeed-body .litespeed-table input.litespeed-regular-text { + width: 100% !important; + } + .litespeed-wrap .litespeed-float-submit { display: none; } @@ -1897,7 +1963,7 @@ input.litespeed-input-warning { padding: 1px 10px 20px 15px; } - .litespeed-body .regular-text { + .litespeed-body .regular-text:not(.litespeed-input-short) { width: 100%; } @@ -1908,6 +1974,26 @@ input.litespeed-input-warning { .litespeed-textarea-recommended > div:first-child { margin-bottom: 1.7em; margin-top: 0; + margin-right: 0; + } + + .litespeed-switch { + max-width: 100%; + flex-wrap: wrap; + } + + .litespeed-switch + .litespeed-warning { + display: block; + margin-top: 10px; + } + + input.litespeed-input[type='file'] { + max-width: calc(100% - 24px); + min-width: 0; + } + + .litespeed-body .litespeed-table .litespeed-row-flex { + flex-direction: column; } } @@ -2330,6 +2416,12 @@ g.litespeed-pie_info .litespeed-pie-done { top: -6px; } +@media screen and (max-width: 600px) { + .litespeed-cdn-mapping-col1 { + max-width: 100%; + } +} + /* ======================================= VIEW - crawler ======================================= */ @@ -2344,6 +2436,43 @@ g.litespeed-pie_info .litespeed-pie-done { margin-top: 5px; } +.litespeed-crawler-sitemap-nav { + display: flex; + justify-content: space-between; +} + +.litespeed-crawler-sitemap-nav > div { + margin-top: 10px; +} + +@media screen and (max-width: 680px) { + .litespeed-crawler-sitemap-nav { + display: block; + } + + .litespeed-table-responsive { + clear: both; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + .litespeed-table-responsive table { + width: 100%; + } + + .litespeed-table-responsive th { + text-wrap: nowrap; + } + + .litespeed-table-responsive [data-crawler-list].wp-list-table td:nth-child(2) { + min-width: 115px; + } + + .litespeed-wrap input[name='kw'] { + width: 100% !important; + } +} + /* ======================================= PROGRESS BAR ======================================= */ @@ -2530,6 +2659,7 @@ g.litespeed-pie_info .litespeed-pie-done { margin-top: 1.65em; display: flex; align-items: flex-end; + flex-wrap: wrap; } .litespeed-img-optim-actions .button-primary { @@ -2554,6 +2684,13 @@ g.litespeed-pie_info .litespeed-pie-done { } } +@media screen and (max-width: 680px) { + .litespeed-img-optim-actions .button + .button.button-secondary { + margin-left: 0; + margin-top: 10px; + } +} + /* ======================================= VIEW - image optm media row ======================================= */ @@ -3014,6 +3151,11 @@ a.litespeed-redetect { width: 100%; } + .litespeed-postbox-double-content .litespeed-postbox-double-col:nth-child(2) { + padding-left: 0; + margin-top: 7px; + } + .litespeed-postbox-double-content { flex-wrap: wrap; } @@ -3267,6 +3409,17 @@ a.litespeed-redetect { .litespeed-body tbody > tr > th.litespeed-padding-left { padding-left: 3em; } +@media screen and (max-width: 680px) { + .litespeed-body tbody > tr > th.litespeed-padding-left { + padding-left: 10px; + } + + .litespeed-body tbody > tr > th.litespeed-padding-left:before { + content: '\2014\2014'; + color: #ccc; + margin-right: 5px; + } +} .litespeed-txt-small { font-size: 12px; @@ -3335,7 +3488,7 @@ a.litespeed-media-href svg:hover { flex-wrap: wrap; } -.litespeed-banner-desciption-content { +.litespeed-banner-description-content { margin: 0px; line-height: 1.25em; } @@ -3876,3 +4029,53 @@ a.litespeed-media-href svg:hover { white-space: normal; width: 100%; } + +/* ======================================= + Misc Mobile TWEAKS +======================================= */ + +@media screen and (max-width: 680px) { + .litespeed-wrap .litespeed-body .field-col { + margin-left: 0; + } + + .litespeed-width-auto.litespeed-table-compact td { + font-size: 12px; + word-break: break-word; + } + + input#input_api_key + .button { + margin-top: 10px; + margin-left: 0; + } + + input#input_api_key + .button + .litespeed-desc { + display: block; + } + + input#input_api_key + .button + .litespeed-desc + .button { + margin-left: 0; + } + + .litespeed-body .litespeed-table td .litespeed-right { + float: none !important; + } + + .litespeed-title a.litespeed-learn-more, + .litespeed-title-short a.litespeed-learn-more { + display: block; + margin-left: 0; + margin-top: 5px; + } +} + +.litespeed-wrap .litespeed-redetect[aria-label][data-balloon-pos][data-balloon-pos='up']:after { + left: auto; + right: 0; + transform: translate(0%, var(--balloon-move)); +} + +.litespeed-wrap .litespeed-redetect[aria-label][data-balloon-pos][data-balloon-pos='up']:hover:after, +.litespeed-wrap .litespeed-redetect[aria-label][data-balloon-pos][data-balloon-pos='up'][data-balloon-visible]:after { + transform: translate(0, 0); +} diff --git a/assets/js/instant_click.min.js b/assets/js/instant_click.min.js index 457c5cf19..e38f5551b 100644 --- a/assets/js/instant_click.min.js +++ b/assets/js/instant_click.min.js @@ -1 +1 @@ -let mouseoverTimer,lastTouchTimestamp;const prefetches=new Set,prefetchElement=document.createElement("link"),isSupported=prefetchElement.relList&&prefetchElement.relList.supports&&prefetchElement.relList.supports("prefetch")&&window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype,allowQueryString="instantAllowQueryString"in document.body.dataset,allowExternalLinks="instantAllowExternalLinks"in document.body.dataset,useWhitelist="instantWhitelist"in document.body.dataset,mousedownShortcut="instantMousedownShortcut"in document.body.dataset,DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION=1111;let delayOnHover=65,useMousedown=!1,useMousedownOnly=!1,useViewport=!1;if("instantIntensity"in document.body.dataset){const e=document.body.dataset.instantIntensity;if("mousedown"==e.substr(0,"mousedown".length))useMousedown=!0,"mousedown-only"==e&&(useMousedownOnly=!0);else if("viewport"==e.substr(0,"viewport".length))navigator.connection&&(navigator.connection.saveData||navigator.connection.effectiveType&&navigator.connection.effectiveType.includes("2g"))||("viewport"==e?document.documentElement.clientWidth*document.documentElement.clientHeight<45e4&&(useViewport=!0):"viewport-all"==e&&(useViewport=!0));else{const t=parseInt(e);isNaN(t)||(delayOnHover=t)}}if(isSupported){const e={capture:!0,passive:!0};if(useMousedownOnly||document.addEventListener("touchstart",touchstartListener,e),useMousedown?mousedownShortcut||document.addEventListener("mousedown",mousedownListener,e):document.addEventListener("mouseover",mouseoverListener,e),mousedownShortcut&&document.addEventListener("mousedown",mousedownShortcutListener,e),useViewport){let e;(e=window.requestIdleCallback?e=>{requestIdleCallback(e,{timeout:1500})}:e=>{e()})(()=>{const e=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){const n=t.target;e.unobserve(n),preload(n.href)}})});document.querySelectorAll("a").forEach(t=>{isPreloadable(t)&&e.observe(t)})})}}function touchstartListener(e){lastTouchTimestamp=performance.now();const t=e.target.closest("a");isPreloadable(t)&&preload(t.href)}function mouseoverListener(e){if(performance.now()-lastTouchTimestamp{preload(t.href),mouseoverTimer=void 0},delayOnHover))}function mousedownListener(e){const t=e.target.closest("a");isPreloadable(t)&&preload(t.href)}function mouseoutListener(e){e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||mouseoverTimer&&(clearTimeout(mouseoverTimer),mouseoverTimer=void 0)}function mousedownShortcutListener(e){if(performance.now()-lastTouchTimestamp1||e.metaKey||e.ctrlKey)return;if(!t)return;t.addEventListener("click",function(e){1337!=e.detail&&e.preventDefault()},{capture:!0,passive:!1,once:!0});const n=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:1337});t.dispatchEvent(n)}function isPreloadable(e){if(e&&e.href&&(!useWhitelist||"instant"in e.dataset)&&(allowExternalLinks||e.origin==location.origin||"instant"in e.dataset)&&["http:","https:"].includes(e.protocol)&&("http:"!=e.protocol||"https:"!=location.protocol)&&(allowQueryString||!e.search||"instant"in e.dataset)&&!(e.hash&&e.pathname+e.search==location.pathname+location.search||"noInstant"in e.dataset))return!0}function preload(e){if(prefetches.has(e))return;const t=document.createElement("link");t.rel="prefetch",t.href=e,document.head.appendChild(t),prefetches.add(e)} \ No newline at end of file +let _chromiumMajorVersionInUserAgent=null,_speculationRulesType,_allowQueryString,_allowExternalLinks,_useWhitelist,_delayOnHover=65,_lastTouchstartEvent,_mouseoverTimer,_preloadedList=new Set;function init(){let e=document.createElement("link").relList,t=e.supports("prefetch")&&e.supports("modulepreload");if(!t)return;let n="instantVaryAccept"in document.body.dataset||"Shopify"in window,r=navigator.userAgent.indexOf("Chrome/");if(r>-1&&(_chromiumMajorVersionInUserAgent=parseInt(navigator.userAgent.substring(r+7))),n&&_chromiumMajorVersionInUserAgent&&_chromiumMajorVersionInUserAgent<110)return;if(_speculationRulesType="none",HTMLScriptElement.supports&&HTMLScriptElement.supports("speculationrules")){let s=document.body.dataset.instantSpecrules;"prerender"==s?_speculationRulesType="prerender":"no"!=s&&(_speculationRulesType="prefetch")}let i="instantMousedownShortcut"in document.body.dataset;_allowQueryString="instantAllowQueryString"in document.body.dataset,_allowExternalLinks="instantAllowExternalLinks"in document.body.dataset,_useWhitelist="instantWhitelist"in document.body.dataset;let o=!1,a=!1,l=!1;if("instantIntensity"in document.body.dataset){let u=document.body.dataset.instantIntensity;if("mousedown"!=u||i||(o=!0),"mousedown-only"!=u||i||(o=!0,a=!0),"viewport"==u){let c=document.documentElement.clientWidth*document.documentElement.clientHeight<45e4,d=navigator.connection&&navigator.connection.saveData,p=navigator.connection&&navigator.connection.effectiveType&&navigator.connection.effectiveType.includes("2g");!c||d||p||(l=!0)}"viewport-all"==u&&(l=!0);let h=parseInt(u);isNaN(h)||(_delayOnHover=h)}let m={capture:!0,passive:!0};if(a?document.addEventListener("touchstart",touchstartEmptyListener,m):document.addEventListener("touchstart",touchstartListener,m),o||document.addEventListener("mouseover",mouseoverListener,m),o&&document.addEventListener("mousedown",mousedownListener,m),i&&document.addEventListener("mousedown",mousedownShortcutListener,m),l){let f=window.requestIdleCallback;f||(f=e=>{e()}),f(function e(){let t=new IntersectionObserver(e=>{e.forEach(e=>{if(e.isIntersecting){let n=e.target;t.unobserve(n),preload(n.href)}})});document.querySelectorAll("a").forEach(e=>{isPreloadable(e)&&t.observe(e)})},{timeout:1500})}}function touchstartListener(e){_lastTouchstartEvent=e;let t=e.target.closest("a");isPreloadable(t)&&preload(t.href,"high")}function touchstartEmptyListener(e){_lastTouchstartEvent=e}function mouseoverListener(e){if(isEventLikelyTriggeredByTouch(e)||!("closest"in e.target))return;let t=e.target.closest("a");isPreloadable(t)&&(t.addEventListener("mouseout",mouseoutListener,{passive:!0}),_mouseoverTimer=setTimeout(()=>{preload(t.href,"high"),_mouseoverTimer=null},_delayOnHover))}function mousedownListener(e){if(isEventLikelyTriggeredByTouch(e))return;let t=e.target.closest("a");isPreloadable(t)&&preload(t.href,"high")}function mouseoutListener(e){(!e.relatedTarget||e.target.closest("a")!=e.relatedTarget.closest("a"))&&_mouseoverTimer&&(clearTimeout(_mouseoverTimer),_mouseoverTimer=null)}function mousedownShortcutListener(e){if(isEventLikelyTriggeredByTouch(e))return;let t=e.target.closest("a");if(e.which>1||e.metaKey||e.ctrlKey||!t)return;t.addEventListener("click",function(e){1337!=e.detail&&e.preventDefault()},{capture:!0,passive:!1,once:!0});let n=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:1337});t.dispatchEvent(n)}function isEventLikelyTriggeredByTouch(e){if(!_lastTouchstartEvent||!e||e.target!=_lastTouchstartEvent.target)return!1;let t=e.timeStamp,n=t-_lastTouchstartEvent.timeStamp;return n<2500}function isPreloadable(e){if(e&&e.href&&(!_useWhitelist||"instant"in e.dataset)&&(e.origin==location.origin||(_allowExternalLinks||"instant"in e.dataset)&&_chromiumMajorVersionInUserAgent)){if(["http:","https:"].includes(e.protocol)&&("http:"!=e.protocol||"https:"!=location.protocol)&&(_allowQueryString||!e.search||"instant"in e.dataset)&&(!e.hash||e.pathname+e.search!=location.pathname+location.search)&&!("noInstant"in e.dataset))return!0}}function preload(e,t="auto"){!_preloadedList.has(e)&&("none"!=_speculationRulesType?preloadUsingSpeculationRules(e):preloadUsingLinkElement(e,t),_preloadedList.add(e))}function preloadUsingSpeculationRules(e){let t=document.createElement("script");t.type="speculationrules",t.textContent=JSON.stringify({[_speculationRulesType]:[{source:"list",urls:[e]}]}),document.head.appendChild(t)}function preloadUsingLinkElement(e,t="auto"){let n=document.createElement("link");n.rel="prefetch",n.href=e,n.fetchPriority=t,n.as="document",document.head.appendChild(n)}init(); diff --git a/assets/js/instant_click.ori.js b/assets/js/instant_click.ori.js index d43a31814..d3e9115c2 100644 --- a/assets/js/instant_click.ori.js +++ b/assets/js/instant_click.ori.js @@ -1,151 +1,252 @@ -/*! instant.page v5.1.0 - (C) 2019-2020 Alexandre Dieulot - https://instant.page/license */ - -let mouseoverTimer -let lastTouchTimestamp -const prefetches = new Set() -const prefetchElement = document.createElement('link') -const isSupported = prefetchElement.relList && prefetchElement.relList.supports && prefetchElement.relList.supports('prefetch') - && window.IntersectionObserver && 'isIntersecting' in IntersectionObserverEntry.prototype -const allowQueryString = 'instantAllowQueryString' in document.body.dataset -const allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset -const useWhitelist = 'instantWhitelist' in document.body.dataset -const mousedownShortcut = 'instantMousedownShortcut' in document.body.dataset -const DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION = 1111 - -let delayOnHover = 65 -let useMousedown = false -let useMousedownOnly = false -let useViewport = false - -if ('instantIntensity' in document.body.dataset) { - const intensity = document.body.dataset.instantIntensity - - if (intensity.substr(0, 'mousedown'.length) == 'mousedown') { - useMousedown = true - if (intensity == 'mousedown-only') { - useMousedownOnly = true +/*! instant.page v5.2.0 - (C) 2019-2024 Alexandre Dieulot - https://instant.page/license */ + +let _chromiumMajorVersionInUserAgent = null + , _speculationRulesType + , _allowQueryString + , _allowExternalLinks + , _useWhitelist + , _delayOnHover = 65 + , _lastTouchstartEvent + , _mouseoverTimer + , _preloadedList = new Set() + +init() + +function init() { + const supportCheckRelList = document.createElement('link').relList + const isSupported = supportCheckRelList.supports('prefetch') + && supportCheckRelList.supports('modulepreload') + // instant.page is meant to be loaded with '; - return $extraRet; + return $token; } /** @@ -1451,7 +1471,9 @@ public function parse_qc_redir($extra = array()) */ public function is_from_cloud() { - if (empty($this->_summary['ips']) || empty($this->_summary['ips_ts']) || time() - $this->_summary['ips_ts'] > 86400 * self::TTL_IPS) { + $check_point = time() - 86400 * self::TTL_IPS; + if (empty($this->_summary['ips']) || empty($this->_summary['ips_ts']) || $this->_summary['ips_ts'] < $check_point) { + self::debug('Force updating ip as ips_ts is older than ' . self::TTL_IPS . ' days'); $this->_update_ips(); } @@ -1459,8 +1481,19 @@ public function is_from_cloud() if (!$res) { self::debug('❌ Not our cloud IP'); - // Refresh IP list for future detection - $this->_update_ips(); + // Auto check ip list again but need an interval limit safety. + if (empty($this->_summary['ips_ts_runner']) || time() - $this->_summary['ips_ts_runner'] > 600) { + self::debug('Force updating ip as ips_ts_runner is older than 10mins'); + // Refresh IP list for future detection + $this->_update_ips(); + $res = $this->cls('Router')->ip_access($this->_summary['ips']); + if (!$res) { + self::debug('❌ 2nd time: Not our cloud IP'); + } else { + self::debug('✅ Passed Cloud IP verification'); + } + return $res; + } } else { self::debug('✅ Passed Cloud IP verification'); } @@ -1476,6 +1509,8 @@ public function is_from_cloud() private function _update_ips() { self::debug('Load remote Cloud IP list from ' . self::CLOUD_IPS); + // Prevent multiple call in a short period + self::save_summary(array('ips_ts' => time(), 'ips_ts_runner' => time())); $response = wp_remote_get(self::CLOUD_IPS . '?json'); if (is_wp_error($response)) { @@ -1484,9 +1519,10 @@ private function _update_ips() throw new \Exception('Failed to fetch QUIC.cloud whitelist ' . $error_message); } - $json = json_decode($response['body'], true); + $json = \json_decode($response['body'], true); - self::save_summary(array('ips_ts' => time(), 'ips' => $json)); + self::debug('Load ips', $json); + self::save_summary(array('ips' => $json)); } /** @@ -1510,6 +1546,35 @@ public static function err($code) return array('_res' => 'err', '_msg' => $code); } + /** + * Return pong for ping to check PHP function availability + * @since 6.5 + */ + public function ping() + { + $resp = array( + 'v_lscwp' => Core::VER, + 'v_php' => PHP_VERSION, + 'v_wp' => $GLOBALS['wp_version'], + ); + if (!empty($_POST['funcs'])) { + foreach ($_POST['funcs'] as $v) { + $resp[$v] = function_exists($v) ? 'y' : 'n'; + } + } + if (!empty($_POST['classes'])) { + foreach ($_POST['classes'] as $v) { + $resp[$v] = class_exists($v) ? 'y' : 'n'; + } + } + if (!empty($_POST['consts'])) { + foreach ($_POST['consts'] as $v) { + $resp[$v] = defined($v) ? 'y' : 'n'; + } + } + return self::ok($resp); + } + /** * Handle all request actions from main cls * diff --git a/src/conf.cls.php b/src/conf.cls.php index 897b6fcce..0fed67ba4 100644 --- a/src/conf.cls.php +++ b/src/conf.cls.php @@ -323,7 +323,7 @@ private function _conf_site_db_init() * Upgrade conf */ if ($ver && $ver != Core::VER) { - // Site plugin versin will change inside + // Site plugin version will change inside Data::cls()->conf_site_upgrade($ver); } @@ -512,7 +512,7 @@ public function update_confs($the_matrix = false) do_action('litespeed_update_confs', $the_matrix); // Update related tables - $this->cls('Data')->correct_tb_existance(); + $this->cls('Data')->correct_tb_existence(); // Update related files $this->cls('Activation')->update_files(); diff --git a/src/control.cls.php b/src/control.cls.php index 323475fe0..7d36e2ba0 100644 --- a/src/control.cls.php +++ b/src/control.cls.php @@ -1,4 +1,5 @@ */ + namespace LiteSpeed; defined('WPINC') || exit(); @@ -132,6 +134,24 @@ public function init_cacheable() } } + // AJAX cache + $ajax_cache = $this->conf(Base::O_CACHE_AJAX_TTL); + foreach ($ajax_cache as $v) { + $v = explode(' ', $v); + if (empty($v[0]) || empty($v[1])) { + continue; + } + // self::debug("Initializing cacheable status for wp_ajax_nopriv_" . $v[0]); + add_action( + 'wp_ajax_nopriv_' . $v[0], + function () use ($v) { + self::set_custom_ttl($v[1]); + self::force_cacheable('ajax Cache setting for action ' . $v[0]); + }, + 4 + ); + } + // Check error page add_filter('status_header', array($this, 'check_error_codes'), 10, 2); } @@ -143,7 +163,7 @@ public function init_cacheable() * @access public * @param $status_header * @param $code - * @return $eror_status + * @return $error_status */ public function check_error_codes($status_header, $code) { @@ -543,8 +563,11 @@ public function check_redirect($location, $status) self::debug("Compare [from] $url_parsed [to] $target"); if ($v == PHP_URL_QUERY) { - $url_parsed = urldecode($url_parsed); - $target = urldecode($target); + $url_parsed = $url_parsed ? urldecode($url_parsed) : ''; + $target = $target ? urldecode($target) : ''; + if (substr($url_parsed, -1) == '&') { + $url_parsed = substr($url_parsed, 0, -1); + } } if ($url_parsed != $target) { @@ -745,6 +768,24 @@ public static function is_mobile() return wp_is_mobile(); } + /** + * Get request method w/ compatibility to X-Http-Method-Override + * + * @since 6.2 + */ + private function _get_req_method() + { + if (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { + self::debug('X-Http-Method-Override -> ' . $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); + defined('LITESPEED_X_HTTP_METHOD_OVERRIDE') || define('LITESPEED_X_HTTP_METHOD_OVERRIDE', true); + return $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; + } + if (isset($_SERVER['REQUEST_METHOD'])) { + return $_SERVER['REQUEST_METHOD']; + } + return 'unknown'; + } + /** * Check if a page is cacheable based on litespeed setting. * @@ -760,7 +801,10 @@ private function _setting_cacheable() return $this->_no_cache_for('Query String Action'); } - $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'unknown'; + $method = $this->_get_req_method(); + if (defined('LITESPEED_X_HTTP_METHOD_OVERRIDE') && LITESPEED_X_HTTP_METHOD_OVERRIDE && $method == 'HEAD') { + return $this->_no_cache_for('HEAD method from override'); + } if ('GET' !== $method && 'HEAD' !== $method) { return $this->_no_cache_for('Not GET method: ' . $method); } @@ -790,7 +834,7 @@ private function _setting_cacheable() if (!self::is_forced_cacheable()) { // Check if URI is excluded from cache - $excludes = $this->conf(Base::O_CACHE_EXC); + $excludes = $this->cls('Data')->load_cache_nocacheable($this->conf(Base::O_CACHE_EXC)); $result = Utility::str_hit_array($_SERVER['REQUEST_URI'], $excludes); if ($result) { return $this->_no_cache_for('Admin configured URI Do not cache: ' . $result); diff --git a/src/core.cls.php b/src/core.cls.php index bd40ff0ff..614501b9f 100644 --- a/src/core.cls.php +++ b/src/core.cls.php @@ -192,7 +192,7 @@ public function init() $this->cls('Activation')->auto_update(); } - if (is_admin()) { + if (is_admin() && !(defined('DOING_AJAX') && DOING_AJAX)) { $this->cls('Admin'); } @@ -289,7 +289,7 @@ public function after_user_init() $this->cls('Localization')->init(); - // Hook cdn for attachements + // Hook cdn for attachments $this->cls('CDN')->init(); // load cron tasks @@ -393,7 +393,7 @@ public function footer_hook() } /** - * Tigger coment info display hook + * Trigger comment info display hook * * @since 1.3 * @access private @@ -452,7 +452,7 @@ private function _check_is_html($buffer = null) /** * For compatibility with those plugins have 'Bad' logic that forced all buffer output even it is NOT their buffer :( * - * Usually this is called after send_headers() if following orignal WP process + * Usually this is called after send_headers() if following original WP process * * @since 1.1.5 * @access public @@ -486,8 +486,9 @@ public function send_headers_force($buffer) $this->send_headers(true); // Log ESI nonce buffer empty issue - if (defined('LSCACHE_IS_ESI') && strlen($buffer) == 0) { - // TODO: log ref somewhere + if (defined('LSCACHE_IS_ESI') && strlen($buffer) != 0) { + // log ref for debug purpose + error_log('ESI buffer empty ' . $_SERVER['REQUEST_URI']); } // Init comment info @@ -527,9 +528,9 @@ public function send_headers_force($buffer) } if (apply_filters('litespeed_is_json', false)) { - if (json_decode($buffer, true) == null) { + if (\json_decode($buffer, true) == null) { Debug2::debug('[Core] Buffer converting to JSON'); - $buffer = json_encode($buffer); + $buffer = \json_encode($buffer); $buffer = trim($buffer, '"'); } else { Debug2::debug('[Core] JSON Buffer'); @@ -610,6 +611,9 @@ public function send_headers($is_forced = false) // send Control header if (defined('LITESPEED_ON') && $control_header) { $this->_http_header($control_header); + if (!Control::is_cacheable()) { + $this->_http_header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0'); // @ref: https://wordpress.org/support/topic/apply_filterslitespeed_control_cacheable-returns-false-for-cacheable/ + } if (defined('LSCWP_LOG')) { $this->_comment($control_header); } diff --git a/src/crawler-map.cls.php b/src/crawler-map.cls.php index 633b10088..3cb88c73c 100644 --- a/src/crawler-map.cls.php +++ b/src/crawler-map.cls.php @@ -298,14 +298,36 @@ public function list_map($limit, $offset = false) $offset = Utility::pagination($total, $limit, true); } + $type = Router::verify_type(); + $where = ''; if (!empty($_POST['kw'])) { - $q = "SELECT * FROM `$this->_tb` WHERE url LIKE %s ORDER BY id LIMIT %d, %d"; + $q = "SELECT * FROM `$this->_tb` WHERE url LIKE %s"; + if ($type == 'hit') { + $q .= " AND res LIKE '%H%'"; + } + if ($type == 'miss') { + $q .= " AND res LIKE '%M%'"; + } + if ($type == 'blacklisted') { + $q .= " AND res LIKE '%B%'"; + } + $q .= ' ORDER BY id LIMIT %d, %d'; $where = '%' . $wpdb->esc_like($_POST['kw']) . '%'; return $wpdb->get_results($wpdb->prepare($q, $where, $offset, $limit), ARRAY_A); } - $q = "SELECT * FROM `$this->_tb` ORDER BY id LIMIT %d, %d"; + $q = "SELECT * FROM `$this->_tb`"; + if ($type == 'hit') { + $q .= " WHERE res LIKE '%H%'"; + } + if ($type == 'miss') { + $q .= " WHERE res LIKE '%M%'"; + } + if ($type == 'blacklisted') { + $q .= " WHERE res LIKE '%B%'"; + } + $q .= ' ORDER BY id LIMIT %d, %d'; // self::debug("q=$q offset=$offset, limit=$limit"); return $wpdb->get_results($wpdb->prepare($q, $offset, $limit), ARRAY_A); } @@ -322,6 +344,18 @@ public function count_map() } $q = "SELECT COUNT(*) FROM `$this->_tb`"; + + $type = Router::verify_type(); + if ($type == 'hit') { + $q .= " WHERE res LIKE '%H%'"; + } + if ($type == 'miss') { + $q .= " WHERE res LIKE '%M%'"; + } + if ($type == 'blacklisted') { + $q .= " WHERE res LIKE '%B%'"; + } + return $wpdb->get_var($q); } @@ -331,7 +365,7 @@ public function count_map() * @since 1.1.0 * @access public */ - public function gen() + public function gen($manual = false) { $count = $this->_gen(); @@ -340,7 +374,7 @@ public function gen() return; } - if (!defined('DOING_CRON')) { + if (!defined('DOING_CRON') && $manual) { $msg = sprintf(__('Sitemap created successfully: %d items', 'litespeed-cache'), $count); Admin_Display::succeed($msg); } diff --git a/src/crawler.cls.php b/src/crawler.cls.php index 7791d76d9..d0e752b22 100644 --- a/src/crawler.cls.php +++ b/src/crawler.cls.php @@ -144,7 +144,7 @@ public function clear_disabled_list() } /** - * Overwride get_summary to init elements + * Overwrite get_summary to init elements * * @since 3.0 * @access public @@ -188,7 +188,7 @@ public static function get_summary($field = false) } /** - * Overwride save_summary + * Overwrite save_summary * * @since 3.0 * @access public @@ -204,7 +204,7 @@ public static function save_summary($data = false, $reload = false, $overwrite = parent::save_summary($data, $reload, $overwrite); - File::save(LITESPEED_STATIC_DIR . '/crawler/' . $instance->_sitemeta, json_encode($data), true); + File::save(LITESPEED_STATIC_DIR . '/crawler/' . $instance->_sitemeta, \json_encode($data), true); } /** @@ -238,12 +238,7 @@ public static function start_async() public static function async_handler($manually_run = false) { self::debug('------------async-------------start_async_handler'); - // self::debug('-------------async------------ check_ajax_referer'); - // add_action('check_ajax_referer', function ($a, $b) { - // \LiteSpeed\Crawler::debug('---------------' . $a . $b); - // }); // check_ajax_referer('async_crawler', 'nonce'); - // self::debug('--------------async----------- start async crawling'); self::start($manually_run); } @@ -263,12 +258,6 @@ public static function start($manually_run = false) if ($manually_run) { self::debug('......crawler manually ran......'); } - // $i = 0; - // while ($i < 100) { - // self::debug('......sleep ' . ($i++) . '......' . time()); - // sleep(1); - // } - // return; self::cls()->_crawl_data($manually_run); } @@ -371,7 +360,7 @@ private function load_conf() $vary_name = $this->cls('Vary')->get_vary_name(); $vary_val = $this->cls('Vary')->finalize_default_vary($current_crawler['uid']); $this->_crawler_conf['cookies'][$vary_name] = $vary_val; - $this->_crawler_conf['cookies']['litespeed_role'] = $current_crawler['uid']; + $this->_crawler_conf['cookies']['litespeed_hash'] = Router::cls()->get_hash($current_crawler['uid']); } /** @@ -896,7 +885,7 @@ private function _status_parse($header, $code, $url) return 'N'; // Blacklist } - $_cache_headers = array('x-litespeed-cache', 'x-lsadc-cache', 'x-qc-cache'); + $_cache_headers = array('x-qc-cache', 'x-lsadc-cache', 'x-litespeed-cache'); foreach ($_cache_headers as $_header) { if (stripos($header, $_header) !== false) { @@ -984,14 +973,6 @@ private function _get_curl_options($crawler_only = false) } $options[CURLOPT_USERAGENT] = $this->_crawler_conf['ua']; - /** - * Append hash to cookie for validation - * @since 1.9.1 - */ - if ($crawler_only) { - $this->_crawler_conf['cookies']['litespeed_hash'] = Router::get_hash(); - } - // Cookies $cookies = array(); foreach ($this->_crawler_conf['cookies'] as $k => $v) { @@ -1021,8 +1002,7 @@ public function self_curl($url, $ua, $uid = false, $accept = false) $this->_crawler_conf['headers'] = array('Accept: ' . $accept); } if ($uid) { - $this->_crawler_conf['cookies']['litespeed_role'] = $uid; - $this->_crawler_conf['cookies']['litespeed_hash'] = Router::get_hash(); + $this->_crawler_conf['cookies']['litespeed_flash_hash'] = Router::cls()->get_flash_hash($uid); } $options = $this->_get_curl_options(); @@ -1302,7 +1282,7 @@ public function handler() switch ($type) { case self::TYPE_REFRESH_MAP: - $this->cls('Crawler_Map')->gen(); + $this->cls('Crawler_Map')->gen(true); break; case self::TYPE_EMPTY: @@ -1325,8 +1305,7 @@ public function handler() } break; - // Handle the ajax request to proceed crawler manually by admin - case self::TYPE_START: + case self::TYPE_START: // Handle the ajax request to proceed crawler manually by admin self::start_async(); break; diff --git a/src/data.cls.php b/src/data.cls.php index e9c4d5d7e..1e2759258 100644 --- a/src/data.cls.php +++ b/src/data.cls.php @@ -58,15 +58,15 @@ public function __construct() } /** - * Correct table existance + * Correct table existence * - * Call when activate -> upadte_confs() - * Call when upadte_confs() + * Call when activate -> update_confs() + * Call when update_confs() * * @since 3.0 * @access public */ - public function correct_tb_existance() + public function correct_tb_existence() { // Gravatar if ($this->conf(Base::O_DISCUSS_AVATAR_CACHE)) { @@ -128,7 +128,7 @@ public function conf_upgrade($ver) // Reload options $this->cls('Conf')->load_options(); - $this->correct_tb_existance(); + $this->correct_tb_existence(); // Update related files $this->cls('Activation')->update_files(); @@ -291,7 +291,7 @@ public function try_upgrade_conf_3_0() // Reload options $this->cls('Conf')->load_options(); - $this->correct_tb_existance(); + $this->correct_tb_existence(); !defined('LSWCP_EMPTYCACHE') && define('LSWCP_EMPTYCACHE', true); // clear all sites caches Purge::purge_all(); @@ -465,6 +465,18 @@ public function url_file_clean($file_type) $type = $this->_url_file_types[$file_type]; $q = 'DELETE FROM ' . $this->tb('url_file') . ' WHERE `type` = %d'; $wpdb->query($wpdb->prepare($q, $type)); + + // Added to cleanup url table. See issue: https://wordpress.org/support/topic/wp_litespeed_url-1-1-gb-in-db-huge-big/ + $wpdb->query( + 'DELETE d + FROM `' . + $this->tb('url') . + '` AS d + LEFT JOIN `' . + $this->tb('url_file') . + '` AS f ON d.`id` = f.`url_id` + WHERE f.`url_id` IS NULL' + ); } /** @@ -591,9 +603,9 @@ public function load_url_file($request_url, $vary, $file_type) public function mark_as_expired($request_url, $auto_q = false) { global $wpdb; + $tb_url = $this->tb('url'); Debug2::debug('[Data] Try to mark as expired: ' . $request_url); - $tb_url = $this->tb('url'); $q = "SELECT * FROM `$tb_url` WHERE url=%s"; $url_row = $wpdb->get_row($wpdb->prepare($q, $request_url), ARRAY_A); if (!$url_row) { @@ -602,7 +614,6 @@ public function mark_as_expired($request_url, $auto_q = false) Debug2::debug('[Data] Mark url_id=' . $url_row['id'] . ' as expired'); - $tb_url = $this->tb('url'); $tb_url_file = $this->tb('url_file'); $existing_url_files = array(); @@ -708,6 +719,21 @@ public function load_esi_nonces($list) return $list; } + /** + * Get list from `data/cache_nocacheable.txt` + * + * @since 6.3.0.1 + */ + public function load_cache_nocacheable($list) + { + $data = $this->_load_per_line('cache_nocacheable.txt'); + if ($data) { + $list = array_unique(array_filter(array_merge($list, $data))); + } + + return $list; + } + /** * Load file per line * diff --git a/src/data.upgrade.func.php b/src/data.upgrade.func.php index 60cff570a..b85654ad8 100644 --- a/src/data.upgrade.func.php +++ b/src/data.upgrade.func.php @@ -357,7 +357,7 @@ function litespeed_update_3_0($ver) 'debug_level' => 'debug-level', 'log_file_size' => 'debug-filesize', 'debug_cookie' => 'debug-cookie', - 'collaps_qs' => 'debug-collaps_qs', + 'collapse_qs' => 'debug-collapse_qs', // 'log_filters' => 'debug-log_filters', 'crawler_cron_active' => 'crawler', @@ -447,7 +447,7 @@ function litespeed_update_3_0($ver) if (!isset($previous_options[$k])) { continue; } - // The folllowing values must be array + // The following values must be array if (!is_array($previous_options[$k])) { if (in_array($v, array('cdn-ori', 'cache-exc_cat', 'cache-exc_tag'))) { $previous_options[$k] = explode(',', $previous_options[$k]); @@ -605,7 +605,7 @@ function litespeed_update_3_0($ver) if (!isset($previous_site_options[$k])) { continue; } - // The folllowing values must be array + // The following values must be array if (!is_array($previous_site_options[$k])) { if (in_array($v, array('cache-mobile_rules', 'cache-exc_useragents', 'cache-exc_cookies'))) { $previous_site_options[$k] = explode('|', str_replace('\\ ', ' ', $previous_site_options[$k])); diff --git a/src/debug2.cls.php b/src/debug2.cls.php index d7a1b3c1b..14bf6bf2f 100644 --- a/src/debug2.cls.php +++ b/src/debug2.cls.php @@ -31,10 +31,13 @@ class Debug2 extends Root */ public function __construct() { - self::$log_path_prefix = defined('LSCWP_DEBUG_PATH') ? LSCWP_DEBUG_PATH : LSCWP_CONTENT_DIR; - self::$log_path = self::$log_path_prefix . '/debug.log'; + self::$log_path_prefix = LITESPEED_STATIC_DIR . '/debug/'; + // Maybe move legacy log files + $this->_maybe_init_folder(); + + self::$log_path = $this->path('debug'); if (!empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'lscache_') === 0) { - self::$log_path = self::$log_path_prefix . '/crawler.log'; + self::$log_path = $this->path('crawler'); } !defined('LSCWP_LOG_TAG') && define('LSCWP_LOG_TAG', get_current_blog_id()); @@ -46,6 +49,51 @@ public function __construct() defined('LSCWP_DEBUG_EXC_STRINGS') || define('LSCWP_DEBUG_EXC_STRINGS', $this->conf(Base::O_DEBUG_EXC_STRINGS)); } + /** + * Try moving legacy logs into /litespeed/debug/ folder + * + * @since 6.5 + */ + private function _maybe_init_folder() + { + if (file_exists(self::$log_path_prefix . 'index.php')) { + return; + } + file::save(self::$log_path_prefix . 'index.php', 'path($log))) { + rename(LSCWP_CONTENT_DIR . '/' . $log . '.log', $this->path($log)); + } + } + } + + /** + * Generate log file path + * + * @since 6.5 + */ + public function path($type) + { + return self::$log_path_prefix . self::FilePath($type); + } + + /** + * Generate the fixed log filename + * + * @since 6.5 + */ + public static function FilePath($type) + { + if ($type == 'debug.purge') { + $type = 'purge'; + } + $key = defined('AUTH_KEY') ? AUTH_KEY : md5(__FILE__); + $rand = substr(md5(substr($key, -16)), -16); + return $type . $rand . '.log'; + } + /** * End call of one request process * @since 4.7 @@ -53,7 +101,13 @@ public function __construct() */ public static function ended() { - self::debug('Response headers', headers_list()); + $headers = headers_list(); + foreach ($headers as $key => $header) { + if (stripos($header, 'Set-Cookie') === 0) { + unset($headers[$key]); + } + } + self::debug('Response headers', $headers); $elapsed_time = number_format((microtime(true) - LSCWP_TS_0) * 1000, 2); self::debug("End response\n--------------------------------------------------Duration: " . $elapsed_time . " ms------------------------------\n"); @@ -143,7 +197,7 @@ public static function log_purge($purge_header) return; } - $purge_file = self::$log_path_prefix . '/debug.purge.log'; + $purge_file = self::cls()->path('purge'); self::cls()->_init_request($purge_file); @@ -246,10 +300,8 @@ private function _init_request($log_file = null) $param = sprintf('💓 ------%s %s %s', $server['REQUEST_METHOD'], $server['SERVER_PROTOCOL'], strtok($server['REQUEST_URI'], '?')); $qs = !empty($server['QUERY_STRING']) ? $server['QUERY_STRING'] : ''; - if ($this->conf(Base::O_DEBUG_COLLAPS_QS)) { - if (strlen($qs) > 53) { - $qs = substr($qs, 0, 53) . '...'; - } + if ($this->conf(Base::O_DEBUG_COLLAPSE_QS)) { + $qs = $this->_omit_long_message($qs); if ($qs) { $param .= ' ? ' . $qs; } @@ -260,17 +312,15 @@ private function _init_request($log_file = null) } if (!empty($_SERVER['HTTP_REFERER'])) { - $params[] = 'HTTP_REFERER: ' . $server['HTTP_REFERER']; + $params[] = 'HTTP_REFERER: ' . $this->_omit_long_message($server['HTTP_REFERER']); } if (defined('LSCWP_LOG_MORE')) { - $params[] = 'User Agent: ' . $server['HTTP_USER_AGENT']; + $params[] = 'User Agent: ' . $this->_omit_long_message($server['HTTP_USER_AGENT']); $params[] = 'Accept: ' . $server['HTTP_ACCEPT']; $params[] = 'Accept Encoding: ' . $server['HTTP_ACCEPT_ENCODING']; } - if ($this->conf(Base::O_DEBUG_COOKIE)) { - $params[] = 'Cookie: ' . $server['HTTP_COOKIE']; - } + // $params[] = 'Cookie: ' . $server['HTTP_COOKIE']; if (isset($_COOKIE['_lscache_vary'])) { $params[] = 'Cookie _lscache_vary: ' . $_COOKIE['_lscache_vary']; } @@ -292,6 +342,18 @@ private function _init_request($log_file = null) File::append($log_file, $request); } + /** + * Trim long msg to keep log neat + * @since 6.3 + */ + private function _omit_long_message($msg) + { + if (strlen($msg) > 53) { + $msg = substr($msg, 0, 53) . '...'; + } + return $msg; + } + /** * Formats the log message with a consistent prefix. * @@ -466,9 +528,9 @@ private static function _backtrace_info($backtrace_limit) */ private function _clear_log() { - $logs = array('debug', 'debug.purge', 'crawler'); + $logs = array('debug', 'purge', 'crawler'); foreach ($logs as $log) { - File::save(self::$log_path_prefix . "/{$log}.log", ''); + File::save($this->path($log), ''); } } diff --git a/src/error.cls.php b/src/error.cls.php index df72b0f3a..549abe269 100644 --- a/src/error.cls.php +++ b/src/error.cls.php @@ -61,11 +61,29 @@ public static function msg($code, $args = null) break; case 'out_of_daily_quota': - $msg = __('You don\'t have enough daily quota left for current service today.', 'litespeed-cache'); + $msg = __('You have used all of your daily quota for today.', 'litespeed-cache'); + $msg .= + ' ' . + Doc::learn_more( + 'https://docs.quic.cloud/billing/services/#daily-limits-on-free-quota-usage', + __('Learn more or purchase additional quota.', 'litespeed-cache'), + false, + false, + true + ); break; case 'out_of_quota': - $msg = __('You don\'t have enough quota left for current service this month.', 'litespeed-cache'); + $msg = __('You have used all of your quota left for current service this month.', 'litespeed-cache'); + $msg .= + ' ' . + Doc::learn_more( + 'https://docs.quic.cloud/billing/services/#daily-limits-on-free-quota-usage', + __('Learn more or purchase additional quota.', 'litespeed-cache'), + false, + false, + true + ); break; case 'too_many_requested': @@ -73,7 +91,7 @@ public static function msg($code, $args = null) break; case 'too_many_notified': - $msg = __('You have too many notified images, please pull down notified images first.', 'litespeed-cache'); + $msg = __('You have images waiting to be pulled. Please wait for the automatic pull to complete, or pull them down manually now.', 'litespeed-cache'); break; case 'empty_list': @@ -159,8 +177,7 @@ public static function msg($code, $args = null) $msg = __('Crawler disabled by the server admin.', 'litespeed-cache'); break; - /*** QC error code ***/ - case 'try_later': + case 'try_later': // QC error code $msg = __('Previous request too recent. Please try again later.', 'litespeed-cache'); break; diff --git a/src/esi.cls.php b/src/esi.cls.php index 25e724acb..6b46ef406 100644 --- a/src/esi.cls.php +++ b/src/esi.cls.php @@ -62,6 +62,11 @@ public function init() return; } + // If page is not cacheable + if (defined('DONOTCACHEPAGE') && apply_filters('litespeed_const_DONOTCACHEPAGE', DONOTCACHEPAGE)) { + return; + } + // Init ESI in `after_setup_theme` hook after detected if LITESPEED_DISABLE_ALL is ON or not $this->_hooks(); @@ -102,7 +107,7 @@ private function _hooks() /** * Shortcode ESI * - * To use it, just change the origianl shortcode as below: + * To use it, just change the original shortcode as below: * old: [someshortcode aa='bb'] * new: [esi someshortcode aa='bb' cache='private,no-vary' ttl='600'] * @@ -359,6 +364,7 @@ private function _register_not_esi_actions() // Add admin_bar esi if (Router::is_logged_in()) { + remove_action('wp_body_open', 'wp_admin_bar_render', 0); // Remove default Admin bar. Fix https://github.com/elementor/elementor/issues/25198 remove_action('wp_footer', 'wp_admin_bar_render', 1000); add_action('wp_footer', array($this, 'sub_admin_bar_block'), 1000); } @@ -453,7 +459,7 @@ private static function _build_inline($url, $inline_param) * @param string $control The cache control attribute if any. * @param bool $silence If generate wrapper comment or not * @param bool $preserved If this ESI block is used in any filter, need to temporarily convert it to a string to avoid the HTML tag being removed/filtered. - * @param bool $svar If store the value in memory or not, in memory wil be faster + * @param bool $svar If store the value in memory or not, in memory will be faster * @param array $inline_val If show the current value for current request( this can avoid multiple esi requests in first time cache generating process ) */ public function sub_esi_block( @@ -502,7 +508,7 @@ public function sub_esi_block( $appended_params['_control'] = $control; } if ($params) { - $appended_params[self::QS_PARAMS] = base64_encode(json_encode($params)); + $appended_params[self::QS_PARAMS] = base64_encode(\json_encode($params)); Debug2::debug2('[ESI] param ', $params); } @@ -608,7 +614,7 @@ private function _parse_esi_param($qs_params = false) Debug2::debug2('[ESI] parms', $unencrypted); // $unencoded = urldecode($unencrypted); no need to do this as $_GET is already parsed - $params = json_decode($unencrypted, true); + $params = \json_decode($unencrypted, true); return $params; } @@ -1006,7 +1012,7 @@ public function comment_form_sub_clean() } /** - * Replace preseved blocks + * Replace preserved blocks * * @since 2.6 * @access public diff --git a/src/gui.cls.php b/src/gui.cls.php index 3317958af..4b8b6b820 100644 --- a/src/gui.cls.php +++ b/src/gui.cls.php @@ -1,4 +1,5 @@ */ + namespace LiteSpeed; + defined('WPINC') || exit(); class GUI extends Base @@ -72,7 +75,7 @@ public function init() } /** - * Print a loading message when redirecting CCSS/UCSS page to aviod whiteboard confusion + * Print a loading message when redirecting CCSS/UCSS page to avoid whiteboard confusion */ public static function print_loading($counter, $type) { @@ -206,7 +209,7 @@ public static function dismiss() if (Router::is_ajax()) { // All dismiss actions are considered as ajax call, so just exit - exit(json_encode(array('success' => 1))); + exit(\json_encode(array('success' => 1))); } // Plain click link, redirect to referral url @@ -502,6 +505,16 @@ public function frontend_shortcut() 'meta' => array('tabindex' => '0'), )); + if ($this->conf(self::O_CDN_CLOUDFLARE)) { + $wp_admin_bar->add_menu(array( + 'parent' => 'litespeed-menu', + 'id' => 'litespeed-purge-cloudflare', + 'title' => __('Purge All', 'litespeed-cache') . ' - ' . __('Cloudflare', 'litespeed-cache'), + 'href' => Utility::build_url(Router::ACTION_CDN_CLOUDFLARE, CDN\Cloudflare::TYPE_PURGE_ALL), + 'meta' => array('tabindex' => '0'), + )); + } + if (defined('LSCWP_OBJECT_CACHE')) { $wp_admin_bar->add_menu(array( 'parent' => 'litespeed-menu', diff --git a/src/htaccess.cls.php b/src/htaccess.cls.php index a608ecbc4..935db3b24 100644 --- a/src/htaccess.cls.php +++ b/src/htaccess.cls.php @@ -44,7 +44,6 @@ class Htaccess extends Root const MARKER_NOCACHE_COOKIES = '### marker NOCACHE COOKIES'; const MARKER_NOCACHE_USER_AGENTS = '### marker NOCACHE USER AGENTS'; const MARKER_CACHE_RESOURCE = '### marker CACHE RESOURCE'; - const MARKER_FAVICON = '### marker FAVICON'; const MARKER_BROWSER_CACHE = '### marker BROWSER CACHE'; const MARKER_MINIFY = '### marker MINIFY'; const MARKER_CORS = '### marker CORS'; @@ -94,7 +93,7 @@ public function __construct() self::REWRITE_ON, 'CacheLookup on', 'RewriteRule .* - [E=Cache-Control:no-autoflush]', - // "RewriteRule \.object-cache\.ini - [F,L]", + 'RewriteRule ' . preg_quote(LITESPEED_DATA_FOLDER) . '/debug/.*\.log$ - [F,L]', 'RewriteRule ' . preg_quote(self::CONF_FILE) . ' - [F,L]', ); @@ -577,16 +576,6 @@ private function _generate_rules($cfg) $new_rules[] = ''; } - // favicon - // frontend and backend - $id = Base::O_CACHE_FAVICON; - if (!empty($cfg[$id])) { - $new_rules[] = $new_rules_backend[] = self::MARKER_FAVICON . self::MARKER_START; - $new_rules[] = $new_rules_backend[] = 'RewriteRule favicon\.ico$ - [E=cache-control:max-age=86400]'; - $new_rules[] = $new_rules_backend[] = self::MARKER_FAVICON . self::MARKER_END; - $new_rules[] = ''; - } - // CORS font rules $id = Base::O_CDN; if (!empty($cfg[$id])) { diff --git a/src/img-optm.cls.php b/src/img-optm.cls.php index 64ce394bc..9ae676023 100644 --- a/src/img-optm.cls.php +++ b/src/img-optm.cls.php @@ -210,7 +210,8 @@ public function new_req() self::save_summary(); // Check if has credit to push - $allowance = Cloud::cls()->allowance(Cloud::SVC_IMG_OPTM); + $err = false; + $allowance = Cloud::cls()->allowance(Cloud::SVC_IMG_OPTM, $err); $wet_limit = $this->wet_limit(); @@ -221,7 +222,7 @@ public function new_req() if (!$allowance) { self::debug('❌ No credit'); - Admin_Display::error(Error::msg('out_of_quota')); + Admin_Display::error(Error::msg($err)); $this->_finished_running(); return; } @@ -242,14 +243,21 @@ public function new_req() return; } + $allowance -= $total_requested; + + if ($allowance < 1) { + self::debug('❌ Too many requested images ' . $total_requested); + Admin_Display::error(Error::msg('too_many_requested')); + $this->_finished_running(); + return; + } + // Limit maximum number of items waiting to be pulled $q = "SELECT COUNT(1) FROM `$this->_table_img_optming` WHERE optm_status = %d"; $q = $wpdb->prepare($q, array(self::STATUS_NOTIFIED)); $total_notified = $wpdb->get_var($q); - $max_notified = $allowance * 5; - - if ($total_notified > $max_notified) { - self::debug('❌ Too many notified images (' . $total_notified . ' > ' . $max_notified . ')'); + if ($total_notified > 0) { + self::debug('❌ Too many notified images (' . $total_notified . ')'); Admin_Display::error(Error::msg('too_many_notified')); $this->_finished_running(); return; @@ -258,11 +266,12 @@ public function new_req() $q = "SELECT COUNT(1) FROM `$this->_table_img_optming` WHERE optm_status IN (%d, %d)"; $q = $wpdb->prepare($q, array(self::STATUS_NEW, self::STATUS_RAW)); $total_new = $wpdb->get_var($q); - $allowance -= $total_new; + // $allowance -= $total_new; - // Get images + // May need to get more images $list = array(); - if ($allowance > 0) { + $more = $allowance - $total_new; + if ($more > 0) { $q = "SELECT b.post_id, b.meta_value FROM `$wpdb->posts` a LEFT JOIN `$wpdb->postmeta` b ON b.post_id = a.ID @@ -274,20 +283,8 @@ public function new_req() ORDER BY a.ID LIMIT %d "; - $q = $wpdb->prepare($q, array($this->_summary['next_post_id'], $allowance)); + $q = $wpdb->prepare($q, array($this->_summary['next_post_id'], $more)); $list = $wpdb->get_results($q); - } - - if (!$list) { - // $msg = __('No new image to send.', 'litespeed-cache'); - // Admin_Display::succeed($msg); - - // self::debug('new_req() bypass: no new image found'); - // $this->_finished_running(); - // return; - } - - if ($list) { foreach ($list as $v) { if (!$v->post_id) { continue; @@ -315,12 +312,6 @@ public function new_req() self::save_summary(); - if (!$this->_img_in_queue) { - self::debug('gather_images bypass: empty _img_in_queue'); - $this->_finished_running(); - return; - } - $num_a = count($this->_img_in_queue); self::debug('Images found: ' . $num_a); $this->_filter_duplicated_src(); @@ -340,7 +331,7 @@ public function new_req() } // Push to Cloud server - $accepted_imgs = $this->_send_request(); + $accepted_imgs = $this->_send_request($allowance); $this->_finished_running(); if (!$accepted_imgs) { @@ -609,11 +600,13 @@ private function _filter_invalid_src() * @since 1.6.7 * @access private */ - private function _send_request() + private function _send_request($allowance) { global $wpdb; - $_img_in_queue = $wpdb->get_results("SELECT id,src,post_id FROM `$this->_table_img_optming` WHERE optm_status=" . self::STATUS_RAW); + $q = "SELECT id, src, post_id FROM `$this->_table_img_optming` WHERE optm_status=%d LIMIT %d"; + $q = $wpdb->prepare($q, array(self::STATUS_RAW, $allowance)); + $_img_in_queue = $wpdb->get_results($q); if (!$_img_in_queue) { return; } @@ -661,7 +654,7 @@ private function _send_request() $data = array( 'action' => self::CLOUD_ACTION_NEW_REQ, - 'list' => json_encode($list), + 'list' => \json_encode($list), 'optm_ori' => $this->conf(self::O_IMG_OPTM_ORI) ? 1 : 0, 'optm_webp' => $this->conf(self::O_IMG_OPTM_WEBP) ? 1 : 0, 'optm_lossless' => $this->conf(self::O_IMG_OPTM_LOSSLESS) ? 1 : 0, @@ -707,7 +700,7 @@ public function notify_img() return Cloud::err('too_often'); } - $post_data = json_decode(file_get_contents('php://input'), true); + $post_data = \json_decode(file_get_contents('php://input'), true); if (is_null($post_data)) { $post_data = $_POST; } @@ -810,7 +803,7 @@ public function notify_img() // Update status and data in working table $q = "UPDATE `$this->_table_img_optming` SET optm_status = %d, server_info = %s WHERE id = %d "; - $wpdb->query($wpdb->prepare($q, array($status, json_encode($server_info), $v->id))); + $wpdb->query($wpdb->prepare($q, array($status, \json_encode($server_info), $v->id))); // Update postmeta for optm summary $postmeta_info = serialize($postmeta_info); @@ -990,7 +983,7 @@ public function pull($manual = false) $req_counter = 0; foreach ($img_rows as $row_img) { // request original image - $server_info = json_decode($row_img->server_info, true); + $server_info = \json_decode($row_img->server_info, true); if (!empty($server_info['ori'])) { $image_url = $server_info['server'] . '/' . $server_info['ori']; self::debug('Queueing pull: ' . $image_url); @@ -1031,7 +1024,7 @@ public function pull($manual = false) $row_type = isset($row_data['type']) ? $row_data['type'] : 'ori'; $row_img = $row_data['data']; $local_file = $this->wp_upload_dir['basedir'] . '/' . $row_img->src; - $server_info = json_decode($row_img->server_info, true); + $server_info = \json_decode($row_img->server_info, true); if (empty($response->success)) { if (!empty($response->status_code) && 404 == $response->status_code) { @@ -1323,7 +1316,7 @@ private function _destroy() { global $wpdb; - self::debug('excuting DESTROY process'); + self::debug('executing DESTROY process'); $offset = !empty($_GET['litespeed_i']) ? $_GET['litespeed_i'] : 0; /** @@ -1506,7 +1499,7 @@ private function _rescan() } } - self::debug('rescaned [img] ' . count($this->_img_in_queue)); + self::debug('rescanned [img] ' . count($this->_img_in_queue)); $count = count($this->_img_in_queue); if ($count > 0) { @@ -1728,7 +1721,7 @@ public function img_count() "; $groups_all = $wpdb->get_var($q); $groups_new = $wpdb->get_var($q . ' AND ID>' . (int) $this->_summary['next_post_id'] . ' ORDER BY ID'); - $groups_done = $wpdb->get_var($q . ' AND ID<' . (int) $this->_summary['next_post_id'] . ' ORDER BY ID'); + $groups_done = $wpdb->get_var($q . ' AND ID<=' . (int) $this->_summary['next_post_id'] . ' ORDER BY ID'); $q = "SELECT b.post_id FROM `$wpdb->posts` a @@ -1810,13 +1803,37 @@ private function _update_cron_running($done = false) * Batch switch images to ori/optm version * * @since 1.6.2 - * @access private + * @access public */ - private function _batch_switch($type) + public function batch_switch($type) { global $wpdb; - $offset = !empty($_GET['litespeed_i']) ? $_GET['litespeed_i'] : 0; + if (defined('LITESPEED_CLI') || defined('DOING_CRON')) { + $offset = 0; + while ($offset !== 'done') { + Admin_Display::info("Starting switch to $type [offset] $offset"); + $offset = $this->_batch_switch($type, $offset); + } + } else { + $offset = !empty($_GET['litespeed_i']) ? $_GET['litespeed_i'] : 0; + + $newOffset = $this->_batch_switch($type, $offset); + if ($newOffset !== 'done') { + return Router::self_redirect(Router::ACTION_IMG_OPTM, $type); + } + } + + $msg = __('Switched images successfully.', 'litespeed-cache'); + Admin_Display::succeed($msg); + } + + /** + * Switch images per offset + */ + private function _batch_switch($type, $offset) + { + global $wpdb; $limit = 500; $this->tmp_type = $type; @@ -1853,16 +1870,14 @@ private function _batch_switch($type) } } - self::debug('batch switched images total: ' . $i); + self::debug('batch switched images total: ' . $i . ' [type] ' . $type); $offset++; $to_be_continued = $wpdb->get_row($wpdb->prepare($img_q, array($offset * $limit, 1))); if ($to_be_continued) { - return Router::self_redirect(Router::ACTION_IMG_OPTM, $type); + return $offset; } - - $msg = __('Switched images successfully.', 'litespeed-cache'); - Admin_Display::succeed($msg); + return 'done'; } /** @@ -1880,8 +1895,10 @@ private function _switch_bk_file($meta_value, $is_ori_file = false) $bk_file = $local_filename . '.bk.' . $extension; $bk_optm_file = $local_filename . '.bk.optm.' . $extension; + // self::debug('_switch_bk_file ' . $bk_file . ' [type] ' . $this->tmp_type); // switch to ori - if ($this->tmp_type === self::TYPE_BATCH_SWITCH_ORI) { + if ($this->tmp_type === self::TYPE_BATCH_SWITCH_ORI || $this->tmp_type == 'orig') { + // self::debug('switch to orig ' . $bk_file); if (!$this->__media->info($bk_file, $this->tmp_pid)) { return; } @@ -1889,7 +1906,8 @@ private function _switch_bk_file($meta_value, $is_ori_file = false) $this->__media->rename($bk_file, $local_filename . '.' . $extension, $this->tmp_pid); } // switch to optm - elseif ($this->tmp_type === self::TYPE_BATCH_SWITCH_OPTM) { + elseif ($this->tmp_type === self::TYPE_BATCH_SWITCH_OPTM || $this->tmp_type == 'optm') { + // self::debug('switch to optm ' . $bk_file); if (!$this->__media->info($bk_optm_file, $this->tmp_pid)) { return; } @@ -2093,13 +2111,9 @@ public function handler() self::start_async(); break; - /** - * Batch switch - * @since 1.6.3 - */ case self::TYPE_BATCH_SWITCH_ORI: case self::TYPE_BATCH_SWITCH_OPTM: - $this->_batch_switch($type); + $this->batch_switch($type); break; case substr($type, 0, 4) === 'webp': diff --git a/src/import.cls.php b/src/import.cls.php index 5a316a14f..614a62fe5 100644 --- a/src/import.cls.php +++ b/src/import.cls.php @@ -42,7 +42,7 @@ public function export($only_data_return = false) $data = array(); foreach ($raw_data as $k => $v) { - $data[] = json_encode(array($k, $v)); + $data[] = \json_encode(array($k, $v)); } $data = implode("\n\n", $data); @@ -76,7 +76,7 @@ public function import($file = false) { if (!$file) { if (empty($_FILES['ls_file']['name']) || substr($_FILES['ls_file']['name'], -5) != '.data' || empty($_FILES['ls_file']['tmp_name'])) { - Debug2::debug('Import: Failed to import, wront ls_file'); + Debug2::debug('Import: Failed to import, wrong ls_file'); $msg = __('Import failed due to file error.', 'litespeed-cache'); Admin_Display::error($msg); @@ -108,11 +108,11 @@ public function import($file = false) if (!$v) { continue; } - list($k, $v) = json_decode($v, true); + list($k, $v) = \json_decode($v, true); $ori_data[$k] = $v; } } else { - $ori_data = json_decode(base64_decode($data), true); + $ori_data = \json_decode(base64_decode($data), true); } } catch (\Exception $ex) { Debug2::debug('[Import] ❌ Failed to parse serialized data'); diff --git a/src/lang.cls.php b/src/lang.cls.php index b2d2dce46..7160dccd7 100644 --- a/src/lang.cls.php +++ b/src/lang.cls.php @@ -100,6 +100,7 @@ public static function title($id) self::O_CACHE_TTL_REST => __('Default REST TTL', 'litespeed-cache'), self::O_CACHE_TTL_STATUS => __('Default HTTP Status Code Page TTL', 'litespeed-cache'), self::O_CACHE_TTL_BROWSER => __('Browser Cache TTL', 'litespeed-cache'), + self::O_CACHE_AJAX_TTL => __('AJAX Cache TTL', 'litespeed-cache'), self::O_AUTO_UPGRADE => __('Automatically Upgrade', 'litespeed-cache'), self::O_GUEST => __('Guest Mode', 'litespeed-cache'), self::O_GUEST_OPTM => __('Guest Optimization', 'litespeed-cache'), @@ -108,7 +109,6 @@ public static function title($id) self::O_CACHE_COMMENTER => __('Cache Commenters', 'litespeed-cache'), self::O_CACHE_REST => __('Cache REST API', 'litespeed-cache'), self::O_CACHE_PAGE_LOGIN => __('Cache Login Page', 'litespeed-cache'), - self::O_CACHE_FAVICON => __('Cache favicon.ico', 'litespeed-cache'), self::O_CACHE_RES => __('Cache PHP Resources', 'litespeed-cache'), self::O_CACHE_MOBILE => __('Cache Mobile', 'litespeed-cache'), self::O_CACHE_MOBILE_RULES => __('List of Mobile User Agents', 'litespeed-cache'), @@ -153,6 +153,7 @@ public static function title($id) self::O_OPTM_JS_COMB_EXT_INL => __('JS Combine External and Inline', 'litespeed-cache'), self::O_OPTM_HTML_MIN => __('HTML Minify', 'litespeed-cache'), self::O_OPTM_HTML_LAZY => __('HTML Lazy Load Selectors', 'litespeed-cache'), + self::O_OPTM_HTML_SKIP_COMMENTS => __('HTML Keep Comments', 'litespeed-cache'), self::O_OPTM_CSS_ASYNC => __('Load CSS Asynchronously', 'litespeed-cache'), self::O_OPTM_CCSS_PER_URL => __('CCSS Per URL', 'litespeed-cache'), self::O_OPTM_CSS_ASYNC_INLINE => __('Inline CSS Async Lib', 'litespeed-cache'), @@ -184,7 +185,6 @@ public static function title($id) self::O_DISCUSS_AVATAR_CRON => __('Gravatar Cache Cron', 'litespeed-cache'), self::O_DISCUSS_AVATAR_CACHE_TTL => __('Gravatar Cache TTL', 'litespeed-cache'), - self::O_MEDIA_PRELOAD_FEATURED => __('Preload Featured Image', 'litespeed-cache'), self::O_MEDIA_LAZY => __('Lazy Load Images', 'litespeed-cache'), self::O_MEDIA_LAZY_EXC => __('Lazy Load Image Excludes', 'litespeed-cache'), self::O_MEDIA_LAZY_CLS_EXC => __('Lazy Load Image Class Name Excludes', 'litespeed-cache'), @@ -269,8 +269,7 @@ public static function title($id) self::O_DEBUG_IPS => __('Admin IPs', 'litespeed-cache'), self::O_DEBUG_LEVEL => __('Debug Level', 'litespeed-cache'), self::O_DEBUG_FILESIZE => __('Log File Size Limit', 'litespeed-cache'), - self::O_DEBUG_COOKIE => __('Log Cookies', 'litespeed-cache'), - self::O_DEBUG_COLLAPS_QS => __('Collapse Query Strings', 'litespeed-cache'), + self::O_DEBUG_COLLAPSE_QS => __('Collapse Query Strings', 'litespeed-cache'), self::O_DEBUG_INC => __('Debug URI Includes', 'litespeed-cache'), self::O_DEBUG_EXC => __('Debug URI Excludes', 'litespeed-cache'), self::O_DEBUG_EXC_STRINGS => __('Debug String Excludes', 'litespeed-cache'), diff --git a/src/localization.cls.php b/src/localization.cls.php index 455fd70a3..ba4aa70e9 100644 --- a/src/localization.cls.php +++ b/src/localization.cls.php @@ -51,7 +51,7 @@ public function serve_static($uri) $type = 'js'; $domain = $v; - // Try to parse space splitted value + // Try to parse space split value if (strpos($v, ' ')) { $v = explode(' ', $v); if (!empty($v[1])) { @@ -170,7 +170,7 @@ public function finalize($content) $type = 'js'; $domain = $v; - // Try to parse space splitted value + // Try to parse space split value if (strpos($v, ' ')) { $v = explode(' ', $v); if (!empty($v[1])) { diff --git a/src/media.cls.php b/src/media.cls.php index fd5a6b3a7..b80596d3b 100644 --- a/src/media.cls.php +++ b/src/media.cls.php @@ -22,6 +22,7 @@ class Media extends Root private $content; private $_wp_upload_dir; + private $_vpi_preload_list = array(); /** * Init @@ -84,16 +85,19 @@ public function finalize_head($content) global $wp_query; // - if ($this->conf(Base::O_MEDIA_PRELOAD_FEATURED) && $wp_query->is_single) { - $featured_image_url = get_the_post_thumbnail_url(); - if ($featured_image_url) { - self::debug('Append featured image to head: ' . $featured_image_url); - if ((defined('LITESPEED_GUEST_OPTM') || $this->conf(Base::O_IMG_OPTM_WEBP)) && $this->webp_support()) { - $featured_image_url = $this->replace_webp($featured_image_url) ?: $featured_image_url; - } - $content .= ''; // TODO: use imagesrcset + if ($this->_vpi_preload_list) { + foreach ($this->_vpi_preload_list as $v) { + $content .= ''; } } + // $featured_image_url = get_the_post_thumbnail_url(); + // if ($featured_image_url) { + // self::debug('Append featured image to head: ' . $featured_image_url); + // if ((defined('LITESPEED_GUEST_OPTM') || $this->conf(Base::O_IMG_OPTM_WEBP)) && $this->webp_support()) { + // $featured_image_url = $this->replace_webp($featured_image_url) ?: $featured_image_url; + // } + // } + // } return $content; } @@ -219,6 +223,7 @@ public function del($short_file_path, $post_id) */ public function rename($short_file_path, $short_file_path_new, $post_id) { + // self::debug('renaming ' . $short_file_path . ' -> ' . $short_file_path_new); $real_file = $this->_wp_upload_dir['basedir'] . '/' . $short_file_path; $real_file_new = $this->_wp_upload_dir['basedir'] . '/' . $short_file_path_new; @@ -524,6 +529,11 @@ private function _finalize() $cfg_trim_noscript = defined('LITESPEED_GUEST_OPTM') || $this->conf(Base::O_OPTM_NOSCRIPT_RM); $cfg_vpi = defined('LITESPEED_GUEST_OPTM') || $this->conf(Base::O_MEDIA_VPI); + // Preload VPI + if ($cfg_vpi) { + $this->_parse_img_for_preload(); + } + if ($cfg_lazy) { if ($cfg_vpi) { add_filter('litespeed_media_lazy_img_excludes', array($this->cls('Metabox'), 'lazy_img_excludes')); @@ -578,6 +588,54 @@ private function _finalize() } } + /** + * Parse img src for VPI preload only + * Note: Didn't reuse the _parse_img() bcoz it contains parent cls replacement and other logic which is not needed for preload + * + * @since 6.2 + */ + private function _parse_img_for_preload() + { + // Load VPI setting + $is_mobile = $this->_separate_mobile(); + $vpi_files = $this->cls('Metabox')->setting($is_mobile ? 'litespeed_vpi_list_mobile' : 'litespeed_vpi_list'); + if ($vpi_files) { + $vpi_files = Utility::sanitize_lines($vpi_files, 'basename'); + } + if (!$vpi_files) { + return; + } + + $content = preg_replace(array('##sU', '#]*)>.*#isU'), '', $this->content); + preg_match_all('#]+)/?>#isU', $content, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $attrs = Utility::parse_attr($match[1]); + + if (empty($attrs['src'])) { + continue; + } + + if (strpos($attrs['src'], 'base64') !== false || substr($attrs['src'], 0, 5) === 'data:') { + Debug2::debug2('[Media] lazyload bypassed base64 img'); + continue; + } + + if (strpos($attrs['src'], '{') !== false) { + Debug2::debug2('[Media] image src has {} ' . $attrs['src']); + continue; + } + + // If the src contains VPI filename, then preload it + if (!Utility::str_hit_array($attrs['src'], $vpi_files)) { + continue; + } + + Debug2::debug2('[Media] VPI preload found and matched: ' . $attrs['src']); + + $this->_vpi_preload_list[] = $attrs['src']; + } + } + /** * Parse img src * @@ -601,7 +659,15 @@ private function _parse_img() $html_list = array(); $placeholder_list = array(); - $content = preg_replace(array('##sU', '#]*)>.*#isU'), '', $this->content); + $content = preg_replace( + array( + '##sU', + '#]*)>.*#isU', + '#]*)>.*#isU', // Added to remove warning of file not found when image size detection is turned ON. + ), + '', + $this->content + ); /** * Exclude parent classes * @since 3.0 @@ -692,7 +758,7 @@ private function _parse_img() $attrs['width'] = $ori_width; $attrs['height'] = $ori_height; - $new_html = preg_replace('#\s+(width|height)=(["\'])[^\2]*\2#', '', $match[0]); + $new_html = preg_replace('#\s+(width|height)=(["\'])[^\2]*?\2#', '', $match[0]); $new_html = preg_replace('#content = str_replace($match[0], $new_html, $this->content); @@ -883,6 +949,9 @@ public function replace_background_webp($content) { Debug2::debug2('[Media] Start replacing bakcground WebP.'); + // Handle Elementors data-settings json encode background-images + $content = $this->replace_urls_in_json($content); + // preg_match_all( '#background-image:(\s*)url\((.*)\)#iU', $content, $matches ); preg_match_all('#url\(([^)]+)\)#iU', $content, $matches); foreach ($matches[1] as $k => $url) { @@ -897,7 +966,7 @@ public function replace_background_webp($content) */ $url = trim($url, '\'"'); - // Fix Elementors Slideshow unusal background images like style="background-image: url("https://xxxx.png");" + // Fix Elementors Slideshow unusual background images like style="background-image: url("https://xxxx.png");" if (strpos($url, '"') === 0 && substr($url, -6) == '"') { $url = substr($url, 6, -6); } @@ -914,6 +983,59 @@ public function replace_background_webp($content) return $content; } + /** + * Replace images in json data settings attributes + * + * @since 6.2 + */ + public function replace_urls_in_json($content) + { + $pattern = '/data-settings="(.*?)"/i'; + $parent_class = $this; + + preg_match_all($pattern, $content, $matches, PREG_SET_ORDER); + + foreach ($matches as $match) { + // Check if the string contains HTML entities + $isEncoded = preg_match('/"|<|>|&|'/', $match[1]); + + // Decode HTML entities in the JSON string + $jsonString = html_entity_decode($match[1]); + + $jsonData = \json_decode($jsonString, true); + + if (json_last_error() === JSON_ERROR_NONE) { + $did_webp_replace = false; + + array_walk_recursive($jsonData, function (&$item, $key) use (&$did_webp_replace, $parent_class) { + if ($key == 'url') { + $item_image = $parent_class->replace_webp($item); + if ($item_image) { + $item = $item_image; + + $did_webp_replace = true; + } + } + }); + + if ($did_webp_replace) { + // Re-encode the modified array back to a JSON string + $newJsonString = \json_encode($jsonData); + + // Re-encode the JSON string to HTML entities only if it was originally encoded + if ($isEncoded) { + $newJsonString = htmlspecialchars($newJsonString, ENT_QUOTES | 0); // ENT_HTML401 is for PHPv5.4+ + } + + // Replace the old JSON string in the content with the new, modified JSON string + $content = str_replace($match[1], $newJsonString, $content); + } + } + } + + return $content; + } + /** * Replace internal image src to webp * diff --git a/src/metabox.cls.php b/src/metabox.cls.php index 7e877e6f9..266bb1db9 100644 --- a/src/metabox.cls.php +++ b/src/metabox.cls.php @@ -47,7 +47,7 @@ public function register_settings() } /** - * Regsiter meta box + * Register meta box * @since 4.7 */ public function add_meta_boxes($post_type) diff --git a/src/object-cache.cls.php b/src/object-cache.cls.php index 3c457e0ef..fdf135be4 100644 --- a/src/object-cache.cls.php +++ b/src/object-cache.cls.php @@ -1,4 +1,5 @@ */ + namespace LiteSpeed; + defined('WPINC') || exit(); require_once dirname(__DIR__) . '/autoload.php'; class Object_Cache extends Root { + const O_DEBUG = 'debug'; const O_OBJECT = 'object'; const O_OBJECT_KIND = 'object-kind'; const O_OBJECT_HOST = 'object-host'; @@ -29,6 +33,7 @@ class Object_Cache extends Root const O_OBJECT_NON_PERSISTENT_GROUPS = 'object-non_persistent_groups'; private $_conn; + private $_cfg_debug; private $_cfg_enabled; private $_cfg_method; private $_cfg_host; @@ -56,8 +61,6 @@ class Object_Cache extends Root */ public function __construct($cfg = false) { - defined('LSCWP_LOG') && Debug2::debug2('[Object] init'); - if ($cfg) { if (!is_array($cfg[Base::O_OBJECT_GLOBAL_GROUPS])) { $cfg[Base::O_OBJECT_GLOBAL_GROUPS] = explode("\n", $cfg[Base::O_OBJECT_GLOBAL_GROUPS]); @@ -65,6 +68,7 @@ public function __construct($cfg = false) if (!is_array($cfg[Base::O_OBJECT_NON_PERSISTENT_GROUPS])) { $cfg[Base::O_OBJECT_NON_PERSISTENT_GROUPS] = explode("\n", $cfg[Base::O_OBJECT_NON_PERSISTENT_GROUPS]); } + $this->_cfg_debug = $cfg[Base::O_DEBUG] ? $cfg[Base::O_DEBUG] : false; $this->_cfg_method = $cfg[Base::O_OBJECT_KIND] ? true : false; $this->_cfg_host = $cfg[Base::O_OBJECT_HOST]; $this->_cfg_port = $cfg[Base::O_OBJECT_PORT]; @@ -83,10 +87,11 @@ public function __construct($cfg = false) } $this->_cfg_enabled = $cfg[Base::O_OBJECT] && class_exists($this->_oc_driver) && $this->_cfg_host; - defined('LSCWP_LOG') && Debug2::debug('[Object] init with cfg result : ', $this->_cfg_enabled); + $this->debug_oc('init with cfg result : ', $this->_cfg_enabled); } // If OC is OFF, will hit here to init OC after conf initialized elseif (defined('LITESPEED_CONF_LOADED')) { + $this->_cfg_debug = $this->conf(Base::O_DEBUG) ? $this->conf(Base::O_DEBUG) : false; $this->_cfg_method = $this->conf(Base::O_OBJECT_KIND) ? true : false; $this->_cfg_host = $this->conf(Base::O_OBJECT_HOST); $this->_cfg_port = $this->conf(Base::O_OBJECT_PORT); @@ -107,8 +112,9 @@ public function __construct($cfg = false) } elseif (defined('self::CONF_FILE') && file_exists(WP_CONTENT_DIR . '/' . self::CONF_FILE)) { // Get cfg from _data_file // Use self::const to avoid loading more classes - $cfg = json_decode(file_get_contents(WP_CONTENT_DIR . '/' . self::CONF_FILE), true); + $cfg = \json_decode(file_get_contents(WP_CONTENT_DIR . '/' . self::CONF_FILE), true); if (!empty($cfg[self::O_OBJECT_HOST])) { + $this->_cfg_debug = !empty($cfg[Base::O_DEBUG]) ? $cfg[Base::O_DEBUG] : false; $this->_cfg_method = !empty($cfg[self::O_OBJECT_KIND]) ? $cfg[self::O_OBJECT_KIND] : false; $this->_cfg_host = $cfg[self::O_OBJECT_HOST]; $this->_cfg_port = $cfg[self::O_OBJECT_PORT]; @@ -134,6 +140,35 @@ public function __construct($cfg = false) } } + /** + * Add debug. + * + * @since 6.3 + * @access private + */ + private function debug_oc($text, $show_error = false) + { + if (defined('LSCWP_LOG')) { + Debug2::debug($text); + + return; + } + + if (!$show_error && !$this->_cfg_debug) { + return; + } + + $LITESPEED_DATA_FOLDER = defined('LITESPEED_DATA_FOLDER') ? LITESPEED_DATA_FOLDER : 'litespeed'; + $LSCWP_CONTENT_DIR = defined('LSCWP_CONTENT_DIR') ? LSCWP_CONTENT_DIR : WP_CONTENT_DIR; + $LITESPEED_STATIC_DIR = $LSCWP_CONTENT_DIR . '/' . $LITESPEED_DATA_FOLDER; + $log_path_prefix = $LITESPEED_STATIC_DIR . '/debug/'; + $log_file = $log_path_prefix . Debug2::FilePath('debug'); + + if (file_exists($log_path_prefix . 'index.php') && file_exists($log_file)) { + error_log(gmdate('m/d/y H:i:s') . ' - OC - ' . $text . PHP_EOL, 3, $log_file); + } + } + /** * Get `Store Transients` setting value * @@ -172,7 +207,7 @@ public function update_file($options) // Update cls file if (!file_exists($_oc_wp_file) || md5_file($_oc_wp_file) !== md5_file($_oc_ori_file)) { - defined('LSCWP_LOG') && Debug2::debug('[Object] copying object-cache.php file to ' . $_oc_wp_file); + $this->debug_oc('copying object-cache.php file to ' . $_oc_wp_file); copy($_oc_ori_file, $_oc_wp_file); $changed = true; @@ -199,7 +234,7 @@ public function del_file() $_oc_wp_file = WP_CONTENT_DIR . '/object-cache.php'; if (file_exists($_oc_wp_file) && md5_file($_oc_wp_file) === md5_file($_oc_ori_file)) { - defined('LSCWP_LOG') && Debug2::debug('[Object] removing ' . $_oc_wp_file); + $this->debug_oc('removing ' . $_oc_wp_file); unlink($_oc_wp_file); } } @@ -223,11 +258,10 @@ public function test_connection() */ private function _reconnect($cfg) { - defined('LSCWP_LOG') && Debug2::debug('[Object] Reconnecting'); - // error_log( 'Object: reconnect !' ); + $this->debug_oc('Reconnecting'); if (isset($this->_conn)) { - // error_log( 'Object: Quiting existing connection!' ); - defined('LSCWP_LOG') && Debug2::debug('[Object] Quiting existing connection'); + // error_log( 'Object: Quitting existing connection!' ); + $this->debug_oc('Quitting existing connection'); $this->flush(); $this->_conn = null; $this->cls(false, true); @@ -261,7 +295,8 @@ private function _connect() return false; } - defined('LSCWP_LOG') && Debug2::debug('[Object] connecting to ' . $this->_cfg_host . ':' . $this->_cfg_port); + $this->debug_oc('Init ' . $this->_oc_driver . ' connection'); + $this->debug_oc('connecting to ' . $this->_cfg_host . ':' . $this->_cfg_port); $failed = false; /** @@ -271,8 +306,6 @@ private function _connect() * @see https://github.com/phpredis/phpredis/#example-1 */ if ($this->_oc_driver == 'Redis') { - defined('LSCWP_LOG') && Debug2::debug('[Object] Init ' . $this->_oc_driver . ' connection'); - set_error_handler('litespeed_exception_handler'); try { $this->_conn = new \Redis(); @@ -293,7 +326,11 @@ private function _connect() } if ($this->_cfg_pswd) { - $this->_conn->auth($this->_cfg_pswd); + if ($this->_cfg_user) { + $this->_conn->auth(array($this->_cfg_user, $this->_cfg_pswd)); + } else { + $this->_conn->auth($this->_cfg_pswd); + } } if ($this->_cfg_db) { @@ -306,28 +343,25 @@ private function _connect() $failed = true; } } catch (\Exception $e) { - error_log($e->getMessage()); + $this->debug_oc('Redis connect exception: ' . $e->getMessage(), true); $failed = true; } catch (\ErrorException $e) { - error_log($e->getMessage()); + $this->debug_oc('Redis connect error: ' . $e->getMessage(), true); $failed = true; } restore_error_handler(); - } /** - * Connect to Memcached - */ else { - defined('LSCWP_LOG') && Debug2::debug('[Object] Init ' . $this->_oc_driver . ' connection'); + } else { // Connect to Memcached if ($this->_cfg_persistent) { $this->_conn = new \Memcached($this->_get_mem_id()); // Check memcached persistent connection if ($this->_validate_mem_server()) { // error_log( 'Object: _validate_mem_server' ); - defined('LSCWP_LOG') && Debug2::debug('[Object] Got persistent ' . $this->_oc_driver . ' connection'); + $this->debug_oc('Got persistent ' . $this->_oc_driver . ' connection'); return true; } - defined('LSCWP_LOG') && Debug2::debug('[Object] No persistent ' . $this->_oc_driver . ' server list!'); + $this->debug_oc('No persistent ' . $this->_oc_driver . ' server list!'); } else { // error_log( 'Object: new memcached!' ); $this->_conn = new \Memcached(); @@ -354,7 +388,7 @@ private function _connect() // If failed to connect if ($failed) { - defined('LSCWP_LOG') && Debug2::debug('[Object] Failed to connect ' . $this->_oc_driver . ' server!'); + $this->debug_oc('❌ Failed to connect ' . $this->_oc_driver . ' server!', true); $this->_conn = null; $this->_cfg_enabled = false; !defined('LITESPEED_OC_FAILURE') && define('LITESPEED_OC_FAILURE', true); @@ -362,7 +396,7 @@ private function _connect() return false; } - defined('LSCWP_LOG') && Debug2::debug2('[Object] Connected'); + $this->debug_oc('Connected'); return true; } @@ -428,8 +462,6 @@ public function get($key) return null; } - // defined( 'LSCWP_LOG' ) && Debug2::debug2( '[Object] get ' . $key ); - $res = $this->_conn->get($key); return $res; @@ -458,11 +490,6 @@ public function set($key, $data, $expire) if (!$this->_connect()) { return null; } - - // defined( 'LSCWP_LOG' ) && Debug2::debug2( '[Object] set ' . $key ); - - // error_log( 'Object: set ' . $key ); - $ttl = $expire ?: $this->_cfg_life; if ($this->_oc_driver == 'Redis') { @@ -471,7 +498,7 @@ public function set($key, $data, $expire) } catch (\RedisException $ex) { $res = false; $msg = sprintf(__('Redis encountered a fatal error: %s (code: %d)', 'litespeed-cache'), $ex->getMessage(), $ex->getCode()); - Debug2::debug('[Object] ' . $msg); + $this->debug_oc($msg); Admin_Display::error($msg); } } else { @@ -511,8 +538,6 @@ public function delete($key) return null; } - // defined( 'LSCWP_LOG' ) && Debug2::debug2( '[Object] delete ' . $key ); - if ($this->_oc_driver == 'Redis') { $res = $this->_conn->del($key); } else { @@ -531,7 +556,7 @@ public function delete($key) public function flush() { if (!$this->_cfg_enabled) { - defined('LSCWP_LOG') && Debug2::debug('[Object] bypass flushing'); + $this->debug_oc('bypass flushing'); return null; } @@ -539,7 +564,7 @@ public function flush() return null; } - defined('LSCWP_LOG') && Debug2::debug('[Object] flush!'); + $this->debug_oc('flush!'); if ($this->_oc_driver == 'Redis') { $res = $this->_conn->flushDb(); diff --git a/src/optimize.cls.php b/src/optimize.cls.php index d680cefad..c31f73982 100644 --- a/src/optimize.cls.php +++ b/src/optimize.cls.php @@ -846,7 +846,7 @@ private function _build_hash_url($src_list, $file_type = 'css') Tag::add(Tag::TYPE_MIN . '.' . $filename); $qs_hash = substr(md5(self::get_option(self::ITEM_TIMESTAMP_PURGE_CSS)), -5); - // As filename is alreay realted to filecon md5, no need QS anymore + // As filename is already related to filecon md5, no need QS anymore $filepath_prefix = $this->_build_filepath_prefix($type); return LITESPEED_STATIC_URL . $filepath_prefix . $filename . '?ver=' . $qs_hash; } @@ -1089,7 +1089,7 @@ private function _parse_css() } // Check if need to inline this css file - if (Utility::str_hit_array($attrs['href'], $ucss_file_exc_inline)) { + if ($this->conf(self::O_OPTM_UCSS) && Utility::str_hit_array($attrs['href'], $ucss_file_exc_inline)) { Debug2::debug('[Optm] ucss_file_exc_inline hit ' . $attrs['href']); // Replace this css to inline from orig html $inline_script = ''; @@ -1227,7 +1227,7 @@ private function _async_css($ori) private function _js_defer($ori, $src) { if (strpos($ori, ' async') !== false) { - $ori = str_replace(' async', '', $ori); + $ori = preg_replace('# async(?:=([\'"])(?:[^\1]+)\1)?#isU', '', $ori); } if (strpos($ori, 'defer') !== false) { diff --git a/src/optimizer.cls.php b/src/optimizer.cls.php index 662c6b680..412d922f4 100644 --- a/src/optimizer.cls.php +++ b/src/optimizer.cls.php @@ -44,6 +44,11 @@ public function html_min($content, $force_inline_minify = false) $options['jsMinifier'] = __CLASS__ . '::minify_js'; } + $skip_comments = $this->conf(Base::O_OPTM_HTML_SKIP_COMMENTS); + if ($skip_comments) { + $options['skipComments'] = $skip_comments; + } + /** * Added exception capture when minify * @since 2.2.3 @@ -51,6 +56,11 @@ public function html_min($content, $force_inline_minify = false) try { $obj = new Lib\HTML_MIN($content, $options); $content_final = $obj->process(); + // check if content from minification is empty + if ($content_final == '') { + Debug2::debug('Failed to minify HTML: HTML minification resulted in empty HTML'); + return $content; + } if (!defined('LSCACHE_ESI_SILENCE')) { $content_final .= "\n" . ''; } diff --git a/src/placeholder.cls.php b/src/placeholder.cls.php index 48ac70fe4..307f1eae6 100644 --- a/src/placeholder.cls.php +++ b/src/placeholder.cls.php @@ -392,7 +392,7 @@ private function _generate_placeholder($raw_size_and_src, $from_cron = false) $file = $this->_placeholder_realpath($src, $size); - // Local generate SVG to serve ( Repeatly doing this here to remove stored cron queue in case the setting _conf_lqip is changed ) + // Local generate SVG to serve ( Repeatedly doing this here to remove stored cron queue in case the setting _conf_lqip is changed ) if (!$this->_conf_lqip || !$this->_lqip_size_check($size)) { $data = $this->_generate_placeholder_locally($size); } else { diff --git a/src/preset.cls.php b/src/preset.cls.php index e10d676c1..d6a74eb91 100644 --- a/src/preset.cls.php +++ b/src/preset.cls.php @@ -218,11 +218,11 @@ function import_file($path) if (empty($line)) { continue; } - list($key, $value) = json_decode($line, true); + list($key, $value) = \json_decode($line, true); $parsed[$key] = $value; } } else { - $parsed = json_decode(base64_decode($contents), true); + $parsed = \json_decode(base64_decode($contents), true); } } catch (\Exception $ex) { Debug2::debug('[Preset] ❌ Failed to parse serialized data'); diff --git a/src/purge.cls.php b/src/purge.cls.php index 32574e4ab..786d46c06 100644 --- a/src/purge.cls.php +++ b/src/purge.cls.php @@ -1118,7 +1118,7 @@ private function _append_prefix($purge_tags, $is_private = false) } /** - * Check if this purge blongs to a subsite purge + * Check if this purge belongs to a subsite purge * * @since 4.0 */ diff --git a/src/report.cls.php b/src/report.cls.php index 3983b64b3..42ea60004 100644 --- a/src/report.cls.php +++ b/src/report.cls.php @@ -1,4 +1,5 @@ */ + namespace LiteSpeed; defined('WPINC') || exit(); @@ -182,7 +184,7 @@ private function build_environment_report($server, $options, $extras = array(), $buf = $this->_format_report_section('Server Variables', $server_vars); - $buf .= $this->_format_report_section('Wordpress Specific Extras', $extras); + $buf .= $this->_format_report_section('WordPress Specific Extras', $extras); $buf .= $this->_format_report_section('LSCache Plugin Options', $options); @@ -230,6 +232,8 @@ private function _format_report_section($section_header, $section) if (!is_string($v)) { $v = var_export($v, true); + } else { + $v = esc_html($v); } $buf .= $v; diff --git a/src/rest.cls.php b/src/rest.cls.php index cbb65fbf1..0a9f7cf72 100644 --- a/src/rest.cls.php +++ b/src/rest.cls.php @@ -72,10 +72,10 @@ public function rest_api_init() 'callback' => array($this, 'token_get'), 'permission_callback' => array($this, 'is_from_cloud'), )); - register_rest_route('litespeed/v1', '/ping', array( - 'methods' => 'GET', + register_rest_route('litespeed/v3', '/ping', array( + 'methods' => 'POST', 'callback' => array($this, 'ping'), - 'permission_callback' => '__return_true', + 'permission_callback' => array($this, 'is_from_cloud'), )); // API key callback notification @@ -147,8 +147,8 @@ public function toggle_crawler_state() */ public function is_from_cloud() { - return true; - // return $this->cls( 'Cloud' )->is_from_cloud(); + // return true; + return $this->cls('Cloud')->is_from_cloud(); } /** @@ -168,7 +168,7 @@ public function token_get() */ public function ping() { - return Cloud::ok(array('ver' => Core::VER)); + return $this->cls('Cloud')->ping(); } /** @@ -359,6 +359,10 @@ public function is_rest($url = false) // Debug2::debug( '[Util] is_rest check [base] ', $rest_url ); // Debug2::debug( '[Util] is_rest check [curr] ', $current_url ); // Debug2::debug( '[Util] is_rest check [curr2] ', wp_parse_url( add_query_arg( array( ) ) ) ); - return strpos($current_url['path'], $rest_url['path']) === 0; + if ($current_url !== false && !empty($current_url['path']) && $rest_url !== false && !empty($rest_url['path'])) { + return strpos($current_url['path'], $rest_url['path']) === 0; + } + + return false; } } diff --git a/src/root.cls.php b/src/root.cls.php index 6a53c23f6..9763c3614 100644 --- a/src/root.cls.php +++ b/src/root.cls.php @@ -155,7 +155,7 @@ public function load_queue($type) $queue = array(); if (file_exists($static_path)) { - $queue = json_decode(file_get_contents($static_path), true) ?: array(); + $queue = \json_decode(file_get_contents($static_path), true) ?: array(); } return $queue; @@ -172,7 +172,7 @@ public function save_queue($type, $list) $filepath_prefix = $this->_build_filepath_prefix($type); $static_path = LITESPEED_STATIC_DIR . $filepath_prefix . '.litespeed_conf.dat'; - $data = json_encode($list); + $data = \json_encode($list); File::save($static_path, $data, true); } @@ -367,7 +367,7 @@ public function conf($id, $ori = false) } } - // Network orignal value will be in _network_options + // Network original value will be in _network_options if (!is_network_admin() || !$this->has_network_conf($id)) { return self::$_options[$id]; } @@ -540,7 +540,7 @@ public static function update_site_option($id, $v) private static function _maybe_decode($v) { if (!is_array($v)) { - $v2 = json_decode($v, true); + $v2 = \json_decode($v, true); if ($v2 !== null) { $v = $v2; } @@ -556,7 +556,7 @@ private static function _maybe_decode($v) private static function _maybe_encode($v) { if (is_array($v)) { - $v = json_encode($v) ?: $v; // Non utf-8 encoded value will get failed, then used ori value + $v = \json_encode($v) ?: $v; // Non utf-8 encoded value will get failed, then used ori value } return $v; } diff --git a/src/router.cls.php b/src/router.cls.php index fc72ca38c..a05013d3b 100644 --- a/src/router.cls.php +++ b/src/router.cls.php @@ -1,4 +1,5 @@ conf(Base::O_CRAWLER_RUN_DURATION) && $_COOKIE['litespeed_hash'] == $hash_data['hash']) { + if (empty($hash_data['ip'])) { + $hash_data['ip'] = self::get_ip(); + self::update_option(self::ITEM_HASH, $hash_data); + } else { + $server_ips = apply_filters('litespeed_server_ips', array($hash_data['ip'])); + if (!self::ip_access($server_ips)) { + self::debug('WARNING: role simulator ip check failed [db ip] ' . $hash_data['ip'], $server_ips); + return; + } + } + wp_set_current_user($hash_data['uid']); + return; + } + } } - $role_uid = $_COOKIE['litespeed_role']; - Debug2::debug('[Router] role simulate litespeed_role uid ' . $role_uid); + self::debug('WARNING: role simulator hash not match'); + } - wp_set_current_user($role_uid); + /** + * Get a short ttl hash (2mins) + * + * @since 6.4 + */ + public function get_flash_hash($uid) + { + $hash_data = self::get_option(self::ITEM_FLASH_HASH, array()); + if ($hash_data && is_array($hash_data) && !empty($hash_data['hash']) && !empty($hash_data['ts'])) { + if (time() - $hash_data['ts'] < 60) { + return $hash_data['hash']; + } + } + + $hash = Str::rrand(32); + self::update_option(self::ITEM_FLASH_HASH, array('hash' => $hash, 'ts' => time(), 'uid' => $uid)); + return $hash; } /** @@ -270,16 +318,11 @@ public function is_role_simulation() * * @since 3.3 */ - public static function get_hash() + public function get_hash($uid) { - // Reuse previous hash if existed - $hash = self::get_option(self::ITEM_HASH); - if ($hash) { - return $hash; - } - - $hash = Str::rrand(6); - self::update_option(self::ITEM_HASH, $hash); + // As this is called only when starting crawling, not per page, no need to reuse + $hash = Str::rrand(32); + self::update_option(self::ITEM_HASH, array('hash' => $hash, 'ts' => time(), 'uid' => $uid)); return $hash; } @@ -540,8 +583,7 @@ private function verify_action() $_can_option = current_user_can('manage_options'); switch ($action) { - // Save network settings - case self::ACTION_SAVE_SETTINGS_NETWORK: + case self::ACTION_SAVE_SETTINGS_NETWORK: // Save network settings if ($_can_network_option) { self::$_action = $action; } @@ -561,7 +603,7 @@ private function verify_action() return; case Core::ACTION_PURGE_EMPTYCACHE: // todo: moved to purge.cls type action - if (defined('LITESPEED_ON') && ($_can_network_option || (!$_is_multisite && $_can_option))) { + if ((defined('LITESPEED_ON') || $_is_network_admin) && ($_can_network_option || (!$_is_multisite && $_can_option))) { self::$_action = $action; } return; @@ -617,7 +659,7 @@ private function verify_action() return; default: - Debug2::debug('[Router] LSCWP_CTRL match falied: ' . $action); + Debug2::debug('[Router] LSCWP_CTRL match failed: ' . $action); return; } } diff --git a/src/task.cls.php b/src/task.cls.php index 55d10504f..adcf9fa0a 100644 --- a/src/task.cls.php +++ b/src/task.cls.php @@ -27,8 +27,8 @@ class Task extends Root private static $_guest_options = array(Base::O_OPTM_CSS_ASYNC, Base::O_OPTM_UCSS, Base::O_MEDIA_VPI); - const FITLER_CRAWLER = 'litespeed_crawl_filter'; - const FITLER = 'litespeed_filter'; + const FILTER_CRAWLER = 'litespeed_crawl_filter'; + const FILTER = 'litespeed_filter'; /** * Keep all tasks in cron @@ -62,7 +62,7 @@ public function init() if (!wp_next_scheduled($trigger['name'])) { self::debug('Cron hook register [name] ' . $trigger['name']); - wp_schedule_event(time(), $id == Base::O_CRAWLER ? self::FITLER_CRAWLER : self::FITLER, $trigger['name']); + wp_schedule_event(time(), $id == Base::O_CRAWLER ? self::FILTER_CRAWLER : self::FILTER, $trigger['name']); } add_action($trigger['name'], $trigger['hook']); @@ -76,8 +76,18 @@ public function init() */ public static function async_litespeed_handler() { - $type = Router::verify_type(); + $hash_data = self::get_option('async_call-hash', array()); + if (!$hash_data || !is_array($hash_data) || empty($hash_data['hash']) || empty($hash_data['ts'])) { + self::debug('async_litespeed_handler no hash data', $hash_data); + return; + } + if (time() - $hash_data['ts'] > 120 || empty($_GET['nonce']) || $_GET['nonce'] != $hash_data['hash']) { + self::debug('async_litespeed_handler nonce mismatch'); + return; + } + self::delete_option('async_call-hash'); + $type = Router::verify_type(); self::debug('type=' . $type); // Don't lock up other requests while processing @@ -106,6 +116,8 @@ public static function async_litespeed_handler() */ public static function async_call($type) { + $hash = Str::rrand(32); + self::update_option('async_call-hash', array('hash' => $hash, 'ts' => time())); $args = array( 'timeout' => 0.01, 'blocking' => false, @@ -114,7 +126,7 @@ public static function async_call($type) ); $qs = array( 'action' => 'async_litespeed', - 'nonce' => wp_create_nonce('async_litespeed'), + 'nonce' => $hash, Router::TYPE => $type, ); $url = add_query_arg($qs, admin_url('admin-ajax.php')); @@ -171,8 +183,8 @@ public function try_clean($id) */ public function lscache_cron_filter($schedules) { - if (!array_key_exists(self::FITLER, $schedules)) { - $schedules[self::FITLER] = array( + if (!array_key_exists(self::FILTER, $schedules)) { + $schedules[self::FILTER] = array( 'interval' => 60, 'display' => __('Every Minute', 'litespeed-cache'), ); @@ -190,9 +202,9 @@ public function lscache_cron_filter_crawler($schedules) { $interval = $this->conf(Base::O_CRAWLER_RUN_INTERVAL); // $wp_schedules = wp_get_schedules(); - if (!array_key_exists(self::FITLER_CRAWLER, $schedules)) { + if (!array_key_exists(self::FILTER_CRAWLER, $schedules)) { // self::debug('Crawler cron log: cron filter '.$interval.' added'); - $schedules[self::FITLER_CRAWLER] = array( + $schedules[self::FILTER_CRAWLER] = array( 'interval' => $interval, 'display' => __('LiteSpeed Crawler Cron', 'litespeed-cache'), ); diff --git a/src/ucss.cls.php b/src/ucss.cls.php index 4118f6a5a..43789744a 100644 --- a/src/ucss.cls.php +++ b/src/ucss.cls.php @@ -501,7 +501,7 @@ private function _filter_whitelist() */ public function notify() { - $post_data = json_decode(file_get_contents('php://input'), true); + $post_data = \json_decode(file_get_contents('php://input'), true); if (is_null($post_data)) { $post_data = $_POST; } diff --git a/src/utility.cls.php b/src/utility.cls.php index 6860b9340..622552ff9 100644 --- a/src/utility.cls.php +++ b/src/utility.cls.php @@ -188,7 +188,7 @@ public static function ping($domain) * @since 1.6.5 * @access public */ - public static function readable_time($seconds_or_timestamp, $timeout = 3600, $forword = false) + public static function readable_time($seconds_or_timestamp, $timeout = 3600, $forward = false) { if (strlen($seconds_or_timestamp) == 10) { $seconds = time() - $seconds_or_timestamp; @@ -232,10 +232,10 @@ public static function readable_time($seconds_or_timestamp, $timeout = 3600, $fo } if (!$res) { - return $forword ? __('right now', 'litespeed-cache') : __('just now', 'litespeed-cache'); + return $forward ? __('right now', 'litespeed-cache') : __('just now', 'litespeed-cache'); } - $res = $forword ? $res : sprintf(__(' %s ago', 'litespeed-cache'), $res); + $res = $forward ? $res : sprintf(__(' %s ago', 'litespeed-cache'), $res); return $res; } @@ -252,7 +252,7 @@ public static function arr2str($arr) return $arr; } - return base64_encode(json_encode($arr)); + return base64_encode(\json_encode($arr)); } /** @@ -615,7 +615,7 @@ public static function sanitize_lines($arr, $type = null) } if (in_array('trailingslash', $types)) { - $arr = array_map('trailingslashit', $arr); // Append trailing slach, `https://example.com` -> `https://example.com/` + $arr = array_map('trailingslashit', $arr); // Append trailing slash, `https://example.com` -> `https://example.com/` $changed = true; } diff --git a/src/vary.cls.php b/src/vary.cls.php index ed0526c18..962303adb 100644 --- a/src/vary.cls.php +++ b/src/vary.cls.php @@ -171,7 +171,7 @@ private function _maybe_guest_mode() // If is the request to update vary, then no guest // Don't need anymore as it is always ajax call - // Still keep it in case some WP blocked the lightweigh guest vary update script, WP can still update the vary + // Still keep it in case some WP blocked the lightweight guest vary update script, WP can still update the vary if (!empty($_GET['litespeed_guest'])) { return; } @@ -213,7 +213,7 @@ public function update_guest_vary() Debug2::debug('[Vary] Will update guest vary in finalize'); // return json - echo json_encode(array('reload' => 'yes')); + echo \json_encode(array('reload' => 'yes')); exit(); } @@ -714,7 +714,7 @@ private function _finalize_curr_vary_cookies($values_json = false) $cookies[$k] = $values_json ? $this->_get_cookie_val($v) : 'cookie=' . $v; } - return $values_json ? json_encode($cookies) : $cookies; + return $values_json ? \json_encode($cookies) : $cookies; } /** diff --git a/src/vpi.cls.php b/src/vpi.cls.php index c1656169e..238182416 100644 --- a/src/vpi.cls.php +++ b/src/vpi.cls.php @@ -88,7 +88,7 @@ public function add_to_queue() */ public function notify() { - $post_data = json_decode(file_get_contents('php://input'), true); + $post_data = \json_decode(file_get_contents('php://input'), true); if (is_null($post_data)) { $post_data = $_POST; } diff --git a/thirdparty/perfmatters.cls.php b/thirdparty/perfmatters.cls.php index 84a283f03..fe7b846a4 100644 --- a/thirdparty/perfmatters.cls.php +++ b/thirdparty/perfmatters.cls.php @@ -1,10 +1,13 @@ widgets['WC_Widget_Recent_Reviews'])) { + return; + } + $recent_reviews = $wp_widget_factory->widgets['WC_Widget_Recent_Reviews']; if (!is_null($recent_reviews)) { do_action('litespeed_tag_add_widget', $recent_reviews->id); diff --git a/tpl/banner/cloud_news.tpl.php b/tpl/banner/cloud_news.tpl.php index 049c66746..07a63e81b 100644 --- a/tpl/banner/cloud_news.tpl.php +++ b/tpl/banner/cloud_news.tpl.php @@ -11,7 +11,7 @@

_summary[ 'news.title' ] ; ?>

-

+

_summary[ 'news.content' ]; ?>

diff --git a/tpl/banner/new_version.php b/tpl/banner/new_version.php index 9773754c5..d963f652e 100644 --- a/tpl/banner/new_version.php +++ b/tpl/banner/new_version.php @@ -1,43 +1,45 @@ conf( Base::O_AUTO_UPGRADE ) ) { +if ($this->conf(Base::O_AUTO_UPGRADE)) { return; } -$current = get_site_transient( 'update_plugins' ); -if ( ! isset( $current->response[ Core::PLUGIN_FILE ] ) ) { +$current = get_site_transient('update_plugins'); +if (!isset($current->response[Core::PLUGIN_FILE])) { return; } -$last_check = empty( $this->_summary[ 'new_version.last_check' ] ) ? 0 : $this->_summary[ 'new_version.last_check' ]; +$last_check = empty($this->_summary['new_version.last_check']) ? 0 : $this->_summary['new_version.last_check']; // Check once in a half day -if ( time() - $last_check > 43200 ) { - Admin_Display::save_summary( array( 'new_version.last_check' => time() ) ); +if (time() - $last_check > 43200) { + GUI::save_summary(array('new_version.last_check' => time())); // Detect version - $auto_v = Cloud::version_check( 'new_version_banner' ); - if ( ! empty( $auto_v[ 'latest' ] ) ) { - Admin_Display::save_summary( array( 'new_version.v' => $auto_v[ 'latest' ] ) ); + $auto_v = Cloud::version_check('new_version_banner'); + if (!empty($auto_v['latest'])) { + GUI::save_summary(array('new_version.v' => $auto_v['latest'])); } // After detect, don't show, just return and show next time return; } -if ( ! isset( $this->_summary[ 'new_version.v' ] ) ) { +if (!isset($this->_summary['new_version.v'])) { return; } // Check if current version is newer than auto_v or not -if ( version_compare( Core::VER, $this->_summary[ 'new_version.v' ], '>=' ) ) { +if (version_compare(Core::VER, $this->_summary['new_version.v'], '>=')) { return; } @@ -45,7 +47,7 @@ $this->_promo_true = true; -if ( $check_only ) { +if ($check_only) { return; } @@ -54,35 +56,35 @@
-

:

+

:

-

- _summary[ 'new_version.v' ] ); ?> +

+ _summary['new_version.v']); ?>

1 ); - $url = Utility::build_url( Router::ACTION_CONF, Conf::TYPE_SET, false, null, $cfg ); + $cfg = array(Conf::TYPE_SET . '[' . Base::O_AUTO_UPGRADE . ']' => 1); + $url = Utility::build_url(Router::ACTION_CONF, Conf::TYPE_SET, false, null, $cfg); ?>   - +
- 'new_version' ) ); ?> + 'new_version')); ?> - +
@@ -90,8 +92,8 @@
- 'new_version', 'later' => 1 ) ); ?> + 'new_version', 'later' => 1)); ?> Dismiss this notice. X
-
+
\ No newline at end of file diff --git a/tpl/banner/new_version_dev.tpl.php b/tpl/banner/new_version_dev.tpl.php index 15589d9df..42c8d054d 100644 --- a/tpl/banner/new_version_dev.tpl.php +++ b/tpl/banner/new_version_dev.tpl.php @@ -12,7 +12,7 @@

:

-

+

_summary[ 'version.dev' ] ) ; ?>

diff --git a/tpl/banner/slack.php b/tpl/banner/slack.php index 6ad9231bd..073c350b6 100644 --- a/tpl/banner/slack.php +++ b/tpl/banner/slack.php @@ -9,7 +9,7 @@

-

+

LiteSpeed Slack' ) ; ?>

diff --git a/tpl/cache/network_settings-cache.tpl.php b/tpl/cache/network_settings-cache.tpl.php index 2363a1d62..2023ff385 100644 --- a/tpl/cache/network_settings-cache.tpl.php +++ b/tpl/cache/network_settings-cache.tpl.php @@ -1,32 +1,34 @@

- - + +

- - - - - - - +
- build_switch( Base::O_CACHE ); ?> -
-
- STRONGLY recommend that the compatibility with other plugins on a single/few sites is tested first.', 'litespeed-cache'); ?> - -
-
+ + + + + -
+ build_switch(Base::O_CACHE); ?> +
+
+ STRONGLY recommend that the compatibility with other plugins on a single/few sites is tested first.', 'litespeed-cache'); ?> + +
+
+ + + \ No newline at end of file diff --git a/tpl/cache/settings-advanced.tpl.php b/tpl/cache/settings-advanced.tpl.php index 1ba31e448..4f4bf8c61 100644 --- a/tpl/cache/settings-advanced.tpl.php +++ b/tpl/cache/settings-advanced.tpl.php @@ -1,57 +1,80 @@

- - + +

-

-

+

+

- +
+ - _is_multisite ) : + + + + + + _is_multisite) : require LSCWP_DIR . 'tpl/cache/settings_inc.login_cookie.tpl.php'; endif; - ?> - - - - - - - - - - - -
+ + title($id); ?> + + +
+ + +
+
- - title( $id ); ?> - - build_switch( $id ); ?> -
- - -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- - -
- ⚠️ - - - -
-
+ ?> + + + + + title($id); ?> + + + build_switch($id); ?> +
+ + +
+ + + + + + + title($id); ?> + + + build_switch($id); ?> +
+ + +
+ + ⚠️ + + + +
+ + + + + \ No newline at end of file diff --git a/tpl/cache/settings-cache.tpl.php b/tpl/cache/settings-cache.tpl.php index 7562d7550..25750eeab 100644 --- a/tpl/cache/settings-cache.tpl.php +++ b/tpl/cache/settings-cache.tpl.php @@ -1,155 +1,160 @@

- - + +

- - - - +
- - title( $id ); ?> - - _is_multisite ) : ?> - build_switch( $id, array( __( 'OFF', 'litespeed-cache' ), __( 'ON', 'litespeed-cache' ), __( 'Use Network Admin Setting', 'litespeed-cache' ) ) ); ?> - - build_switch( $id ); ?> - -
- Information page on how to test the cache.', 'litespeed-cache'), - 'href="https://docs.litespeedtech.com/lscache/lscwp/installation/#testing" target="_blank"'); ?> - - : - - _is_multisite ): ?> -
+ + + + + - - - - - - - - - - - - - - - - - - - - - - - _is_multisite ) : - require LSCWP_DIR . 'tpl/cache/settings_inc.cache_favicon.tpl.php'; +
+ Information page on how to test the cache.', 'litespeed-cache'), + 'href="https://docs.litespeedtech.com/lscache/lscwp/installation/#testing" target="_blank"' + ); ?> + + : + + _is_multisite) : ?> +
+ + + conf(Base::O_CACHE) && $this->conf(Base::O_CDN_QUIC)) : ?> +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + _is_multisite) : require LSCWP_DIR . 'tpl/cache/settings_inc.cache_resources.tpl.php'; require LSCWP_DIR . 'tpl/cache/settings_inc.cache_mobile.tpl.php'; endif; - ?> - - - - - - - - - - - - - - - - - _is_multisite ) : + ?> + + + + + + + + + + + + + + + + + _is_multisite) : require LSCWP_DIR . 'tpl/cache/settings_inc.cache_dropquery.tpl.php'; endif; - ?> - -
+ + title($id); ?> + + _is_multisite) : ?> + build_switch($id, array(__('OFF', 'litespeed-cache'), __('ON', 'litespeed-cache'), __('Use Network Admin Setting', 'litespeed-cache'))); ?> + + build_switch($id); ?> - - conf( Base::O_CACHE ) && $this->conf( Base::O_CDN_QUIC ) ): ?> -
- - -
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - _uri_usage_example(); ?> -
-
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - _uri_usage_example(); ?> -
- /mypath/mypage 300', 300, '/mypath/mypage' ); ?> - -
-
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - _uri_usage_example(); ?> -
- /mypath/mypage 300', 300, '/mypath/mypage' ); ?> - -
-
+ + title($id); ?> + + build_textarea($id); ?> +
+ + _uri_usage_example(); ?> +
+
+ + title($id); ?> + + build_textarea($id); ?> +
+ + _uri_usage_example(); ?> +
+ /mypath/mypage 300', 300, '/mypath/mypage'); ?> + +
+
+ + title($id); ?> + + build_textarea($id); ?> +
+ + _uri_usage_example(); ?> +
+ /mypath/mypage 300', 300, '/mypath/mypage'); ?> + +
+
+ ?> +
\ No newline at end of file diff --git a/tpl/cache/settings-excludes.tpl.php b/tpl/cache/settings-excludes.tpl.php index ed387412d..02eef61a6 100644 --- a/tpl/cache/settings-excludes.tpl.php +++ b/tpl/cache/settings-excludes.tpl.php @@ -1,109 +1,115 @@

- - + +

- +
+ - - - - + + + + - - - - + + + + - - - + - + $this->build_textarea($id, false, $excludes_buf); + ?> +
+ + + +
+
+

:

+
    +
  1. +
+
+ + - - - + - + $this->build_textarea($id, false, $excludes_buf); + ?> +
+ + + +
+
+

:

+
    +
  1. +
  2. http://www.example.com/tag/category/tag-slug/', + 'tag-slug' + ); ?>
  3. +
+
+ + - _is_multisite ) : + _is_multisite) : // Cookie require LSCWP_DIR . 'tpl/cache/settings_inc.exclude_cookies.tpl.php'; @@ -111,24 +117,25 @@ require LSCWP_DIR . 'tpl/cache/settings_inc.exclude_useragent.tpl.php'; endif; - ?> + ?> - - - + + - + + -
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - _uri_usage_example(); ?> -
-
+ + title($id); ?> + + build_textarea($id); ?> + +
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - ?aa=bb&cc=dd', 'aa', 'cc' ); ?> - -
-
+ + title($id); ?> + + build_textarea($id); ?> +
+ + ?aa=bb&cc=dd', 'aa', 'cc'); ?> + +
+
- - title( $id ); ?> - - + + + title($id); ?> + + conf( $id ) ) { - $excludes_buf = implode( "\n", array_map( 'get_cat_name', $this->conf( $id ) ) ); + if ($this->conf($id)) { + $excludes_buf = implode("\n", array_map('get_cat_name', $this->conf($id))); } - $this->build_textarea( $id, false, $excludes_buf ); - ?> -
- - - -
-
-

:

-
    -
  1. -
-
-
- - title( $id ); ?> - - + + + title($id); ?> + + conf( $id ) ) { + if ($this->conf($id)) { $tag_names = array(); - foreach ( array_map( 'get_tag', $this->conf( $id ) ) as $tag ) { + foreach (array_map('get_tag', $this->conf($id)) as $tag) { $tag_names[] = $tag->name; } - if ( ! empty( $tag_names ) ) { - $excludes_buf = implode( "\n", $tag_names ); + if (!empty($tag_names)) { + $excludes_buf = implode("\n", $tag_names); } } - $this->build_textarea( $id, false, $excludes_buf ); - ?> -
- - - -
-
-

:

-
    -
  1. -
  2. http://www.example.com/tag/category/tag-slug/', - 'tag-slug' ); ?>
  3. -
-
-
- - title( $id ); ?> - -
- -
-
- $title ): ?> - build_checkbox( $id . '[]', $title, Control::cls()->in_cache_exc_roles( $role ), $role ); ?> - -
+
+ + title($id); ?> + +
+ +
+
+ $title) : ?> + build_checkbox($id . '[]', $title, Control::cls()->in_cache_exc_roles($role), $role); ?> + +
-
+ + \ No newline at end of file diff --git a/tpl/cache/settings_inc.cache_favicon.tpl.php b/tpl/cache/settings_inc.cache_favicon.tpl.php deleted file mode 100644 index 322c8af83..000000000 --- a/tpl/cache/settings_inc.cache_favicon.tpl.php +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - title( $id ) ; ?> - - - build_switch( $id ) ; ?> -
- - -
-
- - diff --git a/tpl/cdn/auto_setup.tpl.php b/tpl/cdn/auto_setup.tpl.php index d14a662dc..919c0a6e3 100644 --- a/tpl/cdn/auto_setup.tpl.php +++ b/tpl/cdn/auto_setup.tpl.php @@ -19,13 +19,13 @@ $has_setup_token = $__cdnsetup->has_cdn_setup_token(); +if (!empty($setup_summary['cdn_setup_err'])) { + $cdn_setup_err = $setup_summary['cdn_setup_err']; +} + if (!empty($setup_summary['cdn_setup_ts'])) { $cdn_setup_ts = $setup_summary['cdn_setup_ts']; - if (!empty($setup_summary['cdn_setup_err'])) { - $cdn_setup_err = $setup_summary['cdn_setup_err']; - } - if ($this->conf(Base::O_QC_NAMESERVERS)) { $nameservers = explode(',', $this->conf(Base::O_QC_NAMESERVERS)); } @@ -40,11 +40,11 @@ $dom = parse_url(home_url(), PHP_URL_HOST); if ($cdn_setup_done_ts) { - $curr_status = ' ' - . __('Done', 'litespeed-cache') - . ' ' - . sprintf(__('Completed at %s', 'litespeed-cache'), wp_date(get_option('date_format') . ' ' . get_option('time_format'), $cdn_setup_done_ts)) - . ''; + $curr_status = ' ' . __('Done', 'litespeed-cache'); + // wp_date requires WP v5.3+ + if (function_exists('wp_date')) { + $curr_status .= ' ' . sprintf(__('Completed at %s', 'litespeed-cache'), wp_date(get_option('date_format') . ' ' . get_option('time_format'), $cdn_setup_done_ts)) . ''; + } $disabled = 'disabled'; } else if (!$has_setup_token) { $disabled = 'disabled'; diff --git a/tpl/crawler/blacklist.tpl.php b/tpl/crawler/blacklist.tpl.php index fe7011894..59a1ea984 100644 --- a/tpl/crawler/blacklist.tpl.php +++ b/tpl/crawler/blacklist.tpl.php @@ -25,30 +25,34 @@ - - - - - - - - - $v ) : ?> - - - - - - - - -
#
- - - display_status( $v[ 'res' ], $v[ 'reason' ] ); ?> - - -
+ +
+ + + + + + + + + $v ) : ?> + + + + + + + + +
#
+ + + display_status( $v[ 'res' ], $v[ 'reason' ] ); ?> + + +
+
+

API: LITESPEED_CRAWLER_DISABLE_BLOCKLIST" ); ?> diff --git a/tpl/crawler/map.tpl.php b/tpl/crawler/map.tpl.php index c8ce5a7ba..7bf7c46ab 100644 --- a/tpl/crawler/map.tpl.php +++ b/tpl/crawler/map.tpl.php @@ -13,6 +13,7 @@ $pagination = Utility::pagination($count, 30); ?> +

@@ -45,37 +46,48 @@

+
+ + + + + +
+
- - - - - - - - - - - $v) : ?> +
+
#
+ - - - - + + + + - - -
- - - display_status($v['res'], $v['reason']); ?> - - - #
+ + + $v) : ?> + + + + + + + display_status($v['res'], $v['reason']); ?> + + + + + + + + +
+

diff --git a/tpl/crawler/summary.tpl.php b/tpl/crawler/summary.tpl.php index 812bf0728..8e89f23c8 100644 --- a/tpl/crawler/summary.tpl.php +++ b/tpl/crawler/summary.tpl.php @@ -120,69 +120,70 @@ ?>

- - - - - - - - - - - - - - $v) : - $hit = !empty($summary['crawler_stats'][$i]['H']) ? $summary['crawler_stats'][$i]['H'] : 0; - $miss = !empty($summary['crawler_stats'][$i]['M']) ? $summary['crawler_stats'][$i]['M'] : 0; - - $blacklisted = !empty($summary['crawler_stats'][$i]['B']) ? $summary['crawler_stats'][$i]['B'] : 0; - $blacklisted += !empty($summary['crawler_stats'][$i]['N']) ? $summary['crawler_stats'][$i]['N'] : 0; - - if (isset($summary['crawler_stats'][$i]['W'])) { - $waiting = $summary['crawler_stats'][$i]['W'] ?: 0; - } else { - $waiting = $summary['list_size'] - $hit - $miss - $blacklisted; - } - ?> +
+
#
+ - - - - - - + + + + + + - - -
- "; - } - ?> - - - - ' . ($waiting ?: '-') . ' '; ?> - ' . ($hit ?: '-') . ' '; ?> - ' . ($miss ?: '-') . ' '; ?> - ' . ($blacklisted ?: '-') . ' '; ?> - - build_toggle('litespeed-crawler-' . $i, $__crawler->is_active($i)); ?> - - " . __('running', 'litespeed-cache') . ""; - } - } - ?> - #
- + + + $v) : + $hit = !empty($summary['crawler_stats'][$i]['H']) ? $summary['crawler_stats'][$i]['H'] : 0; + $miss = !empty($summary['crawler_stats'][$i]['M']) ? $summary['crawler_stats'][$i]['M'] : 0; + + $blacklisted = !empty($summary['crawler_stats'][$i]['B']) ? $summary['crawler_stats'][$i]['B'] : 0; + $blacklisted += !empty($summary['crawler_stats'][$i]['N']) ? $summary['crawler_stats'][$i]['N'] : 0; + + if (isset($summary['crawler_stats'][$i]['W'])) { + $waiting = $summary['crawler_stats'][$i]['W'] ?: 0; + } else { + $waiting = $summary['list_size'] - $hit - $miss - $blacklisted; + } + ?> + + + "; + } + ?> + + + + + + + ' . ($waiting ?: '-') . ' '; ?> + ' . ($hit ?: '-') . ' '; ?> + ' . ($miss ?: '-') . ' '; ?> + ' . ($blacklisted ?: '-') . ' '; ?> + + + build_toggle('litespeed-crawler-' . $i, $__crawler->is_active($i)); ?> + + + " . __('running', 'litespeed-cache') . ""; + } + } + ?> + + + + + + +

=
=
diff --git a/tpl/dash/dashboard.tpl.php b/tpl/dash/dashboard.tpl.php index ccae5d50d..d1c14e10d 100644 --- a/tpl/dash/dashboard.tpl.php +++ b/tpl/dash/dashboard.tpl.php @@ -190,12 +190,17 @@

diff --git a/tpl/dash/network_dash.tpl.php b/tpl/dash/network_dash.tpl.php index ce958727f..c10fabc8e 100644 --- a/tpl/dash/network_dash.tpl.php +++ b/tpl/dash/network_dash.tpl.php @@ -24,10 +24,10 @@
__( 'Image Optimization', 'litespeed-cache' ), - 'ccss' => __( 'CCSS', 'litespeed-cache' ), - 'cdn' => __( 'CDN Bandwidth', 'litespeed-cache' ), - 'lqip' => __( 'LQIP', 'litespeed-cache' ), + 'img_optm' => __('Image Optimization', 'litespeed-cache'), + 'page_optm' => __('Page Optimization', 'litespeed-cache'), + 'cdn' => __('CDN Bandwidth', 'litespeed-cache'), + 'lqip' => __('Low Quality Image Placeholder', 'litespeed-cache'), ); foreach ( $cat_list as $svc => $title ) : diff --git a/tpl/img_optm/settings.tpl.php b/tpl/img_optm/settings.tpl.php index 426568c01..e8dc61eb8 100644 --- a/tpl/img_optm/settings.tpl.php +++ b/tpl/img_optm/settings.tpl.php @@ -1,169 +1,157 @@ form_action(); ?>

- - + +

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + - - - - - - - - - - - -
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- - -
- 🚨 - - - -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- - -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- - -
-
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ + +
+ + 🚨 + + + +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ + +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ + +
+
- - title( $id ); ?> - - -
+ + title($id); ?> + + + + +
+ + +
element.attribute', '.attribute'); ?> +
-
- recommended( $id ); ?> +
+ + title($id); ?> + + build_switch($id); ?> +
+ srcset'); ?> +
- - -
- - -
element.attribute', '.attribute' ); ?> - -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- srcset' ); ?> - -
-
- - title( $id ); ?> - - build_input( $id, 'litespeed-input-short' ); ?> -
- - recommended( $id ); ?> - _validate_ttl( $id, 0, 100 ); ?> -
-
+ + + + + form_end(); - - - diff --git a/tpl/img_optm/summary.tpl.php b/tpl/img_optm/summary.tpl.php index 5be2ee96a..42b65d9e9 100644 --- a/tpl/img_optm/summary.tpl.php +++ b/tpl/img_optm/summary.tpl.php @@ -136,7 +136,7 @@

 %4$s', + ' %4$s', ($unfinished_num ? Utility::build_url(Router::ACTION_IMG_OPTM, Img_Optm::TYPE_CLEAN) : 'javascript:;'), __('Remove all previous unfinished image optimization requests.', 'litespeed-cache'), ($unfinished_num ? '' : ' disabled'), @@ -238,7 +238,7 @@ - + diff --git a/tpl/page_optm/settings_html.tpl.php b/tpl/page_optm/settings_html.tpl.php index 75374dbed..fde9ffac7 100644 --- a/tpl/page_optm/settings_html.tpl.php +++ b/tpl/page_optm/settings_html.tpl.php @@ -87,6 +87,23 @@ + + + + title($id); ?> + + + build_textarea($id); ?> +

+ + + diff --git a/tpl/page_optm/settings_media.tpl.php b/tpl/page_optm/settings_media.tpl.php index 0aa44be1b..56db584f5 100644 --- a/tpl/page_optm/settings_media.tpl.php +++ b/tpl/page_optm/settings_media.tpl.php @@ -19,20 +19,6 @@ - - - - - + + + +
- - title($id); ?> - - build_switch($id); ?> -
- - -
-
@@ -263,5 +249,19 @@
+ + title($id); ?> + + build_input($id, 'litespeed-input-short'); ?> +
+ + recommended($id); ?> + _validate_ttl($id, 0, 100); ?> +
+
\ No newline at end of file diff --git a/tpl/toolbox/beta_test.tpl.php b/tpl/toolbox/beta_test.tpl.php index 329242705..f07c8101a 100644 --- a/tpl/toolbox/beta_test.tpl.php +++ b/tpl/toolbox/beta_test.tpl.php @@ -6,17 +6,14 @@ // Existing public version list $v_list = array( - '6.0.0.1', + '6.5.0.2', + '6.4.1', + '6.3.0.1', + '6.2.0.1', + '6.1', '5.7.0.1', - '5.6', - '5.5.1', - '5.5', - '5.4', - '5.3.2', - '5.2.1', - '5.1', '4.6', - '4.1', + '3.6.4', ); ?> diff --git a/tpl/toolbox/edit_htaccess.tpl.php b/tpl/toolbox/edit_htaccess.tpl.php index db4dfa0e2..569607ad4 100644 --- a/tpl/toolbox/edit_htaccess.tpl.php +++ b/tpl/toolbox/edit_htaccess.tpl.php @@ -1,24 +1,26 @@ htaccess_read(); -} catch( \Exception $e ) { - echo '

'. $e->getMessage() . '

'; +} catch (\Exception $e) { + echo '

' . $e->getMessage() . '

'; } $htaccess_path = Htaccess::get_frontend_htaccess(); // Check if there is `ExpiresDefault` in .htaccess -if ( defined( 'LITESPEED_ON' ) ) { - if ( $content && stripos( $content, "\nExpiresDefault" ) !== false ) { - $is_dismissed = GUI::get_option( self::DB_DISMISS_MSG ); - if ( $is_dismissed !== self::RULECONFLICT_DISMISSED ) { +if (defined('LITESPEED_ON')) { + if ($content && stripos($content, "\nExpiresDefault") !== false) { + $is_dismissed = GUI::get_option(self::DB_DISMISS_MSG); + if ($is_dismissed !== self::RULECONFLICT_DISMISSED) { // Need to add a notice for browser cache compatibility - if ( $is_dismissed !== self::RULECONFLICT_ON ) { - GUI::update_option( self::DB_DISMISS_MSG, self::RULECONFLICT_ON ); + if ($is_dismissed !== self::RULECONFLICT_ON) { + GUI::update_option(self::DB_DISMISS_MSG, self::RULECONFLICT_ON); } require_once LSCWP_DIR . 'tpl/inc/show_rule_conflict.php'; } @@ -34,50 +36,54 @@

- +

- +

- - - - - - - - - - -
- - - -
- : -
- : - LITESPEED_CFG_HTACCESS' ); ?> - defined("LITESPEED_CFG_HTACCESS") || define("LITESPEED_CFG_HTACCESS", "your path on server");', 'wp-config.php' ); ?> - -
-
- - - -
- : -
- : - LITESPEED_CFG_HTACCESS_BACKEND' ); ?> - defined("LITESPEED_CFG_HTACCESS_BACKEND") || define("LITESPEED_CFG_HTACCESS_BACKEND", "your path on server");', 'wp-config.php' ); ?> - -
-
- - + + + + + + + + + + + + +
+ + + +
+ : +
+ + : + LITESPEED_CFG_HTACCESS'); ?> + defined("LITESPEED_CFG_HTACCESS") || define("LITESPEED_CFG_HTACCESS", "your path on server");', 'wp-config.php'); ?> + +
+
+ + + +
+ : +
+ + : + LITESPEED_CFG_HTACCESS_BACKEND'); ?> + defined("LITESPEED_CFG_HTACCESS_BACKEND") || define("LITESPEED_CFG_HTACCESS_BACKEND", "your path on server");', 'wp-config.php'); ?> + +
+
+ +

@@ -85,4 +91,4 @@ - + \ No newline at end of file diff --git a/tpl/toolbox/log_viewer.tpl.php b/tpl/toolbox/log_viewer.tpl.php index 1a1ea5f95..8dacef464 100644 --- a/tpl/toolbox/log_viewer.tpl.php +++ b/tpl/toolbox/log_viewer.tpl.php @@ -2,23 +2,23 @@ namespace LiteSpeed; -defined( 'WPINC' ) || exit; +defined('WPINC') || exit; $logs = array( array( 'name' => 'debug', - 'label' => esc_html__( 'Debug Log', 'litespeed-cache' ), + 'label' => esc_html__('Debug Log', 'litespeed-cache'), 'accesskey' => 'A', ), array( - 'name' => 'debug.purge', - 'label' => esc_html__( 'Purge Log', 'litespeed-cache' ), + 'name' => 'purge', + 'label' => esc_html__('Purge Log', 'litespeed-cache'), 'accesskey' => 'B', ), array( 'name' => 'crawler', - 'label' => esc_html__( 'Crawler Log', 'litespeed-cache' ), + 'label' => esc_html__('Crawler Log', 'litespeed-cache'), 'accesskey' => 'C', ), ); @@ -27,26 +27,26 @@ * Return a subnav button (subtab) * @since 4.7 */ -function subnav_link( $item ) { +function subnav_link($item) +{ $class = 'button '; $subtab = ''; - if ( ! isset( $item['url'] ) ) { + if (!isset($item['url'])) { $class .= 'button-secondary'; $subtab_name = "{$item['name']}_log"; $subtab = "data-litespeed-subtab='{$subtab_name}'"; - $url ="#{$subtab_name}"; - } - else { + $url = "#{$subtab_name}"; + } else { $class .= 'button-primary'; $url = $item['url']; } $accesskey = - isset( $item['accesskey'] ) + isset($item['accesskey']) ? "litespeed-accesskey='{$item['accesskey']}'" : ''; - $label = isset( $item['label'] ) ? $item['label'] : $item['name']; + $label = isset($item['label']) ? $item['label'] : $item['name']; return "
{$label}"; } @@ -55,51 +55,52 @@ function subnav_link( $item ) { * Print a button to clear all logs * @since 4.7 */ -function clear_logs_link( $accesskey = null ) { +function clear_logs_link($accesskey = null) +{ $item = array( - 'label' => esc_html__( 'Clear Logs', 'litespeed-cache' ), - 'url' => Utility::build_url( Router::ACTION_DEBUG2, Debug2::TYPE_CLEAR_LOG ), + 'label' => esc_html__('Clear Logs', 'litespeed-cache'), + 'url' => Utility::build_url(Router::ACTION_DEBUG2, Debug2::TYPE_CLEAR_LOG), ); - if ( null !== $accesskey ) { + if (null !== $accesskey) { $item['accesskey'] = $accesskey; } - echo subnav_link( $item ); + echo subnav_link($item); } $subnav_links = array(); $log_views = array(); -foreach( $logs as $log ) { - $subnav_links[] = subnav_link( $log ); +foreach ($logs as $log) { + $subnav_links[] = subnav_link($log); - $file = LSCWP_CONTENT_DIR . "/{$log['name']}.log"; - $lines = File::count_lines( $file ); + $file = $this->cls('Debug2')->path($log['name']); + $lines = File::count_lines($file); $start = $lines > 1000 ? $lines - 1000 : 0; - $lines = File::read( $file, $start ); - $lines = $lines ? trim( implode( "\n", $lines ) ) : ''; + $lines = File::read($file, $start); + $lines = $lines ? trim(implode("\n", $lines)) : ''; $log_views[] = "
" - . "

{$log['label']}

" - . '
' - . nl2br( htmlspecialchars( $lines ) ) - . '
' + . "

{$log['label']}

" + . '
' + . nl2br(htmlspecialchars($lines)) + . '
' . '
'; } ?>

- - + +

- - + +
- + generate_environment_report(); -$env_ref = Report::get_summary() ; +$env_ref = Report::get_summary(); // Detect password less plugin $link = ''; $has_pswdless_plugin = false; -if ( function_exists( 'dologin_gen_link' ) ) { +if (function_exists('dologin_gen_link')) { $has_pswdless_plugin = true; - if ( ! empty( $_GET[ 'dologin_gen_link' ] ) ) { - unset( $_GET[ 'dologin_gen_link' ] ); - $link = dologin_gen_link( 'Litespeed Report' ); - ?> - - + + 'dologin' ) ); +$install_link = Utility::build_url(Router::ACTION_ACTIVATION, Activation::TYPE_INSTALL_3RD, false, null, array('plugin' => 'dologin')); ?> - +
-

+

- DoLogin Security' ); ?> + DoLogin Security'); ?>

- - + +

- - + +

-

:

-

:

+

:

+

:

- +

-
- - - - - - - - - - - - - -
- -
- - - - - - -
- - -
🚨 - Settings.', 'litespeed-cache'), 'href="' . menu_page_url( 'dologin', 0 ) . '"' ); ?> - -
-
- -
- : - -
-
+ + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
🚨 + Settings.', 'litespeed-cache'), 'href="' . menu_page_url('dologin', 0) . '"'); ?> + +
+
+ +
+ : + +
+
-
- - +
+ + -

- -

+

+ +

- - + \ No newline at end of file diff --git a/tpl/toolbox/settings-debug.tpl.php b/tpl/toolbox/settings-debug.tpl.php index e625f29e6..daaf9d95b 100644 --- a/tpl/toolbox/settings-debug.tpl.php +++ b/tpl/toolbox/settings-debug.tpl.php @@ -1,177 +1,167 @@ form_action( $this->_is_network_admin ? Router::ACTION_SAVE_SETTINGS_NETWORK : false ); +defined('WPINC') || exit; + +$this->form_action($this->_is_network_admin ? Router::ACTION_SAVE_SETTINGS_NETWORK : false); ?>

- - + + - - + +

- +

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id, array( __( 'OFF', 'litespeed-cache' ), __( 'ON', 'litespeed-cache' ), __( 'Admin IP Only', 'litespeed-cache' ) ) ); ?> -
- - - - wp-content/debug.log' ); ?> -
-
- - title( $id ); ?> - - build_textarea( $id, 50 ); ?> -
- - : - _validate_ip( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id, array( __( 'Basic', 'litespeed-cache' ), __( 'Advanced', 'litespeed-cache' ) ) ); ?> -
- -
-
- - title( $id ); ?> - - build_input( $id, 'litespeed-input-short' ); ?> -
- - recommended( $id ); ?> - _validate_ttl( $id, 3, 3000 ); ?> -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_switch( $id ); ?> -
- -
-
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - _uri_usage_example(); ?> -
-
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - _uri_usage_example(); ?> -
-
- - title( $id ); ?> - - build_textarea( $id ); ?> -
- - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id, array(__('OFF', 'litespeed-cache'), __('ON', 'litespeed-cache'), __('Admin IP Only', 'litespeed-cache'))); ?> +
+ + + + wp-content/debug.log'); ?> +
+
+ + title($id); ?> + + build_textarea($id, 50); ?> +
+ + : + _validate_ip($id); ?> +
+ +
+
+ + title($id); ?> + + build_switch($id, array(__('Basic', 'litespeed-cache'), __('Advanced', 'litespeed-cache'))); ?> +
+ +
+
+ + title($id); ?> + + build_input($id, 'litespeed-input-short'); ?> +
+ + recommended($id); ?> + _validate_ttl($id, 3, 3000); ?> +
+
+ + title($id); ?> + + build_switch($id); ?> +
+ +
+
+ + title($id); ?> + + build_textarea($id); ?> +
+ + _uri_usage_example(); ?> +
+
+ + title($id); ?> + + build_textarea($id); ?> +
+ + _uri_usage_example(); ?> +
+
+ + title($id); ?> + + build_textarea($id); ?> +
+ + +
+
form_end(); -