whoami7 - Manager
:
/
home
/
dataiclx
/
www
/
wp-content
/
plugins
/
nitropack
/
nitropack-sdk
/
NitroPack
/
SDK
/
Upload File:
files >> /home/dataiclx/www/wp-content/plugins/nitropack/nitropack-sdk/NitroPack/SDK/Pagecache.php
<?php namespace NitroPack\SDK; use \NitroPack\Url\Url; class Pagecache { protected $url; protected $cookies; protected $supportedCookies; protected $dataDir; protected $isAjax; protected $referer; protected $parent; protected $Device; protected $useCompression; protected $useInvalidated; private $urlPathVersion; private $cookiesProvider; private $geotVariations; private $NotModifiedHeaderEnabled = false; public static function getUrlDir($dataDir, $url, $useInvalidated = false, $pathVersion = 1) { $safeUrl = str_replace(array('/', '?', ':', ';', '=', '&', '.', '--', '%', '~'), '-', $url); if (defined('NITRO_DEBUG_MODE') && NITRO_DEBUG_MODE) { $urlDir = $dataDir . "/" . $safeUrl; } else { switch ($pathVersion) { case 2: $urlDir = $dataDir . "/" . md5($url); break; default: $urlDir = $dataDir . "/" . md5($safeUrl); break; } } if ($useInvalidated) { return $urlDir . "_i"; } else { return $urlDir; } } public function __construct($url, $userAgent, $cookies = array(), $supportedCookies = array(), $isAjax = false, $referer = NULL) { $this->url = new Url($url); $this->cookies = $cookies; $this->supportedCookies = $supportedCookies; $this->dataDir = NULL; $this->isAjax = $isAjax; $this->parent = NULL; $this->Device = new Device($userAgent); $this->useCompression = false; $this->useInvalidated = false; $this->cookiesProvider = NULL; $this->geotVariations = new \stdClass; $this->setUrlPathVersion(1); $this->setReferer($referer); } public function enableCompression() { $this->useCompression = true; if ($this->parent) { $this->parent->enableCompression(); } } public function disableCompression() { $this->useCompression = false; if ($this->parent) { $this->parent->disableCompression(); } } public function useInvalidated($useInvalidated) { $this->useInvalidated = $useInvalidated; if ($this->parent) { $this->parent->useInvalidated($useInvalidated); } } public function getUseInvalidated() { return $this->useInvalidated; } public function setReferer($referer) { $this->referer = $referer ? new Url($referer) : NULL; if ($this->referer) { $this->parent = new Pagecache($this->referer->getNormalized(), $this->Device->getUserAgent(), $this->cookies, $this->supportedCookies); $this->parent->setUrlPathVersion($this->urlPathVersion); //$this->parent->setCookiesProvider($this->cookiesProvider); if (count(get_object_vars($this->geotVariations)) > 0) { $this->parent->setGeotVariations($this->geotVariations); } if ($this->dataDir) { $this->parent->setDataDir(dirname($this->dataDir)); } } else { $this->parent = NULL; } } public function setUrlPathVersion($version = 1) { $this->urlPathVersion = $version; if ($this->parent) { $this->parent->setUrlPathVersion($version); } } public function getReferer() { return $this->referer; } public function getParent() { return $this->parent; } public function setDataDir($dir) { if ($dir === null) { $this->dataDir = null; } else { $this->dataDir = $dir . "/" . $this->Device->getType(); } if ($this->parent) { $this->parent->setDataDir($dir); } } public function setCookiesProvider($provider) { $this->cookiesProvider = $provider; } public function setGeotVariations($geotVariations) { $this->geotVariations = $geotVariations; } public function enableNotModifiedHeader() { $this->NotModifiedHeaderEnabled = true; } public function hasCache() { // If there is no cache for the parent we do not need to check cache existance for the current object, because we only serve AJAX cache for pages already cached by NitroPack if ($this->parent && !$this->parent->hasCache()) return false; if ($this->useInvalidated) { $this->convertToStaleCache(); return Filesystem::fileExists($this->getCachefilePath("stale")); } else { return Filesystem::fileExists($this->getCachefilePath()); } } public function hasExpired($ttl = 86400, $cacheRevision = NULL) { // If the cache for the parent is expired we do not need to check cache for the current object, because we only serve AJAX cache for pages already cached by NitroPack if ($this->parent && $this->parent->hasExpired($ttl, $cacheRevision)) return true; if ($this->useInvalidated) { $this->convertToStaleCache(); $cachefilePath = $this->getCachefilePath("stale"); $mtime = Filesystem::fileMtime(dirname($cachefilePath)); } else { $cachefilePath = $this->getCachefilePath(); $mtime = Filesystem::fileMtime($cachefilePath); } $now = time(); if ($now - $mtime >= $ttl) { return true; } else { try { $headers = Filesystem::fileGetHeaders($cachefilePath); if (!empty($headers["x-nitro-expires"]) && $now > (int)$headers["x-nitro-expires"]) { return true; } if ( !$this->useInvalidated && !empty($headers["x-cache-ctime"]) && $now - (int)$headers["x-cache-ctime"] > $ttl ) { return true; } $expectedRev = !empty($cacheRevision) ? $cacheRevision : NULL; $cachedRev = !empty($headers["x-nitro-rev"]) ? $headers["x-nitro-rev"] : NULL; // Check if the revision has changed which makes cache file obsolete if ($expectedRev && $expectedRev !== $cachedRev) { return true; } } catch (\Exception $e) { return true; } } return false; } public function getRemainingTtl($ttl = 86400) { // If there is a parent cache file return its remaining TTL if ($this->parent) return $this->parent->getRemainingTtl(); if ($this->useInvalidated) { return 0; } else { $cachefilePath = $this->getCachefilePath(); } $now = time(); try { $headers = Filesystem::fileGetHeaders($cachefilePath); if (!empty($headers["x-nitro-expires"])) { $expireTime = (int)$headers["x-nitro-expires"]; } else if (!empty($headers["x-cache-ctime"])) { $expireTime = (int)$headers["x-cache-ctime"] + $ttl; } else { $mtime = Filesystem::fileMtime($cachefilePath); $expireTime = $mtime + $ttl; } return max($expireTime - $now, 0); } catch (\Exception $e) { return 0; } return 0; } public function setContent($content, $headers = NULL) { if (!$this->dataDir) return; $filePath = $this->getCachefilePath(); if (Filesystem::createDir(dirname($filePath))) { if (!Filesystem::filePutContents($filePath, $content, $this->headersFlatten($headers))) { return false; } else { if ($headers && !empty($headers["x-cache-ctime"])) { Filesystem::touch($filePath, (int)$headers["x-cache-ctime"]); } return $this->compress($filePath); } } } private function headersFlatten($headers) { // The headers from fileGetAll come as associative array // They must be converted to an array of strings before being passed to filePutContents, which is what this function does $headersFlat = array(); foreach ($headers as $name => $value) { if (is_array($value)) { foreach ($value as $subValue) { $headersFlat[] = $name . ":" . $subValue; } } else { $headersFlat[] = $name . ":" . $value; } } return $headersFlat; } private function compress($filePath) { $fileInfo = Filesystem::fileGetAll($filePath); $fileInfo->headers["Content-Encoding"] = "gzip"; $gzPath = $filePath . ".gz"; $res = Filesystem::filePutContents($gzPath, gzencode($fileInfo->content, 4), $this->headersFlatten($fileInfo->headers)); // save compressed version of the cache file if ($res && $fileInfo->headers && !empty($fileInfo->headers["x-cache-ctime"])) { Filesystem::touch($gzPath, (int)$fileInfo->headers["x-cache-ctime"]); } return $res; } public function readfile() { $setOwnLastModified = false; // 304 Not Modified improvement - only when enabled via config if ($this->NotModifiedHeaderEnabled) { $lastModified = $this->getCacheCreationTime(); // Set Last-Modified header based on x-cache-ctime if ($lastModified > 0) { $lastModifiedHeader = gmdate('D, d M Y H:i:s', $lastModified) . ' GMT'; header('Last-Modified: ' . $lastModifiedHeader); $setOwnLastModified = true; // Calculate current variation hash $currentVariationPrefix = $this->getVariationCookiePrefix(); $currentVariationHash = md5($currentVariationPrefix); // Get last served variation from tracking cookie $lastVariationHash = isset($_COOKIE['np_cache_variation']) ? $_COOKIE['np_cache_variation'] : ''; // If variation is different now - bypass 304 mechanism. $variationChanged = ($currentVariationHash !== $lastVariationHash); // Update tracking cookie to current variation if ($variationChanged) { setcookie('np_cache_variation', $currentVariationHash, 0, '/'); } if (!$variationChanged) { $httpModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : 0; if ($httpModifiedSince && $httpModifiedSince >= $lastModified) { http_response_code(304); return; } } // If variation changed, skip 304 - always serve full response } } // Normal flow - serve cache file $cacheFileContent = $this->returnCacheFileContent(); $headers = $cacheFileContent[0]; $contents = $cacheFileContent[1]; foreach ($headers as $header) { // Skip Last-Modified from cache file only if we set our own from x-cache-ctime if ($setOwnLastModified && strtolower($header['name']) === 'last-modified') { continue; } header($header['name'] . ': ' . $header['value'], false); } echo $contents; } /** * Get cache creation time from x-cache-ctime header. */ private function getCacheCreationTime() { if ($this->useInvalidated) { $filePath = $this->getCachefilePath("stale"); } else { $filePath = $this->getCachefilePath(); } try { $headers = Filesystem::fileGetHeaders($filePath); return !empty($headers["x-cache-ctime"]) ? (int)$headers["x-cache-ctime"] : 0; } catch (\Exception $e) { return 0; } } /** * Get variation cookie prefix (only cookies that create cache variations). * Excludes the tracking cookie to prevent circular dependency. * Returns empty string if no variation cookies are present. */ private function getVariationCookiePrefix() { $prefix = ''; $cookies = $this->cookiesProvider ? call_user_func($this->cookiesProvider) : $this->cookies; ksort($cookies); foreach ($cookies as $cookieName => $cookieValue) { // Exclude our tracking cookie to prevent circular dependency // (tracking cookie value depends on this prefix) if ($cookieName === 'np_cache_variation') { continue; } foreach ($this->supportedCookies as $cookie) { if (preg_match('/' . NitroPack::wildcardToRegex($cookie) . '/', $cookieName)) { $prefix .= $cookieName . '=' . $cookieValue . ';'; break; } } } return $prefix; } public function returnCacheFileContent() { if ($this->useInvalidated) { $this->convertToStaleCache(); $filePath = $this->getCachefilePath("stale"); } else { $filePath = $this->getCachefilePath(); } if ($this->canUseCompression() && (ini_get("zlib.output_compression") === "0" || ini_set("zlib.output_compression", "0") !== false)) { $filePath .= ".gz"; } $file = Filesystem::fileGetAll($filePath); $returnHeaders = []; foreach ($file->headers as $name => $value) { if (is_array($value)) { foreach ($value as $subVal) { $returnHeaders[] = [ 'name' => $name, 'value' => $subVal ]; } } else { $returnHeaders[] = [ 'name' => $name, 'value' => $value ]; } } return [ $returnHeaders, $file->content ]; } public function getFileContents() { if ($this->useInvalidated) { $this->convertToStaleCache(); return Filesystem::fileGetContents($this->getCachefilePath("stale")); } return Filesystem::fileGetContents($this->getCachefilePath()); } private function convertToStaleCache() { $staleFile = $this->getCachefilePath("stale"); if (!Filesystem::fileExists($staleFile)) { $freshFile = $this->getCachefilePath(); if (Filesystem::fileExists($freshFile)) { $fileInfo = Filesystem::fileGetAll($freshFile); $newContent = str_replace("NITROPACK_STATE='FRESH'", "NITROPACK_STATE='STALE'", $fileInfo->content); Filesystem::filePutContents($freshFile, $newContent, $this->headersFlatten($fileInfo->headers)); Filesystem::rename($freshFile, $staleFile); Filesystem::deleteFile($freshFile . ".gz"); $this->compress($staleFile); } } } private function cookiePrefix() { $prefix = ''; $cookies = $this->cookiesProvider ? call_user_func($this->cookiesProvider) : $this->cookies; ksort($cookies); foreach ($cookies as $cookieName => $cookieValue) { foreach ($this->supportedCookies as $cookie) { if (preg_match('/' . NitroPack::wildcardToRegex($cookie) . '/', $cookieName)) { if (preg_match("/^nitro_geot_(.*)/", $cookieName, $matches)) { $geotComponent = $matches[1]; if (property_exists($this->geotVariations, $geotComponent) && !empty($this->geotVariations->$geotComponent) && !in_array($cookieValue, $this->geotVariations->$geotComponent)) { $prefix .= $cookieName . '=' . $this->geotVariations->{$geotComponent}[0] . ';'; // Use the first variation as default continue; } } $prefix .= $cookieName . '=' . $cookieValue . ';'; } } } return substr(md5($prefix), 0, 16); } private function sslPrefix() { return $this->url->getScheme() == "https" ? "ssl-" : ""; } private function ajaxPrefix() { return $this->isAjax && $this->parent ? "ajax-" . md5($this->url->getNormalized()) . "-" : ""; } private function customCachePrefix() { $customCachePrefix = NitroPack::getCustomCachePrefix(); return $customCachePrefix ? $customCachePrefix . "-" : ""; } private function isCompressionAllowed() { return isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false; } private function canUseCompression() { return $this->useCompression && $this->isCompressionAllowed() && !headers_sent(); } public function nameOfCachefile() { return $this->customCachePrefix() . $this->ajaxPrefix() . $this->sslPrefix() . $this->cookiePrefix() . ".html"; } public function getCachefilePath($suffix = "") { if ($suffix) $suffix = "." . $suffix; if ($this->isAjax && $this->referer) { return self::getUrlDir($this->dataDir, $this->referer->getNormalized(), $this->useInvalidated, $this->urlPathVersion) . "/" . $this->nameOfCachefile() . $suffix; } return self::getUrlDir($this->dataDir, $this->url->getNormalized(), $this->useInvalidated, $this->urlPathVersion) . "/" . $this->nameOfCachefile() . $suffix; } }
Copyright ©2021 || Defacer Indonesia