Current File : /home/resuelf/www/wp-content/plugins/nitropack/classes/Integration/Server/LiteSpeed.php
<?php

namespace NitroPack\Integration\Server;
use NitroPack\WordPress\NitroPack;
use NitroPack\Url\Url;
use NitroPack\SDK\Device;
use NitroPack\Integration\Hosting\WPX;

class LiteSpeed {
    const STAGE = "very_early";

    public static function detect() {
        return !empty($_SERVER["X-LSCACHE"]) || ( !empty($_SERVER["SERVER_SOFTWARE"]) && strtolower($_SERVER["SERVER_SOFTWARE"]) == "litespeed" );
    }

    public static function isCacheEnabled() {
        return
            !empty($_SERVER["X-LSCACHE"]) &&
            in_array("on", array_map("trim", explode(",", $_SERVER["X-LSCACHE"]))) &&
            !empty($_SERVER['LSCACHE_VARY_VALUE']) &&
            in_array($_SERVER['LSCACHE_VARY_VALUE'], array("nitrodesktop", "nitrotablet", "nitromobile"));
    }

    public static function sendCacheHeader($maxAge = NULL) {
        if (!$maxAge) {
            nitropack_header("X-LiteSpeed-Cache-Control: public");
        } else if (is_numeric($maxAge)) {
            nitropack_header("X-LiteSpeed-Cache-Control: public,max-age=" . (int)$maxAge);
        }
    }

    public static function purge($url = NULL, $tag = NULL) {
        if ($url || $tag) {
            $headerValues = [];

            if ($url) {
                $urlObj = new Url((new Url($url))->getNormalized());
                if (!$urlObj->getQuery()) {
                    $headerValues[] = "uri=" . md5($urlObj->getPath());
                } else {
                    $headerValues[] = "uri=" . md5($urlObj->getPath() . "?" . $urlObj->getQuery());
                }
            }

            if ($tag) {
                $headerValues[] = $tag;
            }

            nitropack_header("X-LiteSpeed-Purge: " . implode(", ", $headerValues), false);
        } else {
            nitropack_header("X-LiteSpeed-Purge: *", false);
        }
    }

    public function init($stage) {
        if (self::detect()) {
            add_filter('nitropack_should_modify_htaccess', function() { return true; });
            add_filter('nitropack_htaccess_rules', [$this, 'getHtaccessRules'], 10);

            if (self::isCacheEnabled()) {
                add_action('nitropack_integration_purge_url', [$this, 'purgeUrl']);
                add_action('nitropack_integration_purge_all', [$this, 'purgeAll']);
                add_action('nitropack_early_cache_headers', [$this, 'setupVary']);
                add_action('nitropack_early_cache_headers', [$this, 'preventProxyCache']);
                add_action('nitropack_cacheable_cache_headers', [$this, 'allowProxyCache']);
                add_filter('nocache_headers', function($headers) {
                    $headers["X-LiteSpeed-Cache-Control"] = "no-cache";
                    return $headers;
                });
            } else {
                add_filter('nitropack_needs_htaccess_changes', function() { return true; });
            }
        }
    }

    public function purgeUrl($url) {
        self::purge($url);
    }

    public function purgeAll() {
        self::purge();
    }

    public function setupVary() {
        $cookies = []; // Configure vary based on NitroPack's variation cookies.

        $nitro = get_nitropack()->getSdk();
        if ($nitro && !empty($nitro->getConfig()->PageCache->SupportedCookies)) {
            $cookies = $nitro->getConfig()->PageCache->SupportedCookies;
        }

        $deviceStr = "nitrodesktop";
        if ( ! empty($_SERVER["HTTP_USER_AGENT"]) ) {
            $device = new Device($_SERVER["HTTP_USER_AGENT"]);

            if ($device->isMobile()) {
                $deviceStr = "nitromobile";
            } else if ($device->isTablet()) {
                $deviceStr = "nitrotablet";
            }
        }

        $varyStr = "";

        if ($cookies) {
            $varyStr = implode(",", array_map(function($name) { return "cookie=$name"; }, $cookies)); // Vary on multiple cookies should look like this: cookie=name1,cookie=name2
        }

        $varyStr .= ($varyStr ? ", " : "") . "value=$deviceStr";

        nitropack_header("X-LiteSpeed-Vary: $varyStr");
    }

