HEX
Server: LiteSpeed
System: Linux cde2.duelhost.dk 4.18.0-553.34.1.lve.el8.x86_64 #1 SMP Thu Jan 9 16:30:32 UTC 2025 x86_64
User: dtptviut (1121)
PHP: 8.0.30
Disabled: exec,system,passthru,shell_exec,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Upload Files
File: /home/dtptviut/public_html/wp-content/plugins/nitropack/classes/Feature/SubrequestCache.php
<?php
namespace NitroPack\Feature;

use NitroPack\Util\CacheStreamWrapper;
use NitroPack\Interfaces\CacheManager;
use NitroPack\SDK\NitroPack as NitroPackSDK;
use NitroPack\SDK\Filesystem;

class SubrequestCache implements CacheManager {
    const STAGE = "very_early";

    private $allowList = array();
    private $blockList = array();

    private $cache = array();
    private $cacheDir = NULL;
    private $cacheTtl = 3600;

    public function init($stage) {
        if ($stage != self::STAGE) {
            return;
        }

        if (!defined("NITROPACK_SUBREQUEST_CACHE_ALLOW_LIST") || !NITROPACK_SUBREQUEST_CACHE_ALLOW_LIST) {
            return;
        }

        if (null === $nitro = get_nitropack_sdk()) {
            return;
        }

        $this->allowList = explode(";", NITROPACK_SUBREQUEST_CACHE_ALLOW_LIST);
        $this->blockList = array();

        if (defined("NITROPACK_SUBREQUEST_CACHE_BLOCK_LIST") && NITROPACK_SUBREQUEST_CACHE_BLOCK_LIST) {
            $this->blockList = explode(";", NITROPACK_SUBREQUEST_CACHE_BLOCK_LIST);
        }

        if (defined("NITROPACK_SUBREQUEST_CACHE_TTL") && NITROPACK_SUBREQUEST_CACHE_TTL >= 0) {
            $this->cacheTtl = NITROPACK_SUBREQUEST_CACHE_TTL;
        }

        add_action('nitropack_execute_purge_all', [$this, 'purgeCache']);

        $this->cacheDir = nitropack_trailingslashit(NITROPACK_DATA_DIR) . nitropack_trailingslashit("subrequest-cache");

        CacheStreamWrapper::setCacheManager($this);
        CacheStreamWrapper::init();

        add_filter('pre_http_request', array($this, "interceptRequest"), 10, 3);
        add_action('http_api_debug', array($this, "interceptResponse"), 10, 5);
    }

    public function interceptRequest($resp, $args, $url) {
        if (!empty($args["method"]) && $args["method"] != "GET") {
            return $resp;
        }

        if (!$this->isCacheAllowed($url)) {
            return $resp;
        }

        $key = "wpremote-" . $url;
        if ($this->hasCache($key)) {
            return unserialize($this->getCache($key));
        }

        return $resp;
    }

    public function interceptResponse($response, $context, $class, $parsed_args, $url) {
        if (is_wp_error($response)) {
            return;
        }

        if (!empty($parsed_args["method"]) && $parsed_args["method"] != "GET") {
            return;
        }

        if (!$this->isCacheAllowed($url)) {
            return;
        }

        $key = "wpremote-" . $url;
        $this->setCache($key, serialize($response));
    }

    public function purgeCache($key = NULL) {
        if (!$this->cacheDir || !is_dir($this->cacheDir)) return;

        if ($key) {
            $cacheFile = $this->getCacheFile($key);
            if (Filesystem::fileExists($cacheFile)) {
                Filesystem::deleteFile($cacheFile);
            }

            $cacheFileWp = $this->getCacheFile("wpremote-" . $key);
            if (Filesystem::fileExists($cacheFileWp)) {
                Filesystem::deleteFile($cacheFileWp);
            }
            return;
        }

        $dh = opendir($this->cacheDir);
        while (($entry = readdir($dh)) !== false) {
            if ($entry == "." || $entry == "..") continue;

            $cacheFile = $this->cacheDir . $entry;
            if (!is_file($cacheFile)) continue;
            Filesystem::deleteFile($cacheFile);
        }
        closedir($dh);
        rmdir($this->cacheDir);
    }

    public function hasCache($key) {
        if(!empty($this->cache[$key])) {
            return true;
        }

        $cacheFile = $this->getCacheFile($key);
        if (Filesystem::fileExists($cacheFile) && time() - filemtime($cacheFile) <= $this->cacheTtl) {
            return true;
        }

        return false;
    }

    public function getCache($key) {
        if(empty($this->cache[$key])) {
            $cacheFile = $this->getCacheFile($key);
            if (Filesystem::fileExists($cacheFile) && time() - filemtime($cacheFile) <= $this->cacheTtl) {
                $this->cache[$key] = file_get_contents($cacheFile);
            }
        }

        if(!empty($this->cache[$key])) {
            return $this->cache[$key];
        }

        return NULL;
    }

    public function setCache($key, $content) {
        $this->cache[$key] = $content;

        if (!$this->cacheDir) {
            return;
        }

        if (!is_dir($this->cacheDir) && !mkdir($this->cacheDir, 0755, true)) {
            return;
        }

        Filesystem::filePutContents($this->getCacheFile($key), $content);
    }

    private function getCacheFile($key) {
        if (!$this->cacheDir) {
            return;
        }

        return $this->cacheDir . md5($key);
    }

    public function isCacheAllowed($key) {
        // Exact match search. Exact matches have higher priority than wildcard matches.
        foreach ($this->allowList as $pattern) {
            if ($pattern == $key) {
                return true;
            }
        }

        // Block list patterns have higher priority than allow list ones
        foreach ($this->blockList as $pattern) {
            if (preg_match("/" . NitroPackSDK::wildcardToRegex($pattern) . "/", $key)) {
                return false;
            }
        }

        foreach ($this->allowList as $pattern) {
            if (preg_match("/" . NitroPackSDK::wildcardToRegex($pattern) . "/", $key)) {
                return true;
            }
        }

        return false;
    }
}