    public function preventProxyCache() {
        nitropack_header("X-LiteSpeed-Cache-Control: no-cache");
    }

    public function allowProxyCache() {
        self::sendCacheHeader(3600);
        $urlObj = new Url(NitroPack::getInstance()->getSdk()->getUrl());
        if (!$urlObj->getQuery()) {
            $uri = md5($urlObj->getPath());
        } else {
            $uri = md5($urlObj->getPath() . "?" . $urlObj->getQuery());
        }

        nitropack_header("X-LiteSpeed-Tag: uri=$uri");

        // TODO: Add LSC-Cookie headers for variation cookies - https://docs.litespeedtech.com/lscache/devguide/controls/#lsc-cookie
    }

    public function getHtaccessRules($ruleLines) {
        $rules = "
<IfModule LiteSpeed>
RewriteEngine on
CacheLookup on

RewriteRule .* - [E=NitroPackHtaccessVersion:NITROPACK_VERSION]
RewriteRule .* - [E=Cache-Control:vary=nitrodesktop]

RewriteCond %{HTTP_USER_AGENT} Android|iPad|RIM\ Tablet|hp-tablet|Kindle\ Fire [NC]
RewriteRule .* - [E=Cache-Control:vary=nitrotablet]

RewriteCond %{HTTP_USER_AGENT} iPod|iPhone|MobileSafari|webOS|BlackBerry|windows\ phone|symbian|vodafone|opera\ mini|windows\ ce|smartphone|palm|midp [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Android.*Mobile [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Mobile.*Android [NC]
RewriteRule .* - [E=Cache-Control:vary=nitromobile]

RewriteCond %{HTTP_COOKIE} COOKIEBYPASS
RewriteRule .* - [E=Cache-Control:no-cache]

# QSDROP

</IfModule>
";

        $rules = str_replace("NITROPACK_VERSION", NITROPACK_VERSION, $rules);

        $nitro = get_nitropack()->getSdk();

        $bypassCookies = ["wordpress_logged_in", "comment_author", "wp-postpass_", "woocommerce_items_in_cart="];
        if (defined('NITROPACK_LOGGED_IN_COOKIE') || defined('LOGGED_IN_COOKIE')) {
            $bypassCookies[] = (defined('NITROPACK_LOGGED_IN_COOKIE') ? NITROPACK_LOGGED_IN_COOKIE : (defined('LOGGED_IN_COOKIE') ? LOGGED_IN_COOKIE : '')) . "="; // Add "=" for exact match
        }
        if ($nitro && !!$nitro->getConfig()->ExcludedCookies->Status && !empty($nitro->getConfig()->ExcludedCookies->Cookies)) {
            foreach ($nitro->getConfig()->ExcludedCookies->Cookies as $excludedCookie) {
                if ($excludedCookie->values) {
                    $bypassCookies[] = $excludedCookie->name . "=(" . implode("|", $excludedCookie->values) . ')\s*(;|$)';
                } else {
                    $bypassCookies[] = $excludedCookie->name . "=";
                }
            }
        }
        $rules = str_replace("COOKIEBYPASS", "(" . implode("|", array_map(function($cookie){ return "(^|\;\s*)$cookie"; }, $bypassCookies)) . ")", $rules);

        if ($nitro && !empty($nitro->getConfig()->IgnoredParams)) {
            $rules = str_replace("# QSDROP", implode("\n", array_map(function($param) { return "CacheKeyModify -qs:$param"; }, array_filter($nitro->getConfig()->IgnoredParams, function($param) { return $param != "ignorenitro"; }))), $rules);
        }

        return array_merge($ruleLines, explode("\n", $rules));
    }
}